701 lines
19 KiB
C
701 lines
19 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <gtksourceview/gtksourceview.h>
|
|
#include <gtksourceview/gtksourcelanguage.h>
|
|
#include <gtksourceview/gtksourcelanguagesmanager.h>
|
|
#include <gtksourceview/gtksourcetag.h>
|
|
|
|
#include "gm-editor-view.h"
|
|
#include "gm-pixbuf.h"
|
|
#include "gm-support.h"
|
|
#include "gm-debug.h"
|
|
#include "gm-string.h"
|
|
#include "gm-options.h"
|
|
#include "gm-color-table.h"
|
|
#include "gm-app.h"
|
|
#include "gm-source-style-scheme.h"
|
|
#include "gm-searchable.h"
|
|
|
|
#ifdef HAVE_PARSER
|
|
#include "parser/gm-parser.h"
|
|
#endif
|
|
|
|
#define GM_EDITOR_VIEW_GET_PRIVATE(object)( \
|
|
G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
|
GM_TYPE_EDITOR_VIEW, GmEditorViewPrivate))
|
|
|
|
struct _GmEditorViewPrivate {
|
|
GmWorld *world;
|
|
GmEditor *editor;
|
|
|
|
#ifdef HAVE_PARSER
|
|
GtkExpander *expander;
|
|
GtkWidget *message_area;
|
|
GtkWidget *error_area;
|
|
GtkWidget *error_label;
|
|
GtkWidget *warning_label;
|
|
GtkWidget *error_frame;
|
|
GtkWidget *warning_frame;
|
|
|
|
gboolean set_style;
|
|
guint timeout_handler;
|
|
guint hide_error_handler;
|
|
gboolean expanding;
|
|
gboolean was_expanded;
|
|
#endif
|
|
|
|
GtkSourceView *source_view;
|
|
};
|
|
|
|
static GtkSourceLanguage *language = NULL;
|
|
|
|
/* Signals */
|
|
|
|
enum {
|
|
MODIFIED_CHANGED,
|
|
NUM_SIGNALS
|
|
};
|
|
|
|
static guint gm_editor_view_signals[NUM_SIGNALS] = {0};
|
|
static void gm_editor_view_searchable_iface_init(
|
|
GmSearchableInterface *iface);
|
|
|
|
static GtkTextView *gm_editor_view_searchable_get_text_view(GmSearchable *sea);
|
|
|
|
void on_gm_editor_view_save_clicked(GtkToolButton *button,
|
|
GmEditorView *view);
|
|
void on_gm_editor_view_saveclose_clicked(GtkToolButton *button,
|
|
GmEditorView *view);
|
|
void on_gm_editor_view_close_clicked(GtkToolButton *button,
|
|
GmEditorView *view);
|
|
void on_gm_editor_view_execute_clicked(GtkToolButton *button,
|
|
GmEditorView *view);
|
|
|
|
void on_gm_editor_view_editor_saved(GmEditor *editor, GmEditorView *view);
|
|
|
|
void on_gm_editor_view_font_changed(GmColorTable *color_table,
|
|
gchar const *desc, GmEditorView *view);
|
|
void on_gm_editor_view_modified_changed(GtkTextBuffer *buffer,
|
|
GmEditorView *view);
|
|
|
|
#ifdef HAVE_PARSER
|
|
void on_gm_editor_view_changed(GtkTextBuffer *buffer,
|
|
GmEditorView *view);
|
|
void on_gm_editor_view_expander(GObject *object, GParamSpec *param_spec,
|
|
GmEditorView *view);
|
|
#endif
|
|
|
|
G_DEFINE_TYPE_EXTENDED(GmEditorView, gm_editor_view, GTK_TYPE_VBOX, 0, \
|
|
G_IMPLEMENT_INTERFACE(GM_TYPE_SEARCHABLE, \
|
|
gm_editor_view_searchable_iface_init))
|
|
|
|
static void
|
|
gm_editor_view_searchable_iface_init(GmSearchableInterface *iface) {
|
|
iface->get_text_view = gm_editor_view_searchable_get_text_view;
|
|
}
|
|
|
|
static GtkTextView *
|
|
gm_editor_view_searchable_get_text_view(GmSearchable *sea) {
|
|
GmEditorView *view = (GmEditorView *)(sea);
|
|
|
|
g_return_val_if_fail(GM_IS_EDITOR_VIEW(sea), NULL);
|
|
|
|
return GTK_TEXT_VIEW(view->priv->source_view);
|
|
}
|
|
|
|
static void
|
|
gm_editor_view_finalize(GObject *object) {
|
|
|
|
#ifdef HAVE_PARSER
|
|
GmEditorView *obj = GM_EDITOR_VIEW(object);
|
|
|
|
if (obj->priv->timeout_handler) {
|
|
g_source_remove(obj->priv->timeout_handler);
|
|
}
|
|
if (obj->priv->hide_error_handler) {
|
|
g_source_remove(obj->priv->hide_error_handler);
|
|
}
|
|
#endif
|
|
|
|
G_OBJECT_CLASS(gm_editor_view_parent_class)->finalize(object);
|
|
}
|
|
|
|
void
|
|
gm_editor_view_init_language() {
|
|
GtkSourceLanguagesManager *manager;
|
|
|
|
if (language == NULL) {
|
|
manager = gtk_source_languages_manager_new();
|
|
language = g_object_ref(gtk_source_languages_manager_get_language_from_mime_type(
|
|
manager, "text/x-moo"));
|
|
|
|
gtk_source_language_set_style_scheme(language,
|
|
gm_source_style_scheme_get_default());
|
|
|
|
g_object_unref(manager);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gm_editor_view_class_init(GmEditorViewClass *klass) {
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
object_class->finalize = gm_editor_view_finalize;
|
|
|
|
gm_editor_view_signals[MODIFIED_CHANGED] =
|
|
g_signal_new("modified_changed",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmEditorViewClass, modified_changed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__BOOLEAN,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_BOOLEAN);
|
|
|
|
gm_editor_view_init_language();
|
|
|
|
g_type_class_add_private(object_class, sizeof(GmEditorViewPrivate));
|
|
}
|
|
|
|
GtkSourceView *
|
|
gm_editor_view_create_source_view(GmEditorView *view) {
|
|
GtkTextBuffer *buffer;
|
|
GtkWidget *source_view;
|
|
GtkTextIter iter;
|
|
gchar *line;
|
|
GList *lines;
|
|
PangoFontDescription *f;
|
|
|
|
GtkSourceTagStyle *st;
|
|
|
|
source_view = gtk_source_view_new();
|
|
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(source_view));
|
|
|
|
if (language) {
|
|
gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buffer), language);
|
|
}
|
|
|
|
gtk_source_buffer_begin_not_undoable_action(GTK_SOURCE_BUFFER(buffer));
|
|
gtk_text_buffer_get_end_iter(buffer, &iter);
|
|
|
|
gm_register_schemed(source_view, gm_app_color_table(gm_app_instance()),
|
|
GM_SCHEMED_COLORS | GM_SCHEMED_FONT);
|
|
|
|
for (lines = gm_editor_lines(view->priv->editor); lines;
|
|
lines = lines->next) {
|
|
line = (gchar *) (lines->data);
|
|
gtk_text_buffer_insert(buffer, &iter, line, -1);
|
|
|
|
if (lines->next) {
|
|
gtk_text_buffer_insert(buffer, &iter, "\r\n", 2);
|
|
}
|
|
}
|
|
|
|
gtk_source_buffer_end_not_undoable_action(GTK_SOURCE_BUFFER(buffer));
|
|
gtk_text_buffer_set_modified(buffer, FALSE);
|
|
|
|
st = gtk_source_tag_style_new();
|
|
st->mask = GTK_SOURCE_TAG_STYLE_USE_BACKGROUND;
|
|
gdk_color_parse("#0000FF", &(st->background));
|
|
gtk_source_buffer_set_bracket_match_style(GTK_SOURCE_BUFFER(buffer), st);
|
|
|
|
f = pango_font_description_from_string(gm_color_table_font_description(
|
|
gm_app_color_table(gm_app_instance())));
|
|
|
|
if (f) {
|
|
gtk_widget_modify_font(source_view, f);
|
|
pango_font_description_free(f);
|
|
}
|
|
|
|
gtk_source_view_set_insert_spaces_instead_of_tabs(GTK_SOURCE_VIEW(
|
|
source_view), TRUE);
|
|
gtk_source_view_set_auto_indent(GTK_SOURCE_VIEW(source_view), TRUE);
|
|
gtk_source_view_set_show_line_numbers(GTK_SOURCE_VIEW(source_view), TRUE);
|
|
gtk_source_view_set_tabs_width(GTK_SOURCE_VIEW(source_view), 2);
|
|
|
|
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(source_view), GTK_WRAP_WORD_CHAR);
|
|
//gtk_text_view_set_left_margin(GTK_TEXT_VIEW(source_view), 6);
|
|
//gtk_text_view_set_right_margin(GTK_TEXT_VIEW(source_view), 6);
|
|
|
|
if (gm_editor_is_code(view->priv->editor)) {
|
|
gtk_source_buffer_set_highlight(GTK_SOURCE_BUFFER(buffer), TRUE);
|
|
|
|
#ifdef HAVE_PARSER
|
|
g_signal_connect(buffer, "changed",
|
|
G_CALLBACK(on_gm_editor_view_changed), view);
|
|
#endif
|
|
} else {
|
|
gtk_source_buffer_set_highlight(GTK_SOURCE_BUFFER(buffer), FALSE);
|
|
gtk_source_buffer_set_check_brackets(GTK_SOURCE_BUFFER(buffer), FALSE);
|
|
}
|
|
|
|
#ifdef HAVE_PARSER
|
|
gtk_text_buffer_create_tag(buffer, "gm_error", "underline",
|
|
PANGO_UNDERLINE_ERROR, NULL);
|
|
#endif
|
|
|
|
g_signal_connect(buffer, "modified_changed",
|
|
G_CALLBACK(on_gm_editor_view_modified_changed), view);
|
|
|
|
gtk_widget_show(source_view);
|
|
|
|
return GTK_SOURCE_VIEW(source_view);
|
|
}
|
|
|
|
#ifdef HAVE_PARSER
|
|
static gboolean
|
|
gm_editor_view_paint_message_area(GtkWidget *widget, GdkEventExpose *event,
|
|
GmEditorView *view) {
|
|
gtk_paint_flat_box(widget->style, widget->window, GTK_STATE_NORMAL,
|
|
GTK_SHADOW_OUT, NULL, widget, "tooltip",
|
|
widget->allocation.x + 1, widget->allocation.y + 1,
|
|
widget->allocation.width - 2, widget->allocation.height - 2);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gm_editor_view_message_area_style_set(GtkWidget *widget, GtkStyle *prev,
|
|
GmEditorView *view) {
|
|
GtkTooltips *tooltips;
|
|
GtkStyle *style;
|
|
|
|
if (view->priv->set_style) {
|
|
return;
|
|
}
|
|
|
|
widget = view->priv->message_area;
|
|
|
|
tooltips = gtk_tooltips_new();
|
|
g_object_ref(G_OBJECT(tooltips));
|
|
gtk_object_sink(GTK_OBJECT(tooltips));
|
|
|
|
gtk_tooltips_force_window(tooltips);
|
|
gtk_widget_ensure_style(tooltips->tip_window);
|
|
style = gtk_widget_get_style(tooltips->tip_window);
|
|
|
|
style->bg[GTK_STATE_PRELIGHT] = style->bg[GTK_STATE_NORMAL];
|
|
|
|
view->priv->set_style = TRUE;
|
|
gtk_widget_set_style(widget, style);
|
|
gtk_widget_set_style(GTK_WIDGET(view->priv->expander), style);
|
|
view->priv->set_style = FALSE;
|
|
g_object_unref(tooltips);
|
|
}
|
|
|
|
static void
|
|
gm_editor_view_create_message_area(GmEditorView *view) {
|
|
GtkWidget *message_area = gtk_vbox_new(FALSE, 0);
|
|
GtkWidget *align;
|
|
GtkWidget *lbl;
|
|
GtkWidget *expander;
|
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(message_area), 10);
|
|
|
|
g_signal_connect(message_area, "expose_event",
|
|
G_CALLBACK(gm_editor_view_paint_message_area), view);
|
|
g_signal_connect(message_area, "style-set",
|
|
G_CALLBACK(gm_editor_view_message_area_style_set), view);
|
|
|
|
view->priv->message_area = message_area;
|
|
|
|
align = gtk_alignment_new(0.0, 1.0, 0.0, 0.0);
|
|
expander = gtk_expander_new(NULL);
|
|
g_signal_connect(expander, "notify::expanded",
|
|
G_CALLBACK(on_gm_editor_view_expander), view);
|
|
gtk_container_add(GTK_CONTAINER(align), expander);
|
|
gtk_box_pack_start(GTK_BOX(message_area), align, FALSE, FALSE, 0);
|
|
view->priv->expander = GTK_EXPANDER(expander);
|
|
|
|
g_signal_connect(expander, "style-set",
|
|
G_CALLBACK(gm_editor_view_message_area_style_set), view);
|
|
|
|
gtk_widget_show(expander);
|
|
gtk_widget_show(align);
|
|
|
|
view->priv->error_area = gtk_vbox_new(FALSE, 0);
|
|
gtk_box_pack_start(GTK_BOX(message_area), view->priv->error_area, TRUE,
|
|
TRUE, 0);
|
|
|
|
lbl = gtk_label_new(NULL);
|
|
gtk_label_set_markup(GTK_LABEL(lbl), _("<b>Errors</b>"));
|
|
view->priv->error_frame = gtk_frame_new(NULL);
|
|
gtk_frame_set_shadow_type(GTK_FRAME(view->priv->error_frame),
|
|
GTK_SHADOW_NONE);
|
|
gtk_frame_set_label_widget(GTK_FRAME(view->priv->error_frame), lbl);
|
|
|
|
view->priv->error_label = gtk_label_new(NULL);
|
|
|
|
gtk_misc_set_alignment(GTK_MISC(view->priv->error_label), 0.0, 0.0);
|
|
align = gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
|
|
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(align), view->priv->error_label);
|
|
gtk_container_add(GTK_CONTAINER(view->priv->error_frame), align);
|
|
gtk_box_pack_start(GTK_BOX(view->priv->error_area),
|
|
view->priv->error_frame, TRUE, TRUE, 0);
|
|
|
|
lbl = gtk_label_new(NULL);
|
|
gtk_label_set_markup(GTK_LABEL(lbl), _("<b>Warnings</b>"));
|
|
view->priv->warning_frame = gtk_frame_new(NULL);
|
|
gtk_frame_set_shadow_type(GTK_FRAME(view->priv->warning_frame),
|
|
GTK_SHADOW_NONE);
|
|
gtk_frame_set_label_widget(GTK_FRAME(view->priv->warning_frame), lbl);
|
|
view->priv->warning_label = gtk_label_new(NULL);
|
|
|
|
gtk_misc_set_alignment(GTK_MISC(view->priv->warning_label), 0.0, 0.0);
|
|
align = gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
|
|
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(align), view->priv->warning_label);
|
|
gtk_container_add(GTK_CONTAINER(view->priv->warning_frame), align);
|
|
gtk_box_pack_start(GTK_BOX(view->priv->error_area),
|
|
view->priv->warning_frame, TRUE, TRUE, 0);
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
gm_editor_view_init(GmEditorView *obj) {
|
|
obj->priv = GM_EDITOR_VIEW_GET_PRIVATE(obj);
|
|
|
|
gtk_box_set_spacing(GTK_BOX(obj), 0);
|
|
gtk_box_set_homogeneous(GTK_BOX(obj), FALSE);
|
|
|
|
#ifdef HAVE_PARSER
|
|
gm_editor_view_create_message_area(obj);
|
|
gtk_box_pack_start(GTK_BOX(obj), obj->priv->message_area, FALSE, FALSE, 0);
|
|
#endif
|
|
}
|
|
|
|
GmEditorView *
|
|
gm_editor_view_new(GmWorld *world, GmEditor *editor) {
|
|
GmEditorView *obj = GM_EDITOR_VIEW(g_object_new(GM_TYPE_EDITOR_VIEW, NULL));
|
|
GtkWidget *srl;
|
|
|
|
obj->priv->editor = editor;
|
|
obj->priv->world = world;
|
|
obj->priv->source_view = gm_editor_view_create_source_view(obj);
|
|
|
|
srl = gtk_scrolled_window_new(NULL, NULL);
|
|
gtk_widget_show(srl);
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(srl),
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
|
|
gtk_container_add(GTK_CONTAINER(srl), GTK_WIDGET(obj->priv->source_view));
|
|
gtk_box_pack_end(GTK_BOX(obj), srl, TRUE, TRUE, 0);
|
|
|
|
g_signal_connect(gm_app_color_table(gm_app_instance()), "font_changed",
|
|
G_CALLBACK(on_gm_editor_view_font_changed), obj);
|
|
g_signal_connect(editor, "saved",
|
|
G_CALLBACK(on_gm_editor_view_editor_saved), obj);
|
|
return obj;
|
|
}
|
|
|
|
GmEditor *
|
|
gm_editor_view_editor(GmEditorView *view) {
|
|
return view->priv->editor;
|
|
}
|
|
|
|
GtkTextView *
|
|
gm_editor_view_text_view(GmEditorView *view) {
|
|
return GTK_TEXT_VIEW(view->priv->source_view);
|
|
}
|
|
|
|
void
|
|
gm_editor_view_save(GmEditorView *view) {
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(
|
|
view->priv->source_view));
|
|
GtkTextIter start, end;
|
|
gchar *text;
|
|
|
|
gtk_text_buffer_get_bounds(buffer, &start, &end);
|
|
text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
|
|
gm_editor_set_lines_from_string(view->priv->editor, text);
|
|
|
|
g_free(text);
|
|
gm_editor_save(view->priv->editor);
|
|
}
|
|
|
|
#ifdef HAVE_PARSER
|
|
gboolean
|
|
gm_editor_view_no_errors(GmEditorView *view) {
|
|
gtk_widget_hide(view->priv->message_area);
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gm_editor_view_parse_error(GmEditorView *view, GmParserError *error,
|
|
GString **str) {
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(
|
|
view->priv->source_view));
|
|
GtkTextIter start, end;
|
|
gchar *msg;
|
|
|
|
if (error->ch == 0) {
|
|
gtk_text_buffer_get_iter_at_line(buffer, &start,
|
|
error->line - 1);
|
|
msg = g_markup_printf_escaped(_("<u>Line %d</u>: %s\n"), error->line,
|
|
error->message);
|
|
} else {
|
|
// Underline line
|
|
gtk_text_buffer_get_iter_at_line(buffer, &start, error->line);
|
|
msg = g_markup_printf_escaped(_("<u>Line %d:%d</u>: %s\n"),
|
|
error->line + 1, error->ch + 1, error->message);
|
|
}
|
|
|
|
if (!*str) {
|
|
*str = g_string_new(msg);
|
|
} else {
|
|
*str = g_string_append(*str, msg);
|
|
}
|
|
|
|
g_free(msg);
|
|
end = start;
|
|
|
|
if (error->ch != 0) {
|
|
gtk_text_iter_forward_chars(&start, error->ch - 1);
|
|
}
|
|
|
|
gtk_text_iter_forward_to_line_end(&end);
|
|
gtk_text_buffer_apply_tag_by_name(buffer, "gm_error", &start, &end);
|
|
}
|
|
|
|
enum {
|
|
SYNTAX_OK = 0,
|
|
SYNTAX_ERRORS = 1 << 0,
|
|
SYNTAX_WARNINGS = 1 << 1
|
|
};
|
|
|
|
int
|
|
gm_editor_view_parse(GmEditorView *view) {
|
|
gchar *text;
|
|
GtkTextIter start, end;
|
|
GList *lines;
|
|
GmParserResult *result;
|
|
GList *errors;
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(
|
|
view->priv->source_view));
|
|
gchar *msg;
|
|
GString *str = NULL, *lbl = NULL;
|
|
int ret = SYNTAX_OK;
|
|
|
|
if (view->priv->hide_error_handler) {
|
|
g_source_remove(view->priv->hide_error_handler);
|
|
}
|
|
|
|
gtk_text_buffer_get_bounds(buffer, &start, &end);
|
|
text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE);
|
|
lines = gm_string_split(text);
|
|
|
|
result = gm_parser_parse(lines);
|
|
|
|
gtk_text_buffer_remove_tag_by_name(buffer, "gm_error", &start, &end);
|
|
|
|
if (!result->isOk) {
|
|
if (result->errors) {
|
|
for (errors = result->errors; errors; errors = errors->next) {
|
|
gm_editor_view_parse_error(view, (GmParserError *)(errors->data),
|
|
&str);
|
|
}
|
|
|
|
str = g_string_truncate(str, str->len - 1);
|
|
gtk_label_set_markup(GTK_LABEL(view->priv->error_label), str->str);
|
|
gtk_widget_show_all(view->priv->error_frame);
|
|
g_string_free(str, TRUE);
|
|
str = NULL;
|
|
|
|
if (g_list_length(result->errors) == 1) {
|
|
msg = g_strdup(_("There is 1 error"));
|
|
} else {
|
|
msg = g_strdup_printf(_("There are %d errors"),
|
|
g_list_length(result->errors));
|
|
}
|
|
|
|
lbl = g_string_new(msg);
|
|
g_free(msg);
|
|
|
|
ret |= SYNTAX_ERRORS;
|
|
} else {
|
|
gtk_widget_hide(view->priv->error_frame);
|
|
}
|
|
if (result->warnings) {
|
|
for (errors = result->warnings; errors; errors = errors->next) {
|
|
gm_editor_view_parse_error(view, (GmParserError *)(errors->data),
|
|
&str);
|
|
}
|
|
|
|
str = g_string_truncate(str, str->len - 1);
|
|
gtk_label_set_markup(GTK_LABEL(view->priv->warning_label),
|
|
str->str);
|
|
gtk_widget_show_all(view->priv->warning_frame);
|
|
g_string_free(str, TRUE);
|
|
|
|
if (g_list_length(result->warnings) == 1) {
|
|
if (!lbl) {
|
|
msg = g_strdup(_("There is 1 warning"));
|
|
} else {
|
|
msg = g_strdup_printf(_(" and 1 warning"));
|
|
}
|
|
} else {
|
|
if (!lbl) {
|
|
msg = g_strdup_printf(_("There are %d warnings"),
|
|
g_list_length(result->warnings));
|
|
} else {
|
|
msg = g_strdup_printf(_(" and %d warnings"),
|
|
g_list_length(result->warnings));
|
|
}
|
|
}
|
|
|
|
if (!lbl) {
|
|
lbl = g_string_new(msg);
|
|
} else {
|
|
lbl = g_string_append(lbl, msg);
|
|
}
|
|
|
|
g_free(msg);
|
|
|
|
ret |= SYNTAX_WARNINGS;
|
|
} else {
|
|
gtk_widget_hide(view->priv->warning_frame);
|
|
}
|
|
|
|
gtk_widget_set_sensitive(GTK_WIDGET(view->priv->expander), TRUE);
|
|
gtk_expander_set_label(view->priv->expander, lbl->str);
|
|
g_string_free(lbl, TRUE);
|
|
gtk_widget_show(view->priv->message_area);
|
|
|
|
if (view->priv->was_expanded &&
|
|
!gtk_expander_get_expanded(view->priv->expander)) {
|
|
view->priv->expanding = TRUE;
|
|
gtk_expander_set_expanded(view->priv->expander, TRUE);
|
|
view->priv->expanding = FALSE;
|
|
}
|
|
|
|
gtk_widget_queue_draw(view->priv->message_area);
|
|
} else {
|
|
gtk_expander_set_label(view->priv->expander, _("There are no errors"));
|
|
|
|
view->priv->expanding = TRUE;
|
|
gtk_expander_set_expanded(view->priv->expander, FALSE);
|
|
view->priv->expanding = FALSE;
|
|
|
|
gtk_widget_set_sensitive(GTK_WIDGET(view->priv->expander), FALSE);
|
|
gtk_widget_hide(view->priv->error_area);
|
|
|
|
view->priv->hide_error_handler = g_timeout_add(3000,
|
|
(GSourceFunc)gm_editor_view_no_errors, view);
|
|
gtk_widget_queue_draw(view->priv->message_area);
|
|
}
|
|
|
|
gm_parser_result_free(result);
|
|
gm_g_list_free_simple(lines);
|
|
g_free(text);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static gboolean
|
|
idle_grab_focus(gpointer user_data) {
|
|
g_message("Grabbing focus");
|
|
gtk_widget_grab_focus(GTK_WIDGET(user_data));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gm_editor_view_check_syntax(GmEditorView *view) {
|
|
int ret = gm_editor_view_parse(view);
|
|
|
|
if (ret == SYNTAX_OK) {
|
|
gtk_expander_set_expanded(view->priv->expander, FALSE);
|
|
gtk_widget_hide(view->priv->message_area);
|
|
gm_info_dialog(_("No errors are found"),
|
|
GTK_WINDOW(gm_find_parent(GTK_WIDGET(view), GTK_TYPE_WINDOW)));
|
|
|
|
g_timeout_add(100, idle_grab_focus, view->priv->source_view);
|
|
} else {
|
|
gtk_expander_set_expanded(view->priv->expander, TRUE);
|
|
gtk_widget_show(view->priv->message_area);
|
|
gtk_widget_show(view->priv->error_area);
|
|
gtk_widget_queue_draw(view->priv->message_area);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Callbacks */
|
|
|
|
void
|
|
on_gm_editor_view_font_changed(GmColorTable *color_table, gchar const *desc,
|
|
GmEditorView *view) {
|
|
PangoFontDescription *f;
|
|
|
|
f = pango_font_description_from_string(gm_color_table_font_description(
|
|
gm_app_color_table(gm_app_instance())));
|
|
|
|
if (f) {
|
|
gtk_widget_modify_font(GTK_WIDGET(view->priv->source_view), f);
|
|
pango_font_description_free(f);
|
|
}
|
|
}
|
|
|
|
void
|
|
on_gm_editor_view_editor_saved(GmEditor *editor, GmEditorView *view) {
|
|
gtk_text_buffer_set_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(
|
|
view->priv->source_view)), FALSE);
|
|
}
|
|
|
|
void
|
|
on_gm_editor_view_modified_changed(GtkTextBuffer *buffer,
|
|
GmEditorView *view) {
|
|
g_signal_emit(view, gm_editor_view_signals[MODIFIED_CHANGED], 0,
|
|
gtk_text_buffer_get_modified(buffer));
|
|
}
|
|
|
|
#ifdef HAVE_PARSER
|
|
gboolean
|
|
gm_editor_view_timeout(GmEditorView *view) {
|
|
gm_editor_view_parse(view);
|
|
view->priv->timeout_handler = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
on_gm_editor_view_changed(GtkTextBuffer *buffer,
|
|
GmEditorView *view) {
|
|
if (view->priv->timeout_handler != 0) {
|
|
g_source_remove(view->priv->timeout_handler);
|
|
}
|
|
|
|
if (gm_options_get_int(gm_app_options(gm_app_instance()),
|
|
"auto_check_syntax")) {
|
|
view->priv->timeout_handler = g_timeout_add(1000,
|
|
(GSourceFunc)gm_editor_view_timeout, view);
|
|
}
|
|
}
|
|
|
|
void
|
|
on_gm_editor_view_expander(GObject *object, GParamSpec *param_spec,
|
|
GmEditorView *view) {
|
|
if (gtk_expander_get_expanded(view->priv->expander)) {
|
|
if (!view->priv->expanding) {
|
|
view->priv->was_expanded = TRUE;
|
|
}
|
|
|
|
gtk_widget_show(view->priv->error_area);
|
|
} else {
|
|
if (!view->priv->expanding) {
|
|
view->priv->was_expanded = FALSE;
|
|
}
|
|
|
|
gtk_widget_hide(view->priv->error_area);
|
|
}
|
|
|
|
gtk_widget_queue_draw(view->priv->message_area);
|
|
}
|
|
#endif
|