Replace deprecated types
[anjuta-extras.git] / plugins / scintilla / text_editor.c
blob9dcfd537f9c8f8bff4212159cb51961750b1827b
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 GtkBoxClass *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);
153 te->editor_settings = g_settings_new (ANJUTA_PREF_SCHEMA_PREFIX IANJUTA_EDITOR_PREF_SCHEMA);
155 gtk_orientable_set_orientation (GTK_ORIENTABLE (te), GTK_ORIENTATION_VERTICAL);
158 static GtkWidget *
159 anjuta_message_area_new (const gchar *text,
160 GtkMessageType type)
162 GtkInfoBar *message_area;
163 GtkWidget *content_area;
164 GtkWidget *message_label = gtk_label_new ("");
166 message_area = GTK_INFO_BAR (gtk_info_bar_new ());
167 gtk_info_bar_set_message_type (message_area, type);
168 content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (message_area));
169 gtk_widget_show (message_label);
170 gtk_container_add (GTK_CONTAINER (content_area), message_label);
172 gchar *markup = g_strdup_printf ("<b>%s</b>", text);
173 gtk_label_set_markup (GTK_LABEL (message_label), markup);
174 g_free (markup);
176 return GTK_WIDGET (message_area);
179 static void
180 text_editor_class_init (TextEditorClass *klass)
182 GObjectClass *object_class = G_OBJECT_CLASS (klass);
184 parent_class = g_type_class_peek_parent (klass);
185 object_class->finalize = text_editor_finalize;
186 object_class->dispose = text_editor_dispose;
189 #if 0
190 static void
191 check_tm_file(TextEditor *te)
193 if (NULL == te->tm_file)
195 // FIXME:
196 // te->tm_file = tm_workspace_find_object(
197 //TM_WORK_OBJECT(app->tm_workspace), te->uri, FALSE);
198 if (NULL == te->tm_file)
200 te->tm_file = tm_source_file_new(te->uri, TRUE);
201 if (NULL != te->tm_file)
202 tm_workspace_add_object(te->tm_file);
206 #endif
208 static void
209 initialize_markers (TextEditor* te, GtkWidget *scintilla)
211 gint marker;
212 gchar ***xpm;
213 g_return_if_fail (te != NULL);
215 marker = 0;
216 for (xpm = marker_pixmap;*xpm != NULL; xpm++)
218 scintilla_send_message (SCINTILLA (scintilla), SCI_MARKERDEFINEPIXMAP,
219 marker, (sptr_t)*xpm);
220 marker++;
224 /* Hack to simulate async loading */
225 static gboolean
226 emit_opened (TextEditor* te)
228 g_signal_emit_by_name (te, "opened");
229 return FALSE;
233 #ifdef DEBUG
234 static void
235 on_scintila_already_destroyed (gpointer te, GObject *obj)
237 /* DEBUG_PRINT ("%s", "Scintilla object has been destroyed"); */
240 static void
241 on_te_already_destroyed (gpointer te, GObject *obj)
243 /* DEBUG_PRINT ("%s", "TextEditor object has been destroyed"); */
245 #endif
247 /* Indicators are setup in both TextEditor and AnEditor object.
248 * AnEditor reads the property file while TexEditor uses the
249 * GSettings object. TextEditor can overwrite properties
250 * set by AnEditor.
252 static void
253 text_editor_setup_indicators_color (TextEditor *te)
255 char* spec;
256 GdkColor color;
258 /* Important color */
259 spec = g_settings_get_string (te->msgman_settings, MSGMAN_COLOR_IMPORTANT);
260 if (gdk_color_parse (spec, &color))
262 glong param = ((color.red >> 8) & 0xFF) + (color.green & 0xFF00) + ((color.blue << 8) & 0x00FF0000);
263 scintilla_send_message (SCINTILLA (te->scintilla), SCI_INDICSETFORE, 0, param);
265 g_free (spec);
266 /* Warning color */
267 spec = g_settings_get_string (te->msgman_settings, MSGMAN_COLOR_WARNING);
268 if (gdk_color_parse (spec, &color))
270 glong param = ((color.red >> 8) & 0xFF) + (color.green & 0xFF00) + ((color.blue << 8) & 0x00FF0000);
271 scintilla_send_message (SCINTILLA (te->scintilla), SCI_INDICSETFORE, 1, param);
273 g_free (spec);
274 /* Error color */
275 spec = g_settings_get_string (te->msgman_settings, MSGMAN_COLOR_ERROR);
276 if (gdk_color_parse (spec, &color))
278 glong param = ((color.red >> 8) & 0xFF) + (color.green & 0xFF00) + ((color.blue << 8) & 0x00FF0000);
279 scintilla_send_message (SCINTILLA (te->scintilla), SCI_INDICSETFORE, 2, param);
281 g_free (spec);
284 static void
285 text_editor_setup_indentation_settings (TextEditor *te)
287 AnEditorID editor_id;
288 GtkWidget *scintilla;
289 gboolean value;
291 editor_id = aneditor_new (sci_prop_get_pointer (te->props_base));
292 scintilla = aneditor_get_widget (editor_id);
294 value = g_settings_get_boolean (te->settings, TAB_INDENTS);
295 scintilla_send_message (SCINTILLA (scintilla), SCI_SETTABINDENTS, value ? 1 : 0, 0);
296 value = g_settings_get_boolean (te->settings, BACKSPACE_UNINDENTS);
297 scintilla_send_message (SCINTILLA (scintilla), SCI_SETBACKSPACEUNINDENTS, value ? 1 : 0, 0);
300 void
301 text_editor_add_view (TextEditor *te)
303 AnEditorID editor_id;
304 GtkWidget *scintilla;
305 gint current_line;
306 gint current_point;
308 if (te->views)
310 current_line = text_editor_get_current_lineno (te);
311 current_point = text_editor_get_current_position (te);
313 else
315 current_line = 0;
316 current_point = 0;
318 editor_id = aneditor_new (sci_prop_get_pointer (te->props_base));
319 scintilla = aneditor_get_widget (editor_id);
321 /* Set notifications to receive */
322 scintilla_send_message (SCINTILLA (scintilla), SCI_SETMODEVENTMASK,
323 (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT), 0);
325 /* Set parent, if it is not primary view */
326 if (te->views)
328 aneditor_set_parent (editor_id, GPOINTER_TO_INT(te->editor_id));
330 te->views = g_list_prepend (te->views, GINT_TO_POINTER (editor_id));
331 te->editor_id = editor_id;
332 te->scintilla = scintilla;
335 aneditor_command (te->editor_id, ANE_SETACCELGROUP,
336 (glong) app->accel_group, 0);
339 gtk_widget_set_size_request (scintilla, 50, 50);
340 gtk_widget_show (scintilla);
342 gtk_box_set_spacing (GTK_BOX (te->vbox), 3);
343 gtk_box_pack_start (GTK_BOX (te->vbox), scintilla, TRUE, TRUE, 0);
344 gtk_widget_grab_focus (scintilla);
346 g_signal_connect (G_OBJECT (scintilla), "event",
347 G_CALLBACK (on_text_editor_text_event), te);
348 g_signal_connect (G_OBJECT (scintilla), "button_press_event",
349 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
350 g_signal_connect (G_OBJECT (scintilla), "key_release_event",
351 G_CALLBACK (on_text_editor_text_keyrelease_event), te);
352 g_signal_connect_after (G_OBJECT (scintilla), "size_allocate",
353 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
354 g_signal_connect (G_OBJECT (scintilla), "sci-notify",
355 G_CALLBACK (on_text_editor_scintilla_notify), te);
356 g_signal_connect (G_OBJECT (scintilla), "focus_in_event",
357 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
359 initialize_markers (te, scintilla);
360 text_editor_hilite_one (te, editor_id);
361 text_editor_set_line_number_width (te);
363 if (current_line)
364 text_editor_goto_line (te, current_line, FALSE, TRUE);
365 if (current_point)
366 text_editor_goto_point (te, current_point);
368 #ifdef DEBUG
369 g_object_weak_ref (G_OBJECT (scintilla), on_scintila_already_destroyed, te);
370 #endif
373 /* Remove the current view */
374 void
375 text_editor_remove_view (TextEditor *te)
377 if (!te->editor_id)
378 return;
379 if (te->views == NULL ||
380 g_list_length (te->views) <= 1)
381 return;
383 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
384 G_CALLBACK (on_text_editor_text_event), te);
385 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
386 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
387 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
388 G_CALLBACK (on_text_editor_text_keyrelease_event), te);
389 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
390 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
391 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
392 G_CALLBACK (on_text_editor_scintilla_notify), te);
393 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
394 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
396 te->views = g_list_remove (te->views, GINT_TO_POINTER(te->editor_id));
397 gtk_container_remove (GTK_CONTAINER (te->vbox), te->scintilla);
398 aneditor_destroy(te->editor_id);
400 /* Set current view */
401 if (te->views)
403 te->editor_id = GPOINTER_TO_INT(te->views->data);
404 te->scintilla = aneditor_get_widget (te->editor_id);
405 gtk_widget_grab_focus (te->scintilla);
407 else
409 gtk_box_set_spacing (GTK_BOX (te->vbox), 0);
410 te->editor_id = 0;
411 te->scintilla = NULL;
415 static void
416 on_reload_dialog_response (GtkWidget *message_area, gint res, TextEditor *te)
418 if (res == GTK_RESPONSE_YES)
420 gint visible_line = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETFIRSTVISIBLELINE, 0, 0);
421 text_editor_load_file (te);
422 scintilla_send_message (SCINTILLA (te->scintilla), SCI_SETFIRSTVISIBLELINE, visible_line, 0);
424 else
426 text_editor_set_saved (te, FALSE);
427 gtk_widget_destroy (message_area);
431 static void
432 on_destroy_message_area (gpointer data, GObject *finalized_object)
434 TextEditor *te = (TextEditor *)data;
436 te->message_area = NULL;
437 g_signal_emit_by_name (G_OBJECT (te), "update-save-ui");
440 static void
441 on_close_dialog_response (GtkWidget *message_area, gint res, TextEditor *te)
443 if (res == GTK_RESPONSE_YES)
445 IAnjutaDocumentManager *docman;
447 docman = anjuta_shell_get_interface (te->shell, IAnjutaDocumentManager, NULL);
448 if (docman == NULL) return;
450 ianjuta_document_manager_remove_document (docman, IANJUTA_DOCUMENT (te), FALSE, NULL);
452 else
454 text_editor_set_saved (te, FALSE);
455 gtk_widget_destroy (message_area);
459 static void
460 text_editor_set_message_area (TextEditor *te, GtkWidget *message_area)
462 if (te->message_area != NULL)
463 gtk_widget_destroy (te->message_area);
464 te->message_area = message_area;
466 if (te->message_area == NULL)
467 return;
469 gtk_widget_show (message_area);
470 gtk_box_pack_start (GTK_BOX (te),
471 message_area,
472 FALSE,
473 FALSE,
475 g_object_weak_ref (G_OBJECT (te->message_area),
476 on_destroy_message_area, te);
478 g_signal_emit_by_name (G_OBJECT (te), "update-save-ui");
481 static void
482 on_text_editor_uri_changed (GFileMonitor *monitor,
483 GFile *file,
484 GFile *other_file,
485 GFileMonitorEvent event_type,
486 gpointer user_data)
488 TextEditor *te = TEXT_EDITOR (user_data);
489 GtkWidget *message_area;
490 gchar *buff;
492 /* DEBUG_PRINT ("%s", "File changed!!!"); */
494 switch (event_type)
496 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
498 if (!anjuta_util_diff (te->uri, te->last_saved_content))
500 /* The file content is same. Remove any previous prompt for reload */
501 if (te->message_area)
502 gtk_widget_destroy (te->message_area);
503 te->message_area = NULL;
504 return;
506 /* No break here */
508 case G_FILE_MONITOR_EVENT_CREATED:
509 if (text_editor_is_saved (te))
511 buff = g_strdup_printf (_("The file '%s' has been changed.\n"
512 "Do you want to reload it?"),
513 te->filename);
515 else
517 buff = g_strdup_printf (_("The file '%s' has been changed.\n"
518 "Do you want to lose your changes and reload it?"),
519 te->filename);
521 message_area = anjuta_message_area_new (buff, GTK_MESSAGE_WARNING);
522 g_free (buff);
523 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
524 GTK_STOCK_REFRESH,
525 GTK_RESPONSE_YES);
526 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
527 GTK_STOCK_CANCEL,
528 GTK_RESPONSE_NO);
529 g_signal_connect (G_OBJECT(message_area), "response",
530 G_CALLBACK (on_reload_dialog_response),
531 te);
532 break;
533 case G_FILE_MONITOR_EVENT_DELETED:
534 if (text_editor_is_saved (te))
536 buff = g_strdup_printf (_
537 ("The file '%s' has been deleted.\n"
538 "Do you confirm and close it?"),
539 te->filename);
541 else
543 buff = g_strdup_printf (_
544 ("The file '%s' has been deleted.\n"
545 "Do you want to lose your changes and close it?"),
546 te->filename);
548 message_area = anjuta_message_area_new (buff, GTK_MESSAGE_WARNING);
549 g_free (buff);
550 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
551 GTK_STOCK_DELETE,
552 GTK_RESPONSE_YES);
553 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
554 GTK_STOCK_CANCEL,
555 GTK_RESPONSE_NO);
556 g_signal_connect (G_OBJECT(message_area), "response",
557 G_CALLBACK (on_close_dialog_response),
558 te);
559 break;
560 case G_FILE_MONITOR_EVENT_CHANGED:
561 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
562 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
563 case G_FILE_MONITOR_EVENT_UNMOUNTED:
564 return;
565 default:
566 g_warn_if_reached ();
567 return;
570 text_editor_set_message_area (te, message_area);
573 static void
574 text_editor_update_monitor (TextEditor *te, gboolean disable_it)
576 if (te->monitor)
578 /* Shutdown existing monitor */
579 g_file_monitor_cancel (te->monitor);
580 te->monitor = NULL;
582 if (te->message_area)
584 /* Remove existing message area */
585 gtk_widget_destroy (te->message_area);
586 te->message_area = NULL;
588 if (te->uri && !disable_it)
590 GFile *gio_uri;
591 GError *error = NULL;
592 /* DEBUG_PRINT ("%s", "Setting up Monitor for %s", te->uri); */
594 gio_uri = g_file_new_for_uri (te->uri);
595 te->monitor = g_file_monitor_file (gio_uri,
596 G_FILE_MONITOR_NONE,
597 NULL,
598 &error);
599 g_file_monitor_set_rate_limit (te->monitor, RATE_LIMIT_IN_MS);
600 g_signal_connect (te->monitor, "changed",
601 G_CALLBACK (on_text_editor_uri_changed), te);
602 g_object_unref (gio_uri);
604 if (error != NULL)
606 DEBUG_PRINT ("Error while setting up file monitor: %s",
607 error->message);
608 g_error_free (error);
614 static void
615 on_shell_value_changed (TextEditor *te, const char *name)
617 g_return_if_fail (name != NULL);
619 if ((strcmp (name, TEXT_EDITOR_PROJECT_TYPE_LIST) == 0) ||
620 (strcmp (name, TEXT_EDITOR_SYSTEM_TYPE_LIST) == 0))
622 /* Type names list has changed, so refresh highlight */
623 text_editor_hilite (te, te->force_pref);
627 static void
628 on_style_changed (TextEditor *te)
630 /* Refresh highlight */
631 text_editor_hilite (te, te->force_pref);
634 static void
635 on_indicators_changed (TextEditor *te)
637 /* Refresh indicator */
638 text_editor_setup_indicators_color (te);
641 GtkWidget *
642 text_editor_new (AnjutaPlugin *plugin, const gchar *uri, const gchar *name)
644 AnjutaShell *shell = plugin->shell;
645 AnjutaStatus *status = anjuta_shell_get_status (shell, NULL);
646 TextEditor *te = TEXT_EDITOR (gtk_widget_new (TYPE_TEXT_EDITOR, NULL));
647 gint zoom_factor;
648 static guint new_file_count;
650 te->status = status;
651 te->shell = shell;
653 te->props_base = text_editor_get_props();
654 if (name && strlen(name) > 0)
655 te->filename = g_strdup(name);
656 else
657 te->filename = g_strdup_printf ("Newfile#%d", ++new_file_count);
658 if (uri && strlen(uri) > 0)
660 new_file_count--;
661 g_free (te->filename);
662 g_free (te->uri);
664 GFile *gio_uri;
665 gio_uri = g_file_new_for_uri (uri);
666 te->filename = g_file_get_basename (gio_uri);
667 g_object_unref (gio_uri);
669 te->uri = g_strdup (uri);
672 /* Create primary view */
673 te->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
674 gtk_box_pack_end (GTK_BOX (te), te->vbox, TRUE, TRUE, 0);
675 text_editor_add_view (te);
677 text_editor_prefs_init (te);
679 if (te->uri)
681 if (text_editor_load_file (te) == FALSE)
683 /* Unable to load file */
684 gtk_widget_destroy (GTK_WIDGET (te));
685 return NULL;
688 text_editor_update_controls (te);
690 /* Apply font zoom separately */
691 zoom_factor = g_settings_get_int (te->docman_settings, TEXT_ZOOM_FACTOR);
692 /* DEBUG_PRINT ("%s", "Initializing zoom factor to: %d", zoom_factor); */
693 text_editor_set_zoom_factor (te, zoom_factor);
694 text_editor_setup_indicators_color (te);
695 text_editor_setup_indentation_settings (te);
697 /* Get type name notification */
698 g_signal_connect_swapped (G_OBJECT (shell), "value-added", G_CALLBACK (on_shell_value_changed), te);
699 g_signal_connect_swapped (G_OBJECT (shell), "value-removed", G_CALLBACK (on_shell_value_changed), te);
700 g_signal_connect_swapped (G_OBJECT (plugin), "style-changed", G_CALLBACK(on_style_changed), te);
701 g_signal_connect_swapped (G_OBJECT (te), "style-updated", G_CALLBACK(on_style_changed), te);
703 g_signal_connect_swapped (G_OBJECT(te->msgman_settings), "changed", G_CALLBACK (on_indicators_changed), te);
705 #ifdef DEBUG
706 g_object_weak_ref (G_OBJECT (te), on_te_already_destroyed, te);
707 #endif
708 return GTK_WIDGET (te);
711 void
712 text_editor_dispose (GObject *obj)
714 TextEditor *te = TEXT_EDITOR (obj);
716 /* Disconnect signal */
717 g_signal_handlers_disconnect_by_func (te->shell, G_CALLBACK (on_shell_value_changed), te);
719 if (te->monitor)
721 text_editor_update_monitor (te, TRUE);
722 te->monitor = NULL;
724 if (te->popup_menu)
726 g_object_unref (te->popup_menu);
727 te->popup_menu = NULL;
729 if (te->views)
731 GtkWidget *scintilla;
732 AnEditorID editor_id;
733 GList *node;
735 node = te->views;
736 while (node)
738 editor_id = GPOINTER_TO_INT (node->data);
739 scintilla = aneditor_get_widget (editor_id);
741 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
742 G_CALLBACK (on_text_editor_text_event), te);
743 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
744 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
745 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
746 G_CALLBACK (on_text_editor_text_keyrelease_event), te);
747 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
748 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
749 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
750 G_CALLBACK (on_text_editor_scintilla_notify), te);
751 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
752 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
754 aneditor_destroy (editor_id);
755 node = g_list_next (node);
757 te->scintilla = NULL;
758 te->editor_id = 0;
759 te->views = NULL;
761 if (te->notify_ids)
763 text_editor_prefs_finalize (te);
764 te->notify_ids = NULL;
766 if (te->provider)
768 g_list_free (te->provider);
769 te->provider = NULL;
771 if (te->completion_string)
773 g_string_free (te->completion_string, TRUE);
774 te->completion_string = NULL;
776 te->completion_count = 0;
777 g_object_unref (te->settings);
778 g_object_unref (te->docman_settings);
779 g_object_unref (te->msgman_settings);
780 g_object_unref (te->editor_settings);
781 G_OBJECT_CLASS (parent_class)->dispose (obj);
784 void
785 text_editor_finalize (GObject *obj)
787 TextEditor *te = TEXT_EDITOR (obj);
788 g_free (te->filename);
789 g_free (te->uri);
790 g_free (te->force_hilite);
791 g_free (te->last_saved_content);
793 G_OBJECT_CLASS (parent_class)->finalize (obj);
796 void
797 text_editor_freeze (TextEditor *te)
799 te->freeze_count++;
802 void
803 text_editor_thaw (TextEditor *te)
805 te->freeze_count--;
806 if (te->freeze_count < 0)
807 te->freeze_count = 0;
810 void
811 text_editor_set_hilite_type (TextEditor * te, const gchar *file_extension)
813 const gchar *past_language;
814 const gchar *curr_language;
816 past_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
818 g_free (te->force_hilite);
819 if (file_extension)
820 te->force_hilite = g_strdup (file_extension);
821 else
822 te->force_hilite = NULL;
824 curr_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
825 if (past_language != curr_language)
826 g_signal_emit_by_name (te, "language-changed", curr_language);
829 static void
830 text_editor_hilite_one (TextEditor * te, AnEditorID editor_id)
832 const gchar *name = NULL;
833 gchar *basename = NULL;
835 /* syntax highlighting is disabled if te->force_pref && pref is disabled */
836 if (!te->force_pref ||
837 !g_settings_get_boolean (te->settings,
838 DISABLE_SYNTAX_HILIGHTING))
840 if (te->force_hilite)
842 name = te->force_hilite;
844 else if (te->uri)
846 basename = g_path_get_basename (te->uri);
847 name = basename;
849 else if (te->filename)
851 name = te->filename;
855 if (name == NULL)
857 /* No syntax higlight */
858 aneditor_command (editor_id, ANE_SETHILITE, (glong) "plain.txt", (glong) 0);
860 else
862 const gchar *typedef_hl[2];
863 GValue sys_value = {0,};
864 GValue prj_value = {0,};
866 anjuta_shell_get_value (te->shell, TEXT_EDITOR_SYSTEM_TYPE_LIST, &sys_value, NULL);
867 typedef_hl[0] = G_VALUE_HOLDS_STRING(&sys_value) ? g_value_get_string (&sys_value) : NULL;
869 anjuta_shell_get_value (te->shell, TEXT_EDITOR_PROJECT_TYPE_LIST, &prj_value, NULL);
870 typedef_hl[1] = G_VALUE_HOLDS_STRING(&prj_value) ? g_value_get_string (&prj_value) : NULL;
872 aneditor_command (editor_id, ANE_SETHILITE, (glong) name, (glong) typedef_hl);
873 if (G_IS_VALUE (&sys_value)) g_value_unset (&sys_value);
874 if (G_IS_VALUE (&prj_value)) g_value_unset (&prj_value);
876 g_free (basename);
879 void
880 text_editor_hilite (TextEditor * te, gboolean override_by_pref)
882 GList *node;
884 te->force_pref = override_by_pref;
885 node = te->views;
886 while (node)
888 text_editor_hilite_one (te, GPOINTER_TO_INT (node->data));
889 node = g_list_next (node);
892 text_editor_setup_indicators_color (te);
895 void
896 text_editor_set_zoom_factor (TextEditor * te, gint zfac)
898 text_editor_command (te, ANE_SETZOOM, zfac, 0);
901 TextEditorAttrib
902 text_editor_get_attribute (TextEditor *te, gint position)
904 int lexer;
905 int style;
906 TextEditorAttrib attrib = TEXT_EDITOR_ATTRIB_TEXT;
908 lexer = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETLEXER,
909 0, 0);
910 style = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETSTYLEAT,
911 position, 0);
912 switch (lexer)
914 case SCLEX_CPP:
915 switch (style)
917 case SCE_C_CHARACTER:
918 case SCE_C_STRING:
919 attrib = TEXT_EDITOR_ATTRIB_STRING;
920 break;
921 case SCE_C_COMMENT:
922 case SCE_C_COMMENTLINE:
923 case SCE_C_COMMENTDOC:
924 case SCE_C_COMMENTLINEDOC:
925 case SCE_C_COMMENTDOCKEYWORD:
926 case SCE_C_COMMENTDOCKEYWORDERROR:
927 attrib = TEXT_EDITOR_ATTRIB_COMMENT;
928 break;
929 case SCE_C_WORD:
930 attrib = TEXT_EDITOR_ATTRIB_KEYWORD;
931 break;
933 break;
934 case SCLEX_PYTHON:
935 switch (style)
937 case SCE_P_CHARACTER:
938 case SCE_P_STRING:
939 case SCE_P_TRIPLE:
940 case SCE_P_TRIPLEDOUBLE:
941 attrib = TEXT_EDITOR_ATTRIB_STRING;
942 break;
943 case SCE_P_COMMENTLINE:
944 case SCE_P_COMMENTBLOCK:
945 attrib = TEXT_EDITOR_ATTRIB_COMMENT;
946 break;
947 case SCE_P_WORD:
948 case SCE_P_WORD2:
949 attrib = TEXT_EDITOR_ATTRIB_KEYWORD;
950 break;
952 break;
954 return attrib;
957 glong
958 text_editor_find (TextEditor * te, const gchar * str, gint scope,
959 gboolean forward, gboolean regexp,
960 gboolean ignore_case, gboolean whole_word, gboolean wrap)
962 glong ret;
963 GtkWidget *editor;
964 glong flags;
965 int current_pos, current_anchor;
967 if (!te) return -1;
968 editor = te->scintilla;
970 flags = (ignore_case ? 0 : SCFIND_MATCHCASE)
971 | (regexp ? SCFIND_REGEXP : 0)
972 | (whole_word ? SCFIND_WHOLEWORD : 0)
973 | (forward ? 0 : ANEFIND_REVERSE_FLAG);
975 switch (scope)
977 case TEXT_EDITOR_FIND_SCOPE_WHOLE:
978 if (forward)
980 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
981 0, 0);
982 scintilla_send_message (SCINTILLA (editor),
983 SCI_SETCURRENTPOS, 0, 0);
985 else
987 glong length;
988 length = scintilla_send_message (SCINTILLA (editor),
989 SCI_GETTEXTLENGTH, 0, 0);
990 scintilla_send_message (SCINTILLA (editor),
991 SCI_SETCURRENTPOS, length-1, 0);
992 scintilla_send_message (SCINTILLA (editor),
993 SCI_SETANCHOR, length-1, 0);
995 break;
996 default:
997 break;
999 current_pos = scintilla_send_message (SCINTILLA (editor),
1000 SCI_GETCURRENTPOS, 0, 0);
1001 current_anchor = scintilla_send_message (SCINTILLA (editor),
1002 SCI_GETANCHOR, 0, 0);
1003 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
1004 if (scope == TEXT_EDITOR_FIND_SCOPE_CURRENT && wrap && ret < 0) {
1005 /* If wrap is requested, wrap it. */
1006 if (forward)
1008 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR, 0, 0);
1009 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
1010 0, 0);
1012 else
1014 glong length;
1015 length = scintilla_send_message (SCINTILLA (editor),
1016 SCI_GETTEXTLENGTH, 0, 0);
1017 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
1018 length-1, 0);
1019 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
1020 length-1, 0);
1022 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
1023 /* If the text is still not found, restore current pos and anchor */
1024 if (ret < 0) {
1025 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
1026 current_anchor, 0);
1027 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
1028 current_pos, 0);
1031 return ret;
1034 void
1035 text_editor_replace_selection (TextEditor * te, const gchar* r_str)
1037 if (!te) return;
1038 scintilla_send_message (SCINTILLA(te->scintilla), SCI_REPLACESEL, 0,
1039 (long)r_str);
1042 guint
1043 text_editor_get_total_lines (TextEditor * te)
1045 guint i;
1046 guint count = 0;
1047 if (te == NULL)
1048 return 0;
1049 if (IS_SCINTILLA (te->scintilla) == FALSE)
1050 return 0;
1051 for (i = 0;
1052 i < scintilla_send_message (SCINTILLA (te->scintilla),
1053 SCI_GETLENGTH, 0, 0); i++)
1055 if (scintilla_send_message
1056 (SCINTILLA (te->scintilla), SCI_GETCHARAT, i,
1057 0) == '\n')
1058 count++;
1060 return count;
1063 guint
1064 text_editor_get_current_lineno (TextEditor * te)
1066 guint count;
1068 g_return_val_if_fail (te != NULL, 0);
1070 count = scintilla_send_message (SCINTILLA (te->scintilla),
1071 SCI_GETCURRENTPOS, 0, 0);
1072 count = scintilla_send_message (SCINTILLA (te->scintilla),
1073 SCI_LINEFROMPOSITION, count, 0);
1074 return linenum_scintilla_to_text_editor(count);
1077 guint
1078 text_editor_get_position_lineno (TextEditor * te, gint position)
1080 guint count;
1081 g_return_val_if_fail (te != NULL, 0);
1083 count = scintilla_send_message (SCINTILLA (te->scintilla),
1084 SCI_LINEFROMPOSITION, position, 0);
1085 return linenum_scintilla_to_text_editor(count);
1088 guint
1089 text_editor_get_current_column (TextEditor * te)
1091 g_return_val_if_fail (te != NULL, 0);
1092 return scintilla_send_message (SCINTILLA (te->scintilla),
1093 SCI_GETCOLUMN,
1094 text_editor_get_current_position (te), 0);
1097 gboolean
1098 text_editor_get_overwrite (TextEditor * te)
1100 g_return_val_if_fail (te != NULL, 0);
1101 return scintilla_send_message (SCINTILLA (te->scintilla),
1102 SCI_GETOVERTYPE, 0, 0);
1105 guint
1106 text_editor_get_line_from_position (TextEditor * te, glong pos)
1108 guint count;
1110 g_return_val_if_fail (te != NULL, 0);
1112 count = scintilla_send_message (SCINTILLA (te->scintilla),
1113 SCI_LINEFROMPOSITION, pos, 0);
1114 return linenum_scintilla_to_text_editor(count);
1117 glong
1118 text_editor_get_current_position (TextEditor * te)
1120 guint count;
1122 g_return_val_if_fail (te != NULL, 0);
1124 count = scintilla_send_message (SCINTILLA (te->scintilla),
1125 SCI_GETCURRENTPOS, 0, 0);
1126 return count;
1129 gboolean
1130 text_editor_goto_point (TextEditor * te, glong point)
1132 g_return_val_if_fail (te != NULL, FALSE);
1133 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
1135 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS, point, 0);
1136 return TRUE;
1139 gboolean
1140 text_editor_goto_line (TextEditor * te, glong line,
1141 gboolean mark, gboolean ensure_visible)
1143 gint selpos;
1144 g_return_val_if_fail (te != NULL, FALSE);
1145 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
1146 g_return_val_if_fail(line >= 0, FALSE);
1148 te->current_line = line;
1149 if (mark) text_editor_set_line_marker (te, line);
1150 if (ensure_visible)
1151 scintilla_send_message (SCINTILLA (te->scintilla),
1152 SCI_ENSUREVISIBLE,
1153 linenum_text_editor_to_scintilla (line), 0);
1154 selpos = scintilla_send_message(SCINTILLA (te->scintilla),
1155 SCI_POSITIONFROMLINE,
1156 linenum_text_editor_to_scintilla (line), 0);
1157 scintilla_send_message (SCINTILLA (te->scintilla),
1158 SCI_SETSELECTIONSTART, selpos, 0);
1159 scintilla_send_message (SCINTILLA (te->scintilla),
1160 SCI_SETSELECTIONEND, selpos, 0);
1162 /* This ensures that we have arround 5 lines visible below the mark */
1163 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
1164 linenum_text_editor_to_scintilla (line)+5, 0);
1165 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
1166 linenum_text_editor_to_scintilla (line), 0);
1167 return TRUE;
1170 gint
1171 text_editor_goto_block_start (TextEditor* te)
1173 gint line;
1174 line = aneditor_command (te->editor_id, ANE_GETBLOCKSTARTLINE, 0, 0);
1175 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
1176 else gdk_beep();
1177 return line;
1180 gint
1181 text_editor_goto_block_end (TextEditor* te)
1183 gint line;
1184 line = aneditor_command (te->editor_id, ANE_GETBLOCKENDLINE, 0, 0);
1185 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
1186 else gdk_beep();
1187 return line;
1190 gint
1191 text_editor_set_marker (TextEditor *te, glong line, gint marker)
1193 g_return_val_if_fail (te != NULL, -1);
1194 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, -1);
1196 /* Scintilla interprets line+1 rather than line */
1197 /* A bug perhaps */
1198 /* So counterbalance it with line-1 */
1199 /* Using the macros linenum_* */
1200 return scintilla_send_message (SCINTILLA (te->scintilla),
1201 SCI_MARKERADD,
1202 linenum_text_editor_to_scintilla (line),
1203 marker);
1206 gint
1207 text_editor_set_indicator (TextEditor *te, gint start,
1208 gint end, gint indicator)
1210 g_return_val_if_fail (te != NULL, -1);
1211 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
1213 scintilla_send_message (SCINTILLA (te->scintilla),
1214 SCI_SETINDICATORCURRENT, indicator, 0);
1215 scintilla_send_message (SCINTILLA (te->scintilla),
1216 SCI_INDICATORFILLRANGE, start, end - start);
1218 return 0;
1221 static gint
1222 text_editor_clear_indicator (TextEditor *te, gint start,
1223 gint end)
1225 gint i;
1227 g_return_val_if_fail (te != NULL, -1);
1228 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
1230 for (i = 0; i < 3; i++)
1232 scintilla_send_message (SCINTILLA (te->scintilla),
1233 SCI_SETINDICATORCURRENT, i, 0);
1234 scintilla_send_message (SCINTILLA (te->scintilla),
1235 SCI_INDICATORCLEARRANGE, start, end - start);
1238 return 0;
1241 static gint
1242 text_editor_clear_all_indicator (TextEditor *te)
1244 glong last;
1245 gint i;
1247 g_return_val_if_fail (te != NULL, -1);
1248 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
1250 last = scintilla_send_message (SCINTILLA (te->scintilla),
1251 SCI_GETTEXTLENGTH, 0, 0);
1252 for (i = 0; i < 3; i++)
1254 scintilla_send_message (SCINTILLA (te->scintilla),
1255 SCI_SETINDICATORCURRENT, i, 0);
1256 scintilla_send_message (SCINTILLA (te->scintilla),
1257 SCI_INDICATORCLEARRANGE, 0, last);
1260 return 0;
1263 void
1264 text_editor_set_line_marker (TextEditor *te, glong line)
1266 g_return_if_fail (te != NULL);
1267 g_return_if_fail(IS_SCINTILLA (te->scintilla) == TRUE);
1269 // FIXME: anjuta_delete_all_marker (TEXT_EDITOR_LINEMARKER);
1270 text_editor_delete_marker_all (te, TEXT_EDITOR_LINEMARKER);
1271 text_editor_set_marker (te, line, TEXT_EDITOR_LINEMARKER);
1274 /* Support for DOS-Files
1276 * On load, Anjuta will detect DOS-files by finding <CR><LF>.
1277 * Anjuta will translate some chars >= 128 to native charset.
1278 * On save the DOS_EOL_CHECK(preferences->editor) will be checked
1279 * and chars >=128 will be replaced by DOS-codes, if any translation
1280 * match(see struct tr_dos in this file) and <CR><LF> will used
1281 * instead of <LF>.
1282 * The DOS_EOL_CHECK-checkbox will be set on loading a DOS-file.
1284 * 23.Sep.2001 Denis Boehme <boehme at syncio dot de>
1288 * this is a translation table from unix->dos
1289 * this table will be used by filter_chars and save filtered.
1291 static struct {
1292 unsigned char c; /* unix-char */
1293 unsigned char b; /* dos-char */
1294 } tr_dos[]= {
1295 { 'ä', 0x84 },
1296 { 'Ä', 0x8e },
1297 { 'ß', 0xe1 },
1298 { 'ü', 0x81 },
1299 { 'Ü', 0x9a },
1300 { 'ö', 0x94 },
1301 { 'Ö', 0x99 },
1302 { 'é', 0x82 },
1303 { 'É', 0x90 },
1304 { 'è', 0x9a },
1305 { 'È', 0xd4 },
1306 { 'ê', 0x88 },
1307 { 'Ê', 0xd2 },
1308 { 'á', 0xa0 },
1309 { 'Á', 0xb5 },
1310 { 'à', 0x85 },
1311 { 'À', 0xb7 },
1312 { 'â', 0x83 },
1313 { 'Â', 0xb6 },
1314 { 'ú', 0xa3 },
1315 { 'Ú', 0xe9 },
1316 { 'ù', 0x97 },
1317 { 'Ù', 0xeb },
1318 { 'û', 0x96 },
1319 { 'Û', 0xea }
1323 * filter chars in buffer, by using tr_dos-table.
1326 static size_t
1327 filter_chars_in_dos_mode(gchar *data_, size_t size )
1329 int k;
1330 size_t i;
1331 unsigned char * data = (unsigned char*)data_;
1332 unsigned char * tr_map;
1334 tr_map = (unsigned char *)malloc( 256 );
1335 memset( tr_map, 0, 256 );
1336 for ( k = 0; k < sizeof(tr_dos )/2 ; k++ )
1337 tr_map[tr_dos[k].b] = tr_dos[k].c;
1339 for ( i = 0; i < size; i++ )
1341 if ( (data[i] >= 128) && ( tr_map[data[i]] != 0) )
1342 data[i] = tr_map[data[i]];;
1345 if ( tr_map )
1346 free( tr_map );
1348 return size;
1352 * save buffer. filter chars and set dos-like CR/LF if dos_text is set.
1354 static gboolean
1355 save_filtered_in_dos_mode(GFileOutputStream* stream, gchar *data_,
1356 gsize size)
1358 gboolean result;
1359 gsize i, j;
1360 unsigned char *data;
1361 unsigned char *tr_map;
1362 int k;
1364 /* build the translation table */
1365 tr_map = malloc( 256 );
1366 memset( tr_map, 0, 256 );
1368 for ( k = 0; k < sizeof(tr_dos)/2; k++)
1369 tr_map[tr_dos[k].c] = tr_dos[k].b;
1371 data = (unsigned char*)data_;
1372 i = 0;
1373 j = 0;
1374 while ( i < size )
1376 if (data[i]>=128)
1378 /* convert dos-text */
1379 if ( tr_map[data[i]] != 0 )
1381 gsize bytes_written;
1382 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1383 &tr_map[data[i]], 1,
1384 &bytes_written,
1385 NULL, NULL);
1387 j += bytes_written;
1389 else
1391 /* char not found, skip transform */
1392 gsize bytes_written;
1393 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1394 &data[i], 1,
1395 &bytes_written,
1396 NULL, NULL);
1397 j += bytes_written;
1399 i++;
1401 else
1403 gsize bytes_written;
1404 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1405 &data[i], 1,
1406 &bytes_written,
1407 NULL, NULL);
1408 j += bytes_written;
1409 i++;
1411 if (!result)
1412 break;
1415 if (tr_map)
1416 free (tr_map);
1417 return result;
1420 static gint
1421 determine_editor_mode(gchar* buffer, glong size)
1423 gint i;
1424 guint cr, lf, crlf, max_mode;
1425 gint mode;
1427 cr = lf = crlf = 0;
1429 for ( i = 0; i < size ; i++ )
1431 if ( buffer[i] == 0x0a ){
1432 // LF
1433 // mode = SC_EOF_LF;
1434 lf++;
1435 } else if ( buffer[i] == 0x0d ) {
1436 if (i >= (size-1)) {
1437 // Last char
1438 // CR
1439 // mode = SC_EOL_CR;
1440 cr++;
1441 } else {
1442 if (buffer[i+1] != 0x0a) {
1443 // CR
1444 // mode = SC_EOL_CR;
1445 cr++;
1446 } else {
1447 // CRLF
1448 // mode = SC_EOL_CRLF;
1449 crlf++;
1451 i++;
1456 /* Vote for the maximum */
1457 mode = SC_EOL_LF;
1458 max_mode = lf;
1459 if (crlf > max_mode) {
1460 mode = SC_EOL_CRLF;
1461 max_mode = crlf;
1463 if (cr > max_mode) {
1464 mode = SC_EOL_CR;
1465 max_mode = cr;
1467 /* DEBUG_PRINT ("EOL chars: LR = %d, CR = %d, CRLF = %d", lf, cr, crlf); */
1468 /* DEBUG_PRINT ("Autodetected Editor mode [%d]", mode); */
1469 return mode;
1472 static gchar *
1473 convert_to_utf8 (PropsID props, const gchar *content, gsize len,
1474 const AnjutaEncoding **encoding_used)
1476 GError* conv_error = NULL;
1477 gchar* new_content;
1478 gsize new_len;
1480 new_content = anjuta_convert_to_utf8 (content,
1481 len,
1482 encoding_used,
1483 &new_len,
1484 &conv_error);
1485 if (new_content == NULL)
1487 /* Last change, let's try 8859-15 */
1488 *encoding_used =
1489 anjuta_encoding_get_from_charset("ISO-8859-15");
1491 new_content = anjuta_convert_to_utf8 (content,
1492 len,
1493 encoding_used,
1494 &new_len,
1495 &conv_error);
1498 if (conv_error)
1499 g_error_free (conv_error);
1501 return new_content;
1504 static gboolean
1505 load_from_file (TextEditor *te, gchar *uri, gchar **err)
1507 GFile *gio_uri;
1508 GFileInputStream *stream;
1509 gboolean result;
1510 GFileInfo *info;
1511 gsize nchars;
1512 gint dos_filter, editor_mode;
1513 gchar *file_content = NULL;
1514 gchar *buffer = NULL;
1515 guint64 size;
1517 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CLEARALL,
1518 0, 0);
1519 gio_uri = g_file_new_for_uri (uri);
1520 info = g_file_query_info (gio_uri,
1521 G_FILE_ATTRIBUTE_STANDARD_SIZE,
1522 G_FILE_QUERY_INFO_NONE,
1523 NULL,
1524 NULL);
1526 if (info == NULL)
1528 *err = g_strdup (_("Could not get file info"));
1529 g_object_unref (gio_uri);
1531 return FALSE;
1533 size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
1534 g_object_unref (info);
1536 buffer = g_malloc (size + 1);
1537 if (buffer == NULL && size != 0)
1539 /* DEBUG_PRINT ("%s", "This file is too big. Unable to allocate memory."); */
1540 *err = g_strdup (_("This file is too big. Unable to allocate memory."));
1541 g_object_unref (gio_uri);
1543 return FALSE;
1546 stream = g_file_read (gio_uri, NULL, NULL);
1547 if (stream == NULL)
1549 *err = g_strdup (_("Could not open file"));
1550 g_object_unref (gio_uri);
1552 return FALSE;
1554 /* Crude way of loading, but faster */
1555 result = g_input_stream_read_all (G_INPUT_STREAM (stream),
1556 buffer, size, &nchars, NULL, NULL);
1557 if (!result)
1559 g_free(buffer);
1560 *err = g_strdup (_("Error while reading from file"));
1561 g_object_unref (gio_uri);
1563 return FALSE;
1566 if (buffer)
1568 buffer[size] = '\0';
1569 file_content = g_strdup (buffer);
1572 if (size != nchars)
1574 /* DEBUG_PRINT ("File size and loaded size not matching"); */
1576 dos_filter =
1577 g_settings_get_boolean (te->settings,
1578 DOS_EOL_CHECK);
1580 /* Set editor mode */
1581 editor_mode = determine_editor_mode (buffer, nchars);
1582 scintilla_send_message (SCINTILLA (te->scintilla),
1583 SCI_SETEOLMODE, editor_mode, 0);
1585 /* DEBUG_PRINT ("Loaded in editor mode [%d]", editor_mode); */
1587 /* Determine character encoding and convert to utf-8*/
1588 if (nchars > 0)
1590 if (g_utf8_validate (buffer, nchars, NULL))
1592 te->encoding = NULL;
1594 else
1596 gchar *converted_text;
1598 converted_text = convert_to_utf8 (te->props_base,
1599 buffer, nchars, &te->encoding);
1601 if (converted_text == NULL)
1603 /* bail out */
1604 g_free (buffer);
1605 g_free (file_content);
1606 *err = g_strdup (_("The file does not look like a text file or the file encoding is not supported."
1607 " Please check if the encoding of file is in the supported encodings list."
1608 " If not, add it from the preferences."));
1609 g_object_unref (gio_uri);
1611 return FALSE;
1613 g_free (buffer);
1614 buffer = converted_text;
1615 nchars = strlen (converted_text);
1618 if (dos_filter && editor_mode == SC_EOL_CRLF){
1619 /* DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Dos => Unix]"); */
1620 nchars = filter_chars_in_dos_mode( buffer, nchars );
1622 scintilla_send_message (SCINTILLA (te->scintilla), SCI_ADDTEXT,
1623 nchars, (long) buffer);
1625 g_free (buffer);
1627 /* Save the buffer as last saved content */
1628 g_free (te->last_saved_content);
1629 te->last_saved_content = file_content;
1631 g_object_unref (gio_uri);
1633 return TRUE;
1636 static void
1637 strip_trailing_space (gchar *data, gsize *size)
1639 gchar *space;
1640 gsize len;
1642 /* Search first trailing space */
1643 for (len = 0;;len++)
1645 while ((len != *size) && (data[len] != ' ') && (data[len] != '\t')) len++;
1646 if (len == *size) break;
1647 space = &data[len];
1648 while ((len != *size) && ((data[len] == ' ') || (data[len] == '\t'))) len++;
1649 if ((len == *size) || (data[len] == '\n') || (data[len] == '\r'))
1651 gchar *strip = space;
1653 /* Search next trailing space */
1654 for (;;)
1656 while ((len != *size) && (data[len] != ' ') && (data[len] != '\t')) *strip++ = data[len++];
1657 if (len == *size) break;
1658 space = &data[len];
1659 while ((len != *size) && ((data[len] == ' ') || (data[len] == '\t'))) *strip++ = data[len++];
1660 if ((len == *size) || (data[len] == '\n') || (data[len] == '\r'))
1662 strip -= (&data[len] - space);
1665 *size -= (&data[len] - strip);
1666 break;
1672 static gboolean
1673 save_to_file (TextEditor *te, gchar *uri, GError **error)
1675 GFileOutputStream *stream;
1676 GFile *gio_uri;
1677 gsize nchars, size;
1678 gint strip;
1679 gchar *data;
1680 gboolean result;
1682 gio_uri = g_file_new_for_uri (uri);
1683 stream = g_file_replace (gio_uri, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
1685 if (stream == NULL)
1686 return FALSE;
1688 result = TRUE;
1690 nchars = scintilla_send_message (SCINTILLA (te->scintilla),
1691 SCI_GETLENGTH, 0, 0);
1692 data = (gchar *) aneditor_command (te->editor_id,
1693 ANE_GETTEXTRANGE, 0, nchars);
1694 if (data)
1696 gint dos_filter, editor_mode;
1698 size = strlen (data);
1701 /* Save in original encoding */
1702 if ((te->encoding != NULL))
1704 GError *conv_error = NULL;
1705 gchar* converted_file_contents = NULL;
1706 gsize new_len;
1708 /* DEBUG_PRINT ("Using encoding %s", te->encoding); */
1710 /* Try to convert it from UTF-8 to original encoding */
1711 converted_file_contents = anjuta_convert_from_utf8 (data, -1,
1712 te->encoding,
1713 &new_len,
1714 &conv_error);
1716 if (conv_error != NULL)
1718 /* Conversion error */
1719 g_error_free (conv_error);
1721 else
1723 g_free (data);
1724 data = converted_file_contents;
1725 size = strlen (converted_file_contents);
1728 else
1730 /* Save in utf-8 */
1731 /* DEBUG_PRINT ("Using utf-8 encoding"); */
1734 /* Strip trailing spaces */
1735 strip = g_settings_get_boolean (te->settings,
1736 STRIP_TRAILING_SPACES);
1737 if (strip)
1739 strip_trailing_space (data, &size);
1741 if ((size > 1) && ('\n' != data[size-1]))
1743 data[size] = '\n';
1744 ++ size;
1746 dos_filter = g_settings_get_boolean (te->settings,
1747 DOS_EOL_CHECK);
1748 editor_mode = scintilla_send_message (SCINTILLA (te->scintilla),
1749 SCI_GETEOLMODE, 0, 0);
1750 /* DEBUG_PRINT ("Saving in editor mode [%d]", editor_mode); */
1751 nchars = size;
1752 if (editor_mode == SC_EOL_CRLF && dos_filter)
1754 /* DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Unix => Dos]"); */
1755 size = save_filtered_in_dos_mode (stream, data, size);
1757 else
1759 result = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
1760 data, size,
1761 &nchars, NULL, error);
1763 data[size] = '\0';
1766 /* Set last content saved to data */
1767 g_free (te->last_saved_content);
1768 te->last_saved_content = data;
1770 if (result)
1771 result = g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, error);
1772 else
1773 g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL);
1775 g_object_unref (gio_uri);
1777 return result;
1780 gboolean
1781 text_editor_load_file (TextEditor * te)
1783 gchar *err = NULL;
1785 if (te == NULL || te->filename == NULL)
1786 return FALSE;
1787 if (IS_SCINTILLA (te->scintilla) == FALSE)
1788 return FALSE;
1789 anjuta_status (te->status, _("Loading file..."), 5);
1791 text_editor_freeze (te);
1793 // te->modified_time = time (NULL);
1794 text_editor_update_monitor (te, FALSE);
1795 if (load_from_file (te, te->uri, &err) == FALSE)
1797 anjuta_util_dialog_error (NULL,
1798 _("Could not load file: %s\n\nDetails: %s"),
1799 te->filename, err);
1800 g_free (err);
1801 text_editor_thaw (te);
1802 return FALSE;
1804 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS,
1805 0, 0);
1806 // check_tm_file(te);
1807 text_editor_thaw (te);
1808 te->force_not_saved = FALSE;
1809 scintilla_send_message (SCINTILLA (te->scintilla),
1810 SCI_SETSAVEPOINT, 0, 0);
1811 scintilla_send_message (SCINTILLA (te->scintilla),
1812 SCI_EMPTYUNDOBUFFER, 0, 0);
1813 text_editor_set_hilite_type (te, NULL);
1814 if (g_settings_get_boolean (te->settings, FOLD_ON_OPEN))
1816 aneditor_command (te->editor_id, ANE_CLOSE_FOLDALL, 0, 0);
1818 text_editor_set_line_number_width(te);
1819 anjuta_status (te->status, _("File loaded successfully"), 5);
1821 g_idle_add ((GSourceFunc) emit_opened, te);
1823 return TRUE;
1826 gboolean
1827 text_editor_save_file (TextEditor * te, gboolean update)
1829 GtkWindow *parent;
1830 GError *error = NULL;
1831 gboolean ret = FALSE;
1833 g_return_val_if_fail (te != NULL, FALSE);
1834 g_return_val_if_fail (IS_SCINTILLA (te->scintilla), FALSE);
1836 text_editor_freeze (te);
1837 text_editor_set_line_number_width(te);
1838 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (te)));
1840 anjuta_status (te->status, _("Saving file..."), 5);
1841 text_editor_update_monitor (te, TRUE);
1843 if (!save_to_file (te, te->uri, &error))
1845 text_editor_thaw (te);
1846 g_return_val_if_fail (error != NULL, FALSE);
1848 anjuta_util_dialog_error (parent,
1849 _("Could not save intermediate file %s: %s"),
1850 te->uri,
1851 error->message);
1852 g_signal_emit_by_name (G_OBJECT (te), "saved", NULL);
1853 g_error_free (error);
1855 else
1857 GFile* file = g_file_new_for_uri (te->uri);
1858 /* we need to update UI with the call to scintilla */
1859 text_editor_thaw (te);
1860 te->force_not_saved = FALSE;
1861 scintilla_send_message (SCINTILLA (te->scintilla),
1862 SCI_SETSAVEPOINT, 0, 0);
1863 g_signal_emit_by_name (G_OBJECT (te), "saved", file);
1864 g_object_unref (file);
1865 anjuta_status (te->status, _("File saved successfully"), 5);
1866 ret = TRUE;
1868 text_editor_update_monitor (te, FALSE);
1870 return ret;
1873 void
1874 text_editor_set_saved (TextEditor *te, gboolean saved)
1876 if (saved)
1878 scintilla_send_message (SCINTILLA (te->scintilla), SCI_SETSAVEPOINT, 0, 0);
1880 te->force_not_saved = !saved;
1881 g_signal_emit_by_name(G_OBJECT (te), "update-save-ui");
1884 gboolean
1885 text_editor_save_yourself (TextEditor * te, FILE * stream)
1887 return TRUE;
1890 gboolean
1891 text_editor_recover_yourself (TextEditor * te, FILE * stream)
1893 return TRUE;
1896 void
1897 text_editor_undo (TextEditor * te)
1899 scintilla_send_message (SCINTILLA (te->scintilla),
1900 SCI_UNDO, 0, 0);
1903 void
1904 text_editor_redo (TextEditor * te)
1906 scintilla_send_message (SCINTILLA (te->scintilla),
1907 SCI_REDO, 0, 0);
1910 void
1911 text_editor_update_controls (TextEditor * te)
1913 #if 0 //FIXME
1914 gboolean F, P, L, C, S;
1916 if (te == NULL)
1917 return;
1918 S = text_editor_is_saved (te);
1919 L = anjuta_launcher_is_busy (app->launcher);
1920 P = app->project_dbase->project_is_open;
1922 switch (get_file_ext_type (te->filename))
1924 case FILE_TYPE_C:
1925 case FILE_TYPE_CPP:
1926 case FILE_TYPE_ASM:
1927 F = TRUE;
1928 break;
1929 default:
1930 F = FALSE;
1932 switch (get_file_ext_type (te->filename))
1934 case FILE_TYPE_C:
1935 case FILE_TYPE_CPP:
1936 case FILE_TYPE_HEADER:
1937 C = TRUE;
1938 break;
1939 default:
1940 C = FALSE;
1942 gtk_widget_set_sensitive (te->buttons.save, !S);
1943 gtk_widget_set_sensitive (te->buttons.reload,
1944 (te->uri != NULL));
1945 gtk_widget_set_sensitive (te->buttons.compile, F && !L);
1946 gtk_widget_set_sensitive (te->buttons.build, (F || P) && !L);
1947 #endif
1950 gboolean
1951 text_editor_is_saved (TextEditor * te)
1953 return !(scintilla_send_message (SCINTILLA (te->scintilla),
1954 SCI_GETMODIFY, 0, 0)) && (!te->force_not_saved);
1957 gboolean
1958 text_editor_has_selection (TextEditor * te)
1960 gint from, to;
1961 from = scintilla_send_message (SCINTILLA (te->scintilla),
1962 SCI_GETSELECTIONSTART, 0, 0);
1963 to = scintilla_send_message (SCINTILLA (te->scintilla),
1964 SCI_GETSELECTIONEND, 0, 0);
1965 return (from == to) ? FALSE : TRUE;
1968 glong text_editor_get_selection_start (TextEditor * te)
1970 return scintilla_send_message (SCINTILLA (te->scintilla),
1971 SCI_GETSELECTIONSTART, 0, 0);
1974 glong text_editor_get_selection_end (TextEditor * te)
1976 return scintilla_send_message (SCINTILLA (te->scintilla),
1977 SCI_GETSELECTIONEND, 0, 0);
1980 gchar*
1981 text_editor_get_selection (TextEditor * te)
1983 guint from, to;
1984 struct Sci_TextRange tr;
1986 from = scintilla_send_message (SCINTILLA (te->scintilla),
1987 SCI_GETSELECTIONSTART, 0, 0);
1988 to = scintilla_send_message (SCINTILLA (te->scintilla),
1989 SCI_GETSELECTIONEND, 0, 0);
1990 if (from == to)
1991 return NULL;
1992 tr.chrg.cpMin = MIN(from, to);
1993 tr.chrg.cpMax = MAX(from, to);
1994 tr.lpstrText = g_malloc (sizeof(gchar)*(tr.chrg.cpMax-tr.chrg.cpMin)+5);
1995 scintilla_send_message (SCINTILLA(te->scintilla), SCI_GETTEXTRANGE, 0, (long)(&tr));
1996 return tr.lpstrText;
1999 gboolean
2000 text_editor_is_marker_set (TextEditor* te, glong line, gint marker)
2002 gint state;
2004 g_return_val_if_fail (te != NULL, FALSE);
2005 g_return_val_if_fail (line >= 0, FALSE);
2006 g_return_val_if_fail (marker < 32, FALSE);
2008 state = scintilla_send_message (SCINTILLA(te->scintilla),
2009 SCI_MARKERGET, linenum_text_editor_to_scintilla (line), 0);
2010 return ((state & (1 << marker)));
2013 void
2014 text_editor_delete_marker_all (TextEditor *te, gint marker)
2016 g_return_if_fail (IS_TEXT_EDITOR (te));
2017 g_return_if_fail (marker < 32);
2018 scintilla_send_message (SCINTILLA (te->scintilla),
2019 SCI_MARKERDELETEALL, marker, 0);
2022 void
2023 text_editor_delete_marker (TextEditor* te, glong line, gint marker)
2025 g_return_if_fail (IS_TEXT_EDITOR (te));
2026 g_return_if_fail (line >= 0);
2027 g_return_if_fail (marker < 32);
2029 scintilla_send_message (SCINTILLA(te->scintilla),
2030 SCI_MARKERDELETE, linenum_text_editor_to_scintilla (line), marker);
2033 gint
2034 text_editor_line_from_handle (TextEditor* te, gint marker_handle)
2036 gint line;
2038 g_return_val_if_fail (te != NULL, -1);
2040 line = scintilla_send_message (SCINTILLA(te->scintilla),
2041 SCI_MARKERLINEFROMHANDLE, marker_handle, 0);
2043 return linenum_scintilla_to_text_editor (line);
2046 gint
2047 text_editor_get_bookmark_line( TextEditor* te, const glong nLineStart )
2049 return aneditor_command (te->editor_id, ANE_GETBOOKMARK_POS, nLineStart, 0);
2052 gint
2053 text_editor_get_num_bookmarks(TextEditor* te)
2055 gint nLineNo = -1 ;
2056 gint nMarkers = 0 ;
2058 g_return_val_if_fail (te != NULL, 0 );
2060 while( ( nLineNo = text_editor_get_bookmark_line( te, nLineNo ) ) >= 0 )
2062 //printf( "Line %d\n", nLineNo );
2063 nMarkers++;
2065 //printf( "out Line %d\n", nLineNo );
2066 return nMarkers ;
2069 /* Gets the word before just before carat */
2070 gchar*
2071 text_editor_get_word_before_carat (TextEditor *te)
2073 gchar buffer[512];
2074 buffer[0] = '\0';
2075 aneditor_command (TEXT_EDITOR (te)->editor_id,
2076 ANE_GETWORDBEFORECARAT, (glong) buffer, 512);
2077 if (buffer[0] != '\0')
2078 return g_strdup (buffer);
2079 else
2080 return NULL;
2084 *Get the current selection. If there is no selection, or if the selection
2085 * is all blanks, get the word under teh cursor.
2087 gchar*
2088 text_editor_get_current_word (TextEditor *te)
2090 char *buf = text_editor_get_selection(te);
2091 if (buf)
2093 g_strstrip(buf);
2094 if ('\0' == *buf)
2096 g_free(buf);
2097 buf = NULL;
2100 if (NULL == buf)
2102 int ret;
2103 buf = g_new(char, 256);
2104 ret = aneditor_command (te->editor_id, ANE_GETCURRENTWORD, (long)buf, 255L);
2105 if (!ret)
2107 g_free(buf);
2108 buf = NULL;
2112 #ifdef DEBUG
2113 if (buf)
2114 DEBUG_PRINT ("Current word is '%s'", buf);
2115 #endif
2117 return buf;
2120 void
2121 text_editor_function_select(TextEditor *te)
2123 gint pos;
2124 gint line;
2125 gint fold_level;
2126 gint start, end;
2127 gint line_count;
2128 gint tmp;
2130 line_count = scintilla_send_message(SCINTILLA(te->scintilla),
2131 SCI_GETLINECOUNT, 0, 0);
2132 pos = scintilla_send_message(SCINTILLA(te->scintilla),
2133 SCI_GETCURRENTPOS, 0, 0);
2134 line = scintilla_send_message(SCINTILLA(te->scintilla),
2135 SCI_LINEFROMPOSITION, pos, 0);
2137 tmp = line + 1;
2138 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2139 SCI_GETFOLDLEVEL, line, 0) ;
2140 if ((fold_level & 0xFF) != 0)
2142 while((fold_level & 0x10FF) != 0x1000 && line >= 0)
2143 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2144 SCI_GETFOLDLEVEL, --line, 0) ;
2145 start = scintilla_send_message(SCINTILLA(te->scintilla),
2146 SCI_POSITIONFROMLINE, line + 1, 0);
2147 line = tmp;
2148 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2149 SCI_GETFOLDLEVEL, line, 0) ;
2150 while((fold_level & 0x10FF) != 0x1000 && line < line_count)
2151 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2152 SCI_GETFOLDLEVEL, ++line, 0) ;
2154 end = scintilla_send_message(SCINTILLA(te->scintilla),
2155 SCI_POSITIONFROMLINE, line , 0);
2156 scintilla_send_message(SCINTILLA(te->scintilla),
2157 SCI_SETSEL, start, end) ;
2161 void
2162 text_editor_grab_focus (TextEditor *te)
2164 g_return_if_fail (IS_TEXT_EDITOR (te));
2165 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GRABFOCUS, 0, 0);
2168 void
2169 text_editor_set_popup_menu (TextEditor *te, GtkWidget *popup_menu)
2171 if (popup_menu)
2172 g_object_ref (popup_menu);
2173 if (te->popup_menu)
2174 g_object_unref (te->popup_menu);
2175 te->popup_menu = popup_menu;
2178 void
2179 text_editor_set_busy (TextEditor *te, gboolean state)
2181 if (state)
2182 scintilla_send_message (SCINTILLA (te->scintilla),
2183 SCI_SETCURSOR, SC_CURSORWAIT, 0);
2184 else
2185 scintilla_send_message (SCINTILLA (te->scintilla),
2186 SCI_SETCURSOR, SC_CURSORNORMAL, 0);
2189 gint
2190 text_editor_get_props ()
2192 /* Built in values */
2193 static PropsID props_built_in = 0;
2195 /* System values */
2196 static PropsID props_global = 0;
2198 /* User values */
2199 // static PropsID props_local = 0;
2201 /* Session values */
2202 static PropsID props_session = 0;
2204 /* Instance values */
2205 static PropsID props = 0;
2207 gchar *propdir, *propfile;
2209 if (props)
2210 return props;
2212 props_built_in = sci_prop_set_new ();
2213 props_global = sci_prop_set_new ();
2214 // props_local = sci_prop_set_new ();
2215 props_session = sci_prop_set_new ();
2216 props = sci_prop_set_new ();
2218 sci_prop_clear (props_built_in);
2219 sci_prop_clear (props_global);
2220 // sci_prop_clear (props_local);
2221 sci_prop_clear (props_session);
2222 sci_prop_clear (props);
2224 sci_prop_set_parent (props_global, props_built_in);
2225 // sci_prop_set_parent (props_local, props_global);
2226 // sci_prop_set_parent (props_session, props_local);
2227 sci_prop_set_parent (props_session, props_global);
2228 sci_prop_set_parent (props, props_session);
2230 propdir = g_build_filename (PACKAGE_DATA_DIR, "properties/", NULL);
2231 propfile = g_build_filename (PACKAGE_DATA_DIR, "properties",
2232 "anjuta.properties", NULL);
2233 /* DEBUG_PRINT ("Reading file: %s", propfile); */
2235 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE)
2237 anjuta_util_dialog_error (NULL,
2238 _("Cannot load Global defaults and configuration files:\n"
2239 "%s.\n"
2240 "This may result in improper behaviour or instabilities.\n"
2241 "Anjuta will fall back to built in (limited) settings"),
2242 propfile);
2244 sci_prop_read (props_global, propfile, propdir);
2245 g_free (propfile);
2246 g_free (propdir);
2248 propdir = anjuta_util_get_user_config_file_path ("scintilla/",NULL);
2249 propfile = anjuta_util_get_user_config_file_path ("scintilla","editor-style.properties",NULL);
2250 /* DEBUG_PRINT ("Reading file: %s", propfile); */
2252 /* Create user.properties file, if it doesn't exist */
2253 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE) {
2254 gchar* old_propfile = anjuta_util_get_user_config_file_path ("scintilla", "session.properties", NULL);
2255 if (g_file_test (old_propfile, G_FILE_TEST_EXISTS) == TRUE)
2256 anjuta_util_copy_file (old_propfile, propfile, FALSE);
2257 g_free (old_propfile);
2259 sci_prop_read (props_session, propfile, propdir);
2260 g_free (propdir);
2261 g_free (propfile);
2263 return props;
2266 void
2267 text_editor_set_line_number_width (TextEditor* te)
2269 /* Set line numbers with according to file size */
2270 if (g_settings_get_boolean (te->settings,
2271 VIEW_LINENUMBERS_MARGIN))
2273 int lines, line_number_width;
2274 gchar* line_number;
2275 gchar* line_number_dummy;
2277 lines =
2278 (int) scintilla_send_message
2279 (SCINTILLA(te->scintilla), SCI_GETLINECOUNT, 0,0);
2280 line_number = g_strdup_printf("%d", lines);
2281 line_number_dummy = g_strnfill(strlen(line_number) + 1, '9');
2282 line_number_width =
2283 (int) scintilla_send_message (SCINTILLA(te->scintilla),
2284 SCI_TEXTWIDTH,
2285 STYLE_LINENUMBER,
2286 (long) line_number_dummy);
2287 text_editor_command (te, ANE_SETLINENUMWIDTH, line_number_width, 0);
2288 g_free(line_number_dummy);
2289 g_free(line_number);
2293 gboolean
2294 text_editor_can_undo (TextEditor *te)
2296 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2297 return scintilla_send_message (SCINTILLA (te->scintilla),
2298 SCI_CANUNDO, 0, 0);
2301 gboolean
2302 text_editor_can_redo (TextEditor *te)
2304 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2305 return scintilla_send_message (SCINTILLA (te->scintilla),
2306 SCI_CANREDO, 0, 0);
2309 void
2310 text_editor_show_hover_tip (TextEditor *te, gint position, const gchar *info)
2312 text_editor_hide_hover_tip (te);
2313 if (!te->hover_tip_on)
2315 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPSHOW,
2316 position, (long)info);
2317 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPSETHLT,
2318 strlen (info), 0);
2319 te->hover_tip_on = TRUE;
2323 void
2324 text_editor_hide_hover_tip (TextEditor *te)
2326 if (te->hover_tip_on)
2328 scintilla_send_message (SCINTILLA (te->scintilla),
2329 SCI_CALLTIPCANCEL, 0, 0);
2330 te->hover_tip_on = FALSE;
2334 void
2335 text_editor_cancel_completion (TextEditor *te)
2337 te->completion_count = 0;
2338 g_string_truncate (te->completion_string, 0);
2341 void
2342 text_editor_suggest_completion (TextEditor *te)
2344 GList *node;
2345 TextEditorCell *iter;
2346 gint position;
2348 position = text_editor_get_current_position (te);
2349 iter = text_editor_cell_new (te, position);
2350 for (node = te->provider; node != NULL; node = g_list_next (node))
2352 ianjuta_provider_populate (IANJUTA_PROVIDER (node->data), IANJUTA_ITERABLE (iter), NULL);
2354 g_object_unref (iter);
2357 void
2358 text_editor_select_completion (TextEditor *te)
2360 TextEditorCell *iter;
2361 gint position;
2362 gint autoc_sel;
2364 autoc_sel = (gint) scintilla_send_message (SCINTILLA (te->scintilla),
2365 SCI_AUTOCGETCURRENT,
2366 0, 0);
2367 scintilla_send_message (SCINTILLA (te->scintilla),
2368 SCI_AUTOCCANCEL, 0, 0);
2370 g_return_if_fail (autoc_sel < te->completion_count);
2372 position = text_editor_get_current_position (te);
2373 iter = text_editor_cell_new (te, position);
2375 ianjuta_provider_activate (IANJUTA_PROVIDER (te->completion[autoc_sel].provider),
2376 IANJUTA_ITERABLE (iter),
2377 te->completion[autoc_sel].data, NULL);
2378 g_object_unref (iter);
2381 void
2382 text_editor_command (TextEditor *te, gint command, glong wparam, glong lparam)
2384 GList *node;
2386 node = te->views;
2387 while (node)
2389 aneditor_command (GPOINTER_TO_INT (node->data), command, wparam, lparam);
2390 node = g_list_next(node);
2394 void
2395 text_editor_scintilla_command (TextEditor *te, gint command, glong wparam,
2396 glong lparam)
2398 GList *node;
2400 node = te->views;
2401 while (node)
2403 GtkWidget *scintilla;
2404 scintilla = aneditor_get_widget (GPOINTER_TO_INT (node->data));
2405 scintilla_send_message (SCINTILLA(scintilla), command, wparam, lparam);
2406 node = g_list_next(node);
2410 /* IAnjutaEditor interface implementation */
2412 static gint
2413 itext_editor_get_tab_size (IAnjutaEditor *editor, GError **e)
2415 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2416 SCI_GETTABWIDTH, 0, 0);
2419 static void
2420 itext_editor_set_tab_size (IAnjutaEditor *editor, gint tabsize, GError **e)
2422 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2423 SCI_SETTABWIDTH, tabsize, 0);
2426 static gboolean
2427 itext_editor_get_use_spaces (IAnjutaEditor *editor, GError **e)
2429 return !scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2430 SCI_GETUSETABS, 0, 0);
2433 static void
2434 itext_editor_set_use_spaces (IAnjutaEditor *editor, gboolean use_spaces, GError **e)
2436 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2437 SCI_SETUSETABS, !use_spaces, 0);
2440 /* This function does not set automatic indentation but allow or not
2441 * the editor to indent the text. Used to disable editor indentation when
2442 * another plugin take care of it. */
2443 static void
2444 itext_editor_set_auto_indent (IAnjutaEditor *editor, gboolean auto_indent, GError **e)
2446 text_editor_command (TEXT_EDITOR(editor), ANE_SETAUTOINDENTATION, auto_indent, 0);
2449 static gint
2450 itext_editor_get_indent_size (IAnjutaEditor *editor, GError **e)
2452 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2453 SCI_GETINDENT, 0, 0);
2456 static void
2457 itext_editor_set_indent_size (IAnjutaEditor *editor, gint indentsize, GError **e)
2459 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2460 SCI_SETINDENT, indentsize, 0);
2463 static void
2464 itext_editor_goto_line (IAnjutaEditor *editor, gint lineno, GError **e)
2466 text_editor_goto_line (TEXT_EDITOR (editor), lineno, FALSE, TRUE);
2467 gtk_widget_grab_focus (TEXT_EDITOR (editor)->scintilla);
2470 static void
2471 itext_editor_goto_start (IAnjutaEditor *editor, GError **e)
2473 text_editor_goto_point (TEXT_EDITOR (editor), 0);
2476 static void
2477 itext_editor_goto_end (IAnjutaEditor *editor, GError **e)
2479 text_editor_goto_point (TEXT_EDITOR (editor), -1);
2482 static void
2483 itext_editor_goto_position (IAnjutaEditor *editor, IAnjutaIterable *position,
2484 GError **e)
2486 text_editor_goto_point (TEXT_EDITOR (editor),
2487 text_editor_cell_get_position (TEXT_EDITOR_CELL
2488 (position)));
2491 static gchar*
2492 itext_editor_get_text_all (IAnjutaEditor *editor, GError **e)
2494 TextEditor *te = TEXT_EDITOR (editor);
2495 gint length = scintilla_send_message (SCINTILLA (te->scintilla),
2496 SCI_GETLENGTH, 0, 0);
2497 if (length > 0)
2498 return (gchar *) aneditor_command (te->editor_id, ANE_GETTEXTRANGE,
2499 0, length);
2500 else
2501 return NULL;
2504 static gchar*
2505 itext_editor_get_text (IAnjutaEditor *editor, IAnjutaIterable* begin,
2506 IAnjutaIterable* end, GError **e)
2508 gchar *data;
2509 gint start_pos = text_editor_cell_get_position (TEXT_EDITOR_CELL (begin));
2510 gint end_pos = text_editor_cell_get_position (TEXT_EDITOR_CELL (end));
2511 TextEditor *te = TEXT_EDITOR (editor);
2512 data = (gchar *) aneditor_command (te->editor_id, ANE_GETTEXTRANGE,
2513 start_pos, end_pos);
2514 return data;
2517 static IAnjutaIterable*
2518 itext_editor_get_position (IAnjutaEditor* editor, GError **e)
2520 TextEditor *te = TEXT_EDITOR (editor);
2521 gint position = text_editor_get_current_position (te);
2522 TextEditorCell *position_iter = text_editor_cell_new (te, position);
2523 return IANJUTA_ITERABLE (position_iter);
2526 static gint
2527 itext_editor_get_offset (IAnjutaEditor *editor, GError **e)
2529 gint pos;
2530 IAnjutaIterable *iter = itext_editor_get_position (editor, NULL);
2531 pos = ianjuta_iterable_get_position (iter, NULL);
2532 g_object_unref (iter);
2533 return pos;
2536 static gint
2537 itext_editor_get_lineno (IAnjutaEditor *editor, GError **e)
2539 return text_editor_get_current_lineno (TEXT_EDITOR (editor));
2542 static gint
2543 itext_editor_get_length (IAnjutaEditor *editor, GError **e)
2545 return aneditor_command (TEXT_EDITOR (editor)->editor_id,
2546 ANE_GETLENGTH, 0, 0);
2549 static gchar*
2550 itext_editor_get_current_word (IAnjutaEditor *editor, GError **e)
2552 gchar buffer[512];
2553 buffer[0] = '\0';
2554 aneditor_command (TEXT_EDITOR (editor)->editor_id,
2555 ANE_GETCURRENTWORD, (glong) buffer, 512);
2556 if (buffer[0] != '\0')
2557 return g_strdup (buffer);
2558 else
2559 return NULL;
2562 static void
2563 itext_editor_insert (IAnjutaEditor *editor, IAnjutaIterable *position,
2564 const gchar *txt, gint length, GError **e)
2566 gchar *text_to_insert;
2567 int pos;
2569 pos = text_editor_cell_get_position (TEXT_EDITOR_CELL (position));
2570 if (length < 0) length = strlen (txt);
2572 text_to_insert = g_strndup (txt, length);
2574 aneditor_command (TEXT_EDITOR(editor)->editor_id, ANE_INSERTTEXT,
2575 pos, (long)text_to_insert);
2577 g_free (text_to_insert);
2580 static void
2581 itext_editor_append (IAnjutaEditor *editor, const gchar *txt,
2582 gint length, GError **e)
2584 gchar *text_to_insert;
2585 if (length >= 0)
2586 text_to_insert = g_strndup (txt, length);
2587 else
2588 text_to_insert = g_strdup (txt);
2590 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2591 SCI_APPENDTEXT, strlen(text_to_insert),
2592 (long)text_to_insert);
2593 g_free (text_to_insert);
2596 static void
2597 itext_editor_erase (IAnjutaEditor *editor,
2598 IAnjutaIterable *position_start,
2599 IAnjutaIterable *position_end, GError **e)
2601 gint start, end;
2603 /* If both positions are NULL, erase all */
2604 if (position_start == NULL && position_end == NULL)
2606 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2607 SCI_CLEARALL,
2608 0, 0);
2609 return;
2612 /* Determine correct start and end byte positions */
2613 if (position_start)
2614 start = text_editor_cell_get_position (TEXT_EDITOR_CELL (position_start));
2615 else
2616 start = 0;
2618 if (position_end)
2619 end = text_editor_cell_get_position (TEXT_EDITOR_CELL (position_end));
2620 else
2621 end = scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2622 SCI_GETLENGTH, 0, 0);
2623 if (start != end)
2625 scintilla_send_message (SCINTILLA(TEXT_EDITOR (editor)->scintilla),
2626 SCI_SETSEL, start, end);
2627 text_editor_replace_selection (TEXT_EDITOR (editor), "");
2631 static void
2632 itext_editor_erase_all (IAnjutaEditor *editor, GError **e)
2634 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2635 SCI_CLEARALL,
2636 0, 0);
2639 static int
2640 itext_editor_get_column (IAnjutaEditor *editor, GError **e)
2642 return text_editor_get_current_column (TEXT_EDITOR(editor));
2645 static gboolean
2646 itext_editor_get_overwrite (IAnjutaEditor *editor, GError **e)
2648 return text_editor_get_overwrite (TEXT_EDITOR (editor));
2651 static void
2652 itext_editor_set_popup_menu (IAnjutaEditor *editor, GtkWidget* menu, GError **e)
2654 text_editor_set_popup_menu (TEXT_EDITOR (editor), menu);
2657 static gint
2658 itext_editor_get_line_from_position (IAnjutaEditor *editor,
2659 IAnjutaIterable *position, GError **e)
2661 return text_editor_get_line_from_position (TEXT_EDITOR (editor),
2662 text_editor_cell_get_position (TEXT_EDITOR_CELL (position)));
2665 static IAnjutaIterable*
2666 itext_editor_get_line_begin_position (IAnjutaEditor *editor, gint line,
2667 GError **e)
2669 gint ln, byte_pos;
2670 TextEditor *te;
2672 g_return_val_if_fail (line > 0, NULL);
2673 te = TEXT_EDITOR (editor);
2674 ln = linenum_text_editor_to_scintilla (line);
2675 byte_pos = scintilla_send_message (SCINTILLA (te->scintilla),
2676 SCI_POSITIONFROMLINE, ln, 0);
2677 return IANJUTA_ITERABLE (text_editor_cell_new (te, byte_pos));
2680 static IAnjutaIterable*
2681 itext_editor_get_line_end_position (IAnjutaEditor *editor, gint line,
2682 GError **e)
2684 gint ln, byte_pos;
2685 TextEditor *te;
2687 g_return_val_if_fail (line > 0, NULL);
2688 te = TEXT_EDITOR (editor);
2690 ln = linenum_text_editor_to_scintilla (line);
2691 byte_pos = scintilla_send_message (SCINTILLA (te->scintilla),
2692 SCI_GETLINEENDPOSITION, ln, 0);
2693 return IANJUTA_ITERABLE (text_editor_cell_new (te, byte_pos));
2696 static IAnjutaIterable*
2697 itext_editor_get_position_from_offset (IAnjutaEditor *editor, gint offset, GError **e)
2699 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor), 0);
2700 /* Set to the right utf8 character offset */
2701 ianjuta_iterable_set_position (IANJUTA_ITERABLE (editor_cell), offset, NULL);
2702 return IANJUTA_ITERABLE (editor_cell);
2705 static IAnjutaIterable*
2706 itext_editor_get_start_position (IAnjutaEditor *editor, GError **e)
2708 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor), 0);
2709 return IANJUTA_ITERABLE (editor_cell);
2712 static IAnjutaIterable*
2713 itext_editor_get_end_position (IAnjutaEditor *editor, GError **e)
2715 gint length = scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2716 SCI_GETLENGTH, 0, 0);
2717 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor),
2718 length);
2719 return IANJUTA_ITERABLE (editor_cell);
2722 static void
2723 itext_editor_iface_init (IAnjutaEditorIface *iface)
2725 iface->get_tabsize = itext_editor_get_tab_size;
2726 iface->set_tabsize = itext_editor_set_tab_size;
2727 iface->get_use_spaces = itext_editor_get_use_spaces;
2728 iface->set_use_spaces = itext_editor_set_use_spaces;
2729 iface->set_auto_indent = itext_editor_set_auto_indent;
2730 iface->get_indentsize = itext_editor_get_indent_size;
2731 iface->set_indentsize = itext_editor_set_indent_size;
2732 iface->goto_line = itext_editor_goto_line;
2733 iface->goto_start = itext_editor_goto_start;
2734 iface->goto_end = itext_editor_goto_end;
2735 iface->goto_position = itext_editor_goto_position;
2736 iface->get_text_all = itext_editor_get_text_all;
2737 iface->get_text = itext_editor_get_text;
2738 iface->get_offset = itext_editor_get_offset;
2739 iface->get_position = itext_editor_get_position;
2740 iface->get_lineno = itext_editor_get_lineno;
2741 iface->get_length = itext_editor_get_length;
2742 iface->get_current_word = itext_editor_get_current_word;
2743 iface->insert = itext_editor_insert;
2744 iface->append = itext_editor_append;
2745 iface->erase = itext_editor_erase;
2746 iface->erase_all = itext_editor_erase_all;
2747 iface->get_column = itext_editor_get_column;
2748 iface->get_overwrite = itext_editor_get_overwrite;
2749 iface->set_popup_menu = itext_editor_set_popup_menu;
2750 iface->get_line_from_position = itext_editor_get_line_from_position;
2751 iface->get_line_begin_position = itext_editor_get_line_begin_position;
2752 iface->get_line_end_position = itext_editor_get_line_end_position;
2753 iface->get_position_from_offset = itext_editor_get_position_from_offset;
2754 iface->get_start_position = itext_editor_get_start_position;
2755 iface->get_end_position = itext_editor_get_end_position;
2758 static const gchar *
2759 idocument_get_filename (IAnjutaDocument *editor, GError **e)
2761 return (TEXT_EDITOR (editor))->filename;
2764 static gboolean
2765 idocument_can_undo(IAnjutaDocument* editor, GError **e)
2767 return text_editor_can_undo(TEXT_EDITOR(editor));
2770 static gboolean
2771 idocument_can_redo(IAnjutaDocument *editor, GError **e)
2773 return text_editor_can_redo(TEXT_EDITOR(editor));
2776 static void
2777 idocument_undo(IAnjutaDocument* te, GError** ee)
2779 text_editor_command(TEXT_EDITOR(te), ANE_UNDO, 0, 0);
2782 static void
2783 idocument_begin_undo_action (IAnjutaDocument* te, GError** ee)
2785 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2786 SCI_BEGINUNDOACTION, 0, 0);
2789 static void
2790 idocument_end_undo_action (IAnjutaDocument* te, GError** ee)
2792 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2793 SCI_ENDUNDOACTION, 0, 0);
2796 static void
2797 idocument_redo(IAnjutaDocument* te, GError** ee)
2799 text_editor_command(TEXT_EDITOR(te), ANE_REDO, 0, 0);
2802 static void
2803 idocument_grab_focus (IAnjutaDocument *editor, GError **e)
2805 text_editor_grab_focus (TEXT_EDITOR (editor));
2808 static void
2809 idocument_cut(IAnjutaDocument * te, GError** ee)
2811 text_editor_command(TEXT_EDITOR(te), ANE_CUT, 0, 0);
2814 static void
2815 idocument_copy(IAnjutaDocument * te, GError** ee)
2817 text_editor_command(TEXT_EDITOR(te), ANE_COPY, 0, 0);
2820 static void
2821 idocument_paste(IAnjutaDocument * te, GError** ee)
2823 text_editor_command(TEXT_EDITOR(te), ANE_PASTE, 0, 0);
2826 static void
2827 idocument_clear(IAnjutaDocument * te, GError** ee)
2829 text_editor_command(TEXT_EDITOR(te), ANE_CLEAR, 0, 0);
2832 static void
2833 idocument_iface_init(IAnjutaDocumentIface* iface)
2835 iface->get_filename = idocument_get_filename;
2836 iface->can_undo = idocument_can_undo;
2837 iface->can_redo = idocument_can_redo;
2838 iface->undo = idocument_undo;
2839 iface->redo = idocument_redo;
2840 iface->begin_undo_action = idocument_begin_undo_action;
2841 iface->end_undo_action = idocument_end_undo_action;
2842 iface->grab_focus = idocument_grab_focus;
2843 iface->cut = idocument_cut;
2844 iface->copy = idocument_copy;
2845 iface->paste = idocument_paste;
2846 iface->clear = idocument_clear;
2849 /* IAnjutaEditorSelection implementation */
2851 static gchar*
2852 iselection_get (IAnjutaEditorSelection *editor, GError **error)
2854 return text_editor_get_selection (TEXT_EDITOR (editor));
2857 static void
2858 iselection_set (IAnjutaEditorSelection* edit,
2859 IAnjutaIterable* istart,
2860 IAnjutaIterable* iend,
2861 gboolean scroll, /* TODO: Is is possible to set this in scintilla? */
2862 GError** e)
2864 TextEditorCell* start = TEXT_EDITOR_CELL (istart);
2865 TextEditorCell* end = TEXT_EDITOR_CELL (iend);
2866 int start_pos = text_editor_cell_get_position (start);
2867 int end_pos = text_editor_cell_get_position (end);
2869 /* Keep current position at the beginning of the selection like GtkSourceView */
2870 scintilla_send_message (SCINTILLA (TEXT_EDITOR (edit)->scintilla),
2871 SCI_SETSEL, end_pos, start_pos);
2874 static gboolean
2875 iselection_has_selection (IAnjutaEditorSelection *editor, GError **e)
2877 return text_editor_has_selection (TEXT_EDITOR (editor));
2880 static IAnjutaIterable*
2881 iselection_get_start (IAnjutaEditorSelection *edit, GError **e)
2883 gint start = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2884 SCI_GETSELECTIONSTART, 0, 0);
2885 gint end = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2886 SCI_GETSELECTIONEND, 0, 0);
2887 if (start != end)
2889 return IANJUTA_ITERABLE (text_editor_cell_new (TEXT_EDITOR (edit), start));
2891 else
2892 return NULL;
2895 static IAnjutaIterable*
2896 iselection_get_end (IAnjutaEditorSelection *edit, GError **e)
2898 gint start = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2899 SCI_GETSELECTIONSTART, 0, 0);
2900 gint end = scintilla_send_message (SCINTILLA(TEXT_EDITOR(edit)->scintilla),
2901 SCI_GETSELECTIONEND, 0, 0);
2902 if (start != end)
2904 return IANJUTA_ITERABLE (text_editor_cell_new (TEXT_EDITOR (edit), end));
2906 else
2907 return NULL;
2910 static void
2911 iselection_replace (IAnjutaEditorSelection *editor, const gchar *txt,
2912 gint length, GError **e)
2914 gchar *text_to_insert;
2915 if (length >= 0)
2916 text_to_insert = g_strndup (txt, length);
2917 else
2918 text_to_insert = g_strdup (txt);
2920 text_editor_replace_selection (TEXT_EDITOR (editor), text_to_insert);
2922 g_free (text_to_insert);
2925 static void
2926 iselection_select_all (IAnjutaEditorSelection* te, GError** ee)
2928 text_editor_command (TEXT_EDITOR (te), ANE_SELECTALL, 0, 0);
2931 static void
2932 iselection_select_block (IAnjutaEditorSelection *te, GError **e)
2934 text_editor_command (TEXT_EDITOR(te), ANE_SELECTBLOCK, 0, 0);
2937 static void
2938 iselection_select_function (IAnjutaEditorSelection *editor, GError **e)
2940 TextEditor* te = TEXT_EDITOR(editor);
2941 gint pos;
2942 gint line;
2943 gint fold_level;
2944 gint start, end;
2945 gint line_count;
2946 gint tmp;
2948 line_count = scintilla_send_message (SCINTILLA (te->scintilla),
2949 SCI_GETLINECOUNT, 0, 0);
2950 pos = scintilla_send_message (SCINTILLA (te->scintilla),
2951 SCI_GETCURRENTPOS, 0, 0);
2952 line = scintilla_send_message (SCINTILLA (te->scintilla),
2953 SCI_LINEFROMPOSITION, pos, 0);
2955 tmp = line + 1;
2956 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2957 SCI_GETFOLDLEVEL, line, 0) ;
2958 if ((fold_level & 0xFF) != 0)
2960 while ((fold_level & 0x10FF) != 0x1000 && line >= 0)
2961 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2962 SCI_GETFOLDLEVEL, --line, 0) ;
2963 start = scintilla_send_message (SCINTILLA (te->scintilla),
2964 SCI_POSITIONFROMLINE, line + 1, 0);
2965 line = tmp;
2966 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2967 SCI_GETFOLDLEVEL, line, 0) ;
2968 while ((fold_level & 0x10FF) != 0x1000 && line < line_count)
2969 fold_level = scintilla_send_message (SCINTILLA (te->scintilla),
2970 SCI_GETFOLDLEVEL, ++line, 0) ;
2972 end = scintilla_send_message (SCINTILLA (te->scintilla),
2973 SCI_POSITIONFROMLINE, line , 0);
2974 scintilla_send_message (SCINTILLA (te->scintilla),
2975 SCI_SETSEL, start, end) ;
2979 static void
2980 iselection_iface_init (IAnjutaEditorSelectionIface *iface)
2982 iface->has_selection = iselection_has_selection;
2983 iface->get = iselection_get;
2984 iface->set = iselection_set;
2985 iface->get_start = iselection_get_start;
2986 iface->get_end = iselection_get_end;
2987 iface->replace = iselection_replace;
2988 iface->select_all = iselection_select_all;
2989 iface->select_block = iselection_select_block;
2990 iface->select_function = iselection_select_function;
2993 /* IAnjutaFile implementation */
2995 static GFile*
2996 ifile_get_file (IAnjutaFile *editor, GError **error)
2998 TextEditor *text_editor;
2999 text_editor = TEXT_EDITOR(editor);
3000 if (text_editor->uri)
3001 return g_file_new_for_uri (text_editor->uri);
3002 else
3003 return NULL;
3006 static void
3007 ifile_open (IAnjutaFile *editor, GFile* file, GError **error)
3009 /* Close current file and open new file in this editor */
3010 TextEditor* text_editor;
3011 text_editor = TEXT_EDITOR(editor);
3013 /* Remove path */
3014 g_free (text_editor->uri);
3015 text_editor->uri = g_file_get_uri (file);
3016 g_free (text_editor->filename);
3017 text_editor->filename = g_file_get_basename (file);
3018 text_editor_load_file (text_editor);
3021 static void
3022 isaveable_save (IAnjutaFileSavable* editor, GError** e)
3024 TextEditor *text_editor = TEXT_EDITOR(editor);
3026 if (text_editor->uri != NULL)
3027 text_editor_save_file(text_editor, FALSE);
3028 else
3029 g_signal_emit_by_name (G_OBJECT (text_editor), "saved", NULL);
3032 static void
3033 isavable_save_as (IAnjutaFileSavable* editor, GFile* file, GError** e)
3035 const gchar *past_language;
3036 const gchar *curr_language;
3037 TextEditor *text_editor = TEXT_EDITOR(editor);
3039 past_language =
3040 ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (text_editor),
3041 NULL);
3043 /* Remove path */
3044 g_free (text_editor->uri);
3045 text_editor->uri = g_file_get_uri (file);
3046 g_free (text_editor->filename);
3047 text_editor->filename = g_file_get_basename (file);
3048 text_editor_save_file (text_editor, FALSE);
3049 text_editor_set_hilite_type (text_editor, NULL);
3050 text_editor_hilite (text_editor, FALSE);
3052 /* We have to take care of 'language-change' signal ourself because
3053 * text_editor_set_hilite_type() only emits it for forced hilite type
3055 curr_language =
3056 ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (text_editor),
3057 NULL);
3058 if (past_language != curr_language)
3059 g_signal_emit_by_name (text_editor, "language-changed", curr_language);
3063 static gboolean
3064 isavable_is_dirty (IAnjutaFileSavable* editor, GError** e)
3066 TextEditor *text_editor = TEXT_EDITOR(editor);
3067 return !text_editor_is_saved (text_editor);
3070 static void
3071 isavable_set_dirty (IAnjutaFileSavable* editor, gboolean dirty, GError** e)
3073 TextEditor *text_editor = TEXT_EDITOR(editor);
3074 text_editor_set_saved (text_editor, !dirty);
3077 static gboolean
3078 isavable_is_read_only (IAnjutaFileSavable* savable, GError** e)
3080 /* FIXME */
3081 return FALSE;
3084 static gboolean
3085 isavable_is_conflict (IAnjutaFileSavable* savable, GError** e)
3087 TextEditor *te = TEXT_EDITOR(savable);
3088 return te->message_area != NULL;
3091 static void
3092 isavable_iface_init (IAnjutaFileSavableIface *iface)
3094 iface->save = isaveable_save;
3095 iface->save_as = isavable_save_as;
3096 iface->set_dirty = isavable_set_dirty;
3097 iface->is_dirty = isavable_is_dirty;
3098 iface->is_read_only = isavable_is_read_only;
3099 iface->is_conflict = isavable_is_conflict;
3102 static void
3103 ifile_iface_init (IAnjutaFileIface *iface)
3105 iface->open = ifile_open;
3106 iface->get_file = ifile_get_file;
3109 /* Implementation of the IAnjutaMarkable interface */
3111 static gint
3112 marker_ianjuta_to_editor (IAnjutaMarkableMarker marker)
3114 gint mark;
3115 switch (marker)
3117 case IANJUTA_MARKABLE_LINEMARKER:
3118 mark = TEXT_EDITOR_LINEMARKER;
3119 break;
3120 case IANJUTA_MARKABLE_BOOKMARK:
3121 mark = TEXT_EDITOR_BOOKMARK;
3122 break;
3123 case IANJUTA_MARKABLE_BREAKPOINT_DISABLED:
3124 mark = TEXT_EDITOR_BREAKPOINT_DISABLED;
3125 break;
3126 case IANJUTA_MARKABLE_BREAKPOINT_ENABLED:
3127 mark = TEXT_EDITOR_BREAKPOINT_ENABLED;
3128 break;
3129 case IANJUTA_MARKABLE_PROGRAM_COUNTER:
3130 mark = TEXT_EDITOR_PROGRAM_COUNTER;
3131 break;
3132 default:
3133 mark = TEXT_EDITOR_LINEMARKER;
3135 return mark;
3138 static gint
3139 imarkable_mark (IAnjutaMarkable* editor, gint location,
3140 IAnjutaMarkableMarker marker, const gchar *tooltip, GError** e)
3142 return text_editor_set_marker (TEXT_EDITOR (editor), location,
3143 marker_ianjuta_to_editor (marker));
3146 static gint
3147 imarkable_location_from_handle (IAnjutaMarkable* editor, gint handle, GError** e)
3149 return text_editor_line_from_handle (TEXT_EDITOR (editor), handle);
3152 static void
3153 imarkable_unmark (IAnjutaMarkable* editor, gint location,
3154 IAnjutaMarkableMarker marker, GError** e)
3156 text_editor_delete_marker (TEXT_EDITOR (editor), location,
3157 marker_ianjuta_to_editor (marker));
3160 static gboolean
3161 imarkable_is_marker_set (IAnjutaMarkable* editor, gint location,
3162 IAnjutaMarkableMarker marker, GError** e)
3164 return text_editor_is_marker_set (TEXT_EDITOR (editor), location,
3165 marker_ianjuta_to_editor (marker));
3168 static void
3169 imarkable_delete_all_markers (IAnjutaMarkable* editor,
3170 IAnjutaMarkableMarker marker, GError** e)
3172 text_editor_delete_marker_all (TEXT_EDITOR (editor),
3173 marker_ianjuta_to_editor (marker));
3176 static void
3177 imarkable_iface_init (IAnjutaMarkableIface *iface)
3179 iface->mark = imarkable_mark;
3180 iface->location_from_handle = imarkable_location_from_handle;
3181 iface->unmark = imarkable_unmark;
3182 iface->is_marker_set = imarkable_is_marker_set;
3183 iface->delete_all_markers = imarkable_delete_all_markers;
3186 /* IAnjutaEditorConvert implementation */
3188 static void
3189 iconvert_to_upper (IAnjutaEditorConvert* te, IAnjutaIterable *start_position,
3190 IAnjutaIterable *end_position, GError** ee)
3192 gint start, end;
3193 start = text_editor_cell_get_position (TEXT_EDITOR_CELL (start_position));
3194 end = text_editor_cell_get_position (TEXT_EDITOR_CELL (end_position));
3195 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
3196 SCI_SETSEL, start, end);
3197 text_editor_command (TEXT_EDITOR(te), ANE_UPRCASE, 0, 0);
3200 static void
3201 iconvert_to_lower(IAnjutaEditorConvert* te, IAnjutaIterable *start_position,
3202 IAnjutaIterable *end_position, GError** ee)
3204 gint start, end;
3205 start = text_editor_cell_get_position (TEXT_EDITOR_CELL (start_position));
3206 end = text_editor_cell_get_position (TEXT_EDITOR_CELL (end_position));
3207 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
3208 SCI_SETSEL, start, end);
3209 text_editor_command (TEXT_EDITOR (te), ANE_LWRCASE, 0, 0);
3212 static void
3213 iconvert_iface_init (IAnjutaEditorConvertIface *iface)
3215 iface->to_lower = iconvert_to_lower;
3216 iface->to_upper = iconvert_to_upper;
3219 /* IAnjutaEditorLineMode implementation */
3221 static IAnjutaEditorLineModeType
3222 ilinemode_get (IAnjutaEditorLineMode* te, GError** err)
3224 glong eolmode;
3225 IAnjutaEditorLineModeType retmode;
3227 g_return_val_if_fail (IS_TEXT_EDITOR (te), IANJUTA_EDITOR_LINE_MODE_LF);
3229 eolmode = scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
3230 SCI_GETEOLMODE, 0, 0);
3232 switch (eolmode) {
3233 case SC_EOL_CR:
3234 retmode = IANJUTA_EDITOR_LINE_MODE_CR;
3235 break;
3236 case SC_EOL_CRLF:
3237 retmode = IANJUTA_EDITOR_LINE_MODE_CRLF;
3238 break;
3239 case SC_EOL_LF:
3240 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
3241 break;
3242 default:
3243 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
3244 g_warning ("Should not be here");
3246 return retmode;
3249 static void
3250 ilinemode_set (IAnjutaEditorLineMode* te, IAnjutaEditorLineModeType mode,
3251 GError** err)
3253 g_return_if_fail (IS_TEXT_EDITOR (te));
3255 switch (mode)
3257 case IANJUTA_EDITOR_LINE_MODE_LF:
3258 text_editor_command(TEXT_EDITOR(te), ANE_EOL_LF, 0, 0);
3259 break;
3261 case IANJUTA_EDITOR_LINE_MODE_CR:
3262 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CR, 0, 0);
3263 break;
3265 case IANJUTA_EDITOR_LINE_MODE_CRLF:
3266 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CRLF, 0, 0);
3267 break;
3269 default:
3270 g_warning ("Should not reach here");
3271 break;
3275 static void
3276 ilinemode_convert (IAnjutaEditorLineMode *te, IAnjutaEditorLineModeType mode,
3277 GError **err)
3279 switch (mode)
3281 case IANJUTA_EDITOR_LINE_MODE_LF:
3282 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
3283 ANE_EOL_LF, 0);
3284 break;
3286 case IANJUTA_EDITOR_LINE_MODE_CR:
3287 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
3288 ANE_EOL_CR, 0);
3289 break;
3291 case IANJUTA_EDITOR_LINE_MODE_CRLF:
3292 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
3293 ANE_EOL_CRLF, 0);
3294 break;
3296 default:
3297 g_warning ("Should not reach here");
3298 break;
3302 static void
3303 ilinemode_fix (IAnjutaEditorLineMode* te, GError** err)
3305 IAnjutaEditorLineModeType mode = ilinemode_get (te, NULL);
3306 ilinemode_convert (te, mode, NULL);
3309 static void
3310 ilinemode_iface_init (IAnjutaEditorLineModeIface *iface)
3312 iface->set = ilinemode_set;
3313 iface->get = ilinemode_get;
3314 iface->convert = ilinemode_convert;
3315 iface->fix = ilinemode_fix;
3318 static void
3319 itip_show (IAnjutaEditorTip *itip, GList* tips,
3320 IAnjutaIterable *position, GError **err)
3322 GString *calltip;
3323 GList *tip;
3324 gint tips_count;
3325 TextEditor *te = TEXT_EDITOR (itip);
3326 TextEditorCell *cell = TEXT_EDITOR_CELL (position);
3327 gint calltip_pos;
3329 g_return_if_fail (IS_TEXT_EDITOR (te));
3330 g_return_if_fail (tips != NULL);
3331 tips_count = g_list_length (tips);
3332 g_return_if_fail (tips_count > 0);
3334 DEBUG_PRINT ("Number of calltips found %d\n", tips_count);
3336 calltip = g_string_sized_new (256);
3337 tip = tips;
3338 while (tip)
3340 if (calltip->len > 0)
3341 g_string_append_c (calltip, '\n');
3342 g_string_append (calltip, (gchar*) tip->data);
3343 tip = g_list_next (tip);
3346 /* It is not possible to display the calltip above, as the position is defined
3347 * in characters. We cannot be sure that there is enough characters in
3348 * the line above */
3349 calltip_pos = text_editor_cell_get_position (cell);
3351 scintilla_send_message (SCINTILLA (te->scintilla),
3352 SCI_CALLTIPSHOW,
3353 calltip_pos,
3354 (uptr_t) calltip->str);
3355 g_string_free (calltip, TRUE);
3358 static void
3359 itip_cancel (IAnjutaEditorTip *itip, GError **err)
3361 TextEditor *te = TEXT_EDITOR (itip);
3362 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPCANCEL, 0, 0);
3365 static gboolean
3366 itip_visible (IAnjutaEditorTip* itip, GError **err)
3368 TextEditor *te = TEXT_EDITOR (itip);
3369 return scintilla_send_message (SCINTILLA (te->scintilla),
3370 SCI_CALLTIPACTIVE, 0, 0);
3373 static void
3374 itip_iface_init (IAnjutaEditorTipIface *iface)
3376 iface->show = itip_show;
3377 iface->cancel = itip_cancel;
3378 iface->visible = itip_visible;
3381 /* IAnjutaEditorAssist implementation */
3382 static void
3383 iassist_add(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider, GError** err)
3385 TextEditor *te = TEXT_EDITOR (iassist);
3386 te->provider = g_list_prepend (te->provider, provider);
3389 static void
3390 iassist_remove(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider, GError** err)
3392 TextEditor *te = TEXT_EDITOR (iassist);
3393 te->provider = g_list_remove (te->provider, provider);
3396 static void
3397 iassist_invoke(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider, GError** err)
3399 TextEditor *te = TEXT_EDITOR (iassist);
3401 text_editor_suggest_completion (te);
3404 static void
3405 iassist_proposals(IAnjutaEditorAssist* iassist, IAnjutaProvider* provider,
3406 GList* proposals, const gchar *pre_word, gboolean finished, GError** err)
3408 TextEditor *te = TEXT_EDITOR (iassist);
3409 GList *node;
3410 glong length;
3412 /* Hide if the only suggetions is exactly the typed word */
3413 if (pre_word && proposals && g_list_length (proposals) == 1)
3415 IAnjutaEditorAssistProposal* prop = proposals->data;
3416 if (g_str_equal (pre_word, prop->label))
3417 proposals = NULL;
3420 if (proposals == NULL)
3422 te->completion_count = 0;
3423 g_string_truncate (te->completion_string, 0);
3425 scintilla_send_message (SCINTILLA (te->scintilla), SCI_AUTOCCANCEL,
3426 0, 0);
3427 return;
3430 if (te->completion_finished)
3432 te->completion_count = 0;
3433 g_string_truncate (te->completion_string, 0);
3435 te->completion_finished = finished;
3437 for (node = proposals; node != NULL; node = g_list_next (node))
3439 IAnjutaEditorAssistProposal* prop = node->data;
3441 /* Give up if there is too much completion */
3442 if (te->completion_count >= SCINTILLA_MAX_COMPLETION) return;
3443 if (prop->label)
3445 if (te->completion_string->len > 0)
3446 g_string_append_c (te->completion_string, ' ');
3447 g_string_append(te->completion_string, prop->label);
3448 te->completion[te->completion_count].provider = provider;
3449 te->completion[te->completion_count].data = prop->data;
3450 te->completion_count++;
3454 scintilla_send_message (SCINTILLA (te->scintilla),
3455 SCI_AUTOCSETAUTOHIDE, 1, 0);
3456 scintilla_send_message (SCINTILLA (te->scintilla),
3457 SCI_AUTOCSETDROPRESTOFWORD, 1, 0);
3458 scintilla_send_message (SCINTILLA (te->scintilla),
3459 SCI_AUTOCSETCANCELATSTART, 0, 0);
3460 scintilla_send_message (SCINTILLA (te->scintilla),
3461 SCI_AUTOCSETCHOOSESINGLE, 0, 0);
3463 length = text_editor_get_current_position (te);
3464 length -= text_editor_cell_get_position (TEXT_EDITOR_CELL (ianjuta_provider_get_start_iter (provider, NULL)));
3466 scintilla_send_message (SCINTILLA (te->scintilla),
3467 SCI_AUTOCSHOW, length,
3468 (uptr_t) te->completion_string->str);
3471 static void
3472 iassist_iface_init(IAnjutaEditorAssistIface* iface)
3474 iface->add = iassist_add;
3475 iface->remove = iassist_remove;
3476 iface->invoke = iassist_invoke;
3477 iface->proposals = iassist_proposals;
3480 /* IAnutaEditorFolds implementation */
3482 static void
3483 ifolds_open_all(IAnjutaEditorFolds* view, GError **e)
3485 text_editor_command(TEXT_EDITOR(view), ANE_OPEN_FOLDALL, 0, 0);
3488 static void
3489 ifolds_close_all(IAnjutaEditorFolds* view, GError **e)
3491 text_editor_command(TEXT_EDITOR(view), ANE_CLOSE_FOLDALL, 0, 0);
3494 static void
3495 ifolds_toggle_current(IAnjutaEditorFolds* view, GError **e)
3497 text_editor_command(TEXT_EDITOR(view), ANE_TOGGLE_FOLD, 0, 0);
3500 static void
3501 ifolds_iface_init(IAnjutaEditorFoldsIface* iface)
3503 iface->open_all = ifolds_open_all;
3504 iface->close_all = ifolds_close_all;
3505 iface->toggle_current = ifolds_toggle_current;
3508 /* IAnjutaEditorView implementation */
3509 static void
3510 iview_create (IAnjutaEditorView *view, GError **err)
3512 g_return_if_fail (IS_TEXT_EDITOR (view));
3513 text_editor_add_view (TEXT_EDITOR (view));
3516 static void
3517 iview_remove_current (IAnjutaEditorView *view, GError **err)
3519 g_return_if_fail (IS_TEXT_EDITOR (view));
3520 text_editor_remove_view (TEXT_EDITOR (view));
3523 static gint
3524 iview_get_count (IAnjutaEditorView *view, GError **err)
3526 g_return_val_if_fail (IS_TEXT_EDITOR (view), -1);
3527 return g_list_length (TEXT_EDITOR (view)->views);
3530 static void
3531 iview_iface_init (IAnjutaEditorViewIface *iface)
3533 iface->create = iview_create;
3534 iface->remove_current = iview_remove_current;
3535 iface->get_count = iview_get_count;
3538 static void
3539 iindicable_set (IAnjutaIndicable *te, IAnjutaIterable *begin_location,
3540 IAnjutaIterable *end_location,
3541 IAnjutaIndicableIndicator indicator, GError **err)
3543 gint begin = text_editor_cell_get_position (TEXT_EDITOR_CELL (begin_location));
3544 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (end_location));
3545 switch (indicator)
3547 case IANJUTA_INDICABLE_NONE:
3548 text_editor_clear_indicator (TEXT_EDITOR (te), begin, end);
3549 break;
3550 case IANJUTA_INDICABLE_IMPORTANT:
3551 text_editor_set_indicator (TEXT_EDITOR (te), begin, end, 0);
3552 break;
3553 case IANJUTA_INDICABLE_WARNING:
3554 text_editor_set_indicator (TEXT_EDITOR (te), begin, end, 1);
3555 break;
3556 case IANJUTA_INDICABLE_CRITICAL:
3557 text_editor_set_indicator (TEXT_EDITOR (te), begin, end, 2);
3558 break;
3559 default:
3560 g_warning ("Unsupported indicator %d", indicator);
3561 text_editor_clear_indicator (TEXT_EDITOR (te), begin, end);
3562 break;
3566 static void
3567 iindicable_clear (IAnjutaIndicable *te, GError **err)
3569 text_editor_clear_all_indicator (TEXT_EDITOR (te));
3572 static void
3573 iindicable_iface_init (IAnjutaIndicableIface *iface)
3575 iface->set = iindicable_set;
3576 iface->clear = iindicable_clear;
3579 static void
3580 iprint_print(IAnjutaPrint* print, GError** e)
3582 TextEditor* te = TEXT_EDITOR(print);
3583 anjuta_print(FALSE, te->settings, te);
3586 static void
3587 iprint_preview(IAnjutaPrint* print, GError** e)
3589 TextEditor* te = TEXT_EDITOR(print);
3590 anjuta_print(TRUE, te->settings, te);
3593 static void
3594 iprint_iface_init(IAnjutaPrintIface* iface)
3596 iface->print = iprint_print;
3597 iface->print_preview = iprint_preview;
3600 static void
3601 icomment_block(IAnjutaEditorComment* comment, GError** e)
3603 TextEditor* te = TEXT_EDITOR(comment);
3604 aneditor_command (te->editor_id, ANE_BLOCKCOMMENT, 0, 0);
3607 static void
3608 icomment_stream(IAnjutaEditorComment* comment, GError** e)
3610 TextEditor* te = TEXT_EDITOR(comment);
3611 aneditor_command (te->editor_id, ANE_STREAMCOMMENT, 0, 0);
3614 static void
3615 icomment_box(IAnjutaEditorComment* comment, GError** e)
3617 TextEditor* te = TEXT_EDITOR(comment);
3618 aneditor_command (te->editor_id, ANE_BOXCOMMENT, 0, 0);
3621 static void
3622 icomment_iface_init(IAnjutaEditorCommentIface* iface)
3624 iface->block = icomment_block;
3625 iface->box = icomment_box;
3626 iface->stream = icomment_stream;
3629 #define MAX_ZOOM_FACTOR 8
3630 #define MIN_ZOOM_FACTOR -8
3632 static void
3633 izoom_in(IAnjutaEditorZoom* zoom, GError** e)
3635 TextEditor* te = TEXT_EDITOR(zoom);
3636 gint zoom_factor = g_settings_get_int (te->docman_settings,
3637 TEXT_ZOOM_FACTOR) + 1;
3639 if (zoom_factor > MAX_ZOOM_FACTOR)
3640 zoom_factor = MAX_ZOOM_FACTOR;
3641 else if (zoom_factor < MIN_ZOOM_FACTOR)
3642 zoom_factor = MIN_ZOOM_FACTOR;
3644 g_settings_set_int (te->docman_settings, TEXT_ZOOM_FACTOR, zoom_factor);
3647 static void
3648 izoom_out(IAnjutaEditorZoom* zoom, GError** e)
3650 TextEditor* te = TEXT_EDITOR(zoom);
3651 gint zoom_factor = g_settings_get_int (te->docman_settings,
3652 TEXT_ZOOM_FACTOR) - 1;
3654 if (zoom_factor > MAX_ZOOM_FACTOR)
3655 zoom_factor = MAX_ZOOM_FACTOR;
3656 else if (zoom_factor < MIN_ZOOM_FACTOR)
3657 zoom_factor = MIN_ZOOM_FACTOR;
3659 g_settings_set_int (te->docman_settings, TEXT_ZOOM_FACTOR, zoom_factor);
3662 static void
3663 izoom_iface_init(IAnjutaEditorZoomIface* iface)
3665 iface->in = izoom_in;
3666 iface->out = izoom_out;
3669 static void
3670 igoto_start_block(IAnjutaEditorGoto* editor, GError** e)
3672 TextEditor* te = TEXT_EDITOR(editor);
3673 text_editor_goto_block_start(te);
3676 static void
3677 igoto_end_block(IAnjutaEditorGoto* editor, GError** e)
3679 TextEditor* te = TEXT_EDITOR(editor);
3680 text_editor_goto_block_end(te);
3683 static void
3684 igoto_matching_brace(IAnjutaEditorGoto* editor, GError** e)
3686 TextEditor* te = TEXT_EDITOR(editor);
3687 text_editor_command (te, ANE_MATCHBRACE, 0, 0);
3690 static void
3691 igoto_iface_init(IAnjutaEditorGotoIface* iface)
3693 iface->start_block = igoto_start_block;
3694 iface->end_block = igoto_end_block;
3695 iface->matching_brace = igoto_matching_brace;
3698 static const GList*
3699 ilanguage_get_supported_languages (IAnjutaEditorLanguage *ilanguage,
3700 GError **err)
3702 if (supported_languages == NULL)
3704 gchar **strv;
3705 gchar **token;
3706 gchar *menu_entries;
3708 supported_languages_name =
3709 g_hash_table_new_full (g_str_hash, g_str_equal,
3710 NULL, g_free);
3711 supported_languages_ext =
3712 g_hash_table_new_full (g_str_hash, g_str_equal,
3713 NULL, g_free);
3715 supported_languages_by_lexer =
3716 g_hash_table_new_full (g_str_hash, g_str_equal,
3717 g_free, NULL);
3719 menu_entries = sci_prop_get (text_editor_get_props (), "menu.language");
3720 g_return_val_if_fail (menu_entries != NULL, NULL);
3722 strv = g_strsplit (menu_entries, "|", -1);
3723 token = strv;
3724 while (*token)
3726 gchar *lexer;
3727 gchar *possible_file;
3728 gchar *iter;
3729 gchar *name, *extension;
3730 GString *lang;
3732 lang = g_string_new ("");
3734 name = *token++;
3735 if (!name)
3736 break;
3738 extension = *token++;
3739 if (!extension)
3740 break;
3741 token++;
3743 if (name[0] == '#')
3744 continue;
3746 iter = name;
3747 while (*iter)
3749 if (*iter == '&')
3751 *iter = '_';
3753 else
3755 g_string_append_c (lang, g_ascii_tolower (*iter));
3757 iter++;
3760 /* HACK: Convert the weird c++ name to cpp */
3761 if (strcmp (lang->str, "c / c++") == 0)
3763 g_string_assign (lang, "cpp");
3766 /* Updated mapping hash tables */
3767 g_hash_table_insert (supported_languages_name, lang->str,
3768 g_strdup (name));
3769 g_hash_table_insert (supported_languages_ext, lang->str,
3770 g_strconcat ("file.", extension, NULL));
3771 /* Map lexer to language */
3772 possible_file = g_strconcat ("file.", extension, NULL);
3773 lexer = sci_prop_get_new_expand (TEXT_EDITOR (ilanguage)->props_base,
3774 "lexer.", possible_file);
3775 g_free (possible_file);
3776 if (lexer)
3778 /* We only map the first (which is hopefully the true) language */
3779 if (!g_hash_table_lookup (supported_languages_by_lexer, lexer))
3781 /* DEBUG_PRINT ("Mapping (lexer)%s to (language)%s", lexer, lang->str); */
3782 g_hash_table_insert (supported_languages_by_lexer,
3783 lexer, lang->str);
3784 /* lexer is taken in the hash, so no free */
3786 else
3788 g_free (lexer);
3790 lexer = NULL;
3792 supported_languages = g_list_prepend (supported_languages,
3793 lang->str);
3794 g_string_free (lang, FALSE);
3796 g_strfreev (strv);
3798 return supported_languages;
3801 static const gchar*
3802 ilanguage_get_language_name (IAnjutaEditorLanguage *ilanguage,
3803 const gchar *language, GError **err)
3805 if (!supported_languages_name)
3806 ilanguage_get_supported_languages (ilanguage, NULL);
3808 return g_hash_table_lookup (supported_languages_name, language);
3811 static void
3812 ilanguage_set_language (IAnjutaEditorLanguage *ilanguage,
3813 const gchar *language, GError **err)
3815 if (!supported_languages_ext)
3816 ilanguage_get_supported_languages (ilanguage, NULL);
3818 if (language)
3819 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage),
3820 g_hash_table_lookup (supported_languages_ext,
3821 language));
3822 else /* Autodetect */
3823 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage), NULL);
3825 text_editor_hilite (TEXT_EDITOR (ilanguage), FALSE);
3828 static const gchar*
3829 ilanguage_get_language (IAnjutaEditorLanguage *ilanguage, GError **err)
3831 const gchar *language = NULL;
3832 const gchar *filename = NULL;
3833 TextEditor *te = TEXT_EDITOR (ilanguage);
3835 if (te->force_hilite)
3836 filename = te->force_hilite;
3837 else if (te->filename)
3838 filename = te->filename;
3840 if (filename)
3842 gchar *lexer = NULL;
3843 lexer = sci_prop_get_new_expand (te->props_base,
3844 "lexer.", filename);
3846 /* No lexer, no language */
3847 if (lexer)
3849 if (!supported_languages_by_lexer)
3850 ilanguage_get_supported_languages (ilanguage, NULL);
3852 language = g_hash_table_lookup (supported_languages_by_lexer, lexer);
3853 /* DEBUG_PRINT ("Found (language)%s for (lexer)%s", language, lexer); */
3854 g_free (lexer);
3857 return language;
3860 static void
3861 ilanguage_iface_init (IAnjutaEditorLanguageIface *iface)
3863 iface->get_supported_languages = ilanguage_get_supported_languages;
3864 iface->get_language_name = ilanguage_get_language_name;
3865 iface->get_language = ilanguage_get_language;
3866 iface->set_language = ilanguage_set_language;
3869 static gboolean
3870 isearch_forward (IAnjutaEditorSearch* isearch,
3871 const gchar* search,
3872 gboolean case_sensitive,
3873 IAnjutaEditorCell* istart,
3874 IAnjutaEditorCell* iend,
3875 IAnjutaEditorCell** iresult_start,
3876 IAnjutaEditorCell** iresult_end,
3877 GError** e)
3879 TextEditor *te = TEXT_EDITOR (isearch);
3880 gint start = text_editor_cell_get_position (TEXT_EDITOR_CELL (istart));
3881 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (iend));
3883 gint flags = 0;
3884 gint retval;
3886 if (case_sensitive)
3888 flags = SCFIND_MATCHCASE;
3891 struct Sci_TextToFind to_find;
3893 to_find.chrg.cpMin = start;
3894 to_find.chrg.cpMax = end;
3896 to_find.lpstrText = (gchar*) search;
3898 retval = scintilla_send_message (SCINTILLA (te->scintilla),
3899 SCI_FINDTEXT, flags, (long) &to_find);
3900 if (retval == -1)
3901 return FALSE;
3902 else
3904 *iresult_start = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMin));
3905 *iresult_end = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMax));
3906 return TRUE;
3910 static gboolean
3911 isearch_backward (IAnjutaEditorSearch* isearch,
3912 const gchar* search,
3913 gboolean case_sensitive,
3914 IAnjutaEditorCell* istart,
3915 IAnjutaEditorCell* iend,
3916 IAnjutaEditorCell** iresult_start,
3917 IAnjutaEditorCell** iresult_end,
3918 GError** e)
3920 TextEditor *te = TEXT_EDITOR (isearch);
3921 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (iend));
3922 gint start = text_editor_cell_get_position (TEXT_EDITOR_CELL (istart));
3924 gint flags = 0;
3925 gint retval;
3927 if (case_sensitive)
3929 flags = SCFIND_MATCHCASE;
3932 struct Sci_TextToFind to_find;
3934 to_find.chrg.cpMin = start;
3935 to_find.chrg.cpMax = end;
3937 to_find.lpstrText = (gchar*) search;
3939 retval = scintilla_send_message (SCINTILLA (te->scintilla), SCI_FINDTEXT, flags, (long) &to_find);
3940 if (retval == -1)
3941 return FALSE;
3942 else
3944 *iresult_start = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMin));
3945 *iresult_end = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMax));
3946 return TRUE;
3950 static void
3951 isearch_iface_init(IAnjutaEditorSearchIface* iface)
3953 iface->forward = isearch_forward;
3954 iface->backward = isearch_backward;
3957 static void
3958 ihover_display (IAnjutaEditorHover *ihover, IAnjutaIterable *pos,
3959 const gchar *info, GError **e)
3961 TextEditor *te = TEXT_EDITOR (ihover);
3962 gint position = text_editor_cell_get_position (TEXT_EDITOR_CELL (pos));
3963 g_return_if_fail (position >= 0);
3964 g_return_if_fail (info != NULL);
3965 text_editor_show_hover_tip (te, position, info);
3968 static void
3969 ihover_iface_init(IAnjutaEditorHoverIface* iface)
3971 iface->display = ihover_display;
3974 ANJUTA_TYPE_BEGIN(TextEditor, text_editor, GTK_TYPE_VBOX);
3975 ANJUTA_TYPE_ADD_INTERFACE(ifile, IANJUTA_TYPE_FILE);
3976 ANJUTA_TYPE_ADD_INTERFACE(isavable, IANJUTA_TYPE_FILE_SAVABLE);
3977 ANJUTA_TYPE_ADD_INTERFACE(idocument, IANJUTA_TYPE_DOCUMENT);
3978 ANJUTA_TYPE_ADD_INTERFACE(itext_editor, IANJUTA_TYPE_EDITOR);
3979 ANJUTA_TYPE_ADD_INTERFACE(ilinemode, IANJUTA_TYPE_EDITOR_LINE_MODE);
3980 ANJUTA_TYPE_ADD_INTERFACE(iselection, IANJUTA_TYPE_EDITOR_SELECTION);
3981 ANJUTA_TYPE_ADD_INTERFACE(iconvert, IANJUTA_TYPE_EDITOR_CONVERT);
3982 ANJUTA_TYPE_ADD_INTERFACE(iassist, IANJUTA_TYPE_EDITOR_ASSIST);
3983 ANJUTA_TYPE_ADD_INTERFACE(itip, IANJUTA_TYPE_EDITOR_TIP);
3984 ANJUTA_TYPE_ADD_INTERFACE(ilanguage, IANJUTA_TYPE_EDITOR_LANGUAGE);
3985 ANJUTA_TYPE_ADD_INTERFACE(iview, IANJUTA_TYPE_EDITOR_VIEW);
3986 ANJUTA_TYPE_ADD_INTERFACE(ifolds, IANJUTA_TYPE_EDITOR_FOLDS);
3987 ANJUTA_TYPE_ADD_INTERFACE(imarkable, IANJUTA_TYPE_MARKABLE);
3988 ANJUTA_TYPE_ADD_INTERFACE(iindicable, IANJUTA_TYPE_INDICABLE);
3989 ANJUTA_TYPE_ADD_INTERFACE(iprint, IANJUTA_TYPE_PRINT);
3990 ANJUTA_TYPE_ADD_INTERFACE(icomment, IANJUTA_TYPE_EDITOR_COMMENT);
3991 ANJUTA_TYPE_ADD_INTERFACE(izoom, IANJUTA_TYPE_EDITOR_ZOOM);
3992 ANJUTA_TYPE_ADD_INTERFACE(igoto, IANJUTA_TYPE_EDITOR_GOTO);
3993 ANJUTA_TYPE_ADD_INTERFACE(isearch, IANJUTA_TYPE_EDITOR_SEARCH);
3994 ANJUTA_TYPE_ADD_INTERFACE(ihover, IANJUTA_TYPE_EDITOR_HOVER);
3995 ANJUTA_TYPE_END;