scintilla: Keep window position when reloading a file
[anjuta-extras.git] / plugins / scintilla / text_editor.c
blobeb24ae7b7e9681624a6ec7fa1907eed7882ef4ba
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
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 <stdlib.h>
29 #include <ctype.h>
30 #include <gio/gio.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdk.h>
33 #include <errno.h>
35 #include "plugin.h"
36 #include <libanjuta/resources.h>
37 #include <libanjuta/anjuta-utils.h>
38 #include <libanjuta/anjuta-encodings.h>
39 #include <libanjuta/anjuta-convert.h>
40 #include <libanjuta/anjuta-debug.h>
41 #include <libanjuta/anjuta-shell.h>
42 #include <libanjuta/interfaces/ianjuta-document-manager.h>
43 #include <libanjuta/interfaces/ianjuta-editor.h>
44 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
45 #include <libanjuta/interfaces/ianjuta-editor-convert.h>
46 #include <libanjuta/interfaces/ianjuta-editor-line-mode.h>
47 #include <libanjuta/interfaces/ianjuta-editor-view.h>
48 #include <libanjuta/interfaces/ianjuta-editor-folds.h>
49 #include <libanjuta/interfaces/ianjuta-editor-comment.h>
50 #include <libanjuta/interfaces/ianjuta-editor-zoom.h>
51 #include <libanjuta/interfaces/ianjuta-editor-goto.h>
52 #include <libanjuta/interfaces/ianjuta-editor-language.h>
53 #include <libanjuta/interfaces/ianjuta-editor-tip.h>
54 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
55 #include <libanjuta/interfaces/ianjuta-editor-search.h>
56 #include <libanjuta/interfaces/ianjuta-editor-hover.h>
57 #include <libanjuta/interfaces/ianjuta-editor-factory.h>
58 #include <libanjuta/interfaces/ianjuta-file.h>
59 #include <libanjuta/interfaces/ianjuta-file-savable.h>
60 #include <libanjuta/interfaces/ianjuta-markable.h>
61 #include <libanjuta/interfaces/ianjuta-indicable.h>
62 #include <libanjuta/interfaces/ianjuta-print.h>
63 #include <libanjuta/interfaces/ianjuta-document.h>
64 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
66 #include "properties.h"
67 #include "text_editor.h"
68 #include "text_editor_cbs.h"
69 #include "text-editor-iterable.h"
70 #include "print.h"
72 #define GTK
73 #undef PLAT_GTK
74 #define PLAT_GTK 1
75 #include "Scintilla.h"
76 #include "SciLexer.h"
77 #include "ScintillaWidget.h"
79 #include "lexer.h"
80 #include "aneditor.h"
81 #include "text_editor_prefs.h"
83 /* Order is important, as marker with the lowest number is drawn first */
84 #define TEXT_EDITOR_BOOKMARK 0
85 #define TEXT_EDITOR_BREAKPOINT_DISABLED 1
86 #define TEXT_EDITOR_BREAKPOINT_ENABLED 2
87 #define TEXT_EDITOR_PROGRAM_COUNTER 3
88 #define TEXT_EDITOR_LINEMARKER 4
90 #define RATE_LIMIT_IN_MS 2000
92 /* Include marker pixmaps */
93 #include "anjuta-bookmark-16.xpm"
94 #include "anjuta-breakpoint-disabled-16.xpm"
95 #include "anjuta-breakpoint-enabled-16.xpm"
96 #include "anjuta-pcmark-16.xpm"
97 #include "anjuta-linemark-16.xpm"
99 static gchar** marker_pixmap[] =
101 anjuta_bookmark_16_xpm,
102 anjuta_breakpoint_disabled_16_xpm,
103 anjuta_breakpoint_enabled_16_xpm,
104 anjuta_pcmark_16_xpm,
105 anjuta_linemark_16_xpm,
106 NULL
109 /* Editor language supports */
110 static GList *supported_languages = NULL;
111 static GHashTable *supported_languages_name = NULL;
112 static GHashTable *supported_languages_ext = NULL;
113 static GHashTable *supported_languages_by_lexer = NULL;
115 static void text_editor_finalize (GObject *obj);
116 static void text_editor_dispose (GObject *obj);
117 static void text_editor_hilite_one (TextEditor * te, AnEditorID editor);
119 static GtkVBoxClass *parent_class;
122 static void
123 text_editor_instance_init (TextEditor *te)
125 te->filename = NULL;
126 te->uri = NULL;
127 te->views = NULL;
128 te->popup_menu = NULL;
130 te->monitor = NULL;
131 te->force_hilite = NULL;
132 te->force_pref = FALSE;
133 te->freeze_count = 0;
134 te->current_line = 0;
135 te->popup_menu = NULL;
136 te->props_base = 0;
137 te->first_time_expose = TRUE;
138 te->encoding = NULL;
139 te->notify_ids = NULL;
140 te->hover_tip_on = FALSE;
141 te->last_saved_content = NULL;
142 te->force_not_saved = FALSE;
143 te->message_area = NULL;
145 te->provider = NULL;
146 te->completion_count = 0;
147 te->completion_string = g_string_sized_new (256);
148 te->completion_finished = FALSE;
150 te->settings = g_settings_new (PREF_SCHEMA);
151 te->docman_settings = g_settings_new (DOCMAN_PREF_SCHEMA);
152 te->msgman_settings = g_settings_new (MSGMAN_PREF_SCHEMA);
155 static GtkWidget *
156 anjuta_message_area_new (const gchar *text,
157 GtkMessageType type)
159 GtkInfoBar *message_area;
160 GtkWidget *content_area;
161 GtkWidget *message_label = gtk_label_new ("");
163 message_area = GTK_INFO_BAR (gtk_info_bar_new ());
164 gtk_info_bar_set_message_type (message_area, type);
165 content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (message_area));
166 gtk_widget_show (message_label);
167 gtk_container_add (GTK_CONTAINER (content_area), message_label);
169 gchar *markup = g_strdup_printf ("<b>%s</b>", text);
170 gtk_label_set_markup (GTK_LABEL (message_label), markup);
171 g_free (markup);
173 return GTK_WIDGET (message_area);
176 static void
177 text_editor_class_init (TextEditorClass *klass)
179 GObjectClass *object_class = G_OBJECT_CLASS (klass);
181 parent_class = g_type_class_peek_parent (klass);
182 object_class->finalize = text_editor_finalize;
183 object_class->dispose = text_editor_dispose;
186 #if 0
187 static void
188 check_tm_file(TextEditor *te)
190 if (NULL == te->tm_file)
192 // FIXME:
193 // te->tm_file = tm_workspace_find_object(
194 //TM_WORK_OBJECT(app->tm_workspace), te->uri, FALSE);
195 if (NULL == te->tm_file)
197 te->tm_file = tm_source_file_new(te->uri, TRUE);
198 if (NULL != te->tm_file)
199 tm_workspace_add_object(te->tm_file);
203 #endif
205 static void
206 initialize_markers (TextEditor* te, GtkWidget *scintilla)
208 gint marker;
209 gchar ***xpm;
210 g_return_if_fail (te != NULL);
212 marker = 0;
213 for (xpm = marker_pixmap;*xpm != NULL; xpm++)
215 scintilla_send_message (SCINTILLA (scintilla), SCI_MARKERDEFINEPIXMAP,
216 marker, (sptr_t)*xpm);
217 marker++;
221 /* Hack to simulate async loading */
222 static gboolean
223 emit_opened (TextEditor* te)
225 g_signal_emit_by_name (te, "opened");
226 return FALSE;
230 #ifdef DEBUG
231 static void
232 on_scintila_already_destroyed (gpointer te, GObject *obj)
234 /* DEBUG_PRINT ("%s", "Scintilla object has been destroyed"); */
237 static void
238 on_te_already_destroyed (gpointer te, GObject *obj)
240 /* DEBUG_PRINT ("%s", "TextEditor object has been destroyed"); */
242 #endif
244 /* Indicators are setup in both TextEditor and AnEditor object.
245 * AnEditor reads the property file while TexEditor uses the
246 * GSettings object. TextEditor can overwrite properties
247 * set by AnEditor.
249 static void
250 text_editor_setup_indicators_color (TextEditor *te)
252 char* spec;
253 GdkColor color;
255 /* Important color */
256 spec = g_settings_get_string (te->msgman_settings, MSGMAN_COLOR_IMPORTANT);
257 if (gdk_color_parse (spec, &color))
259 glong param = ((color.red >> 8) & 0xFF) + (color.green & 0xFF00) + ((color.blue << 8) & 0x00FF0000);
260 scintilla_send_message (SCINTILLA (te->scintilla), SCI_INDICSETFORE, 0, param);
262 g_free (spec);
263 /* Warning color */
264 spec = g_settings_get_string (te->msgman_settings, MSGMAN_COLOR_WARNING);
265 if (gdk_color_parse (spec, &color))
267 glong param = ((color.red >> 8) & 0xFF) + (color.green & 0xFF00) + ((color.blue << 8) & 0x00FF0000);
268 scintilla_send_message (SCINTILLA (te->scintilla), SCI_INDICSETFORE, 1, param);
270 g_free (spec);
271 /* Error color */
272 spec = g_settings_get_string (te->msgman_settings, MSGMAN_COLOR_ERROR);
273 if (gdk_color_parse (spec, &color))
275 glong param = ((color.red >> 8) & 0xFF) + (color.green & 0xFF00) + ((color.blue << 8) & 0x00FF0000);
276 scintilla_send_message (SCINTILLA (te->scintilla), SCI_INDICSETFORE, 2, param);
278 g_free (spec);
281 void
282 text_editor_add_view (TextEditor *te)
284 AnEditorID editor_id;
285 GtkWidget *scintilla;
286 gint current_line;
287 gint current_point;
289 if (te->views)
291 current_line = text_editor_get_current_lineno (te);
292 current_point = text_editor_get_current_position (te);
294 else
296 current_line = 0;
297 current_point = 0;
299 editor_id = aneditor_new (sci_prop_get_pointer (te->props_base));
300 scintilla = aneditor_get_widget (editor_id);
302 /* Set notifications to receive */
303 scintilla_send_message (SCINTILLA (scintilla), SCI_SETMODEVENTMASK,
304 (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT), 0);
306 /* Set parent, if it is not primary view */
307 if (te->views)
309 aneditor_set_parent (editor_id, GPOINTER_TO_INT(te->editor_id));
311 te->views = g_list_prepend (te->views, GINT_TO_POINTER (editor_id));
312 te->editor_id = editor_id;
313 te->scintilla = scintilla;
316 aneditor_command (te->editor_id, ANE_SETACCELGROUP,
317 (glong) app->accel_group, 0);
320 gtk_widget_set_size_request (scintilla, 50, 50);
321 gtk_widget_show (scintilla);
323 gtk_box_set_spacing (GTK_BOX (te->vbox), 3);
324 gtk_box_pack_start (GTK_BOX (te->vbox), scintilla, TRUE, TRUE, 0);
325 gtk_widget_grab_focus (scintilla);
327 g_signal_connect (G_OBJECT (scintilla), "event",
328 G_CALLBACK (on_text_editor_text_event), te);
329 g_signal_connect (G_OBJECT (scintilla), "button_press_event",
330 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
331 g_signal_connect (G_OBJECT (scintilla), "key_release_event",
332 G_CALLBACK (on_text_editor_text_keyrelease_event), te);
333 g_signal_connect_after (G_OBJECT (scintilla), "size_allocate",
334 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
335 g_signal_connect (G_OBJECT (scintilla), "sci-notify",
336 G_CALLBACK (on_text_editor_scintilla_notify), te);
337 g_signal_connect (G_OBJECT (scintilla), "focus_in_event",
338 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
340 initialize_markers (te, scintilla);
341 text_editor_hilite_one (te, editor_id);
342 text_editor_set_line_number_width (te);
344 if (current_line)
345 text_editor_goto_line (te, current_line, FALSE, TRUE);
346 if (current_point)
347 text_editor_goto_point (te, current_point);
349 #ifdef DEBUG
350 g_object_weak_ref (G_OBJECT (scintilla), on_scintila_already_destroyed, te);
351 #endif
354 /* Remove the current view */
355 void
356 text_editor_remove_view (TextEditor *te)
358 if (!te->editor_id)
359 return;
360 if (te->views == NULL ||
361 g_list_length (te->views) <= 1)
362 return;
364 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
365 G_CALLBACK (on_text_editor_text_event), te);
366 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
367 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
368 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
369 G_CALLBACK (on_text_editor_text_keyrelease_event), te);
370 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
371 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
372 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
373 G_CALLBACK (on_text_editor_scintilla_notify), te);
374 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
375 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
377 te->views = g_list_remove (te->views, GINT_TO_POINTER(te->editor_id));
378 gtk_container_remove (GTK_CONTAINER (te->vbox), te->scintilla);
379 aneditor_destroy(te->editor_id);
381 /* Set current view */
382 if (te->views)
384 te->editor_id = GPOINTER_TO_INT(te->views->data);
385 te->scintilla = aneditor_get_widget (te->editor_id);
386 gtk_widget_grab_focus (te->scintilla);
388 else
390 gtk_box_set_spacing (GTK_BOX (te->vbox), 0);
391 te->editor_id = 0;
392 te->scintilla = NULL;
396 static void
397 on_reload_dialog_response (GtkWidget *message_area, gint res, TextEditor *te)
399 if (res == GTK_RESPONSE_YES)
401 gint visible_line = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETFIRSTVISIBLELINE, 0, 0);
402 text_editor_load_file (te);
403 scintilla_send_message (SCINTILLA (te->scintilla), SCI_SETFIRSTVISIBLELINE, visible_line, 0);
405 else
407 text_editor_set_saved (te, FALSE);
408 gtk_widget_destroy (message_area);
412 static void
413 on_destroy_message_area (gpointer data, GObject *finalized_object)
415 TextEditor *te = (TextEditor *)data;
417 te->message_area = NULL;
418 g_signal_emit_by_name (G_OBJECT (te), "update-save-ui");
421 static void
422 on_close_dialog_response (GtkWidget *message_area, gint res, TextEditor *te)
424 if (res == GTK_RESPONSE_YES)
426 IAnjutaDocumentManager *docman;
428 docman = anjuta_shell_get_interface (te->shell, IAnjutaDocumentManager, NULL);
429 if (docman == NULL) return;
431 ianjuta_document_manager_remove_document (docman, IANJUTA_DOCUMENT (te), FALSE, NULL);
433 else
435 text_editor_set_saved (te, FALSE);
436 gtk_widget_destroy (message_area);
440 static void
441 text_editor_set_message_area (TextEditor *te, GtkWidget *message_area)
443 if (te->message_area != NULL)
444 gtk_widget_destroy (te->message_area);
445 te->message_area = message_area;
447 if (te->message_area == NULL)
448 return;
450 gtk_widget_show (message_area);
451 gtk_box_pack_start (GTK_BOX (te),
452 message_area,
453 FALSE,
454 FALSE,
456 g_object_weak_ref (G_OBJECT (te->message_area),
457 on_destroy_message_area, te);
459 g_signal_emit_by_name (G_OBJECT (te), "update-save-ui");
462 static void
463 on_text_editor_uri_changed (GFileMonitor *monitor,
464 GFile *file,
465 GFile *other_file,
466 GFileMonitorEvent event_type,
467 gpointer user_data)
469 TextEditor *te = TEXT_EDITOR (user_data);
470 GtkWidget *message_area;
471 gchar *buff;
473 /* DEBUG_PRINT ("%s", "File changed!!!"); */
475 switch (event_type)
477 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
479 if (!anjuta_util_diff (te->uri, te->last_saved_content))
481 /* The file content is same. Remove any previous prompt for reload */
482 if (te->message_area)
483 gtk_widget_destroy (te->message_area);
484 te->message_area = NULL;
485 return;
487 /* No break here */
489 case G_FILE_MONITOR_EVENT_CREATED:
490 if (text_editor_is_saved (te))
492 buff = g_strdup_printf (_("The file '%s' has been changed.\n"
493 "Do you want to reload it ?"),
494 te->filename);
496 else
498 buff = g_strdup_printf (_("The file '%s' has been changed.\n"
499 "Do you want to loose your changes and reload it ?"),
500 te->filename);
502 message_area = anjuta_message_area_new (buff, GTK_MESSAGE_WARNING);
503 g_free (buff);
504 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
505 GTK_STOCK_REFRESH,
506 GTK_RESPONSE_YES);
507 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
508 GTK_STOCK_CANCEL,
509 GTK_RESPONSE_NO);
510 g_signal_connect (G_OBJECT(message_area), "response",
511 G_CALLBACK (on_reload_dialog_response),
512 te);
513 break;
514 case G_FILE_MONITOR_EVENT_DELETED:
515 if (text_editor_is_saved (te))
517 buff = g_strdup_printf (_
518 ("The file '%s' has been deleted.\n"
519 "Do you confirm and close it ?"),
520 te->filename);
522 else
524 buff = g_strdup_printf (_
525 ("The file '%s' has been deleted.\n"
526 "Do you want to loose your changes and close it ?"),
527 te->filename);
529 message_area = anjuta_message_area_new (buff, GTK_MESSAGE_WARNING);
530 g_free (buff);
531 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
532 GTK_STOCK_DELETE,
533 GTK_RESPONSE_YES);
534 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
535 GTK_STOCK_CANCEL,
536 GTK_RESPONSE_NO);
537 g_signal_connect (G_OBJECT(message_area), "response",
538 G_CALLBACK (on_close_dialog_response),
539 te);
540 break;
541 case G_FILE_MONITOR_EVENT_CHANGED:
542 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
543 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
544 case G_FILE_MONITOR_EVENT_UNMOUNTED:
545 return;
546 default:
547 g_warn_if_reached ();
548 return;
551 text_editor_set_message_area (te, message_area);
554 static void
555 text_editor_update_monitor (TextEditor *te, gboolean disable_it)
557 if (te->monitor)
559 /* Shutdown existing monitor */
560 g_file_monitor_cancel (te->monitor);
561 te->monitor = NULL;
563 if (te->message_area)
565 /* Remove existing message area */
566 gtk_widget_destroy (te->message_area);
567 te->message_area = NULL;
569 if (te->uri && !disable_it)
571 GFile *gio_uri;
572 GError *error = NULL;
573 /* DEBUG_PRINT ("%s", "Setting up Monitor for %s", te->uri); */
575 gio_uri = g_file_new_for_uri (te->uri);
576 te->monitor = g_file_monitor_file (gio_uri,
577 G_FILE_MONITOR_NONE,
578 NULL,
579 &error);
580 g_file_monitor_set_rate_limit (te->monitor, RATE_LIMIT_IN_MS);
581 g_signal_connect (te->monitor, "changed",
582 G_CALLBACK (on_text_editor_uri_changed), te);
583 g_object_unref (gio_uri);
585 if (error != NULL)
587 DEBUG_PRINT ("Error while setting up file monitor: %s",
588 error->message);
589 g_error_free (error);
595 static void
596 on_shell_value_changed (TextEditor *te, const char *name)
598 g_return_if_fail (name != NULL);
600 if ((strcmp (name, TEXT_EDITOR_PROJECT_TYPE_LIST) == 0) ||
601 (strcmp (name, TEXT_EDITOR_SYSTEM_TYPE_LIST) == 0))
603 /* Type names list has changed, so refresh highlight */
604 text_editor_hilite (te, te->force_pref);
608 static void
609 on_style_changed (TextEditor *te)
611 /* Refresh highlight */
612 text_editor_hilite (te, te->force_pref);
615 static void
616 on_indicators_changed (TextEditor *te)
618 /* Refresh indicator */
619 text_editor_setup_indicators_color (te);
622 GtkWidget *
623 text_editor_new (AnjutaPlugin *plugin, const gchar *uri, const gchar *name)
625 AnjutaShell *shell = plugin->shell;
626 AnjutaStatus *status = anjuta_shell_get_status (shell, NULL);
627 TextEditor *te = TEXT_EDITOR (gtk_widget_new (TYPE_TEXT_EDITOR, NULL));
628 gint zoom_factor;
629 static guint new_file_count;
631 te->status = status;
632 te->shell = shell;
634 te->props_base = text_editor_get_props();
635 if (name && strlen(name) > 0)
636 te->filename = g_strdup(name);
637 else
638 te->filename = g_strdup_printf ("Newfile#%d", ++new_file_count);
639 if (uri && strlen(uri) > 0)
641 new_file_count--;
642 g_free (te->filename);
643 g_free (te->uri);
645 GFile *gio_uri;
646 gio_uri = g_file_new_for_uri (uri);
647 te->filename = g_file_get_basename (gio_uri);
648 g_object_unref (gio_uri);
650 te->uri = g_strdup (uri);
653 text_editor_prefs_init (te);
655 /* Create primary view */
656 te->vbox = gtk_vbox_new (TRUE, 3);
657 gtk_box_pack_end (GTK_BOX (te), te->vbox, TRUE, TRUE, 0);
658 text_editor_add_view (te);
660 if (te->uri)
662 if (text_editor_load_file (te) == FALSE)
664 /* Unable to load file */
665 gtk_widget_destroy (GTK_WIDGET (te));
666 return NULL;
669 text_editor_update_controls (te);
671 /* Apply font zoom separately */
672 zoom_factor = g_settings_get_int (te->docman_settings, TEXT_ZOOM_FACTOR);
673 /* DEBUG_PRINT ("%s", "Initializing zoom factor to: %d", zoom_factor); */
674 text_editor_set_zoom_factor (te, zoom_factor);
675 text_editor_setup_indicators_color (te);
677 /* Get type name notification */
678 g_signal_connect_swapped (G_OBJECT (shell), "value-added", G_CALLBACK (on_shell_value_changed), te);
679 g_signal_connect_swapped (G_OBJECT (shell), "value-removed", G_CALLBACK (on_shell_value_changed), te);
680 g_signal_connect_swapped (G_OBJECT (plugin), "style-changed", G_CALLBACK(on_style_changed), te);
682 g_signal_connect_swapped (G_OBJECT(te->msgman_settings), "changed", G_CALLBACK (on_indicators_changed), te);
684 #ifdef DEBUG
685 g_object_weak_ref (G_OBJECT (te), on_te_already_destroyed, te);
686 #endif
687 return GTK_WIDGET (te);
690 void
691 text_editor_dispose (GObject *obj)
693 TextEditor *te = TEXT_EDITOR (obj);
695 /* Disconnect signal */
696 g_signal_handlers_disconnect_by_func (te->shell, G_CALLBACK (on_shell_value_changed), te);
698 if (te->monitor)
700 text_editor_update_monitor (te, TRUE);
701 te->monitor = NULL;
703 if (te->popup_menu)
705 g_object_unref (te->popup_menu);
706 te->popup_menu = NULL;
708 if (te->views)
710 GtkWidget *scintilla;
711 AnEditorID editor_id;
712 GList *node;
714 node = te->views;
715 while (node)
717 editor_id = GPOINTER_TO_INT (node->data);
718 scintilla = aneditor_get_widget (editor_id);
720 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
721 G_CALLBACK (on_text_editor_text_event), te);
722 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
723 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
724 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
725 G_CALLBACK (on_text_editor_text_keyrelease_event), te);
726 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
727 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
728 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
729 G_CALLBACK (on_text_editor_scintilla_notify), te);
730 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
731 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
733 aneditor_destroy (editor_id);
734 node = g_list_next (node);
736 te->scintilla = NULL;
737 te->editor_id = 0;
738 te->views = NULL;
740 if (te->notify_ids)
742 text_editor_prefs_finalize (te);
743 te->notify_ids = NULL;
745 if (te->provider)
747 g_list_free (te->provider);
749 if (te->completion_string)
751 g_string_free (te->completion_string, TRUE);
752 te->completion_string = NULL;
754 te->completion_count = 0;
755 g_object_unref (te->settings);
756 g_object_unref (te->docman_settings);
757 g_object_unref (te->msgman_settings);
758 G_OBJECT_CLASS (parent_class)->dispose (obj);
761 void
762 text_editor_finalize (GObject *obj)
764 TextEditor *te = TEXT_EDITOR (obj);
765 g_free (te->filename);
766 g_free (te->uri);
767 g_free (te->force_hilite);
768 g_free (te->last_saved_content);
770 G_OBJECT_CLASS (parent_class)->finalize (obj);
773 void
774 text_editor_freeze (TextEditor *te)
776 te->freeze_count++;
779 void
780 text_editor_thaw (TextEditor *te)
782 te->freeze_count--;
783 if (te->freeze_count < 0)
784 te->freeze_count = 0;
787 void
788 text_editor_set_hilite_type (TextEditor * te, const gchar *file_extension)
790 const gchar *past_language;
791 const gchar *curr_language;
793 past_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
795 g_free (te->force_hilite);
796 if (file_extension)
797 te->force_hilite = g_strdup (file_extension);
798 else
799 te->force_hilite = NULL;
801 curr_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
802 if (past_language != curr_language)
803 g_signal_emit_by_name (te, "language-changed", curr_language);
806 static void
807 text_editor_hilite_one (TextEditor * te, AnEditorID editor_id)
809 const gchar *name = NULL;
810 gchar *basename = NULL;
812 /* syntax highlighting is disabled if te->force_pref && pref is disabled */
813 if (!te->force_pref ||
814 !g_settings_get_boolean (te->settings,
815 DISABLE_SYNTAX_HILIGHTING))
817 if (te->force_hilite)
819 name = te->force_hilite;
821 else if (te->uri)
823 basename = g_path_get_basename (te->uri);
824 name = basename;
826 else if (te->filename)
828 name = te->filename;
832 if (name == NULL)
834 /* No syntax higlight */
835 aneditor_command (editor_id, ANE_SETHILITE, (glong) "plain.txt", (glong) 0);
837 else
839 const gchar *typedef_hl[2];
840 GValue sys_value = {0,};
841 GValue prj_value = {0,};
843 anjuta_shell_get_value (te->shell, TEXT_EDITOR_SYSTEM_TYPE_LIST, &sys_value, NULL);
844 typedef_hl[0] = G_VALUE_HOLDS_STRING(&sys_value) ? g_value_get_string (&sys_value) : NULL;
846 anjuta_shell_get_value (te->shell, TEXT_EDITOR_PROJECT_TYPE_LIST, &prj_value, NULL);
847 typedef_hl[1] = G_VALUE_HOLDS_STRING(&prj_value) ? g_value_get_string (&prj_value) : NULL;
849 aneditor_command (editor_id, ANE_SETHILITE, (glong) name, (glong) typedef_hl);
850 if (G_IS_VALUE (&sys_value)) g_value_unset (&sys_value);
851 if (G_IS_VALUE (&prj_value)) g_value_unset (&prj_value);
853 g_free (basename);
856 void
857 text_editor_hilite (TextEditor * te, gboolean override_by_pref)
859 GList *node;
861 te->force_pref = override_by_pref;
862 node = te->views;
863 while (node)
865 text_editor_hilite_one (te, GPOINTER_TO_INT (node->data));
866 node = g_list_next (node);
869 text_editor_setup_indicators_color (te);
872 void
873 text_editor_set_zoom_factor (TextEditor * te, gint zfac)
875 text_editor_command (te, ANE_SETZOOM, zfac, 0);
878 TextEditorAttrib
879 text_editor_get_attribute (TextEditor *te, gint position)
881 int lexer;
882 int style;
883 TextEditorAttrib attrib = TEXT_EDITOR_ATTRIB_TEXT;
885 lexer = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETLEXER,
886 0, 0);
887 style = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETSTYLEAT,
888 position, 0);
889 switch (lexer)
891 case SCLEX_CPP:
892 switch (style)
894 case SCE_C_CHARACTER:
895 case SCE_C_STRING:
896 attrib = TEXT_EDITOR_ATTRIB_STRING;
897 break;
898 case SCE_C_COMMENT:
899 case SCE_C_COMMENTLINE:
900 case SCE_C_COMMENTDOC:
901 case SCE_C_COMMENTLINEDOC:
902 case SCE_C_COMMENTDOCKEYWORD:
903 case SCE_C_COMMENTDOCKEYWORDERROR:
904 attrib = TEXT_EDITOR_ATTRIB_COMMENT;
905 break;
906 case SCE_C_WORD:
907 attrib = TEXT_EDITOR_ATTRIB_KEYWORD;
908 break;
910 break;
911 case SCLEX_PYTHON:
912 switch (style)
914 case SCE_P_CHARACTER:
915 case SCE_P_STRING:
916 case SCE_P_TRIPLE:
917 case SCE_P_TRIPLEDOUBLE:
918 attrib = TEXT_EDITOR_ATTRIB_STRING;
919 break;
920 case SCE_P_COMMENTLINE:
921 case SCE_P_COMMENTBLOCK:
922 attrib = TEXT_EDITOR_ATTRIB_COMMENT;
923 break;
924 case SCE_P_WORD:
925 case SCE_P_WORD2:
926 attrib = TEXT_EDITOR_ATTRIB_KEYWORD;
927 break;
929 break;
931 return attrib;
934 glong
935 text_editor_find (TextEditor * te, const gchar * str, gint scope,
936 gboolean forward, gboolean regexp,
937 gboolean ignore_case, gboolean whole_word, gboolean wrap)
939 glong ret;
940 GtkWidget *editor;
941 glong flags;
942 int current_pos, current_anchor;
944 if (!te) return -1;
945 editor = te->scintilla;
947 flags = (ignore_case ? 0 : SCFIND_MATCHCASE)
948 | (regexp ? SCFIND_REGEXP : 0)
949 | (whole_word ? SCFIND_WHOLEWORD : 0)
950 | (forward ? 0 : ANEFIND_REVERSE_FLAG);
952 switch (scope)
954 case TEXT_EDITOR_FIND_SCOPE_WHOLE:
955 if (forward)
957 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
958 0, 0);
959 scintilla_send_message (SCINTILLA (editor),
960 SCI_SETCURRENTPOS, 0, 0);
962 else
964 glong length;
965 length = scintilla_send_message (SCINTILLA (editor),
966 SCI_GETTEXTLENGTH, 0, 0);
967 scintilla_send_message (SCINTILLA (editor),
968 SCI_SETCURRENTPOS, length-1, 0);
969 scintilla_send_message (SCINTILLA (editor),
970 SCI_SETANCHOR, length-1, 0);
972 break;
973 default:
974 break;
976 current_pos = scintilla_send_message (SCINTILLA (editor),
977 SCI_GETCURRENTPOS, 0, 0);
978 current_anchor = scintilla_send_message (SCINTILLA (editor),
979 SCI_GETANCHOR, 0, 0);
980 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
981 if (scope == TEXT_EDITOR_FIND_SCOPE_CURRENT && wrap && ret < 0) {
982 /* If wrap is requested, wrap it. */
983 if (forward)
985 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR, 0, 0);
986 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
987 0, 0);
989 else
991 glong length;
992 length = scintilla_send_message (SCINTILLA (editor),
993 SCI_GETTEXTLENGTH, 0, 0);
994 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
995 length-1, 0);
996 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
997 length-1, 0);
999 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
1000 /* If the text is still not found, restore current pos and anchor */
1001 if (ret < 0) {
1002 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
1003 current_anchor, 0);
1004 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
1005 current_pos, 0);
1008 return ret;
1011 void
1012 text_editor_replace_selection (TextEditor * te, const gchar* r_str)
1014 if (!te) return;
1015 scintilla_send_message (SCINTILLA(te->scintilla), SCI_REPLACESEL, 0,
1016 (long)r_str);
1019 guint
1020 text_editor_get_total_lines (TextEditor * te)
1022 guint i;
1023 guint count = 0;
1024 if (te == NULL)
1025 return 0;
1026 if (IS_SCINTILLA (te->scintilla) == FALSE)
1027 return 0;
1028 for (i = 0;
1029 i < scintilla_send_message (SCINTILLA (te->scintilla),
1030 SCI_GETLENGTH, 0, 0); i++)
1032 if (scintilla_send_message
1033 (SCINTILLA (te->scintilla), SCI_GETCHARAT, i,
1034 0) == '\n')
1035 count++;
1037 return count;
1040 guint
1041 text_editor_get_current_lineno (TextEditor * te)
1043 guint count;
1045 g_return_val_if_fail (te != NULL, 0);
1047 count = scintilla_send_message (SCINTILLA (te->scintilla),
1048 SCI_GETCURRENTPOS, 0, 0);
1049 count = scintilla_send_message (SCINTILLA (te->scintilla),
1050 SCI_LINEFROMPOSITION, count, 0);
1051 return linenum_scintilla_to_text_editor(count);
1054 guint
1055 text_editor_get_position_lineno (TextEditor * te, gint position)
1057 guint count;
1058 g_return_val_if_fail (te != NULL, 0);
1060 count = scintilla_send_message (SCINTILLA (te->scintilla),
1061 SCI_LINEFROMPOSITION, position, 0);
1062 return linenum_scintilla_to_text_editor(count);
1065 guint
1066 text_editor_get_current_column (TextEditor * te)
1068 g_return_val_if_fail (te != NULL, 0);
1069 return scintilla_send_message (SCINTILLA (te->scintilla),
1070 SCI_GETCOLUMN,
1071 text_editor_get_current_position (te), 0);
1074 gboolean
1075 text_editor_get_overwrite (TextEditor * te)
1077 g_return_val_if_fail (te != NULL, 0);
1078 return scintilla_send_message (SCINTILLA (te->scintilla),
1079 SCI_GETOVERTYPE, 0, 0);
1082 guint
1083 text_editor_get_line_from_position (TextEditor * te, glong pos)
1085 guint count;
1087 g_return_val_if_fail (te != NULL, 0);
1089 count = scintilla_send_message (SCINTILLA (te->scintilla),
1090 SCI_LINEFROMPOSITION, pos, 0);
1091 return linenum_scintilla_to_text_editor(count);
1094 glong
1095 text_editor_get_current_position (TextEditor * te)
1097 guint count;
1099 g_return_val_if_fail (te != NULL, 0);
1101 count = scintilla_send_message (SCINTILLA (te->scintilla),
1102 SCI_GETCURRENTPOS, 0, 0);
1103 return count;
1106 gboolean
1107 text_editor_goto_point (TextEditor * te, glong point)
1109 g_return_val_if_fail (te != NULL, FALSE);
1110 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
1112 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS, point, 0);
1113 return TRUE;
1116 gboolean
1117 text_editor_goto_line (TextEditor * te, glong line,
1118 gboolean mark, gboolean ensure_visible)
1120 gint selpos;
1121 g_return_val_if_fail (te != NULL, FALSE);
1122 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
1123 g_return_val_if_fail(line >= 0, FALSE);
1125 te->current_line = line;
1126 if (mark) text_editor_set_line_marker (te, line);
1127 if (ensure_visible)
1128 scintilla_send_message (SCINTILLA (te->scintilla),
1129 SCI_ENSUREVISIBLE,
1130 linenum_text_editor_to_scintilla (line), 0);
1131 selpos = scintilla_send_message(SCINTILLA (te->scintilla),
1132 SCI_POSITIONFROMLINE,
1133 linenum_text_editor_to_scintilla (line), 0);
1134 scintilla_send_message (SCINTILLA (te->scintilla),
1135 SCI_SETSELECTIONSTART, selpos, 0);
1136 scintilla_send_message (SCINTILLA (te->scintilla),
1137 SCI_SETSELECTIONEND, selpos, 0);
1139 /* This ensures that we have arround 5 lines visible below the mark */
1140 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
1141 linenum_text_editor_to_scintilla (line)+5, 0);
1142 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
1143 linenum_text_editor_to_scintilla (line), 0);
1144 return TRUE;
1147 gint
1148 text_editor_goto_block_start (TextEditor* te)
1150 gint line;
1151 line = aneditor_command (te->editor_id, ANE_GETBLOCKSTARTLINE, 0, 0);
1152 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
1153 else gdk_beep();
1154 return line;
1157 gint
1158 text_editor_goto_block_end (TextEditor* te)
1160 gint line;
1161 line = aneditor_command (te->editor_id, ANE_GETBLOCKENDLINE, 0, 0);
1162 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
1163 else gdk_beep();
1164 return line;
1167 gint
1168 text_editor_set_marker (TextEditor *te, glong line, gint marker)
1170 g_return_val_if_fail (te != NULL, -1);
1171 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, -1);
1173 /* Scintilla interprets line+1 rather than line */
1174 /* A bug perhaps */
1175 /* So counterbalance it with line-1 */
1176 /* Using the macros linenum_* */
1177 return scintilla_send_message (SCINTILLA (te->scintilla),
1178 SCI_MARKERADD,
1179 linenum_text_editor_to_scintilla (line),
1180 marker);
1183 gint
1184 text_editor_set_indicator (TextEditor *te, gint start,
1185 gint end, gint indicator)
1187 g_return_val_if_fail (te != NULL, -1);
1188 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
1190 scintilla_send_message (SCINTILLA (te->scintilla),
1191 SCI_SETINDICATORCURRENT, indicator, 0);
1192 scintilla_send_message (SCINTILLA (te->scintilla),
1193 SCI_INDICATORFILLRANGE, start, end - start);
1195 return 0;
1198 static gint
1199 text_editor_clear_indicator (TextEditor *te, gint start,
1200 gint end)
1202 gint i;
1204 g_return_val_if_fail (te != NULL, -1);
1205 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
1207 for (i = 0; i < 3; i++)
1209 scintilla_send_message (SCINTILLA (te->scintilla),
1210 SCI_SETINDICATORCURRENT, i, 0);
1211 scintilla_send_message (SCINTILLA (te->scintilla),
1212 SCI_INDICATORCLEARRANGE, start, end - start);
1215 return 0;
1218 static gint
1219 text_editor_clear_all_indicator (TextEditor *te)
1221 glong last;
1222 gint i;
1224 g_return_val_if_fail (te != NULL, -1);
1225 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
1227 last = scintilla_send_message (SCINTILLA (te->scintilla),
1228 SCI_GETTEXTLENGTH, 0, 0);
1229 for (i = 0; i < 3; i++)
1231 scintilla_send_message (SCINTILLA (te->scintilla),
1232 SCI_SETINDICATORCURRENT, i, 0);
1233 scintilla_send_message (SCINTILLA (te->scintilla),
1234 SCI_INDICATORCLEARRANGE, 0, last);
1237 return 0;
1240 void
1241 text_editor_set_line_marker (TextEditor *te, glong line)
1243 g_return_if_fail (te != NULL);
1244 g_return_if_fail(IS_SCINTILLA (te->scintilla) == TRUE);
1246 // FIXME: anjuta_delete_all_marker (TEXT_EDITOR_LINEMARKER);
1247 text_editor_delete_marker_all (te, TEXT_EDITOR_LINEMARKER);
1248 text_editor_set_marker (te, line, TEXT_EDITOR_LINEMARKER);
1251 /* Support for DOS-Files
1253 * On load, Anjuta will detect DOS-files by finding <CR><LF>.
1254 * Anjuta will translate some chars >= 128 to native charset.
1255 * On save the DOS_EOL_CHECK(preferences->editor) will be checked
1256 * and chars >=128 will be replaced by DOS-codes, if any translation
1257 * match(see struct tr_dos in this file) and <CR><LF> will used
1258 * instead of <LF>.
1259 * The DOS_EOL_CHECK-checkbox will be set on loading a DOS-file.
1261 * 23.Sep.2001 Denis Boehme <boehme at syncio dot de>
1265 * this is a translation table from unix->dos
1266 * this table will be used by filter_chars and save filtered.
1268 static struct {
1269 unsigned char c; /* unix-char */
1270 unsigned char b; /* dos-char */
1271 } tr_dos[]= {
1272 { 'ä', 0x84 },
1273 { 'Ä', 0x8e },
1274 { 'ß', 0xe1 },
1275 { 'ü', 0x81 },
1276 { 'Ü', 0x9a },
1277 { 'ö', 0x94 },
1278 { 'Ö', 0x99 },
1279 { 'é', 0x82 },
1280 { 'É', 0x90 },
1281 { 'è', 0x9a },
1282 { 'È', 0xd4 },
1283 { 'ê', 0x88 },
1284 { 'Ê', 0xd2 },
1285 { 'á', 0xa0 },
1286 { 'Á', 0xb5 },
1287 { 'à', 0x85 },
1288 { 'À', 0xb7 },
1289 { 'â', 0x83 },
1290 { 'Â', 0xb6 },
1291 { 'ú', 0xa3 },
1292 { 'Ú', 0xe9 },
1293 { 'ù', 0x97 },
1294 { 'Ù', 0xeb },
1295 { 'û', 0x96 },
1296 { 'Û', 0xea }
1300 * filter chars in buffer, by using tr_dos-table.
1303 static size_t
1304 filter_chars_in_dos_mode(gchar *data_, size_t size )
1306 int k;
1307 size_t i;
1308 unsigned char * data = (unsigned char*)data_;
1309 unsigned char * tr_map;
1311 tr_map = (unsigned char *)malloc( 256 );
1312 memset( tr_map, 0, 256 );
1313 for ( k = 0; k < sizeof(tr_dos )/2 ; k++ )
1314 tr_map[tr_dos[k].b] = tr_dos[k].c;
1316 for ( i = 0; i < size; i++ )
1318 if ( (data[i] >= 128) && ( tr_map[data[i]] != 0) )
1319 data[i] = tr_map[data[i]];;
1322 if ( tr_map )
1323 free( tr_map );
1325 return size;
1329 * save buffer. filter chars and set dos-like CR/LF if dos_text is set.
1331 static gboolean
1332 save_filtered_in_dos_mode(GFileOutputStream* stream, gchar *data_,
1333 gsize size)
1335 gboolean result;
1336 gsize i, j;
1337 unsigned char *data;
1338 unsigned char *tr_map;
1339 int k;
1341 /* build the translation table */
1342 tr_map = malloc( 256 );
1343 memset( tr_map, 0, 256 );
1345 for ( k = 0; k < sizeof(tr_dos)/2; k++)
1346 tr_map[tr_dos[k].c] = tr_dos[k].b;
1348 data = (unsigned char*)data_;
1349 i = 0;
1350 j = 0;
1351 while ( i < size )
1353 if (data[i]>=128)
1355 /* convert dos-text */
1356 if ( tr_map[data[i]] != 0 )
1358 gsize bytes_written;
1359 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1360 &tr_map[data[i]], 1,
1361 &bytes_written,
1362 NULL, NULL);
1364 j += bytes_written;
1366 else
1368 /* char not found, skip transform */
1369 gsize bytes_written;
1370 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1371 &data[i], 1,
1372 &bytes_written,
1373 NULL, NULL);
1374 j += bytes_written;
1376 i++;
1378 else
1380 gsize bytes_written;
1381 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1382 &data[i], 1,
1383 &bytes_written,
1384 NULL, NULL);
1385 j += bytes_written;
1386 i++;
1388 if (!result)
1389 break;
1392 if (tr_map)
1393 free (tr_map);
1394 return result;
1397 static gint
1398 determine_editor_mode(gchar* buffer, glong size)
1400 gint i;
1401 guint cr, lf, crlf, max_mode;
1402 gint mode;
1404 cr = lf = crlf = 0;
1406 for ( i = 0; i < size ; i++ )
1408 if ( buffer[i] == 0x0a ){
1409 // LF
1410 // mode = SC_EOF_LF;
1411 lf++;
1412 } else if ( buffer[i] == 0x0d ) {
1413 if (i >= (size-1)) {
1414 // Last char
1415 // CR
1416 // mode = SC_EOL_CR;
1417 cr++;
1418 } else {
1419 if (buffer[i+1] != 0x0a) {
1420 // CR
1421 // mode = SC_EOL_CR;
1422 cr++;
1423 } else {
1424 // CRLF
1425 // mode = SC_EOL_CRLF;
1426 crlf++;
1428 i++;
1433 /* Vote for the maximum */
1434 mode = SC_EOL_LF;
1435 max_mode = lf;
1436 if (crlf > max_mode) {
1437 mode = SC_EOL_CRLF;
1438 max_mode = crlf;
1440 if (cr > max_mode) {
1441 mode = SC_EOL_CR;
1442 max_mode = cr;
1444 /* DEBUG_PRINT ("EOL chars: LR = %d, CR = %d, CRLF = %d", lf, cr, crlf); */
1445 /* DEBUG_PRINT ("Autodetected Editor mode [%d]", mode); */
1446 return mode;
1449 static gchar *
1450 convert_to_utf8 (PropsID props, const gchar *content, gsize len,
1451 const AnjutaEncoding **encoding_used)
1453 GError* conv_error = NULL;
1454 gchar* new_content;
1455 gsize new_len;
1457 new_content = anjuta_convert_to_utf8 (content,
1458 len,
1459 encoding_used,
1460 &new_len,
1461 &conv_error);
1462 if (new_content == NULL)
1464 /* Last change, let's try 8859-15 */
1465 *encoding_used =
1466 anjuta_encoding_get_from_charset("ISO-8859-15");
1468 new_content = anjuta_convert_to_utf8 (content,
1469 len,
1470 encoding_used,
1471 &new_len,
1472 &conv_error);
1475 if (conv_error)
1476 g_error_free (conv_error);
1478 return new_content;
1481 static gboolean
1482 load_from_file (TextEditor *te, gchar *uri, gchar **err)
1484 GFile *gio_uri;
1485 GFileInputStream *stream;
1486 gboolean result;
1487 GFileInfo *info;
1488 gsize nchars;
1489 gint dos_filter, editor_mode;
1490 gchar *file_content = NULL;
1491 gchar *buffer = NULL;
1492 guint64 size;
1494 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CLEARALL,
1495 0, 0);
1496 gio_uri = g_file_new_for_uri (uri);
1497 info = g_file_query_info (gio_uri,
1498 G_FILE_ATTRIBUTE_STANDARD_SIZE,
1499 G_FILE_QUERY_INFO_NONE,
1500 NULL,
1501 NULL);
1503 if (info == NULL)
1505 *err = g_strdup (_("Could not get file info"));
1506 g_object_unref (gio_uri);
1508 return FALSE;
1510 size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
1511 g_object_unref (info);
1513 buffer = g_malloc (size + 1);
1514 if (buffer == NULL && size != 0)
1516 /* DEBUG_PRINT ("%s", "This file is too big. Unable to allocate memory."); */
1517 *err = g_strdup (_("This file is too big. Unable to allocate memory."));
1518 g_object_unref (gio_uri);
1520 return FALSE;
1523 stream = g_file_read (gio_uri, NULL, NULL);
1524 if (stream == NULL)
1526 *err = g_strdup (_("Could not open file"));
1527 g_object_unref (gio_uri);
1529 return FALSE;
1531 /* Crude way of loading, but faster */
1532 result = g_input_stream_read_all (G_INPUT_STREAM (stream),
1533 buffer, size, &nchars, NULL, NULL);
1534 if (!result)
1536 g_free(buffer);
1537 *err = g_strdup (_("Error while reading from file"));
1538 g_object_unref (gio_uri);
1540 return FALSE;
1543 if (buffer)
1545 buffer[size] = '\0';
1546 file_content = g_strdup (buffer);
1549 if (size != nchars)
1551 /* DEBUG_PRINT ("File size and loaded size not matching"); */
1553 dos_filter =
1554 g_settings_get_boolean (te->settings,
1555 DOS_EOL_CHECK);
1557 /* Set editor mode */
1558 editor_mode = determine_editor_mode (buffer, nchars);
1559 scintilla_send_message (SCINTILLA (te->scintilla),
1560 SCI_SETEOLMODE, editor_mode, 0);
1562 /* DEBUG_PRINT ("Loaded in editor mode [%d]", editor_mode); */
1564 /* Determine character encoding and convert to utf-8*/
1565 if (nchars > 0)
1567 if (g_utf8_validate (buffer, nchars, NULL))
1569 te->encoding = NULL;
1571 else
1573 gchar *converted_text;
1575 converted_text = convert_to_utf8 (te->props_base,
1576 buffer, nchars, &te->encoding);
1578 if (converted_text == NULL)
1580 /* bail out */
1581 g_free (buffer);
1582 g_free (file_content);
1583 *err = g_strdup (_("The file does not look like a text file or the file encoding is not supported."
1584 " Please check if the encoding of file is in the supported encodings list."
1585 " If not, add it from the preferences."));
1586 g_object_unref (gio_uri);
1588 return FALSE;
1590 g_free (buffer);
1591 buffer = converted_text;
1592 nchars = strlen (converted_text);
1595 if (dos_filter && editor_mode == SC_EOL_CRLF){
1596 /* DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Dos => Unix]"); */
1597 nchars = filter_chars_in_dos_mode( buffer, nchars );
1599 scintilla_send_message (SCINTILLA (te->scintilla), SCI_ADDTEXT,
1600 nchars, (long) buffer);
1602 g_free (buffer);
1604 /* Save the buffer as last saved content */
1605 g_free (te->last_saved_content);
1606 te->last_saved_content = file_content;
1608 g_object_unref (gio_uri);
1610 return TRUE;
1613 static void
1614 strip_trailing_space (gchar *data, gsize *size)
1616 gchar *space;
1617 gsize len;
1619 /* Search first trailing space */
1620 for (len = 0;;len++)
1622 while ((len != *size) && (data[len] != ' ') && (data[len] != '\t')) len++;
1623 if (len == *size) break;
1624 space = &data[len];
1625 while ((len != *size) && ((data[len] == ' ') || (data[len] == '\t'))) len++;
1626 if ((len == *size) || (data[len] == '\n') || (data[len] == '\r'))
1628 gchar *strip = space;
1630 /* Search next trailing space */
1631 for (;;)
1633 while ((len != *size) && (data[len] != ' ') && (data[len] != '\t')) *strip++ = data[len++];
1634 if (len == *size) break;
1635 space = &data[len];
1636 while ((len != *size) && ((data[len] == ' ') || (data[len] == '\t'))) *strip++ = data[len++];
1637 if ((len == *size) || (data[len] == '\n') || (data[len] == '\r'))
1639 strip -= (&data[len] - space);
1642 *size -= (&data[len] - strip);
1643 break;
1649 static gboolean
1650 save_to_file (TextEditor *te, gchar *uri, GError **error)
1652 GFileOutputStream *stream;
1653 GFile *gio_uri;
1654 gsize nchars, size;
1655 gint strip;
1656 gchar *data;
1657 gboolean result;
1659 gio_uri = g_file_new_for_uri (uri);
1660 stream = g_file_replace (gio_uri, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
1662 if (stream == NULL)
1663 return FALSE;
1665 result = TRUE;
1667 nchars = scintilla_send_message (SCINTILLA (te->scintilla),
1668 SCI_GETLENGTH, 0, 0);
1669 data = (gchar *) aneditor_command (te->editor_id,
1670 ANE_GETTEXTRANGE, 0, nchars);
1671 if (data)
1673 gint dos_filter, editor_mode;
1675 size = strlen (data);
1678 /* Save in original encoding */
1679 if ((te->encoding != NULL))
1681 GError *conv_error = NULL;
1682 gchar* converted_file_contents = NULL;
1683 gsize new_len;
1685 /* DEBUG_PRINT ("Using encoding %s", te->encoding); */
1687 /* Try to convert it from UTF-8 to original encoding */
1688 converted_file_contents = anjuta_convert_from_utf8 (data, -1,
1689 te->encoding,
1690 &new_len,
1691 &conv_error);
1693 if (conv_error != NULL)
1695 /* Conversion error */
1696 g_error_free (conv_error);
1698 else
1700 g_free (data);
1701 data = converted_file_contents;
1702 size = strlen (converted_file_contents);
1705 else
1707 /* Save in utf-8 */
1708 /* DEBUG_PRINT ("Using utf-8 encoding"); */
1711 /* Strip trailing spaces */
1712 strip = g_settings_get_boolean (te->settings,
1713 STRIP_TRAILING_SPACES);
1714 if (strip)
1716 strip_trailing_space (data, &size);
1718 if ((size > 1) && ('\n' != data[size-1]))
1720 data[size] = '\n';
1721 ++ size;
1723 dos_filter = g_settings_get_boolean (te->settings,
1724 DOS_EOL_CHECK);
1725 editor_mode = scintilla_send_message (SCINTILLA (te->scintilla),
1726 SCI_GETEOLMODE, 0, 0);
1727 /* DEBUG_PRINT ("Saving in editor mode [%d]", editor_mode); */
1728 nchars = size;
1729 if (editor_mode == SC_EOL_CRLF && dos_filter)
1731 /* DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Unix => Dos]"); */
1732 size = save_filtered_in_dos_mode (stream, data, size);
1734 else
1736 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1737 data, size,
1738 &nchars, NULL, error);
1740 data[size] = '\0';
1743 /* Set last content saved to data */
1744 g_free (te->last_saved_content);
1745 te->last_saved_content = data;
1747 if (result)
1748 result = g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, error);
1749 else
1750 g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL);
1752 g_object_unref (gio_uri);
1754 return result;
1757 gboolean
1758 text_editor_load_file (TextEditor * te)
1760 gchar *err = NULL;
1762 if (te == NULL || te->filename == NULL)
1763 return FALSE;
1764 if (IS_SCINTILLA (te->scintilla) == FALSE)
1765 return FALSE;
1766 anjuta_status (te->status, _("Loading file..."), 5);
1768 text_editor_freeze (te);
1770 // te->modified_time = time (NULL);
1771 text_editor_update_monitor (te, FALSE);
1772 if (load_from_file (te, te->uri, &err) == FALSE)
1774 anjuta_util_dialog_error (NULL,
1775 _("Could not load file: %s\n\nDetails: %s"),
1776 te->filename, err);
1777 g_free (err);
1778 text_editor_thaw (te);
1779 return FALSE;
1781 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS,
1782 0, 0);
1783 // check_tm_file(te);
1784 text_editor_thaw (te);
1785 te->force_not_saved = FALSE;
1786 scintilla_send_message (SCINTILLA (te->scintilla),
1787 SCI_SETSAVEPOINT, 0, 0);
1788 scintilla_send_message (SCINTILLA (te->scintilla),
1789 SCI_EMPTYUNDOBUFFER, 0, 0);
1790 text_editor_set_hilite_type (te, NULL);
1791 if (g_settings_get_boolean (te->settings, FOLD_ON_OPEN))
1793 aneditor_command (te->editor_id, ANE_CLOSE_FOLDALL, 0, 0);
1795 text_editor_set_line_number_width(te);
1796 anjuta_status (te->status, _("File loaded successfully"), 5);
1798 g_idle_add ((GSourceFunc) emit_opened, te);
1800 return TRUE;
1803 gboolean
1804 text_editor_save_file (TextEditor * te, gboolean update)
1806 GtkWindow *parent;
1807 GError *error = NULL;
1808 gboolean ret = FALSE;
1810 g_return_val_if_fail (te != NULL, FALSE);
1811 g_return_val_if_fail (IS_SCINTILLA (te->scintilla), FALSE);
1813 text_editor_freeze (te);
1814 text_editor_set_line_number_width(te);
1815 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (te)));
1817 anjuta_status (te->status, _("Saving file..."), 5);
1818 text_editor_update_monitor (te, TRUE);
1820 if (!save_to_file (te, te->uri, &error))
1822 text_editor_thaw (te);
1823 g_return_val_if_fail (error != NULL, FALSE);
1825 anjuta_util_dialog_error (parent,
1826 _("Could not save intermediate file %s: %s"),
1827 te->uri,
1828 error->message);
1829 g_signal_emit_by_name (G_OBJECT (te), "saved", NULL);
1830 g_error_free (error);
1832 else
1834 GFile* file = g_file_new_for_uri (te->uri);
1835 /* we need to update UI with the call to scintilla */
1836 text_editor_thaw (te);
1837 te->force_not_saved = FALSE;
1838 scintilla_send_message (SCINTILLA (te->scintilla),
1839 SCI_SETSAVEPOINT, 0, 0);
1840 g_signal_emit_by_name (G_OBJECT (te), "saved", file);
1841 g_object_unref (file);
1842 anjuta_status (te->status, _("File saved successfully"), 5);
1843 ret = TRUE;
1845 text_editor_update_monitor (te, FALSE);
1847 return ret;
1850 void
1851 text_editor_set_saved (TextEditor *te, gboolean saved)
1853 if (saved)
1855 scintilla_send_message (SCINTILLA (te->scintilla), SCI_SETSAVEPOINT, 0, 0);
1857 te->force_not_saved = !saved;
1858 g_signal_emit_by_name(G_OBJECT (te), "update-save-ui");
1861 gboolean
1862 text_editor_save_yourself (TextEditor * te, FILE * stream)
1864 return TRUE;
1867 gboolean
1868 text_editor_recover_yourself (TextEditor * te, FILE * stream)
1870 return TRUE;
1873 void
1874 text_editor_undo (TextEditor * te)
1876 scintilla_send_message (SCINTILLA (te->scintilla),
1877 SCI_UNDO, 0, 0);
1880 void
1881 text_editor_redo (TextEditor * te)
1883 scintilla_send_message (SCINTILLA (te->scintilla),
1884 SCI_REDO, 0, 0);
1887 void
1888 text_editor_update_controls (TextEditor * te)
1890 #if 0 //FIXME
1891 gboolean F, P, L, C, S;
1893 if (te == NULL)
1894 return;
1895 S = text_editor_is_saved (te);
1896 L = anjuta_launcher_is_busy (app->launcher);
1897 P = app->project_dbase->project_is_open;
1899 switch (get_file_ext_type (te->filename))
1901 case FILE_TYPE_C:
1902 case FILE_TYPE_CPP:
1903 case FILE_TYPE_ASM:
1904 F = TRUE;
1905 break;
1906 default:
1907 F = FALSE;
1909 switch (get_file_ext_type (te->filename))
1911 case FILE_TYPE_C:
1912 case FILE_TYPE_CPP:
1913 case FILE_TYPE_HEADER:
1914 C = TRUE;
1915 break;
1916 default:
1917 C = FALSE;
1919 gtk_widget_set_sensitive (te->buttons.save, !S);
1920 gtk_widget_set_sensitive (te->buttons.reload,
1921 (te->uri != NULL));
1922 gtk_widget_set_sensitive (te->buttons.compile, F && !L);
1923 gtk_widget_set_sensitive (te->buttons.build, (F || P) && !L);
1924 #endif
1927 gboolean
1928 text_editor_is_saved (TextEditor * te)
1930 return !(scintilla_send_message (SCINTILLA (te->scintilla),
1931 SCI_GETMODIFY, 0, 0)) && (!te->force_not_saved);
1934 gboolean
1935 text_editor_has_selection (TextEditor * te)
1937 gint from, to;
1938 from = scintilla_send_message (SCINTILLA (te->scintilla),
1939 SCI_GETSELECTIONSTART, 0, 0);
1940 to = scintilla_send_message (SCINTILLA (te->scintilla),
1941 SCI_GETSELECTIONEND, 0, 0);
1942 return (from == to) ? FALSE : TRUE;
1945 glong text_editor_get_selection_start (TextEditor * te)
1947 return scintilla_send_message (SCINTILLA (te->scintilla),
1948 SCI_GETSELECTIONSTART, 0, 0);
1951 glong text_editor_get_selection_end (TextEditor * te)
1953 return scintilla_send_message (SCINTILLA (te->scintilla),
1954 SCI_GETSELECTIONEND, 0, 0);
1957 gchar*
1958 text_editor_get_selection (TextEditor * te)
1960 guint from, to;
1961 struct TextRange tr;
1963 from = scintilla_send_message (SCINTILLA (te->scintilla),
1964 SCI_GETSELECTIONSTART, 0, 0);
1965 to = scintilla_send_message (SCINTILLA (te->scintilla),
1966 SCI_GETSELECTIONEND, 0, 0);
1967 if (from == to)
1968 return NULL;
1969 tr.chrg.cpMin = MIN(from, to);
1970 tr.chrg.cpMax = MAX(from, to);
1971 tr.lpstrText = g_malloc (sizeof(gchar)*(tr.chrg.cpMax-tr.chrg.cpMin)+5);
1972 scintilla_send_message (SCINTILLA(te->scintilla), SCI_GETTEXTRANGE, 0, (long)(&tr));
1973 return tr.lpstrText;
1976 gboolean
1977 text_editor_is_marker_set (TextEditor* te, glong line, gint marker)
1979 gint state;
1981 g_return_val_if_fail (te != NULL, FALSE);
1982 g_return_val_if_fail (line >= 0, FALSE);
1983 g_return_val_if_fail (marker < 32, FALSE);
1985 state = scintilla_send_message (SCINTILLA(te->scintilla),
1986 SCI_MARKERGET, linenum_text_editor_to_scintilla (line), 0);
1987 return ((state & (1 << marker)));
1990 void
1991 text_editor_delete_marker_all (TextEditor *te, gint marker)
1993 g_return_if_fail (IS_TEXT_EDITOR (te));
1994 g_return_if_fail (marker < 32);
1995 scintilla_send_message (SCINTILLA (te->scintilla),
1996 SCI_MARKERDELETEALL, marker, 0);
1999 void
2000 text_editor_delete_marker (TextEditor* te, glong line, gint marker)
2002 g_return_if_fail (IS_TEXT_EDITOR (te));
2003 g_return_if_fail (line >= 0);
2004 g_return_if_fail (marker < 32);
2006 scintilla_send_message (SCINTILLA(te->scintilla),
2007 SCI_MARKERDELETE, linenum_text_editor_to_scintilla (line), marker);
2010 gint
2011 text_editor_line_from_handle (TextEditor* te, gint marker_handle)
2013 gint line;
2015 g_return_val_if_fail (te != NULL, -1);
2017 line = scintilla_send_message (SCINTILLA(te->scintilla),
2018 SCI_MARKERLINEFROMHANDLE, marker_handle, 0);
2020 return linenum_scintilla_to_text_editor (line);
2023 gint
2024 text_editor_get_bookmark_line( TextEditor* te, const glong nLineStart )
2026 return aneditor_command (te->editor_id, ANE_GETBOOKMARK_POS, nLineStart, 0);
2029 gint
2030 text_editor_get_num_bookmarks(TextEditor* te)
2032 gint nLineNo = -1 ;
2033 gint nMarkers = 0 ;
2035 g_return_val_if_fail (te != NULL, 0 );
2037 while( ( nLineNo = text_editor_get_bookmark_line( te, nLineNo ) ) >= 0 )
2039 //printf( "Line %d\n", nLineNo );
2040 nMarkers++;
2042 //printf( "out Line %d\n", nLineNo );
2043 return nMarkers ;
2046 /* Gets the word before just before carat */
2047 gchar*
2048 text_editor_get_word_before_carat (TextEditor *te)
2050 gchar buffer[512];
2051 buffer[0] = '\0';
2052 aneditor_command (TEXT_EDITOR (te)->editor_id,
2053 ANE_GETWORDBEFORECARAT, (glong) buffer, 512);
2054 if (buffer[0] != '\0')
2055 return g_strdup (buffer);
2056 else
2057 return NULL;
2061 *Get the current selection. If there is no selection, or if the selection
2062 * is all blanks, get the word under teh cursor.
2064 gchar*
2065 text_editor_get_current_word (TextEditor *te)
2067 char *buf = text_editor_get_selection(te);
2068 if (buf)
2070 g_strstrip(buf);
2071 if ('\0' == *buf)
2073 g_free(buf);
2074 buf = NULL;
2077 if (NULL == buf)
2079 int ret;
2080 buf = g_new(char, 256);
2081 ret = aneditor_command (te->editor_id, ANE_GETCURRENTWORD, (long)buf, 255L);
2082 if (!ret)
2084 g_free(buf);
2085 buf = NULL;
2089 #ifdef DEBUG
2090 if (buf)
2091 DEBUG_PRINT ("Current word is '%s'", buf);
2092 #endif
2094 return buf;
2097 void
2098 text_editor_function_select(TextEditor *te)
2100 gint pos;
2101 gint line;
2102 gint fold_level;
2103 gint start, end;
2104 gint line_count;
2105 gint tmp;
2107 line_count = scintilla_send_message(SCINTILLA(te->scintilla),
2108 SCI_GETLINECOUNT, 0, 0);
2109 pos = scintilla_send_message(SCINTILLA(te->scintilla),
2110 SCI_GETCURRENTPOS, 0, 0);
2111 line = scintilla_send_message(SCINTILLA(te->scintilla),
2112 SCI_LINEFROMPOSITION, pos, 0);
2114 tmp = line + 1;
2115 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2116 SCI_GETFOLDLEVEL, line, 0) ;
2117 if ((fold_level & 0xFF) != 0)
2119 while((fold_level & 0x10FF) != 0x1000 && line >= 0)
2120 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2121 SCI_GETFOLDLEVEL, --line, 0) ;
2122 start = scintilla_send_message(SCINTILLA(te->scintilla),
2123 SCI_POSITIONFROMLINE, line + 1, 0);
2124 line = tmp;
2125 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2126 SCI_GETFOLDLEVEL, line, 0) ;
2127 while((fold_level & 0x10FF) != 0x1000 && line < line_count)
2128 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2129 SCI_GETFOLDLEVEL, ++line, 0) ;
2131 end = scintilla_send_message(SCINTILLA(te->scintilla),
2132 SCI_POSITIONFROMLINE, line , 0);
2133 scintilla_send_message(SCINTILLA(te->scintilla),
2134 SCI_SETSEL, start, end) ;
2138 void
2139 text_editor_grab_focus (TextEditor *te)
2141 g_return_if_fail (IS_TEXT_EDITOR (te));
2142 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GRABFOCUS, 0, 0);
2145 void
2146 text_editor_set_popup_menu (TextEditor *te, GtkWidget *popup_menu)
2148 if (popup_menu)
2149 g_object_ref (popup_menu);
2150 if (te->popup_menu)
2151 g_object_unref (te->popup_menu);
2152 te->popup_menu = popup_menu;
2155 void
2156 text_editor_set_busy (TextEditor *te, gboolean state)
2158 if (state)
2159 scintilla_send_message (SCINTILLA (te->scintilla),
2160 SCI_SETCURSOR, SC_CURSORWAIT, 0);
2161 else
2162 scintilla_send_message (SCINTILLA (te->scintilla),
2163 SCI_SETCURSOR, SC_CURSORNORMAL, 0);
2166 gint
2167 text_editor_get_props ()
2169 /* Built in values */
2170 static PropsID props_built_in = 0;
2172 /* System values */
2173 static PropsID props_global = 0;
2175 /* User values */
2176 // static PropsID props_local = 0;
2178 /* Session values */
2179 static PropsID props_session = 0;
2181 /* Instance values */
2182 static PropsID props = 0;
2184 gchar *propdir, *propfile;
2186 if (props)
2187 return props;
2189 props_built_in = sci_prop_set_new ();
2190 props_global = sci_prop_set_new ();
2191 // props_local = sci_prop_set_new ();
2192 props_session = sci_prop_set_new ();
2193 props = sci_prop_set_new ();
2195 sci_prop_clear (props_built_in);
2196 sci_prop_clear (props_global);
2197 // sci_prop_clear (props_local);
2198 sci_prop_clear (props_session);
2199 sci_prop_clear (props);
2201 sci_prop_set_parent (props_global, props_built_in);
2202 // sci_prop_set_parent (props_local, props_global);
2203 // sci_prop_set_parent (props_session, props_local);
2204 sci_prop_set_parent (props_session, props_global);
2205 sci_prop_set_parent (props, props_session);
2207 propdir = g_build_filename (PACKAGE_DATA_DIR, "properties/", NULL);
2208 propfile = g_build_filename (PACKAGE_DATA_DIR, "properties",
2209 "anjuta.properties", NULL);
2210 /* DEBUG_PRINT ("Reading file: %s", propfile); */
2212 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE)
2214 anjuta_util_dialog_error (NULL,
2215 _("Cannot load Global defaults and configuration files:\n"
2216 "%s.\n"
2217 "This may result in improper behaviour or instabilities.\n"
2218 "Anjuta will fall back to built in (limited) settings"),
2219 propfile);
2221 sci_prop_read (props_global, propfile, propdir);
2222 g_free (propfile);
2223 g_free (propdir);
2225 propdir = anjuta_util_get_user_config_file_path ("scintilla/",NULL);
2226 propfile = anjuta_util_get_user_config_file_path ("scintilla","editor-style.properties",NULL);
2227 /* DEBUG_PRINT ("Reading file: %s", propfile); */
2229 /* Create user.properties file, if it doesn't exist */
2230 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE) {
2231 gchar* old_propfile = anjuta_util_get_user_config_file_path ("scintilla", "session.properties", NULL);
2232 if (g_file_test (old_propfile, G_FILE_TEST_EXISTS) == TRUE)
2233 anjuta_util_copy_file (old_propfile, propfile, FALSE);
2234 g_free (old_propfile);
2236 sci_prop_read (props_session, propfile, propdir);
2237 g_free (propdir);
2238 g_free (propfile);
2240 return props;
2243 void
2244 text_editor_set_line_number_width (TextEditor* te)
2246 /* Set line numbers with according to file size */
2247 if (g_settings_get_boolean (te->settings,
2248 VIEW_LINENUMBERS_MARGIN))
2250 int lines, line_number_width;
2251 gchar* line_number;
2252 gchar* line_number_dummy;
2254 lines =
2255 (int) scintilla_send_message
2256 (SCINTILLA(te->scintilla), SCI_GETLINECOUNT, 0,0);
2257 line_number = g_strdup_printf("%d", lines);
2258 line_number_dummy = g_strnfill(strlen(line_number) + 1, '9');
2259 line_number_width =
2260 (int) scintilla_send_message (SCINTILLA(te->scintilla),
2261 SCI_TEXTWIDTH,
2262 STYLE_LINENUMBER,
2263 (long) line_number_dummy);
2264 text_editor_command (te, ANE_SETLINENUMWIDTH, line_number_width, 0);
2265 g_free(line_number_dummy);
2266 g_free(line_number);
2270 gboolean
2271 text_editor_can_undo (TextEditor *te)
2273 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2274 return scintilla_send_message (SCINTILLA (te->scintilla),
2275 SCI_CANUNDO, 0, 0);
2278 gboolean
2279 text_editor_can_redo (TextEditor *te)
2281 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2282 return scintilla_send_message (SCINTILLA (te->scintilla),
2283 SCI_CANREDO, 0, 0);
2286 void
2287 text_editor_show_hover_tip (TextEditor *te, gint position, const gchar *info)
2289 text_editor_hide_hover_tip (te);
2290 if (!te->hover_tip_on)
2292 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPSHOW,
2293 position, (long)info);
2294 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPSETHLT,
2295 strlen (info), 0);
2296 te->hover_tip_on = TRUE;
2300 void
2301 text_editor_hide_hover_tip (TextEditor *te)
2303 if (te->hover_tip_on)
2305 scintilla_send_message (SCINTILLA (te->scintilla),
2306 SCI_CALLTIPCANCEL, 0, 0);
2307 te->hover_tip_on = FALSE;
2311 void
2312 text_editor_cancel_completion (TextEditor *te)
2314 te->completion_count = 0;
2315 g_string_truncate (te->completion_string, 0);
2318 void
2319 text_editor_suggest_completion (TextEditor *te)
2321 GList *node;
2322 TextEditorCell *iter;
2323 gint position;
2325 position = text_editor_get_current_position (te);
2326 iter = text_editor_cell_new (te, position);
2327 for (node = te->provider; node != NULL; node = g_list_next (node))
2329 ianjuta_provider_populate (IANJUTA_PROVIDER (node->data), IANJUTA_ITERABLE (iter), NULL);
2331 g_object_unref (iter);
2334 void
2335 text_editor_select_completion (TextEditor *te)
2337 TextEditorCell *iter;
2338 gint position;
2339 gint autoc_sel;
2341 autoc_sel = (gint) scintilla_send_message (SCINTILLA (te->scintilla),
2342 SCI_AUTOCGETCURRENT,
2343 0, 0);
2344 scintilla_send_message (SCINTILLA (te->scintilla),
2345 SCI_AUTOCCANCEL, 0, 0);
2347 g_return_if_fail (autoc_sel < te->completion_count);
2349 position = text_editor_get_current_position (te);
2350 iter = text_editor_cell_new (te, position);
2352 ianjuta_provider_activate (IANJUTA_PROVIDER (te->completion[autoc_sel].provider),
2353 IANJUTA_ITERABLE (iter),
2354 te->completion[autoc_sel].data, NULL);
2355 g_object_unref (iter);
2358 void
2359 text_editor_command (TextEditor *te, gint command, glong wparam, glong lparam)
2361 GList *node;
2363 node = te->views;
2364 while (node)
2366 aneditor_command (GPOINTER_TO_INT (node->data), command, wparam, lparam);
2367 node = g_list_next(node);
2371 void
2372 text_editor_scintilla_command (TextEditor *te, gint command, glong wparam,
2373 glong lparam)
2375 GList *node;
2377 node = te->views;
2378 while (node)
2380 GtkWidget *scintilla;
2381 scintilla = aneditor_get_widget (GPOINTER_TO_INT (node->data));
2382 scintilla_send_message (SCINTILLA(scintilla), command, wparam, lparam);
2383 node = g_list_next(node);
2387 /* IAnjutaEditor interface implementation */
2389 static gint
2390 itext_editor_get_tab_size (IAnjutaEditor *editor, GError **e)
2392 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2393 SCI_GETTABWIDTH, 0, 0);
2396 static void
2397 itext_editor_set_tab_size (IAnjutaEditor *editor, gint tabsize, GError **e)
2399 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2400 SCI_SETTABWIDTH, tabsize, 0);
2403 static gboolean
2404 itext_editor_get_use_spaces (IAnjutaEditor *editor, GError **e)
2406 return !scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2407 SCI_GETUSETABS, 0, 0);
2410 static void
2411 itext_editor_set_use_spaces (IAnjutaEditor *editor, gboolean use_spaces, GError **e)
2413 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2414 SCI_SETUSETABS, !use_spaces, 0);
2417 /* This function does not set automatic indentation but allow or not
2418 * the editor to indent the text. Used to disable editor indentation when
2419 * another plugin take care of it. */
2420 static void
2421 itext_editor_set_auto_indent (IAnjutaEditor *editor, gboolean auto_indent, GError **e)
2423 text_editor_command (TEXT_EDITOR(editor), ANE_SETAUTOINDENTATION, auto_indent, 0);
2426 static void
2427 itext_editor_goto_line (IAnjutaEditor *editor, gint lineno, GError **e)
2429 text_editor_goto_line (TEXT_EDITOR (editor), lineno, FALSE, TRUE);
2430 gtk_widget_grab_focus (TEXT_EDITOR (editor)->scintilla);
2433 static void
2434 itext_editor_goto_start (IAnjutaEditor *editor, GError **e)
2436 text_editor_goto_point (TEXT_EDITOR (editor), 0);
2439 static void
2440 itext_editor_goto_end (IAnjutaEditor *editor, GError **e)
2442 text_editor_goto_point (TEXT_EDITOR (editor), -1);
2445 static void
2446 itext_editor_goto_position (IAnjutaEditor *editor, IAnjutaIterable *position,
2447 GError **e)
2449 text_editor_goto_point (TEXT_EDITOR (editor),
2450 text_editor_cell_get_position (TEXT_EDITOR_CELL
2451 (position)));
2454 static gchar*
2455 itext_editor_get_text_all (IAnjutaEditor *editor, GError **e)
2457 TextEditor *te = TEXT_EDITOR (editor);
2458 gint length = scintilla_send_message (SCINTILLA (te->scintilla),
2459 SCI_GETLENGTH, 0, 0);
2460 if (length > 0)
2461 return (gchar *) aneditor_command (te->editor_id, ANE_GETTEXTRANGE,
2462 0, length);
2463 else
2464 return NULL;
2467 static gchar*
2468 itext_editor_get_text (IAnjutaEditor *editor, IAnjutaIterable* begin,
2469 IAnjutaIterable* end, GError **e)
2471 gchar *data;
2472 gint start_pos = text_editor_cell_get_position (TEXT_EDITOR_CELL (begin));
2473 gint end_pos = text_editor_cell_get_position (TEXT_EDITOR_CELL (end));
2474 TextEditor *te = TEXT_EDITOR (editor);
2475 data = (gchar *) aneditor_command (te->editor_id, ANE_GETTEXTRANGE,
2476 start_pos, end_pos);
2477 return data;
2480 static IAnjutaIterable*
2481 itext_editor_get_position (IAnjutaEditor* editor, GError **e)
2483 TextEditor *te = TEXT_EDITOR (editor);
2484 gint position = text_editor_get_current_position (te);
2485 TextEditorCell *position_iter = text_editor_cell_new (te, position);
2486 return IANJUTA_ITERABLE (position_iter);
2489 static gint
2490 itext_editor_get_offset (IAnjutaEditor *editor, GError **e)
2492 gint pos;
2493 IAnjutaIterable *iter = itext_editor_get_position (editor, NULL);
2494 pos = ianjuta_iterable_get_position (iter, NULL);
2495 g_object_unref (iter);
2496 return pos;
2499 static gint
2500 itext_editor_get_lineno (IAnjutaEditor *editor, GError **e)
2502 return text_editor_get_current_lineno (TEXT_EDITOR (editor));
2505 static gint
2506 itext_editor_get_length (IAnjutaEditor *editor, GError **e)
2508 return aneditor_command (TEXT_EDITOR (editor)->editor_id,
2509 ANE_GETLENGTH, 0, 0);
2512 static gchar*
2513 itext_editor_get_current_word (IAnjutaEditor *editor, GError **e)
2515 gchar buffer[512];
2516 buffer[0] = '\0';
2517 aneditor_command (TEXT_EDITOR (editor)->editor_id,
2518 ANE_GETCURRENTWORD, (glong) buffer, 512);
2519 if (buffer[0] != '\0')
2520 return g_strdup (buffer);
2521 else
2522 return NULL;
2525 static void
2526 itext_editor_insert (IAnjutaEditor *editor, IAnjutaIterable *position,
2527 const gchar *txt, gint length, GError **e)
2529 gchar *text_to_insert;
2530 int pos;
2532 pos = text_editor_cell_get_position (TEXT_EDITOR_CELL (position));
2533 if (length < 0) length = strlen (txt);
2535 text_to_insert = g_strndup (txt, length);
2537 aneditor_command (TEXT_EDITOR(editor)->editor_id, ANE_INSERTTEXT,
2538 pos, (long)text_to_insert);
2540 g_free (text_to_insert);
2543 static void
2544 itext_editor_append (IAnjutaEditor *editor, const gchar *txt,
2545 gint length, GError **e)
2547 gchar *text_to_insert;
2548 if (length >= 0)
2549 text_to_insert = g_strndup (txt, length);
2550 else
2551 text_to_insert = g_strdup (txt);
2553 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2554 SCI_APPENDTEXT, strlen(text_to_insert),
2555 (long)text_to_insert);
2556 g_free (text_to_insert);
2559 static void
2560 itext_editor_erase (IAnjutaEditor *editor,
2561 IAnjutaIterable *position_start,
2562 IAnjutaIterable *position_end, GError **e)
2564 gint start, end;
2566 /* If both positions are NULL, erase all */
2567 if (position_start == NULL && position_end == NULL)
2569 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2570 SCI_CLEARALL,
2571 0, 0);
2572 return;
2575 /* Determine correct start and end byte positions */
2576 if (position_start)
2577 start = text_editor_cell_get_position (TEXT_EDITOR_CELL (position_start));
2578 else
2579 start = 0;
2581 if (position_end)
2582 end = text_editor_cell_get_position (TEXT_EDITOR_CELL (position_end));
2583 else
2584 end = scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2585 SCI_GETLENGTH, 0, 0);
2586 if (start != end)
2588 scintilla_send_message (SCINTILLA(TEXT_EDITOR (editor)->scintilla),
2589 SCI_SETSEL, start, end);
2590 text_editor_replace_selection (TEXT_EDITOR (editor), "");
2594 static void
2595 itext_editor_erase_all (IAnjutaEditor *editor, GError **e)
2597 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2598 SCI_CLEARALL,
2599 0, 0);
2602 static int
2603 itext_editor_get_column (IAnjutaEditor *editor, GError **e)
2605 return text_editor_get_current_column (TEXT_EDITOR(editor));
2608 static gboolean
2609 itext_editor_get_overwrite (IAnjutaEditor *editor, GError **e)
2611 return text_editor_get_overwrite (TEXT_EDITOR (editor));
2614 static void
2615 itext_editor_set_popup_menu (IAnjutaEditor *editor, GtkWidget* menu, GError **e)
2617 text_editor_set_popup_menu (TEXT_EDITOR (editor), menu);
2620 static gint
2621 itext_editor_get_line_from_position (IAnjutaEditor *editor,
2622 IAnjutaIterable *position, GError **e)
2624 return text_editor_get_line_from_position (TEXT_EDITOR (editor),
2625 text_editor_cell_get_position (TEXT_EDITOR_CELL (position)));
2628 static IAnjutaIterable*
2629 itext_editor_get_line_begin_position (IAnjutaEditor *editor, gint line,
2630 GError **e)
2632 gint ln, byte_pos;
2633 TextEditor *te;
2635 g_return_val_if_fail (line > 0, NULL);
2636 te = TEXT_EDITOR (editor);
2637 ln = linenum_text_editor_to_scintilla (line);
2638 byte_pos = scintilla_send_message (SCINTILLA (te->scintilla),
2639 SCI_POSITIONFROMLINE, ln, 0);
2640 return IANJUTA_ITERABLE (text_editor_cell_new (te, byte_pos));
2643 static IAnjutaIterable*
2644 itext_editor_get_line_end_position (IAnjutaEditor *editor, gint line,
2645 GError **e)
2647 gint ln, byte_pos;
2648 TextEditor *te;
2650 g_return_val_if_fail (line > 0, NULL);
2651 te = TEXT_EDITOR (editor);
2653 ln = linenum_text_editor_to_scintilla (line);
2654 byte_pos = scintilla_send_message (SCINTILLA (te->scintilla),
2655 SCI_GETLINEENDPOSITION, ln, 0);
2656 return IANJUTA_ITERABLE (text_editor_cell_new (te, byte_pos));
2659 static IAnjutaIterable*
2660 itext_editor_get_position_from_offset (IAnjutaEditor *editor, gint offset, GError **e)
2662 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor), 0);
2663 /* Set to the right utf8 character offset */
2664 ianjuta_iterable_set_position (IANJUTA_ITERABLE (editor_cell), offset, NULL);
2665 return IANJUTA_ITERABLE (editor_cell);
2668 static IAnjutaIterable*
2669 itext_editor_get_start_position (IAnjutaEditor *editor, GError **e)
2671 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor), 0);
2672 return IANJUTA_ITERABLE (editor_cell);
2675 static IAnjutaIterable*
2676 itext_editor_get_end_position (IAnjutaEditor *editor, GError **e)
2678 gint length = scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2679 SCI_GETLENGTH, 0, 0);
2680 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor),
2681 length);
2682 return IANJUTA_ITERABLE (editor_cell);
2685 static void
2686 itext_editor_iface_init (IAnjutaEditorIface *iface)
2688 iface->get_tabsize = itext_editor_get_tab_size;
2689 iface->set_tabsize = itext_editor_set_tab_size;
2690 iface->get_use_spaces = itext_editor_get_use_spaces;
2691 iface->set_use_spaces = itext_editor_set_use_spaces;
2692 iface->set_auto_indent = itext_editor_set_auto_indent;
2693 iface->goto_line = itext_editor_goto_line;
2694 iface->goto_start = itext_editor_goto_start;
2695 iface->goto_end = itext_editor_goto_end;
2696 iface->goto_position = itext_editor_goto_position;
2697 iface->get_text_all = itext_editor_get_text_all;
2698 iface->get_text = itext_editor_get_text;
2699 iface->get_offset = itext_editor_get_offset;
2700 iface->get_position = itext_editor_get_position;
2701 iface->get_lineno = itext_editor_get_lineno;
2702 iface->get_length = itext_editor_get_length;
2703 iface->get_current_word = itext_editor_get_current_word;
2704 iface->insert = itext_editor_insert;
2705 iface->append = itext_editor_append;
2706 iface->erase = itext_editor_erase;
2707 iface->erase_all = itext_editor_erase_all;
2708 iface->get_column = itext_editor_get_column;
2709 iface->get_overwrite = itext_editor_get_overwrite;
2710 iface->set_popup_menu = itext_editor_set_popup_menu;
2711 iface->get_line_from_position = itext_editor_get_line_from_position;
2712 iface->get_line_begin_position = itext_editor_get_line_begin_position;
2713 iface->get_line_end_position = itext_editor_get_line_end_position;
2714 iface->get_position_from_offset = itext_editor_get_position_from_offset;
2715 iface->get_start_position = itext_editor_get_start_position;
2716 iface->get_end_position = itext_editor_get_end_position;
2719 static const gchar *
2720 idocument_get_filename (IAnjutaDocument *editor, GError **e)
2722 return (TEXT_EDITOR (editor))->filename;
2725 static gboolean
2726 idocument_can_undo(IAnjutaDocument* editor, GError **e)
2728 return text_editor_can_undo(TEXT_EDITOR(editor));
2731 static gboolean
2732 idocument_can_redo(IAnjutaDocument *editor, GError **e)
2734 return text_editor_can_redo(TEXT_EDITOR(editor));
2737 static void
2738 idocument_undo(IAnjutaDocument* te, GError** ee)
2740 text_editor_command(TEXT_EDITOR(te), ANE_UNDO, 0, 0);
2743 static void
2744 idocument_begin_undo_action (IAnjutaDocument* te, GError** ee)
2746 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2747 SCI_BEGINUNDOACTION, 0, 0);
2750 static void
2751 idocument_end_undo_action (IAnjutaDocument* te, GError** ee)
2753 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2754 SCI_ENDUNDOACTION, 0, 0);
2757 static void
2758 idocument_redo(IAnjutaDocument* te, GError** ee)
2760 text_editor_command(TEXT_EDITOR(te), ANE_REDO, 0, 0);
2763 static void
2764 idocument_grab_focus (IAnjutaDocument *editor, GError **e)
2766 text_editor_grab_focus (TEXT_EDITOR (editor));
2769 static void
2770 idocument_cut(IAnjutaDocument * te, GError** ee)
2772 text_editor_command(TEXT_EDITOR(te), ANE_CUT, 0, 0);
2775 static void
2776 idocument_copy(IAnjutaDocument * te, GError** ee)
2778 text_editor_command(TEXT_EDITOR(te), ANE_COPY, 0, 0);
2781 static void
2782 idocument_paste(IAnjutaDocument * te, GError** ee)
2784 text_editor_command(TEXT_EDITOR(te), ANE_PASTE, 0, 0);
2787 static void
2788 idocument_clear(IAnjutaDocument * te, GError** ee)
2790 text_editor_command(TEXT_EDITOR(te), ANE_CLEAR, 0, 0);
2793 static void
2794 idocument_iface_init(IAnjutaDocumentIface* iface)
2796 iface->get_filename = idocument_get_filename;
2797 iface->can_undo = idocument_can_undo;
2798 iface->can_redo = idocument_can_redo;
2799 iface->undo = idocument_undo;
2800 iface->redo = idocument_redo;
2801 iface->begin_undo_action = idocument_begin_undo_action;
2802 iface->end_undo_action = idocument_end_undo_action;
2803 iface->grab_focus = idocument_grab_focus;
2804 iface->cut = idocument_cut;
2805 iface->copy = idocument_copy;
2806 iface->paste = idocument_paste;
2807 iface->clear = idocument_clear;
2810 /* IAnjutaEditorSelection implementation */
2812 static gchar*
2813 iselection_get (IAnjutaEditorSelection *editor, GError **error)
2815 return text_editor_get_selection (TEXT_EDITOR (editor));
2818 static void
2819 iselection_set (IAnjutaEditorSelection* edit,
2820 IAnjutaIterable* istart,
2821 IAnjutaIterable* iend,
2822 gboolean scroll, /* TODO: Is is possible to set this in scintilla? */
2823 GError** e)
2825 TextEditorCell* start = TEXT_EDITOR_CELL (istart);
2826 TextEditorCell* end = TEXT_EDITOR_CELL (iend);
2827 int start_pos = text_editor_cell_get_position (start);
2828 int end_pos = text_editor_cell_get_position (end);
2830 scintilla_send_message (SCINTILLA (TEXT_EDITOR (edit)->scintilla),
2831 SCI_SETSEL, start_pos, end_pos);
2834 static gboolean
2835 iselection_has_selection (IAnjutaEditorSelection *editor, GError **e)
2837 return text_editor_has_selection (TEXT_EDITOR (editor));
2840 static IAnjutaIterable*
2841 iselection_get_start (IAnjutaEditorSelection *edit, GError **e)
2843 gint start = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2844 SCI_GETSELECTIONSTART, 0, 0);
2845 gint end = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2846 SCI_GETSELECTIONEND, 0, 0);
2847 if (start != end)
2849 return IANJUTA_ITERABLE (text_editor_cell_new (TEXT_EDITOR (edit), start));
2851 else
2852 return NULL;
2855 static IAnjutaIterable*
2856 iselection_get_end (IAnjutaEditorSelection *edit, GError **e)
2858 gint start = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2859 SCI_GETSELECTIONSTART, 0, 0);
2860 gint end = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2861 SCI_GETSELECTIONEND, 0, 0);
2862 if (start != end)
2864 return IANJUTA_ITERABLE (text_editor_cell_new (TEXT_EDITOR (edit), end));
2866 else
2867 return NULL;
2870 static void
2871 iselection_replace (IAnjutaEditorSelection *editor, const gchar *txt,
2872 gint length, GError **e)
2874 gchar *text_to_insert;
2875 if (length >= 0)
2876 text_to_insert = g_strndup (txt, length);
2877 else
2878 text_to_insert = g_strdup (txt);
2880 text_editor_replace_selection (TEXT_EDITOR (editor), text_to_insert);
2882 g_free (text_to_insert);
2885 static void
2886 iselection_select_all (IAnjutaEditorSelection* te, GError** ee)
2888 text_editor_command (TEXT_EDITOR (te), ANE_SELECTALL, 0, 0);
2891 static void
2892 iselection_select_block (IAnjutaEditorSelection *te, GError **e)
2894 text_editor_command (TEXT_EDITOR(te), ANE_SELECTBLOCK, 0, 0);
2897 static void
2898 iselection_select_function (IAnjutaEditorSelection *editor, GError **e)
2900 TextEditor* te = TEXT_EDITOR(editor);
2901 gint pos;
2902 gint line;
2903 gint fold_level;
2904 gint start, end;
2905 gint line_count;
2906 gint tmp;
2908 line_count = scintilla_send_message (SCINTILLA (te->scintilla),
2909 SCI_GETLINECOUNT, 0, 0);
2910 pos = scintilla_send_message (SCINTILLA (te->scintilla),
2911 SCI_GETCURRENTPOS, 0, 0);
2912 line = scintilla_send_message (SCINTILLA (te->scintilla),
2913 SCI_LINEFROMPOSITION, pos, 0);
2915 tmp = line + 1;
2916 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2917 SCI_GETFOLDLEVEL, line, 0) ;
2918 if ((fold_level & 0xFF) != 0)
2920 while ((fold_level & 0x10FF) != 0x1000 && line >= 0)
2921 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2922 SCI_GETFOLDLEVEL, --line, 0) ;
2923 start = scintilla_send_message (SCINTILLA (te->scintilla),
2924 SCI_POSITIONFROMLINE, line + 1, 0);
2925 line = tmp;
2926 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2927 SCI_GETFOLDLEVEL, line, 0) ;
2928 while ((fold_level & 0x10FF) != 0x1000 && line < line_count)
2929 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2930 SCI_GETFOLDLEVEL, ++line, 0) ;
2932 end = scintilla_send_message (SCINTILLA (te->scintilla),
2933 SCI_POSITIONFROMLINE, line , 0);
2934 scintilla_send_message (SCINTILLA (te->scintilla),
2935 SCI_SETSEL, start, end) ;
2939 static void
2940 iselection_iface_init (IAnjutaEditorSelectionIface *iface)
2942 iface->has_selection = iselection_has_selection;
2943 iface->get = iselection_get;
2944 iface->set = iselection_set;
2945 iface->get_start = iselection_get_start;
2946 iface->get_end = iselection_get_end;
2947 iface->replace = iselection_replace;
2948 iface->select_all = iselection_select_all;
2949 iface->select_block = iselection_select_block;
2950 iface->select_function = iselection_select_function;
2953 /* IAnjutaFile implementation */
2955 static GFile*
2956 ifile_get_file (IAnjutaFile *editor, GError **error)
2958 TextEditor *text_editor;
2959 text_editor = TEXT_EDITOR(editor);
2960 if (text_editor->uri)
2961 return g_file_new_for_uri (text_editor->uri);
2962 else
2963 return NULL;
2966 static void
2967 ifile_open (IAnjutaFile *editor, GFile* file, GError **error)
2969 /* Close current file and open new file in this editor */
2970 TextEditor* text_editor;
2971 text_editor = TEXT_EDITOR(editor);
2973 /* Remove path */
2974 g_free (text_editor->uri);
2975 text_editor->uri = g_file_get_uri (file);
2976 g_free (text_editor->filename);
2977 text_editor->filename = g_file_get_basename (file);
2978 text_editor_load_file (text_editor);
2981 static void
2982 isaveable_save (IAnjutaFileSavable* editor, GError** e)
2984 TextEditor *text_editor = TEXT_EDITOR(editor);
2986 if (text_editor->uri != NULL)
2987 text_editor_save_file(text_editor, FALSE);
2988 else
2989 g_signal_emit_by_name (G_OBJECT (text_editor), "saved", NULL);
2992 static void
2993 isavable_save_as (IAnjutaFileSavable* editor, GFile* file, GError** e)
2995 const gchar *past_language;
2996 const gchar *curr_language;
2997 TextEditor *text_editor = TEXT_EDITOR(editor);
2999 past_language =
3000 ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (text_editor),
3001 NULL);
3003 /* Remove path */
3004 g_free (text_editor->uri);
3005 text_editor->uri = g_file_get_uri (file);
3006 g_free (text_editor->filename);
3007 text_editor->filename = g_file_get_basename (file);
3008 text_editor_save_file (text_editor, FALSE);
3009 text_editor_set_hilite_type (text_editor, NULL);
3010 text_editor_hilite (text_editor, FALSE);
3012 /* We have to take care of 'language-change' signal ourself because
3013 * text_editor_set_hilite_type() only emits it for forced hilite type
3015 curr_language =
3016 ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (text_editor),
3017 NULL);
3018 if (past_language != curr_language)
3019 g_signal_emit_by_name (text_editor, "language-changed", curr_language);
3023 static gboolean
3024 isavable_is_dirty (IAnjutaFileSavable* editor, GError** e)
3026 TextEditor *text_editor = TEXT_EDITOR(editor);
3027 return !text_editor_is_saved (text_editor);
3030 static void
3031 isavable_set_dirty (IAnjutaFileSavable* editor, gboolean dirty, GError** e)
3033 TextEditor *text_editor = TEXT_EDITOR(editor);
3034 text_editor_set_saved (text_editor, !dirty);
3037 static gboolean
3038 isavable_is_read_only (IAnjutaFileSavable* savable, GError** e)
3040 /* FIXME */
3041 return FALSE;
3044 static gboolean
3045 isavable_is_conflict (IAnjutaFileSavable* savable, GError** e)
3047 TextEditor *te = TEXT_EDITOR(savable);
3048 return te->message_area != NULL;
3051 static void
3052 isavable_iface_init (IAnjutaFileSavableIface *iface)
3054 iface->save = isaveable_save;
3055 iface->save_as = isavable_save_as;
3056 iface->set_dirty = isavable_set_dirty;
3057 iface->is_dirty = isavable_is_dirty;
3058 iface->is_read_only = isavable_is_read_only;
3059 iface->is_conflict = isavable_is_conflict;
3062 static void
3063 ifile_iface_init (IAnjutaFileIface *iface)
3065 iface->open = ifile_open;
3066 iface->get_file = ifile_get_file;
3069 /* Implementation of the IAnjutaMarkable interface */
3071 static gint
3072 marker_ianjuta_to_editor (IAnjutaMarkableMarker marker)
3074 gint mark;
3075 switch (marker)
3077 case IANJUTA_MARKABLE_LINEMARKER:
3078 mark = TEXT_EDITOR_LINEMARKER;
3079 break;
3080 case IANJUTA_MARKABLE_BOOKMARK:
3081 mark = TEXT_EDITOR_BOOKMARK;
3082 break;
3083 case IANJUTA_MARKABLE_BREAKPOINT_DISABLED:
3084 mark = TEXT_EDITOR_BREAKPOINT_DISABLED;
3085 break;
3086 case IANJUTA_MARKABLE_BREAKPOINT_ENABLED:
3087 mark = TEXT_EDITOR_BREAKPOINT_ENABLED;
3088 break;
3089 case IANJUTA_MARKABLE_PROGRAM_COUNTER:
3090 mark = TEXT_EDITOR_PROGRAM_COUNTER;
3091 break;
3092 default:
3093 mark = TEXT_EDITOR_LINEMARKER;
3095 return mark;
3098 static gint
3099 imarkable_mark (IAnjutaMarkable* editor, gint location,
3100 IAnjutaMarkableMarker marker, const gchar *tooltip, GError** e)
3102 return text_editor_set_marker (TEXT_EDITOR (editor), location,
3103 marker_ianjuta_to_editor (marker));
3106 static gint
3107 imarkable_location_from_handle (IAnjutaMarkable* editor, gint handle, GError** e)
3109 return text_editor_line_from_handle (TEXT_EDITOR (editor), handle);
3112 static void
3113 imarkable_unmark (IAnjutaMarkable* editor, gint location,
3114 IAnjutaMarkableMarker marker, GError** e)
3116 text_editor_delete_marker (TEXT_EDITOR (editor), location,
3117 marker_ianjuta_to_editor (marker));
3120 static gboolean
3121 imarkable_is_marker_set (IAnjutaMarkable* editor, gint location,
3122 IAnjutaMarkableMarker marker, GError** e)
3124 return text_editor_is_marker_set (TEXT_EDITOR (editor), location,
3125 marker_ianjuta_to_editor (marker));
3128 static void
3129 imarkable_delete_all_markers (IAnjutaMarkable* editor,
3130 IAnjutaMarkableMarker marker, GError** e)
3132 text_editor_delete_marker_all (TEXT_EDITOR (editor),
3133 marker_ianjuta_to_editor (marker));
3136 static void
3137 imarkable_iface_init (IAnjutaMarkableIface *iface)
3139 iface->mark = imarkable_mark;
3140 iface->location_from_handle = imarkable_location_from_handle;
3141 iface->unmark = imarkable_unmark;
3142 iface->is_marker_set = imarkable_is_marker_set;
3143 iface->delete_all_markers = imarkable_delete_all_markers;
3146 /* IAnjutaEditorConvert implementation */
3148 static void
3149 iconvert_to_upper (IAnjutaEditorConvert* te, IAnjutaIterable *start_position,
3150 IAnjutaIterable *end_position, GError** ee)
3152 gint start, end;
3153 start = text_editor_cell_get_position (TEXT_EDITOR_CELL (start_position));
3154 end = text_editor_cell_get_position (TEXT_EDITOR_CELL (end_position));
3155 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
3156 SCI_SETSEL, start, end);
3157 text_editor_command (TEXT_EDITOR(te), ANE_UPRCASE, 0, 0);
3160 static void
3161 iconvert_to_lower(IAnjutaEditorConvert* te, IAnjutaIterable *start_position,
3162 IAnjutaIterable *end_position, GError** ee)
3164 gint start, end;
3165 start = text_editor_cell_get_position (TEXT_EDITOR_CELL (start_position));
3166 end = text_editor_cell_get_position (TEXT_EDITOR_CELL (end_position));
3167 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
3168 SCI_SETSEL, start, end);
3169 text_editor_command (TEXT_EDITOR (te), ANE_LWRCASE, 0, 0);
3172 static void
3173 iconvert_iface_init (IAnjutaEditorConvertIface *iface)
3175 iface->to_lower = iconvert_to_lower;
3176 iface->to_upper = iconvert_to_upper;
3179 /* IAnjutaEditorLineMode implementation */
3181 static IAnjutaEditorLineModeType
3182 ilinemode_get (IAnjutaEditorLineMode* te, GError** err)
3184 glong eolmode;
3185 IAnjutaEditorLineModeType retmode;
3187 g_return_val_if_fail (IS_TEXT_EDITOR (te), IANJUTA_EDITOR_LINE_MODE_LF);
3189 eolmode = scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
3190 SCI_GETEOLMODE, 0, 0);
3192 switch (eolmode) {
3193 case SC_EOL_CR:
3194 retmode = IANJUTA_EDITOR_LINE_MODE_CR;
3195 break;
3196 case SC_EOL_CRLF:
3197 retmode = IANJUTA_EDITOR_LINE_MODE_CRLF;
3198 break;
3199 case SC_EOL_LF:
3200 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
3201 break;
3202 default:
3203 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
3204 g_warning ("Should not be here");
3206 return retmode;
3209 static void
3210 ilinemode_set (IAnjutaEditorLineMode* te, IAnjutaEditorLineModeType mode,
3211 GError** err)
3213 g_return_if_fail (IS_TEXT_EDITOR (te));
3215 switch (mode)
3217 case IANJUTA_EDITOR_LINE_MODE_LF:
3218 text_editor_command(TEXT_EDITOR(te), ANE_EOL_LF, 0, 0);
3219 break;
3221 case IANJUTA_EDITOR_LINE_MODE_CR:
3222 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CR, 0, 0);
3223 break;
3225 case IANJUTA_EDITOR_LINE_MODE_CRLF:
3226 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CRLF, 0, 0);
3227 break;
3229 default:
3230 g_warning ("Should not reach here");
3231 break;
3235 static void
3236 ilinemode_convert (IAnjutaEditorLineMode *te, IAnjutaEditorLineModeType mode,
3237 GError **err)
3239 switch (mode)
3241 case IANJUTA_EDITOR_LINE_MODE_LF:
3242 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
3243 ANE_EOL_LF, 0);
3244 break;
3246 case IANJUTA_EDITOR_LINE_MODE_CR:
3247 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
3248 ANE_EOL_CR, 0);
3249 break;
3251 case IANJUTA_EDITOR_LINE_MODE_CRLF:
3252 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
3253 ANE_EOL_CRLF, 0);
3254 break;
3256 default:
3257 g_warning ("Should not reach here");
3258 break;
3262 static void
3263 ilinemode_fix (IAnjutaEditorLineMode* te, GError** err)
3265 IAnjutaEditorLineModeType mode = ilinemode_get (te, NULL);
3266 ilinemode_convert (te, mode, NULL);
3269 static void
3270 ilinemode_iface_init (IAnjutaEditorLineModeIface *iface)
3272 iface->set = ilinemode_set;
3273 iface->get = ilinemode_get;
3274 iface->convert = ilinemode_convert;
3275 iface->fix = ilinemode_fix;
3278 static void
3279 itip_show (IAnjutaEditorTip *itip, GList* tips,
3280 IAnjutaIterable *position, GError **err)
3282 GString *calltip;
3283 GList *tip;
3284 gint tips_count;
3285 TextEditor *te = TEXT_EDITOR (itip);
3286 TextEditorCell *cell = TEXT_EDITOR_CELL (position);
3287 gint calltip_pos;
3289 g_return_if_fail (IS_TEXT_EDITOR (te));
3290 g_return_if_fail (tips != NULL);
3291 tips_count = g_list_length (tips);
3292 g_return_if_fail (tips_count > 0);
3294 DEBUG_PRINT ("Number of calltips found %d\n", tips_count);
3296 calltip = g_string_sized_new (256);
3297 tip = tips;
3298 while (tip)
3300 if (calltip->len > 0)
3301 g_string_append_c (calltip, '\n');
3302 g_string_append (calltip, (gchar*) tip->data);
3303 tip = g_list_next (tip);
3306 /* It is not possible to display the calltip above, as the position is defined
3307 * in characters. We cannot be sure that there is enough characters in
3308 * the line above */
3309 calltip_pos = text_editor_cell_get_position (cell);
3311 scintilla_send_message (SCINTILLA (te->scintilla),
3312 SCI_CALLTIPSHOW,
3313 calltip_pos,
3314 (uptr_t) calltip->str);
3315 g_string_free (calltip, TRUE);
3318 static void
3319 itip_cancel (IAnjutaEditorTip *itip, GError **err)
3321 TextEditor *te = TEXT_EDITOR (itip);
3322 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPCANCEL, 0, 0);
3325 static gboolean
3326 itip_visible (IAnjutaEditorTip* itip, GError **err)
3328 TextEditor *te = TEXT_EDITOR (itip);
3329 return scintilla_send_message (SCINTILLA (te->scintilla),
3330 SCI_CALLTIPACTIVE, 0, 0);
3333 static void
3334 itip_iface_init (IAnjutaEditorTipIface *iface)
3336 iface->show = itip_show;
3337 iface->cancel = itip_cancel;
3338 iface->visible = itip_visible;
3341 /* IAnjutaEditorAssist implementation */
3342 static void
3343 iassist_add(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider, GError** err)
3345 TextEditor *te = TEXT_EDITOR (iassist);
3346 te->provider = g_list_prepend (te->provider, provider);
3349 static void
3350 iassist_remove(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider, GError** err)
3352 TextEditor *te = TEXT_EDITOR (iassist);
3353 te->provider = g_list_remove (te->provider, provider);
3356 static void
3357 iassist_invoke(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider, GError** err)
3359 TextEditor *te = TEXT_EDITOR (iassist);
3361 text_editor_suggest_completion (te);
3364 static void
3365 iassist_proposals(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider,
3366 GList* proposals, gboolean finished, GError** err)
3368 TextEditor *te = TEXT_EDITOR (iassist);
3369 GList *node;
3370 glong length;
3372 if (proposals == NULL)
3374 te->completion_count = 0;
3375 g_string_truncate (te->completion_string, 0);
3377 scintilla_send_message (SCINTILLA (te->scintilla), SCI_AUTOCCANCEL,
3378 0, 0);
3379 return;
3382 if (te->completion_finished)
3384 te->completion_count = 0;
3385 g_string_truncate (te->completion_string, 0);
3387 te->completion_finished = finished;
3389 for (node = proposals; node != NULL; node = g_list_next (node))
3391 IAnjutaEditorAssistProposal* prop = node->data;
3393 /* Give up if there is too much completion */
3394 if (te->completion_count >= SCINTILLA_MAX_COMPLETION) return;
3395 if (prop->label)
3397 if (te->completion_string->len > 0)
3398 g_string_append_c (te->completion_string, ' ');
3399 g_string_append(te->completion_string, prop->label);
3400 te->completion[te->completion_count].provider = provider;
3401 te->completion[te->completion_count].data = prop->data;
3402 te->completion_count++;
3406 scintilla_send_message (SCINTILLA (te->scintilla),
3407 SCI_AUTOCSETAUTOHIDE, 1, 0);
3408 scintilla_send_message (SCINTILLA (te->scintilla),
3409 SCI_AUTOCSETDROPRESTOFWORD, 1, 0);
3410 scintilla_send_message (SCINTILLA (te->scintilla),
3411 SCI_AUTOCSETCANCELATSTART, 0, 0);
3412 scintilla_send_message (SCINTILLA (te->scintilla),
3413 SCI_AUTOCSETCHOOSESINGLE, 0, 0);
3415 length = text_editor_get_current_position (te);
3416 length -= text_editor_cell_get_position (TEXT_EDITOR_CELL (ianjuta_provider_get_start_iter (provider, NULL)));
3418 scintilla_send_message (SCINTILLA (te->scintilla),
3419 SCI_AUTOCSHOW, length,
3420 (uptr_t) te->completion_string->str);
3423 static void
3424 iassist_iface_init(IAnjutaEditorAssistIface* iface)
3426 iface->add = iassist_add;
3427 iface->remove = iassist_remove;
3428 iface->invoke = iassist_invoke;
3429 iface->proposals = iassist_proposals;
3432 /* IAnutaEditorFolds implementation */
3434 static void
3435 ifolds_open_all(IAnjutaEditorFolds* view, GError **e)
3437 text_editor_command(TEXT_EDITOR(view), ANE_OPEN_FOLDALL, 0, 0);
3440 static void
3441 ifolds_close_all(IAnjutaEditorFolds* view, GError **e)
3443 text_editor_command(TEXT_EDITOR(view), ANE_CLOSE_FOLDALL, 0, 0);
3446 static void
3447 ifolds_toggle_current(IAnjutaEditorFolds* view, GError **e)
3449 text_editor_command(TEXT_EDITOR(view), ANE_TOGGLE_FOLD, 0, 0);
3452 static void
3453 ifolds_iface_init(IAnjutaEditorFoldsIface* iface)
3455 iface->open_all = ifolds_open_all;
3456 iface->close_all = ifolds_close_all;
3457 iface->toggle_current = ifolds_toggle_current;
3460 /* IAnjutaEditorView implementation */
3461 static void
3462 iview_create (IAnjutaEditorView *view, GError **err)
3464 g_return_if_fail (IS_TEXT_EDITOR (view));
3465 text_editor_add_view (TEXT_EDITOR (view));
3468 static void
3469 iview_remove_current (IAnjutaEditorView *view, GError **err)
3471 g_return_if_fail (IS_TEXT_EDITOR (view));
3472 text_editor_remove_view (TEXT_EDITOR (view));
3475 static gint
3476 iview_get_count (IAnjutaEditorView *view, GError **err)
3478 g_return_val_if_fail (IS_TEXT_EDITOR (view), -1);
3479 return g_list_length (TEXT_EDITOR (view)->views);
3482 static void
3483 iview_iface_init (IAnjutaEditorViewIface *iface)
3485 iface->create = iview_create;
3486 iface->remove_current = iview_remove_current;
3487 iface->get_count = iview_get_count;
3490 static void
3491 iindicable_set (IAnjutaIndicable *te, IAnjutaIterable *begin_location,
3492 IAnjutaIterable *end_location,
3493 IAnjutaIndicableIndicator indicator, GError **err)
3495 gint begin = text_editor_cell_get_position (TEXT_EDITOR_CELL (begin_location));
3496 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (end_location));
3497 switch (indicator)
3499 case IANJUTA_INDICABLE_NONE:
3500 text_editor_clear_indicator (TEXT_EDITOR (te), begin, end);
3501 break;
3502 case IANJUTA_INDICABLE_IMPORTANT:
3503 text_editor_set_indicator (TEXT_EDITOR (te), begin, end, 0);
3504 break;
3505 case IANJUTA_INDICABLE_WARNING:
3506 text_editor_set_indicator (TEXT_EDITOR (te), begin, end, 1);
3507 break;
3508 case IANJUTA_INDICABLE_CRITICAL:
3509 text_editor_set_indicator (TEXT_EDITOR (te), begin, end, 2);
3510 break;
3511 default:
3512 g_warning ("Unsupported indicator %d", indicator);
3513 text_editor_clear_indicator (TEXT_EDITOR (te), begin, end);
3514 break;
3518 static void
3519 iindicable_clear (IAnjutaIndicable *te, GError **err)
3521 text_editor_clear_all_indicator (TEXT_EDITOR (te));
3524 static void
3525 iindicable_iface_init (IAnjutaIndicableIface *iface)
3527 iface->set = iindicable_set;
3528 iface->clear = iindicable_clear;
3531 static void
3532 iprint_print(IAnjutaPrint* print, GError** e)
3534 TextEditor* te = TEXT_EDITOR(print);
3535 anjuta_print(FALSE, te->settings, te);
3538 static void
3539 iprint_preview(IAnjutaPrint* print, GError** e)
3541 TextEditor* te = TEXT_EDITOR(print);
3542 anjuta_print(TRUE, te->settings, te);
3545 static void
3546 iprint_iface_init(IAnjutaPrintIface* iface)
3548 iface->print = iprint_print;
3549 iface->print_preview = iprint_preview;
3552 static void
3553 icomment_block(IAnjutaEditorComment* comment, GError** e)
3555 TextEditor* te = TEXT_EDITOR(comment);
3556 aneditor_command (te->editor_id, ANE_BLOCKCOMMENT, 0, 0);
3559 static void
3560 icomment_stream(IAnjutaEditorComment* comment, GError** e)
3562 TextEditor* te = TEXT_EDITOR(comment);
3563 aneditor_command (te->editor_id, ANE_STREAMCOMMENT, 0, 0);
3566 static void
3567 icomment_box(IAnjutaEditorComment* comment, GError** e)
3569 TextEditor* te = TEXT_EDITOR(comment);
3570 aneditor_command (te->editor_id, ANE_BOXCOMMENT, 0, 0);
3573 static void
3574 icomment_iface_init(IAnjutaEditorCommentIface* iface)
3576 iface->block = icomment_block;
3577 iface->box = icomment_box;
3578 iface->stream = icomment_stream;
3581 #define MAX_ZOOM_FACTOR 8
3582 #define MIN_ZOOM_FACTOR -8
3584 static void
3585 izoom_in(IAnjutaEditorZoom* zoom, GError** e)
3587 TextEditor* te = TEXT_EDITOR(zoom);
3588 gint zoom_factor = g_settings_get_int (te->docman_settings,
3589 TEXT_ZOOM_FACTOR) + 1;
3591 if (zoom_factor > MAX_ZOOM_FACTOR)
3592 zoom_factor = MAX_ZOOM_FACTOR;
3593 else if (zoom_factor < MIN_ZOOM_FACTOR)
3594 zoom_factor = MIN_ZOOM_FACTOR;
3596 g_settings_set_int (te->docman_settings, TEXT_ZOOM_FACTOR, zoom_factor);
3599 static void
3600 izoom_out(IAnjutaEditorZoom* zoom, GError** e)
3602 TextEditor* te = TEXT_EDITOR(zoom);
3603 gint zoom_factor = g_settings_get_int (te->docman_settings,
3604 TEXT_ZOOM_FACTOR) - 1;
3606 if (zoom_factor > MAX_ZOOM_FACTOR)
3607 zoom_factor = MAX_ZOOM_FACTOR;
3608 else if (zoom_factor < MIN_ZOOM_FACTOR)
3609 zoom_factor = MIN_ZOOM_FACTOR;
3611 g_settings_set_int (te->docman_settings, TEXT_ZOOM_FACTOR, zoom_factor);
3614 static void
3615 izoom_iface_init(IAnjutaEditorZoomIface* iface)
3617 iface->in = izoom_in;
3618 iface->out = izoom_out;
3621 static void
3622 igoto_start_block(IAnjutaEditorGoto* editor, GError** e)
3624 TextEditor* te = TEXT_EDITOR(editor);
3625 text_editor_goto_block_start(te);
3628 static void
3629 igoto_end_block(IAnjutaEditorGoto* editor, GError** e)
3631 TextEditor* te = TEXT_EDITOR(editor);
3632 text_editor_goto_block_end(te);
3635 static void
3636 igoto_matching_brace(IAnjutaEditorGoto* editor, GError** e)
3638 TextEditor* te = TEXT_EDITOR(editor);
3639 text_editor_command (te, ANE_MATCHBRACE, 0, 0);
3642 static void
3643 igoto_iface_init(IAnjutaEditorGotoIface* iface)
3645 iface->start_block = igoto_start_block;
3646 iface->end_block = igoto_end_block;
3647 iface->matching_brace = igoto_matching_brace;
3650 static const GList*
3651 ilanguage_get_supported_languages (IAnjutaEditorLanguage *ilanguage,
3652 GError **err)
3654 if (supported_languages == NULL)
3656 gchar **strv;
3657 gchar **token;
3658 gchar *menu_entries;
3660 supported_languages_name =
3661 g_hash_table_new_full (g_str_hash, g_str_equal,
3662 NULL, g_free);
3663 supported_languages_ext =
3664 g_hash_table_new_full (g_str_hash, g_str_equal,
3665 NULL, g_free);
3667 supported_languages_by_lexer =
3668 g_hash_table_new_full (g_str_hash, g_str_equal,
3669 g_free, NULL);
3671 menu_entries = sci_prop_get (text_editor_get_props (), "menu.language");
3672 g_return_val_if_fail (menu_entries != NULL, NULL);
3674 strv = g_strsplit (menu_entries, "|", -1);
3675 token = strv;
3676 while (*token)
3678 gchar *lexer;
3679 gchar *possible_file;
3680 gchar *iter;
3681 gchar *name, *extension;
3682 GString *lang;
3684 lang = g_string_new ("");
3686 name = *token++;
3687 if (!name)
3688 break;
3690 extension = *token++;
3691 if (!extension)
3692 break;
3693 token++;
3695 if (name[0] == '#')
3696 continue;
3698 iter = name;
3699 while (*iter)
3701 if (*iter == '&')
3703 *iter = '_';
3705 else
3707 g_string_append_c (lang, g_ascii_tolower (*iter));
3709 iter++;
3712 /* HACK: Convert the weird c++ name to cpp */
3713 if (strcmp (lang->str, "c / c++") == 0)
3715 g_string_assign (lang, "cpp");
3718 /* Updated mapping hash tables */
3719 g_hash_table_insert (supported_languages_name, lang->str,
3720 g_strdup (name));
3721 g_hash_table_insert (supported_languages_ext, lang->str,
3722 g_strconcat ("file.", extension, NULL));
3723 /* Map lexer to language */
3724 possible_file = g_strconcat ("file.", extension, NULL);
3725 lexer = sci_prop_get_new_expand (TEXT_EDITOR (ilanguage)->props_base,
3726 "lexer.", possible_file);
3727 g_free (possible_file);
3728 if (lexer)
3730 /* We only map the first (which is hopefully the true) language */
3731 if (!g_hash_table_lookup (supported_languages_by_lexer, lexer))
3733 /* DEBUG_PRINT ("Mapping (lexer)%s to (language)%s", lexer, lang->str); */
3734 g_hash_table_insert (supported_languages_by_lexer,
3735 lexer, lang->str);
3736 /* lexer is taken in the hash, so no free */
3738 else
3740 g_free (lexer);
3742 lexer = NULL;
3744 supported_languages = g_list_prepend (supported_languages,
3745 lang->str);
3746 g_string_free (lang, FALSE);
3748 g_strfreev (strv);
3750 return supported_languages;
3753 static const gchar*
3754 ilanguage_get_language_name (IAnjutaEditorLanguage *ilanguage,
3755 const gchar *language, GError **err)
3757 if (!supported_languages_name)
3758 ilanguage_get_supported_languages (ilanguage, NULL);
3760 return g_hash_table_lookup (supported_languages_name, language);
3763 static void
3764 ilanguage_set_language (IAnjutaEditorLanguage *ilanguage,
3765 const gchar *language, GError **err)
3767 if (!supported_languages_ext)
3768 ilanguage_get_supported_languages (ilanguage, NULL);
3770 if (language)
3771 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage),
3772 g_hash_table_lookup (supported_languages_ext,
3773 language));
3774 else /* Autodetect */
3775 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage), NULL);
3777 text_editor_hilite (TEXT_EDITOR (ilanguage), FALSE);
3780 static const gchar*
3781 ilanguage_get_language (IAnjutaEditorLanguage *ilanguage, GError **err)
3783 const gchar *language = NULL;
3784 const gchar *filename = NULL;
3785 TextEditor *te = TEXT_EDITOR (ilanguage);
3787 if (te->force_hilite)
3788 filename = te->force_hilite;
3789 else if (te->filename)
3790 filename = te->filename;
3792 if (filename)
3794 gchar *lexer = NULL;
3795 lexer = sci_prop_get_new_expand (te->props_base,
3796 "lexer.", filename);
3798 /* No lexer, no language */
3799 if (lexer)
3801 if (!supported_languages_by_lexer)
3802 ilanguage_get_supported_languages (ilanguage, NULL);
3804 language = g_hash_table_lookup (supported_languages_by_lexer, lexer);
3805 /* DEBUG_PRINT ("Found (language)%s for (lexer)%s", language, lexer); */
3806 g_free (lexer);
3809 return language;
3812 static void
3813 ilanguage_iface_init (IAnjutaEditorLanguageIface *iface)
3815 iface->get_supported_languages = ilanguage_get_supported_languages;
3816 iface->get_language_name = ilanguage_get_language_name;
3817 iface->get_language = ilanguage_get_language;
3818 iface->set_language = ilanguage_set_language;
3821 static gboolean
3822 isearch_forward (IAnjutaEditorSearch* isearch,
3823 const gchar* search,
3824 gboolean case_sensitive,
3825 IAnjutaEditorCell* istart,
3826 IAnjutaEditorCell* iend,
3827 IAnjutaEditorCell** iresult_start,
3828 IAnjutaEditorCell** iresult_end,
3829 GError** e)
3831 TextEditor *te = TEXT_EDITOR (isearch);
3832 gint start = text_editor_cell_get_position (TEXT_EDITOR_CELL (istart));
3833 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (iend));
3835 gint flags = 0;
3836 gint retval;
3838 if (case_sensitive)
3840 flags = SCFIND_MATCHCASE;
3843 struct TextToFind to_find;
3845 to_find.chrg.cpMin = start;
3846 to_find.chrg.cpMax = end;
3848 to_find.lpstrText = (gchar*) search;
3850 retval = scintilla_send_message (SCINTILLA (te->scintilla),
3851 SCI_FINDTEXT, flags, (long) &to_find);
3852 if (retval == -1)
3853 return FALSE;
3854 else
3856 *iresult_start = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMin));
3857 *iresult_end = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMax));
3858 return TRUE;
3862 static gboolean
3863 isearch_backward (IAnjutaEditorSearch* isearch,
3864 const gchar* search,
3865 gboolean case_sensitive,
3866 IAnjutaEditorCell* istart,
3867 IAnjutaEditorCell* iend,
3868 IAnjutaEditorCell** iresult_start,
3869 IAnjutaEditorCell** iresult_end,
3870 GError** e)
3872 TextEditor *te = TEXT_EDITOR (isearch);
3873 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (istart));
3874 gint start = text_editor_cell_get_position (TEXT_EDITOR_CELL (iend));
3876 gint flags = 0;
3877 gint retval;
3879 if (case_sensitive)
3881 flags = SCFIND_MATCHCASE;
3884 struct TextToFind to_find;
3886 to_find.chrg.cpMin = start;
3887 to_find.chrg.cpMax = end;
3889 to_find.lpstrText = (gchar*) search;
3891 retval = scintilla_send_message (SCINTILLA (te->scintilla), SCI_FINDTEXT, flags, (long) &to_find);
3892 if (retval == -1)
3893 return FALSE;
3894 else
3896 *iresult_start = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMin));
3897 *iresult_end = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMax));
3898 return TRUE;
3902 static void
3903 isearch_iface_init(IAnjutaEditorSearchIface* iface)
3905 iface->forward = isearch_forward;
3906 iface->backward = isearch_backward;
3909 static void
3910 ihover_display (IAnjutaEditorHover *ihover, IAnjutaIterable *pos,
3911 const gchar *info, GError **e)
3913 TextEditor *te = TEXT_EDITOR (ihover);
3914 gint position = text_editor_cell_get_position (TEXT_EDITOR_CELL (pos));
3915 g_return_if_fail (position >= 0);
3916 g_return_if_fail (info != NULL);
3917 text_editor_show_hover_tip (te, position, info);
3920 static void
3921 ihover_iface_init(IAnjutaEditorHoverIface* iface)
3923 iface->display = ihover_display;
3926 ANJUTA_TYPE_BEGIN(TextEditor, text_editor, GTK_TYPE_VBOX);
3927 ANJUTA_TYPE_ADD_INTERFACE(ifile, IANJUTA_TYPE_FILE);
3928 ANJUTA_TYPE_ADD_INTERFACE(isavable, IANJUTA_TYPE_FILE_SAVABLE);
3929 ANJUTA_TYPE_ADD_INTERFACE(idocument, IANJUTA_TYPE_DOCUMENT);
3930 ANJUTA_TYPE_ADD_INTERFACE(itext_editor, IANJUTA_TYPE_EDITOR);
3931 ANJUTA_TYPE_ADD_INTERFACE(ilinemode, IANJUTA_TYPE_EDITOR_LINE_MODE);
3932 ANJUTA_TYPE_ADD_INTERFACE(iselection, IANJUTA_TYPE_EDITOR_SELECTION);
3933 ANJUTA_TYPE_ADD_INTERFACE(iconvert, IANJUTA_TYPE_EDITOR_CONVERT);
3934 ANJUTA_TYPE_ADD_INTERFACE(iassist, IANJUTA_TYPE_EDITOR_ASSIST);
3935 ANJUTA_TYPE_ADD_INTERFACE(itip, IANJUTA_TYPE_EDITOR_TIP);
3936 ANJUTA_TYPE_ADD_INTERFACE(ilanguage, IANJUTA_TYPE_EDITOR_LANGUAGE);
3937 ANJUTA_TYPE_ADD_INTERFACE(iview, IANJUTA_TYPE_EDITOR_VIEW);
3938 ANJUTA_TYPE_ADD_INTERFACE(ifolds, IANJUTA_TYPE_EDITOR_FOLDS);
3939 ANJUTA_TYPE_ADD_INTERFACE(imarkable, IANJUTA_TYPE_MARKABLE);
3940 ANJUTA_TYPE_ADD_INTERFACE(iindicable, IANJUTA_TYPE_INDICABLE);
3941 ANJUTA_TYPE_ADD_INTERFACE(iprint, IANJUTA_TYPE_PRINT);
3942 ANJUTA_TYPE_ADD_INTERFACE(icomment, IANJUTA_TYPE_EDITOR_COMMENT);
3943 ANJUTA_TYPE_ADD_INTERFACE(izoom, IANJUTA_TYPE_EDITOR_ZOOM);
3944 ANJUTA_TYPE_ADD_INTERFACE(igoto, IANJUTA_TYPE_EDITOR_GOTO);
3945 ANJUTA_TYPE_ADD_INTERFACE(isearch, IANJUTA_TYPE_EDITOR_SEARCH);
3946 ANJUTA_TYPE_ADD_INTERFACE(ihover, IANJUTA_TYPE_EDITOR_HOVER);
3947 ANJUTA_TYPE_END;