gtksourceview r2190 - in branches/indenters: . gtksourceview tests
- From: icq svn gnome org
- To: svn-commits-list gnome org
- Subject: gtksourceview r2190 - in branches/indenters: . gtksourceview tests
- Date: Sat, 28 Feb 2009 17:01:13 +0000 (UTC)
Author: icq
Date: Sat Feb 28 17:01:13 2009
New Revision: 2190
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=2190&view=rev
Log:
2009-02-28 Ignacio Casal Quinteiro <nacho resa gmail com>
* gtksourceview/gtksourcelanguage.c:
* gtksourceview/gtksourcelanguage.h:
* gtksourceview/c-indenter.c:
* gtksourceview/gtksourceindentermanager.c:
* gtksourceview/c-indenter.h:
* gtksourceview/gtksourceindenter-utils.c:
* gtksourceview/simple-indenter.c:
* gtksourceview/gtksourceview-utils.c:
* gtksourceview/gtksourceindentermanager.h:
* gtksourceview/gtksourceindenter.c:
* gtksourceview/gtksourceview.c:
* gtksourceview/gtksourceindenter-utils.h:
* gtksourceview/gtksourceview-utils.h:
* gtksourceview/simple-indenter.h:
* gtksourceview/gtksourceindenter.h:
* gtksourceview/gtksourceview.h:
* gtksourceview/Makefile.am:
* tests/test-widget.c:
Added initial framework files.
Added a simple indenter that makes the same functionaly
that gsv had before, and added the c-indenter that tries
to be an smart indenter for c files.
Added:
branches/indenters/gtksourceview/c-indenter.c (contents, props changed)
branches/indenters/gtksourceview/c-indenter.h (contents, props changed)
branches/indenters/gtksourceview/gtksourceindenter-utils.c (contents, props changed)
branches/indenters/gtksourceview/gtksourceindenter-utils.h (contents, props changed)
branches/indenters/gtksourceview/gtksourceindenter.c (contents, props changed)
branches/indenters/gtksourceview/gtksourceindenter.h (contents, props changed)
branches/indenters/gtksourceview/gtksourceindentermanager.c (contents, props changed)
branches/indenters/gtksourceview/gtksourceindentermanager.h (contents, props changed)
branches/indenters/gtksourceview/simple-indenter.c (contents, props changed)
branches/indenters/gtksourceview/simple-indenter.h (contents, props changed)
Modified:
branches/indenters/ChangeLog
branches/indenters/gtksourceview/Makefile.am
branches/indenters/gtksourceview/gtksourcelanguage.c
branches/indenters/gtksourceview/gtksourcelanguage.h
branches/indenters/gtksourceview/gtksourceview-utils.c
branches/indenters/gtksourceview/gtksourceview-utils.h
branches/indenters/gtksourceview/gtksourceview.c
branches/indenters/gtksourceview/gtksourceview.h
branches/indenters/tests/test-widget.c
Modified: branches/indenters/gtksourceview/Makefile.am
==============================================================================
--- branches/indenters/gtksourceview/Makefile.am (original)
+++ branches/indenters/gtksourceview/Makefile.am Sat Feb 28 17:01:13 2009
@@ -27,7 +27,8 @@
gtksourcestyleschememanager.h \
gtksourcestylescheme.h \
gtksourcemark.h \
- gtksourceprintcompositor.h
+ gtksourceprintcompositor.h \
+ gtksourceindenter.h
libgtksourceview_2_0_la_SOURCES = \
gtksourcebuffer.c \
@@ -56,6 +57,15 @@
gtksourcecontextengine.c \
gtksourcemark.c \
gtksourceprintcompositor.c \
+ gtksourceindenter.c \
+ gtksourceindentermanager.c \
+ gtksourceindentermanager.h \
+ c-indenter.c \
+ c-indenter.h \
+ simple-indenter.c \
+ simple-indenter.h \
+ gtksourceindenter-utils.c \
+ gtksourceindenter-utils.h \
$(libgtksourceview_headers)
# do not distribute generated files
Added: branches/indenters/gtksourceview/c-indenter.c
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/c-indenter.c Sat Feb 28 17:01:13 2009
@@ -0,0 +1,371 @@
+/*
+ * c-indenter.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "c-indenter.h"
+#include "gtksourceindenter.h"
+#include "gtksourceview.h"
+#include "gtksourceindenter-utils.h"
+
+#define C_INDENTER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object),\
+ C_TYPE_INDENTER, CIndenterPrivate))
+
+struct _CIndenterPrivate
+{
+};
+
+G_DEFINE_TYPE (CIndenter, c_indenter, GTK_TYPE_SOURCE_INDENTER)
+
+static const gchar * regexes[] =
+{
+ "^\\s*(if|while|else if|for|switch)\\s*\\(.*\\)\\s*$",
+ "^\\s*(else|do)\\s*$",
+ NULL
+};
+
+static gboolean
+match_regexes (GtkTextIter *iter)
+{
+ gint i = 0;
+ gboolean match = FALSE;
+ gchar *string;
+ GtkTextIter start;
+
+ start = *iter;
+
+ gtk_source_indenter_find_open_char (&start, '(', ')', FALSE);
+
+ gtk_text_iter_set_line_offset (&start, 0);
+ gtk_text_iter_forward_char (iter);
+
+ string = gtk_text_iter_get_text (&start, iter);
+ gtk_text_iter_backward_char (iter);
+ g_warning (string);
+
+ while (regexes[i] != NULL)
+ {
+ GRegex *regex;
+ GMatchInfo *match_info;
+
+ regex = g_regex_new (regexes[i], G_REGEX_DOTALL, 0, NULL);
+ g_regex_match (regex, string, 0, &match_info);
+
+ if (g_match_info_matches (match_info))
+ match = TRUE;
+
+ g_match_info_free (match_info);
+ g_regex_unref (regex);
+
+ if (match)
+ {
+ break;
+ }
+ i++;
+ }
+
+ g_free (string);
+
+ return match;
+}
+
+static gboolean
+is_caselabel (const gchar *label)
+{
+ const gchar *case_label = "case";
+ gchar *p;
+ gunichar c;
+ gint i = 0;
+ gboolean is_case = TRUE;
+
+ p = (gchar *)label;
+ c = g_utf8_get_char (p);
+
+ while (case_label[i] != '\0')
+ {
+ g_warning ("%c|%c", c, case_label[i]);
+
+ if (case_label[i] != c)
+ {
+ is_case = FALSE;
+ break;
+ }
+
+ p = g_utf8_next_char (p);
+ c = g_utf8_get_char (p);
+ i++;
+ }
+
+ return is_case;
+}
+
+static gfloat
+c_indenter_get_indentation_level (GtkSourceIndenter *indenter,
+ GtkTextView *view,
+ GtkTextIter *cur,
+ gboolean relocating)
+{
+ /*
+ * The idea of this algorithm is just move the iter to the right position
+ * and manage the iter to get a context to get the right amount of indents
+ */
+ GtkTextIter iter;
+ gunichar c;
+ gfloat amount = 0.;
+
+ iter = *cur;
+
+ if (!gtk_source_indenter_move_to_no_space (&iter, -1))
+ return 0.;
+
+ /*
+ * Check for comments
+ */
+ if (!gtk_source_indenter_move_to_no_comments (&iter))
+ return 0.;
+
+ c = gtk_text_iter_get_char (&iter);
+ g_warning ("char %c", c);
+
+ if (c == '*')
+ {
+ gunichar ch;
+
+ /*
+ * We are in a comment
+ */
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+
+ /* We are in the case "/ *" so we have to add an space */
+ gtk_text_iter_backward_char (&iter);
+ ch = gtk_text_iter_get_char (&iter);
+
+ if (ch == '/')
+ {
+ amount = gtk_source_indenter_add_space (view, amount);
+ }
+ }
+ else if (c == ';')
+ {
+ gfloat current_indent;
+
+ current_indent = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+
+ /*
+ * We have to check that we are not in something like:
+ * hello (eoeo,
+ * eoeo);
+ */
+ gtk_text_iter_backward_char (&iter);
+ c = gtk_text_iter_get_char (&iter);
+ if (c == ')' && gtk_source_indenter_find_open_char (&iter, '(', ')', FALSE))
+ {
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+ }
+ else
+ {
+ /*
+ * We have to check if we are in just one line block
+ */
+ while (!gtk_text_iter_ends_line (&iter) &&
+ gtk_text_iter_backward_char (&iter))
+ continue;
+
+ gtk_text_iter_backward_char (&iter);
+
+ if (match_regexes (&iter))
+ {
+ gtk_source_indenter_find_open_char (&iter, '(', ')', FALSE);
+
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+ }
+ else
+ {
+ amount = current_indent;
+ }
+ }
+ }
+ else if (c == '}')
+ {
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+
+ /*
+ * We need to look backward for {.
+ * FIXME: We need to set a number of lines to look backward.
+ */
+ if (relocating && gtk_source_indenter_find_open_char (&iter, '{', '}', FALSE))
+ {
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+ }
+ }
+ else if (c == '{')
+ {
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+
+ /*
+ * Check that the previous line match regexes
+ */
+ while (gtk_text_iter_backward_char (&iter) &&
+ !gtk_text_iter_ends_line (&iter))
+ continue;
+
+ gtk_text_iter_backward_char (&iter);
+
+ if (relocating)
+ {
+ if (match_regexes (&iter))
+ {
+ gtk_source_indenter_find_open_char (&iter, '(', ')', FALSE);
+
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+ }
+ }
+ else
+ {
+ amount++;
+ }
+ }
+ else if (c == ',' || c == '&' || c == '|')
+ {
+ GtkTextIter s;
+
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+
+ s = iter;
+ if (gtk_source_indenter_find_open_char (&s, '(', ')', TRUE))
+ {
+ amount = gtk_source_indenter_get_amount_indents_from_position (view, &s);
+ amount = gtk_source_indenter_add_space (view, amount);
+ }
+ }
+ else if (c == ')' && relocating)
+ {
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter);
+
+ if (gtk_source_indenter_find_open_char (&iter, '(', ')', FALSE))
+ {
+ amount = gtk_source_indenter_get_amount_indents_from_position (view, &iter);
+ }
+ }
+ else if (c == ':')
+ {
+ if (relocating)
+ {
+ GtkTextIter start;
+ gchar *label;
+
+ start = iter;
+ gtk_text_iter_set_line_offset (&start, 0);
+ gtk_source_indenter_move_to_no_space (&start, 1);
+
+ label = gtk_text_iter_get_text (&start, &iter);
+
+ if (!is_caselabel (label))
+ {
+ amount = 0.;
+ }
+ else
+ {
+ amount = gtk_source_indenter_get_amount_indents (view, &iter);
+ }
+
+ g_free (label);
+ }
+ else
+ {
+ amount = 1.;
+ }
+ }
+ else if (c == '=')
+ {
+ amount = gtk_source_indenter_get_amount_indents (view, &iter) + 1;
+ }
+ else if (match_regexes (&iter))
+ {
+ gtk_source_indenter_find_open_char (&iter, '(', ')', FALSE);
+
+ amount = gtk_source_indenter_get_amount_indents (view,
+ &iter) + 1;
+ }
+ else
+ {
+ GtkTextIter copy;
+ gunichar ch;
+
+ amount = gtk_source_indenter_get_amount_indents (view, &iter);
+
+ /*
+ * Now we have to check for the start of the line
+ */
+ copy = iter;
+
+ gtk_source_indenter_move_to_no_space (©, 1);
+ ch = gtk_text_iter_get_char (©);
+
+ /* # is always indent 0. Example: #ifdef */
+ if (relocating && ch == '#')
+ {
+ amount = 0;
+ }
+ }
+
+ return amount;
+}
+
+static void
+c_indenter_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (c_indenter_parent_class)->finalize (object);
+}
+
+static void
+c_indenter_class_init (CIndenterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkSourceIndenterClass *indenter_class = GTK_SOURCE_INDENTER_CLASS (klass);
+
+ object_class->finalize = c_indenter_finalize;
+
+ indenter_class->get_indentation_level = c_indenter_get_indentation_level;
+
+ //g_type_class_add_private (object_class, sizeof (CIndenterPrivate));
+}
+
+static void
+c_indenter_init (CIndenter *self)
+{
+ //self->priv = C_INDENTER_GET_PRIVATE (self);
+}
+
+CIndenter *
+c_indenter_new ()
+{
+ return g_object_new (C_TYPE_INDENTER, NULL);
+}
Added: branches/indenters/gtksourceview/c-indenter.h
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/c-indenter.h Sat Feb 28 17:01:13 2009
@@ -0,0 +1,61 @@
+/*
+ * c-indenter.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef __C_INDENTER_H__
+#define __C_INDENTER_H__
+
+#include <glib-object.h>
+#include "gtksourceindenter.h"
+
+G_BEGIN_DECLS
+
+#define C_TYPE_INDENTER (c_indenter_get_type ())
+#define C_INDENTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), C_TYPE_INDENTER, CIndenter))
+#define C_INDENTER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), C_TYPE_INDENTER, CIndenter const))
+#define C_INDENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), C_TYPE_INDENTER, CIndenterClass))
+#define C_IS_INDENTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), C_TYPE_INDENTER))
+#define C_IS_INDENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), C_TYPE_INDENTER))
+#define C_INDENTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), C_TYPE_INDENTER, CIndenterClass))
+
+typedef struct _CIndenter CIndenter;
+typedef struct _CIndenterClass CIndenterClass;
+typedef struct _CIndenterPrivate CIndenterPrivate;
+
+struct _CIndenter
+{
+ GtkSourceIndenter parent;
+
+ CIndenterPrivate *priv;
+};
+
+struct _CIndenterClass
+{
+ GtkSourceIndenterClass parent_class;
+};
+
+GType c_indenter_get_type (void) G_GNUC_CONST;
+CIndenter *c_indenter_new (void);
+
+
+G_END_DECLS
+
+#endif /* __C_INDENTER_H__ */
Added: branches/indenters/gtksourceview/gtksourceindenter-utils.c
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/gtksourceindenter-utils.c Sat Feb 28 17:01:13 2009
@@ -0,0 +1,272 @@
+/*
+ * gtksourceindenter-utils.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gtksourceindenter-utils.h"
+#include "gtksourceview-utils.h"
+#include "gtksourceview.h"
+
+
+gfloat
+gtk_source_indenter_get_amount_indents (GtkTextView *view,
+ GtkTextIter *cur)
+{
+ gint indent_width;
+ GtkTextIter start;
+ gunichar c;
+ gint amount = 0;
+ gint rest = 0;
+
+ start = *cur;
+ gtk_text_iter_set_line_offset (&start, 0);
+
+ c = gtk_text_iter_get_char (&start);
+ if (!g_unichar_isspace (c))
+ return 0;
+
+ indent_width = _gtk_source_view_get_real_indent_width (GTK_SOURCE_VIEW (view));
+
+ while (g_unichar_isspace (c) &&
+ c != '\n' &&
+ c != '\r' &&
+ gtk_text_iter_compare (&start, cur) < 0)
+ {
+ if (c == '\t')
+ {
+ if (rest != 0)
+ rest = 0;
+ amount++;
+ }
+ else
+ {
+ rest++;
+ }
+
+ if (rest == indent_width)
+ {
+ amount++;
+ rest = 0;
+ }
+
+ if (!gtk_text_iter_forward_char (&start))
+ break;
+
+ c = gtk_text_iter_get_char (&start);
+ }
+
+ return (gfloat)amount + (gfloat)(0.1 * rest);
+}
+
+gfloat
+gtk_source_indenter_get_amount_indents_from_position (GtkTextView *view,
+ GtkTextIter *cur)
+{
+ gint indent_width;
+ GtkTextIter start;
+ gunichar c;
+ gint amount = 0;
+ gint rest = 0;
+
+ indent_width = _gtk_source_view_get_real_indent_width (GTK_SOURCE_VIEW (view));
+
+ start = *cur;
+ gtk_text_iter_set_line_offset (&start, 0);
+
+ c = gtk_text_iter_get_char (&start);
+
+ while (gtk_text_iter_compare (&start, cur) < 0)
+ {
+ if (c == '\t')
+ {
+ if (rest != 0)
+ rest = 0;
+ amount++;
+ }
+ else
+ {
+ rest++;
+ }
+
+ if (rest == indent_width)
+ {
+ amount++;
+ rest = 0;
+ }
+
+ if (!gtk_text_iter_forward_char (&start))
+ break;
+
+ c = gtk_text_iter_get_char (&start);
+ }
+
+ return (gfloat)amount + (gfloat)(0.1 * rest);
+}
+
+gboolean
+gtk_source_indenter_move_to_no_space (GtkTextIter *iter,
+ gint direction)
+{
+ gunichar c;
+ gboolean moved = TRUE;
+
+ c = gtk_text_iter_get_char (iter);
+
+ while (g_unichar_isspace (c))
+ {
+ if (!gtk_text_iter_forward_chars (iter, direction))
+ {
+ moved = FALSE;
+ break;
+ }
+ c = gtk_text_iter_get_char (iter);
+ }
+
+ return moved;
+}
+
+gboolean
+gtk_source_indenter_move_to_no_comments (GtkTextIter *iter)
+{
+ gunichar c;
+
+ c = gtk_text_iter_get_char (iter);
+
+ if (c == '/' && gtk_text_iter_backward_char (iter))
+ {
+ c = gtk_text_iter_get_char (iter);
+
+ if (c == '*')
+ {
+ /*
+ * We look backward for '*' '/'
+ */
+ for (;;)
+ {
+ if (!gtk_text_iter_backward_char (iter))
+ return FALSE;
+ c = gtk_text_iter_get_char (iter);
+
+ if (c == '*')
+ {
+ if (!gtk_text_iter_backward_char (iter))
+ return FALSE;
+ c = gtk_text_iter_get_char (iter);
+
+ if (c == '/')
+ {
+ /*
+ * We reached to the beggining of the comment,
+ * now we have to look backward for non spaces
+ */
+ if (!gtk_text_iter_backward_char (iter))
+ return FALSE;
+ c = gtk_text_iter_get_char (iter);
+
+ while (g_unichar_isspace (c) && gtk_text_iter_backward_char (iter))
+ {
+ c = gtk_text_iter_get_char (iter);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+gtk_source_indenter_find_open_char (GtkTextIter *iter,
+ gchar open,
+ gchar close,
+ gboolean skip_first)
+{
+ GtkTextIter copy;
+ gunichar c;
+ gboolean moved = FALSE;
+ gint counter = 0;
+
+ copy = *iter;
+
+ /*
+ * FIXME: We have to take care of number of lines to go back
+ */
+ c = gtk_text_iter_get_char (©);
+ do
+ {
+ /*
+ * This algorithm has to work even if we have if (xxx, xx(),
+ */
+ if (c == close || skip_first)
+ {
+ counter--;
+ skip_first = FALSE;
+ }
+
+ if (c == open && counter != 0)
+ {
+ counter++;
+ }
+
+ if (counter == 0)
+ {
+ *iter = copy;
+ moved = TRUE;
+ break;
+ }
+ }
+ while (gtk_text_iter_backward_char (©) &&
+ (c = gtk_text_iter_get_char (©)));
+
+ return moved;
+}
+
+gfloat
+gtk_source_indenter_add_space (GtkTextView *view,
+ gfloat current_level)
+{
+ gint indent_width;
+ gint spaces;
+ gint tabs;
+
+ indent_width = _gtk_source_view_get_real_indent_width (GTK_SOURCE_VIEW (view));
+ tabs = (gint)current_level;
+ spaces = round (10 * (gfloat)(current_level - tabs));
+
+ /*
+ * We add the new space
+ */
+ spaces++;
+
+ if (spaces == indent_width)
+ {
+ spaces = 0;
+ tabs++;
+ }
+
+ return (gfloat)tabs + (gfloat)(0.1 * spaces);
+}
Added: branches/indenters/gtksourceview/gtksourceindenter-utils.h
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/gtksourceindenter-utils.h Sat Feb 28 17:01:13 2009
@@ -0,0 +1,53 @@
+/*
+ * gtksourceindenter-utils.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_VIEW_UTILS_H__
+#define __GTK_SOURCE_VIEW_UTILS_H__
+
+#include <glib.h>
+#include "gtksourceview.h"
+
+G_BEGIN_DECLS
+
+gfloat gtk_source_indenter_get_amount_indents (GtkTextView *view,
+ GtkTextIter *cur);
+
+gfloat gtk_source_indenter_get_amount_indents_from_position
+ (GtkTextView *view,
+ GtkTextIter *cur);
+
+gboolean gtk_source_indenter_move_to_no_space (GtkTextIter *iter,
+ gint direction);
+
+gboolean gtk_source_indenter_move_to_no_comments (GtkTextIter *iter);
+
+gboolean gtk_source_indenter_find_open_char (GtkTextIter *iter,
+ gchar open,
+ gchar close,
+ gboolean skip_first);
+
+gfloat gtk_source_indenter_add_space (GtkTextView *view,
+ gfloat current_level);
+
+G_END_DECLS
+
+#endif
Added: branches/indenters/gtksourceview/gtksourceindenter.c
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/gtksourceindenter.c Sat Feb 28 17:01:13 2009
@@ -0,0 +1,159 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourceindenter.c
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro <icq gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "gtksourceindenter.h"
+#include "gtksourceview.h"
+#include "gtksourceview-utils.h"
+
+
+G_DEFINE_TYPE(GtkSourceIndenter, gtk_source_indenter, G_TYPE_OBJECT)
+
+static const gchar * relocatables[] =
+{
+ "0{",
+ "0}",
+ "0)",
+ "0#",
+ ":",
+ NULL
+};
+
+static const gchar * extra_indent_words[] =
+{
+ "if",
+ "else",
+ "while",
+ "do",
+ "for",
+ "switch",
+ NULL
+};
+
+/* Default implementation */
+static const gchar * const *
+gtk_source_indenter_get_relocatables_default (GtkSourceIndenter *self)
+{
+ return relocatables;
+}
+
+/* Default implementation */
+static const gchar * const *
+gtk_source_indenter_get_extra_indent_words_default (GtkSourceIndenter *self)
+{
+ return extra_indent_words;
+}
+
+/* Default implementation */
+static gfloat
+gtk_source_indenter_get_indentation_level_default (GtkSourceIndenter *self,
+ GtkTextView *view,
+ GtkTextIter *iter,
+ gboolean relocating)
+{
+ g_return_val_if_reached (0);
+}
+
+static void
+gtk_source_indenter_finalize (GObject *object)
+{
+ /* Empty */
+}
+
+static void
+gtk_source_indenter_class_init (GtkSourceIndenterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ klass->get_relocatables = gtk_source_indenter_get_relocatables_default;
+ klass->get_extra_indent_words = gtk_source_indenter_get_extra_indent_words_default;
+ klass->get_indentation_level = gtk_source_indenter_get_indentation_level_default;
+
+ object_class->finalize = gtk_source_indenter_finalize;
+}
+
+static void
+gtk_source_indenter_init (GtkSourceIndenter *self)
+{
+ /* Empty */
+}
+
+/**
+ * gtk_source_indenter_get_indentation_level:
+ * @self: a #GtkSourceIndenter
+ * @view: a #GtkTextView
+ * @iter: a #GtkTextIter
+ *
+ * Gets the indentation level for a line determined by @iter.
+ * This func is expensive so it must be called only when it is neccessary,
+ * for example when is tiped a trigger, or when the user moves to a determined
+ * line.
+ * Always this func is called the indenter is going to search for a context
+ * to know the indentation level.
+ *
+ * Returns: the indentation level for a line determined by @iter.
+ */
+gfloat
+gtk_source_indenter_get_indentation_level (GtkSourceIndenter *self,
+ GtkTextView *view,
+ GtkTextIter *iter,
+ gboolean relocating)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_INDENTER (self), 0);
+
+ return GTK_SOURCE_INDENTER_GET_CLASS (self)->get_indentation_level (self, view, iter, relocating);
+}
+
+/**
+ * gtk_source_indenter_get_extra_indent_words:
+ * @self: a #GtkSourceIndenter
+ *
+ * Gets the words that start an extra indent in the next line.
+ * This will not change the indentation level.
+ *
+ * Returns: the words that start an extra indent in the next line.
+ */
+const gchar * const *
+gtk_source_indenter_get_extra_indent_words (GtkSourceIndenter *self)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_INDENTER (self), NULL);
+
+ return GTK_SOURCE_INDENTER_GET_CLASS (self)->get_extra_indent_words (self);
+}
+
+/**
+ * gtk_source_indenter_get_relocatables:
+ * @self: a #GtkSourceIndenter
+ *
+ * Gets the words that should be relocated on indentation. For example: {,}...
+ * This will trigger a gtk_source_indenter_get_indentation_level() to know
+ * where must be relocated.
+ * This is going to be detected only when a extra indent is added,
+ * see gtk_source_indenter_get_extra_indent_words(), and in case you add a \t
+ * or a \n the detection is finished.
+ *
+ * Returns: the words that should be relocated on indentation.
+ */
+const gchar * const *
+gtk_source_indenter_get_relocatables (GtkSourceIndenter *self)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_INDENTER (self), NULL);
+
+ return GTK_SOURCE_INDENTER_GET_CLASS (self)->get_relocatables (self);
+}
Added: branches/indenters/gtksourceview/gtksourceindenter.h
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/gtksourceindenter.h Sat Feb 28 17:01:13 2009
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourceindenter.h
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro <icq gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_SOURCE_INDENTER_H__
+#define __GTK_SOURCE_INDENTER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTK_TYPE_SOURCE_INDENTER (gtk_source_indenter_get_type())
+#define GTK_SOURCE_INDENTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_SOURCE_INDENTER, GtkSourceIndenter))
+#define GTK_SOURCE_INDENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_SOURCE_INDENTER, GtkSourceIndenterClass))
+#define GTK_IS_SOURCE_INDENTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_SOURCE_INDENTER))
+#define GTK_IS_SOURCE_INDENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_INDENTER))
+#define GTK_SOURCE_INDENTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_SOURCE_INDENTER, GtkSourceIndenterClass))
+
+typedef struct _GtkSourceIndenter GtkSourceIndenter;
+
+struct _GtkSourceIndenter
+{
+ GObject parent;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtkSourceIndenterClass GtkSourceIndenterClass;
+
+struct _GtkSourceIndenterClass
+{
+ GObjectClass parent_class;
+
+ const gchar * const * (*get_relocatables) (GtkSourceIndenter *self);
+
+ const gchar * const * (*get_extra_indent_words) (GtkSourceIndenter *self);
+
+ gfloat (*get_indentation_level) (GtkSourceIndenter *self,
+ GtkTextView *view,
+ GtkTextIter *iter,
+ gboolean relocating);
+};
+
+GType gtk_source_indenter_get_type (void);
+
+const gchar * const *
+ gtk_source_indenter_get_relocatables (GtkSourceIndenter *self);
+
+const gchar * const *
+ gtk_source_indenter_get_extra_indent_words
+ (GtkSourceIndenter *self);
+
+gfloat gtk_source_indenter_get_indentation_level
+ (GtkSourceIndenter *self,
+ GtkTextView *buf,
+ GtkTextIter *iter,
+ gboolean relocating);
+
+gfloat gtk_source_indenter_get_amount_indents (GtkTextView *view,
+ GtkTextIter *cur);
+
+gfloat gtk_source_indenter_get_amount_indents_from_position
+ (GtkTextView *view,
+ GtkTextIter *cur);
+
+G_END_DECLS
+
+#endif
+
Added: branches/indenters/gtksourceview/gtksourceindentermanager.c
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/gtksourceindentermanager.c Sat Feb 28 17:01:13 2009
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourceindentermanager.c
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro <icq gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "gtksourceindentermanager.h"
+#include "c-indenter.h"
+#include "simple-indenter.h"
+
+
+#define GTK_SOURCE_INDENTER_MANAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_INDENTER_MANAGER, GtkSourceIndenterManagerPrivate))
+
+struct _GtkSourceIndenterManagerPrivate
+{
+};
+
+G_DEFINE_TYPE (GtkSourceIndenterManager, gtk_source_indenter_manager, G_TYPE_OBJECT)
+
+static void
+gtk_source_indenter_manager_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gtk_source_indenter_manager_parent_class)->finalize (object);
+}
+
+static void
+gtk_source_indenter_manager_class_init (GtkSourceIndenterManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_source_indenter_manager_finalize;
+
+ //g_type_class_add_private (object_class, sizeof(GtkSourceIndenterManagerPrivate));
+}
+
+static void
+gtk_source_indenter_manager_init (GtkSourceIndenterManager *self)
+{
+ //self->priv = GTK_SOURCE_INDENTER_MANAGER_GET_PRIVATE (self);
+}
+
+GtkSourceIndenterManager *
+gtk_source_indenter_manager_get_default ()
+{
+ static GtkSourceIndenterManager *manager = NULL;
+
+ if (manager == NULL)
+ {
+ manager = g_object_new (GTK_TYPE_SOURCE_INDENTER_MANAGER, NULL);
+ }
+
+ return manager;
+}
+
+GtkSourceIndenter *
+gtk_source_indenter_manager_get_indenter_by_id (GtkSourceIndenterManager *manager,
+ const gchar *id)
+{
+ GtkSourceIndenter *indenter;
+
+ if (id != NULL && strcmp (id, "c") == 0)
+ {
+ indenter = GTK_SOURCE_INDENTER (c_indenter_new ());
+ }
+ else
+ {
+ indenter = GTK_SOURCE_INDENTER (simple_indenter_new ());
+ }
+
+ return indenter;
+}
Added: branches/indenters/gtksourceview/gtksourceindentermanager.h
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/gtksourceindentermanager.h Sat Feb 28 17:01:13 2009
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourceindentermanager.h
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro <icq gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_SOURCE_INDENTER_MANAGER_H__
+#define __GTK_SOURCE_INDENTER_MANAGER_H__
+
+#include <glib-object.h>
+
+#include "gtksourceindenter.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_INDENTER_MANAGER (gtk_source_indenter_manager_get_type ())
+#define GTK_SOURCE_INDENTER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_INDENTER_MANAGER, GtkSourceIndenterManager))
+#define GTK_SOURCE_INDENTER_MANAGER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_INDENTER_MANAGER, GtkSourceIndenterManager const))
+#define GTK_SOURCE_INDENTER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_INDENTER_MANAGER, GtkSourceIndenterManagerClass))
+#define GTK_IS_SOURCE_INDENTER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_INDENTER_MANAGER))
+#define GTK_IS_SOURCE_INDENTER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_INDENTER_MANAGER))
+#define GTK_SOURCE_INDENTER_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_INDENTER_MANAGER, GtkSourceIndenterManagerClass))
+
+typedef struct _GtkSourceIndenterManager GtkSourceIndenterManager;
+typedef struct _GtkSourceIndenterManagerClass GtkSourceIndenterManagerClass;
+typedef struct _GtkSourceIndenterManagerPrivate GtkSourceIndenterManagerPrivate;
+
+struct _GtkSourceIndenterManager
+{
+ GObject parent;
+
+ GtkSourceIndenterManagerPrivate *priv;
+};
+
+struct _GtkSourceIndenterManagerClass
+{
+ GObjectClass parent_class;
+};
+
+GType gtk_source_indenter_manager_get_type (void) G_GNUC_CONST;
+
+GtkSourceIndenterManager *gtk_source_indenter_manager_get_default(void);
+
+GtkSourceIndenter *gtk_source_indenter_manager_get_indenter_by_id
+ (GtkSourceIndenterManager *manager,
+ const gchar *id);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_INDENTER_MANAGER_H__ */
Modified: branches/indenters/gtksourceview/gtksourcelanguage.c
==============================================================================
--- branches/indenters/gtksourceview/gtksourcelanguage.c (original)
+++ branches/indenters/gtksourceview/gtksourcelanguage.c Sat Feb 28 17:01:13 2009
@@ -38,6 +38,7 @@
#include "gtksourcelanguage-private.h"
#include "gtksourcelanguage.h"
#include "gtksourceview-marshal.h"
+#include "gtksourceindentermanager.h"
#define DEFAULT_SECTION _("Others")
@@ -879,6 +880,24 @@
return info->name;
}
+GtkSourceIndenter *
+_gtk_source_language_get_indenter (GtkSourceLanguage *language)
+{
+ GtkSourceIndenterManager *manager;
+ GtkSourceIndenter *indenter;
+
+ manager = gtk_source_indenter_manager_get_default ();
+
+ if (GTK_IS_SOURCE_LANGUAGE (language))
+ indenter = gtk_source_indenter_manager_get_indenter_by_id (manager,
+ language->priv->id);
+ else
+ indenter = gtk_source_indenter_manager_get_indenter_by_id (manager,
+ NULL);
+
+ return indenter;
+}
+
/* Utility functions for GtkSourceStyleInfo */
GtkSourceStyleInfo *
Modified: branches/indenters/gtksourceview/gtksourcelanguage.h
==============================================================================
--- branches/indenters/gtksourceview/gtksourcelanguage.h (original)
+++ branches/indenters/gtksourceview/gtksourcelanguage.h Sat Feb 28 17:01:13 2009
@@ -24,6 +24,7 @@
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
+#include "gtksourceindenter.h"
G_BEGIN_DECLS
@@ -77,6 +78,9 @@
const char *gtk_source_language_get_style_name (GtkSourceLanguage *language,
const char *style_id);
+GtkSourceIndenter *
+ _gtk_source_language_get_indenter (GtkSourceLanguage *language);
+
G_END_DECLS
#endif /* __GTK_SOURCE_LANGUAGE_H__ */
Modified: branches/indenters/gtksourceview/gtksourceview-utils.c
==============================================================================
--- branches/indenters/gtksourceview/gtksourceview-utils.c (original)
+++ branches/indenters/gtksourceview/gtksourceview-utils.c Sat Feb 28 17:01:13 2009
@@ -23,6 +23,7 @@
#endif
#include "gtksourceview-utils.h"
+#include "gtksourceview.h"
#define SOURCEVIEW_DIR "gtksourceview-2.0"
@@ -123,3 +124,14 @@
return g_slist_reverse (files);
}
+
+/*********************** Indenter utils functions ****************************/
+
+gint
+_gtk_source_view_get_real_indent_width (GtkSourceView *view)
+{
+ gint indent_width = gtk_source_view_get_indent_width (view);
+ guint tab_width = gtk_source_view_get_tab_width (view);
+
+ return indent_width < 0 ? tab_width : indent_width;
+}
Modified: branches/indenters/gtksourceview/gtksourceview-utils.h
==============================================================================
--- branches/indenters/gtksourceview/gtksourceview-utils.h (original)
+++ branches/indenters/gtksourceview/gtksourceview-utils.h Sat Feb 28 17:01:13 2009
@@ -22,6 +22,8 @@
#define __GTK_SOURCE_VIEW_UTILS_H__
#include <glib.h>
+#include "gtksourceview.h"
+#include <gtk/gtk.h>
G_BEGIN_DECLS
@@ -32,6 +34,8 @@
const gchar *suffix,
gboolean only_dirs);
+gint _gtk_source_view_get_real_indent_width (GtkSourceView *view);
+
G_END_DECLS
#endif /* __GTK_SOURCE_VIEW_UTILS_H__ */
Modified: branches/indenters/gtksourceview/gtksourceview.c
==============================================================================
--- branches/indenters/gtksourceview/gtksourceview.c (original)
+++ branches/indenters/gtksourceview/gtksourceview.c Sat Feb 28 17:01:13 2009
@@ -39,6 +39,7 @@
#include "gtksourceview-typebuiltins.h"
#include "gtksourcemark.h"
#include "gtksourceview.h"
+#include "gtksourceview-utils.h"
/*
#define ENABLE_DEBUG
@@ -188,6 +189,9 @@
gint *countp);
static gint gtk_source_view_expose (GtkWidget *widget,
GdkEventExpose *event);
+static void gtk_source_view_event_after (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer useless);
static gboolean gtk_source_view_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static gboolean gtk_source_view_button_press_event (GtkWidget *widget,
@@ -737,6 +741,11 @@
"notify::buffer",
G_CALLBACK (notify_buffer),
NULL);
+
+ g_signal_connect (view,
+ "event-after",
+ G_CALLBACK (gtk_source_view_event_after),
+ NULL);
}
static GObject *
@@ -2757,51 +2766,6 @@
}
static gchar *
-compute_indentation (GtkSourceView *view,
- GtkTextIter *cur)
-{
- GtkTextIter start;
- GtkTextIter end;
-
- gunichar ch;
- gint line;
-
- line = gtk_text_iter_get_line (cur);
-
- gtk_text_buffer_get_iter_at_line (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)),
- &start,
- line);
-
- end = start;
-
- ch = gtk_text_iter_get_char (&end);
-
- while (g_unichar_isspace (ch) &&
- (ch != '\n') &&
- (ch != '\r') &&
- (gtk_text_iter_compare (&end, cur) < 0))
- {
- if (!gtk_text_iter_forward_char (&end))
- break;
-
- ch = gtk_text_iter_get_char (&end);
- }
-
- if (gtk_text_iter_equal (&start, &end))
- return NULL;
-
- return gtk_text_iter_get_slice (&start, &end);
-}
-
-static gint
-get_real_indent_width (GtkSourceView *view)
-{
- return view->priv->indent_width < 0 ?
- view->priv->tab_width :
- view->priv->indent_width;
-}
-
-static gchar *
get_indent_string (gint tabs, gint spaces)
{
gchar *str;
@@ -2816,6 +2780,31 @@
return str;
}
+static gchar *
+get_indent_string_from_indent_level (GtkSourceView *view,
+ gfloat level)
+{
+ gint tabs;
+ gint spaces;
+ gchar *indent = NULL;
+ gint indent_width;
+
+ tabs = (gint)level;
+ spaces = round (10 * (gfloat)(level - tabs));
+ indent_width = _gtk_source_view_get_real_indent_width (view);
+
+ if (view->priv->insert_spaces)
+ {
+ indent = g_strnfill (indent_width * tabs + spaces, ' ');
+ }
+ else
+ {
+ indent = get_indent_string (tabs, spaces);
+ }
+
+ return indent;
+}
+
static void
indent_lines (GtkSourceView *view, GtkTextIter *start, GtkTextIter *end)
{
@@ -2839,7 +2828,7 @@
if (view->priv->insert_spaces)
{
- spaces = get_real_indent_width (view);
+ spaces = _gtk_source_view_get_real_indent_width (view);
tab_buffer = g_strnfill (spaces, ' ');
}
@@ -2847,7 +2836,7 @@
{
gint indent_width;
- indent_width = get_real_indent_width (view);
+ indent_width = _gtk_source_view_get_real_indent_width (view);
spaces = indent_width % view->priv->tab_width;
tabs = indent_width / view->priv->tab_width;
@@ -2941,7 +2930,7 @@
}
tab_width = view->priv->tab_width;
- indent_width = get_real_indent_width (view);
+ indent_width = _gtk_source_view_get_real_indent_width (view);
gtk_text_buffer_begin_user_action (buf);
@@ -3036,7 +3025,7 @@
gint pos;
gint spaces;
- indent_width = get_real_indent_width (view);
+ indent_width = _gtk_source_view_get_real_indent_width (view);
/* CHECK: is this a performance problem? */
pos = get_line_offset_in_equivalent_spaces (view, start);
@@ -3059,7 +3048,7 @@
gint spaces;
tab_width = view->priv->tab_width;
- indent_width = get_real_indent_width (view);
+ indent_width = _gtk_source_view_get_real_indent_width (view);
/* CHECK: is this a performance problem? */
from = get_line_offset_in_equivalent_spaces (view, start);
@@ -3183,11 +3172,192 @@
}
static gboolean
+check_whitespaces (GtkTextIter *cur)
+{
+ GtkTextIter start;
+ gunichar c;
+ gboolean check = FALSE;
+
+ start = *cur;
+
+ gtk_text_iter_set_line_offset (&start, 0);
+ c = gtk_text_iter_get_char (&start);
+
+ while (gtk_text_iter_compare (&start, cur) < 0)
+ {
+ if (!g_unichar_isspace (c))
+ {
+ check = FALSE;
+ break;
+ }
+ else
+ check = TRUE;
+
+ gtk_text_iter_forward_char (&start);
+ c = gtk_text_iter_get_char (&start);
+ }
+
+ return check;
+}
+
+static gchar *
+get_current_token (GtkTextBuffer *buf,
+ GtkTextIter *cur)
+{
+ GtkTextIter start;
+ gchar *word = NULL;
+ gunichar w;
+
+ start = *cur;
+
+ if (gtk_text_iter_ends_word (cur) ||
+ (gtk_text_iter_inside_word (cur) && gtk_text_iter_starts_word (cur)))
+ {
+ gtk_text_iter_backward_word_start (&start);
+ word = gtk_text_buffer_get_text (buf, &start, cur, FALSE);
+ }
+
+ if (word == NULL && gtk_text_iter_backward_char (&start))
+ {
+ w = gtk_text_iter_get_char (&start);
+ if (!g_unichar_isspace (w))
+ word = g_strdup_printf ("%c", w);
+ }
+
+ *cur = start;
+
+ return word;
+}
+
+static void
+gtk_source_view_event_after (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer useless)
+{
+ GtkSourceView *view;
+ GtkTextBuffer *buf;
+ GtkTextIter cur;
+ GtkTextMark *mark;
+ GtkSourceLanguage *lang;
+ GtkSourceIndenter *indenter;
+ GtkTextIter copy;
+ const gchar * const *relocatables;
+ gfloat level;
+ gint m = 0;
+
+ if (event->type != GDK_KEY_PRESS ||
+ event->key.state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))
+ return;
+
+ view = GTK_SOURCE_VIEW (widget);
+ buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
+
+ mark = gtk_text_buffer_get_insert (buf);
+ gtk_text_buffer_get_iter_at_mark (buf, &cur, mark);
+
+ lang = gtk_source_buffer_get_language (view->priv->source_buffer);
+ indenter = _gtk_source_language_get_indenter (lang);
+
+ /*
+ * Relocations
+ */
+ relocatables = gtk_source_indenter_get_relocatables (indenter);
+ while (relocatables != NULL && relocatables[m] != NULL)
+ {
+ const gchar *reloc = relocatables[m];
+ GtkTextIter start;
+ gchar *word;
+ gchar *word2;
+ gchar *indent = NULL;
+ guint keyval;
+
+ /*
+ * Check that the key entered is the same as the last character
+ * in reloc
+ */
+ keyval = gdk_unicode_to_keyval (reloc[strlen (reloc) - 1]);
+ if (event->key.keyval != keyval)
+ {
+ m++;
+ continue;
+ }
+
+ start = copy = cur;
+ gtk_text_iter_set_line_offset (&start, 0);
+
+ /*
+ * First check the word
+ */
+ word = get_current_token (buf, ©);
+
+ if (word != NULL)
+ {
+ switch (reloc[0])
+ {
+ case '0': if (check_whitespaces (©))
+ {
+ word2 = g_strndup (reloc + 1, strlen (reloc) - 1);
+
+ if (strcmp (word, word2) == 0)
+ {
+ level = gtk_source_indenter_get_indentation_level (indenter,
+ GTK_TEXT_VIEW (view),
+ ©,
+ TRUE);
+ indent = get_indent_string_from_indent_level (view, level);
+ }
+ g_free (word2);
+ }
+ break;
+ default: if (strcmp (word, reloc) == 0)
+ {
+ level = gtk_source_indenter_get_indentation_level (indenter,
+ GTK_TEXT_VIEW (view),
+ ©,
+ TRUE);
+ indent = get_indent_string_from_indent_level (view, level);
+ }
+ break;
+ }
+ g_free (word);
+ }
+
+ if (indent != NULL)
+ {
+ GtkTextIter end;
+ gunichar c;
+
+ gtk_text_iter_set_line_offset (&start, 0);
+ end = start;
+
+ c = gtk_text_iter_get_char (&end);
+ while (g_unichar_isspace (c))
+ {
+ gtk_text_iter_forward_char (&end);
+ c = gtk_text_iter_get_char (&end);
+ }
+
+ gtk_text_buffer_begin_user_action (buf);
+ gtk_text_buffer_delete (buf, &start, &end);
+
+ gtk_text_buffer_insert (buf, &start, indent, -1);
+ gtk_text_buffer_end_user_action (buf);
+
+ g_free (indent);
+ break;
+ }
+ m++;
+ }
+}
+
+static gboolean
gtk_source_view_key_press_event (GtkWidget *widget,
GdkEventKey *event)
{
GtkSourceView *view;
GtkTextBuffer *buf;
+ GtkSourceLanguage *lang;
+ GtkSourceIndenter *indenter;
GtkTextIter cur;
GtkTextMark *mark;
guint modifiers;
@@ -3207,7 +3377,10 @@
mark = gtk_text_buffer_get_insert (buf);
gtk_text_buffer_get_iter_at_mark (buf, &cur, mark);
-
+
+ lang = gtk_source_buffer_get_language (view->priv->source_buffer);
+ indenter = _gtk_source_language_get_indenter (lang);
+
if ((key == GDK_Return || key == GDK_KP_Enter) &&
!(event->state & GDK_SHIFT_MASK) &&
view->priv->auto_indent)
@@ -3217,11 +3390,17 @@
* level as the previous line.
* SHIFT+ENTER allows to avoid autoindentation.
*/
+ gfloat indent_level;
gchar *indent = NULL;
/* Calculate line indentation and create indent string. */
- indent = compute_indentation (view, &cur);
-
+ indent_level = gtk_source_indenter_get_indentation_level (indenter,
+ GTK_TEXT_VIEW (view),
+ &cur, FALSE);
+ indent = get_indent_string_from_indent_level (view, indent_level);
+
+ g_warning ("%f", indent_level);
+
if (indent != NULL)
{
/* Allow input methods to internally handle a key press event.
@@ -3235,6 +3414,7 @@
gtk_text_buffer_get_iter_at_mark (buf, &cur, mark);
/* Insert new line and auto-indent. */
+ //FIXME: Remove current indentation before insert the new one
gtk_text_buffer_begin_user_action (buf);
gtk_text_buffer_insert (buf, &cur, "\n", 1);
gtk_text_buffer_insert (buf, &cur, indent, strlen (indent));
@@ -3787,6 +3967,87 @@
return view->priv->draw_spaces;
}
+/**
+ * gtk_source_view_reindent_lines:
+ * @view: a #GtkSourceView
+ * @start: iterator to initilize with selection start
+ * @end: iterator to initialize with selection end
+ *
+ * FIXME: Add a real doc.
+ * Reindent the lines from @start to @end
+ */
+void
+gtk_source_view_reindent_lines (GtkSourceView *view,
+ GtkTextIter *start,
+ GtkTextIter *end)
+{
+ GtkSourceLanguage *lang;
+ GtkSourceIndenter *indenter;
+ GtkTextBuffer *buf;
+ GtkTextMark *end_mark;
+
+ g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
+ g_return_if_fail (start != NULL && end != NULL);
+
+ buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ lang = gtk_source_buffer_get_language (view->priv->source_buffer);
+ indenter = _gtk_source_language_get_indenter (lang);
+
+ end_mark = gtk_text_buffer_create_mark (buf, NULL, end, FALSE);
+ gtk_text_buffer_get_iter_at_mark (buf, end, end_mark);
+
+ while (gtk_text_iter_get_line (start) <=
+ gtk_text_iter_get_line (end))
+ {
+ gfloat level;
+ gchar *str;
+
+ /*
+ * Put start in the end of the previous line
+ */
+ gtk_text_iter_set_line_offset (start, 0);
+ //gtk_text_iter_backward_char (start);
+
+ level = gtk_source_indenter_get_indentation_level (indenter,
+ GTK_TEXT_VIEW (view),
+ start,
+ FALSE);
+ g_warning ("reindent level: %f", level);
+ str = get_indent_string_from_indent_level (view, level);
+ if (str != NULL)
+ {
+ GtkTextIter iter;
+ gunichar c;
+
+ iter = *start;
+
+ c = gtk_text_iter_get_char (&iter);
+ while (g_unichar_isspace (c) &&
+ c != '\n' &&
+ c != '\r')
+ {
+ gtk_text_iter_forward_char (&iter);
+ c = gtk_text_iter_get_char (&iter);
+ }
+
+ gtk_text_buffer_begin_user_action (buf);
+ gtk_text_buffer_delete (buf, start, &iter);
+
+ gtk_text_buffer_insert (buf, start, str, -1);
+ gtk_text_buffer_end_user_action (buf);
+
+ g_free (str);
+ }
+
+ gtk_text_buffer_get_iter_at_mark (buf, end, end_mark);
+ gtk_text_iter_forward_line (start);
+ //gtk_text_iter_forward_line (start);
+ }
+
+ gtk_text_buffer_delete_mark (buf, end_mark);
+}
+
+
static void
gtk_source_view_style_set (GtkWidget *widget, GtkStyle *previous_style)
{
Modified: branches/indenters/gtksourceview/gtksourceview.h
==============================================================================
--- branches/indenters/gtksourceview/gtksourceview.h (original)
+++ branches/indenters/gtksourceview/gtksourceview.h Sat Feb 28 17:01:13 2009
@@ -198,5 +198,9 @@
GtkSourceDrawSpacesFlags
gtk_source_view_get_draw_spaces (GtkSourceView *view);
+void gtk_source_view_reindent_lines (GtkSourceView *view,
+ GtkTextIter *start,
+ GtkTextIter *end);
+
G_END_DECLS
#endif /* end of SOURCE_VIEW_H__ */
Added: branches/indenters/gtksourceview/simple-indenter.c
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/simple-indenter.c Sat Feb 28 17:01:13 2009
@@ -0,0 +1,81 @@
+/*
+ * c-indenter.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "simple-indenter.h"
+#include "gtksourceindenter.h"
+#include "gtksourceview-utils.h"
+
+#define SIMPLE_INDENTER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object),\
+ SIMPLE_TYPE_INDENTER, SimpleIndenterPrivate))
+
+struct _SimpleIndenterPrivate
+{
+};
+
+G_DEFINE_TYPE (SimpleIndenter, simple_indenter, GTK_TYPE_SOURCE_INDENTER)
+
+static gfloat
+simple_indenter_get_indentation_level (GtkSourceIndenter *indenter,
+ GtkTextView *view,
+ GtkTextIter *iter,
+ gboolean relocating)
+{
+ return gtk_source_indenter_get_amount_indents (view, iter);
+}
+
+static const gchar * const *
+simple_indenter_get_relocatables (GtkSourceIndenter *self)
+{
+ return NULL;
+}
+
+static void
+simple_indenter_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (simple_indenter_parent_class)->finalize (object);
+}
+
+static void
+simple_indenter_class_init (SimpleIndenterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkSourceIndenterClass *indenter_class = GTK_SOURCE_INDENTER_CLASS (klass);
+
+ object_class->finalize = simple_indenter_finalize;
+
+ indenter_class->get_indentation_level = simple_indenter_get_indentation_level;
+ indenter_class->get_relocatables = simple_indenter_get_relocatables;
+
+ //g_type_class_add_private (object_class, sizeof (SimpleIndenterPrivate));
+}
+
+static void
+simple_indenter_init (SimpleIndenter *self)
+{
+ //self->priv = SIMPLE_INDENTER_GET_PRIVATE (self);
+}
+
+SimpleIndenter *
+simple_indenter_new ()
+{
+ return g_object_new (SIMPLE_TYPE_INDENTER, NULL);
+}
Added: branches/indenters/gtksourceview/simple-indenter.h
==============================================================================
--- (empty file)
+++ branches/indenters/gtksourceview/simple-indenter.h Sat Feb 28 17:01:13 2009
@@ -0,0 +1,61 @@
+/*
+ * c-indenter.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2009 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SIMPLE_INDENTER_H__
+#define __SIMPLE_INDENTER_H__
+
+#include <glib-object.h>
+#include "gtksourceindenter.h"
+
+G_BEGIN_DECLS
+
+#define SIMPLE_TYPE_INDENTER (simple_indenter_get_type ())
+#define SIMPLE_INDENTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SIMPLE_TYPE_INDENTER, SimpleIndenter))
+#define SIMPLE_INDENTER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SIMPLE_TYPE_INDENTER, SimpleIndenter const))
+#define SIMPLE_INDENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SIMPLE_TYPE_INDENTER, SimpleIndenterClass))
+#define SIMPLE_IS_INDENTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SIMPLE_TYPE_INDENTER))
+#define SIMPLE_IS_INDENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SIMPLE_TYPE_INDENTER))
+#define SIMPLE_INDENTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SIMPLE_TYPE_INDENTER, SimpleIndenterClass))
+
+typedef struct _SimpleIndenter SimpleIndenter;
+typedef struct _SimpleIndenterClass SimpleIndenterClass;
+typedef struct _SimpleIndenterPrivate SimpleIndenterPrivate;
+
+struct _SimpleIndenter
+{
+ GtkSourceIndenter parent;
+
+ SimpleIndenterPrivate *priv;
+};
+
+struct _SimpleIndenterClass
+{
+ GtkSourceIndenterClass parent_class;
+};
+
+GType simple_indenter_get_type (void) G_GNUC_CONST;
+SimpleIndenter *simple_indenter_new (void);
+
+
+G_END_DECLS
+
+#endif /* __SIMPLE_INDENTER_H__ */
Modified: branches/indenters/tests/test-widget.c
==============================================================================
--- branches/indenters/tests/test-widget.c (original)
+++ branches/indenters/tests/test-widget.c Sat Feb 28 17:01:13 2009
@@ -94,7 +94,8 @@
static GtkWidget *create_view_window (GtkSourceBuffer *buffer,
GtkSourceView *from);
-
+static void reindent_cb (GtkAction *action,
+ gpointer user_data);
/* Actions & UI definition ---------------------------------------------------- */
@@ -119,6 +120,8 @@
"Find", G_CALLBACK (find_cb) },
{ "Replace", GTK_STOCK_FIND_AND_REPLACE, "Search and _Replace", "<control>R",
"Search and Replace", G_CALLBACK (replace_cb) },
+ { "SmartIndent", GTK_STOCK_ADD, "Rein_dent", "<control>I",
+ "Reindent code", G_CALLBACK (reindent_cb) },
};
static GtkToggleActionEntry toggle_entries[] = {
@@ -223,6 +226,8 @@
" <menuitem action=\"SmartHomeEndAfter\"/>"
" <menuitem action=\"SmartHomeEndAlways\"/>"
" </menu>"
+" <separator/>"
+" <menuitem action=\"SmartIndent\"/>"
" </menu>"
" </menubar>"
"</ui>";
@@ -619,6 +624,30 @@
gtk_widget_show (window);
}
+static void
+reindent_cb (GtkAction *action, gpointer user_data)
+{
+ GtkSourceView *view;
+ GtkTextBuffer *buf;
+ GtkTextIter start, end;
+
+ g_return_if_fail (GTK_IS_SOURCE_VIEW (user_data));
+
+ view = GTK_SOURCE_VIEW (user_data);
+ buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ if (!gtk_text_buffer_get_selection_bounds (buf, &start, &end))
+ {
+ GtkTextMark *insert;
+
+ insert = gtk_text_buffer_get_insert (buf);
+ gtk_text_buffer_get_iter_at_mark (buf, &start, insert);
+ end = start;
+ }
+
+ gtk_source_view_reindent_lines (view, &start, &end);
+}
+
/* Buffer action callbacks ------------------------------------------------------------ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]