[gnome-builder/wip/libide] libide: move c indenter into libide
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/libide] libide: move c indenter into libide
- Date: Wed, 18 Feb 2015 06:49:43 +0000 (UTC)
commit cb338efb8b32491ee8a7d6ae8911f237928c37a5
Author: Christian Hergert <christian hergert me>
Date: Tue Feb 17 22:48:49 2015 -0800
libide: move c indenter into libide
libide/Makefile.am | 2 +
libide/c/c-parse-helper.c | 252 ++++++++
libide/c/c-parse-helper.h | 41 ++
libide/c/ide-c-indenter.c | 1387 +++++++++++++++++++++++++++++++++++++++++++--
libide/c/ide-c-indenter.h | 7 +-
5 files changed, 1649 insertions(+), 40 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index ad64a95..7a717cb 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -142,6 +142,8 @@ libide_1_0_la_public_sources = \
libide_1_0_la_SOURCES = \
$(libide_1_0_la_public_sources) \
+ libide/c/c-parse-helper.c \
+ libide/c/c-parse-helper.h \
libide/editorconfig/editorconfig-glib.c \
libide/editorconfig/editorconfig-glib.h \
libide/fuzzy/fuzzy.c \
diff --git a/libide/c/c-parse-helper.c b/libide/c/c-parse-helper.c
new file mode 100644
index 0000000..43ce7ed
--- /dev/null
+++ b/libide/c/c-parse-helper.c
@@ -0,0 +1,252 @@
+/* c-parse-helper.c
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * This program 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 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "c-parser"
+
+#include <string.h>
+
+#include "c-parse-helper.h"
+
+void
+parameter_free (Parameter *p)
+{
+ if (p)
+ {
+ g_free (p->name);
+ g_free (p->type);
+ g_free (p);
+ }
+}
+
+Parameter *
+parameter_copy (const Parameter *src)
+{
+ Parameter *copy;
+
+ copy = g_new0 (Parameter, 1);
+ copy->name = g_strdup (src->name);
+ copy->type = g_strdup (src->type);
+ copy->ellipsis = src->ellipsis;
+ copy->n_star = src->n_star;
+
+ return copy;
+}
+
+gboolean
+parameter_validate (Parameter *param)
+{
+ const gchar *tmp;
+
+ if (param->ellipsis)
+ return TRUE;
+
+ if (!param->name || !param->type)
+ return FALSE;
+
+ for (tmp = param->name; *tmp; tmp = g_utf8_next_char (tmp))
+ {
+ gunichar ch = g_utf8_get_char (tmp);
+
+ switch (ch) {
+ case '_':
+ case '[':
+ case ']':
+ continue;
+
+ default:
+ if (g_unichar_isalnum (ch))
+ continue;
+ break;
+ }
+
+ return FALSE;
+ }
+
+ for (tmp = param->type; *tmp; tmp = g_utf8_next_char (tmp))
+ {
+ gunichar ch = g_utf8_get_char (tmp);
+
+ switch (ch) {
+ case '*':
+ case ' ':
+ case '_':
+ continue;
+
+ default:
+ if (g_unichar_isalnum (ch))
+ continue;
+ break;
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+parameter_compute (Parameter *param)
+{
+ const gchar *tmp;
+ gchar *rev;
+ guint n_star = 0;
+
+ rev = g_utf8_strreverse (param->type, -1);
+
+ for (tmp = rev; tmp; tmp = g_utf8_next_char (tmp))
+ {
+ switch (g_utf8_get_char (tmp))
+ {
+ case ' ':
+ break;
+
+ case '*':
+ n_star++;
+ break;
+
+ default:
+ if (n_star)
+ {
+ gchar *cleaned;
+
+ cleaned = g_strstrip (g_utf8_strreverse (tmp, -1));
+ g_free (param->type);
+ param->type = cleaned;
+ }
+ goto finish;
+ }
+ }
+
+finish:
+ param->n_star = n_star;
+
+ g_free (rev);
+}
+
+GSList *
+parse_parameters (const gchar *text)
+{
+ GSList *ret = NULL;
+ gchar **parts = NULL;
+ guint i;
+
+ parts = g_strsplit (text, ",", 0);
+
+ for (i = 0; parts [i]; i++)
+ {
+ const gchar *tmp;
+ const gchar *word;
+
+ word = g_strstrip (parts [i]);
+
+ if (!*word)
+ goto failure;
+
+ if (g_strcmp0 (word, "...") == 0)
+ {
+ Parameter param = { NULL, NULL, TRUE };
+ ret = g_slist_append (ret, parameter_copy (¶m));
+ continue;
+ }
+
+ /*
+ * Check that each word only contains valid characters for a
+ * parameter list.
+ */
+ for (tmp = word; *tmp; tmp = g_utf8_next_char (tmp))
+ {
+ gunichar ch;
+
+ ch = g_utf8_get_char (tmp);
+
+ switch (ch)
+ {
+ case '\t':
+ case ' ':
+ case '*':
+ case '_':
+ case '[':
+ case ']':
+ break;
+
+ default:
+ if (g_unichar_isalnum (ch))
+ break;
+
+ goto failure;
+ }
+ }
+
+ if (strchr (word, '[') && strchr (word, ']'))
+ {
+ /*
+ * TODO: Special case parsing of parameters that have [] after the
+ * name. Such as "char foo[12]" or "char foo[static 12]".
+ */
+ }
+ else
+ {
+ const gchar *name_sep;
+ Parameter param = { 0 };
+ gboolean success = FALSE;
+ gchar *reversed = NULL;
+ gchar *name_rev = NULL;
+
+ reversed = g_utf8_strreverse (word, -1);
+ name_sep = strpbrk (reversed, "\t\n *");
+
+ if (name_sep && *name_sep && *(name_sep + 1))
+ {
+ name_rev = g_strndup (reversed, name_sep - reversed);
+
+ param.name = g_strstrip (g_utf8_strreverse (name_rev, -1));
+ param.type = g_strstrip (g_utf8_strreverse (name_sep, -1));
+
+ parameter_compute (¶m);
+
+ if (parameter_validate (¶m))
+ {
+ ret = g_slist_append (ret, parameter_copy (¶m));
+ success = TRUE;
+ }
+
+ g_free (param.name);
+ g_free (param.type);
+ g_free (name_rev);
+ }
+
+ g_free (reversed);
+
+ if (success)
+ continue;
+ }
+
+ goto failure;
+ }
+
+ goto cleanup;
+
+failure:
+ g_slist_foreach (ret, (GFunc)parameter_free, NULL);
+ g_clear_pointer (&ret, g_slist_free);
+
+cleanup:
+ g_strfreev (parts);
+
+ return ret;
+}
diff --git a/libide/c/c-parse-helper.h b/libide/c/c-parse-helper.h
new file mode 100644
index 0000000..418f518
--- /dev/null
+++ b/libide/c/c-parse-helper.h
@@ -0,0 +1,41 @@
+/* c-parse-helper.h
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * This program 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 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef C_PARSE_HELPER_H
+#define C_PARSE_HELPER_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ gchar *type;
+ gchar *name;
+ guint ellipsis : 1;
+ guint n_star : 4;
+} Parameter;
+
+gboolean parameter_validate (Parameter *param);
+void parameter_free (Parameter *p);
+Parameter *parameter_copy (const Parameter *src);
+GSList *parse_parameters (const gchar *text);
+
+G_END_DECLS
+
+#endif /* C_PARSE_HELPER_H */
diff --git a/libide/c/ide-c-indenter.c b/libide/c/ide-c-indenter.c
index 926dd2d..292c35a 100644
--- a/libide/c/ide-c-indenter.c
+++ b/libide/c/ide-c-indenter.c
@@ -18,72 +18,1391 @@
#include <glib/gi18n.h>
+#include "c-parse-helper.h"
#include "ide-c-indenter.h"
-typedef struct
-{
- void *foo;
-} IdeCIndenterPrivate;
+#define ITER_INIT_LINE_START(iter, other) \
+ gtk_text_buffer_get_iter_at_line( \
+ gtk_text_iter_get_buffer(other), \
+ (iter), \
+ gtk_text_iter_get_line(other))
+
+#define ENTRY
+#define EXIT return
+#define GOTO(_l) goto _l
+#define RETURN(_v) return _v
-G_DEFINE_TYPE_WITH_PRIVATE (IdeCIndenter, ide_c_indenter, IDE_TYPE_INDENTER)
+struct _IdeCIndenter
+{
+ IdeIndenter parent_instance;
-enum {
- PROP_0,
- LAST_PROP
+ gint scope_indent;
+ gint condition_indent;
+ gint directive_indent;
+ guint space_before_paren : 1;
};
-static GParamSpec *gParamSpecs [LAST_PROP];
+G_DEFINE_TYPE (IdeCIndenter, ide_c_indenter, IDE_TYPE_INDENTER)
-static void
-ide_c_indenter_finalize (GObject *object)
+static gunichar
+text_iter_peek_next_char (const GtkTextIter *location)
{
- IdeCIndenter *self = (IdeCIndenter *)object;
- IdeCIndenterPrivate *priv = ide_c_indenter_get_instance_private (self);
+ GtkTextIter iter = *location;
+
+ if (gtk_text_iter_forward_char (&iter))
+ return gtk_text_iter_get_char (&iter);
- G_OBJECT_CLASS (ide_c_indenter_parent_class)->finalize (object);
+ return 0;
}
-static void
-ide_c_indenter_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+static gunichar
+text_iter_peek_prev_char (const GtkTextIter *location)
{
- IdeCIndenter *self = IDE_C_INDENTER (object);
+ GtkTextIter iter = *location;
+
+ if (gtk_text_iter_backward_char (&iter))
+ return gtk_text_iter_get_char (&iter);
+
+ return 0;
+}
+
+static inline void
+build_indent (IdeCIndenter *c,
+ guint line_offset,
+ GtkTextIter *matching_line,
+ GString *str)
+{
+ GtkTextIter iter;
+ gunichar ch;
+
+ if (!line_offset)
+ return;
- switch (prop_id)
+ gtk_text_buffer_get_iter_at_line (gtk_text_iter_get_buffer (matching_line),
+ &iter,
+ gtk_text_iter_get_line (matching_line));
+
+ do {
+ ch = gtk_text_iter_get_char (&iter);
+
+ switch (ch)
+ {
+ case '\t':
+ case ' ':
+ g_string_append_unichar (str, ch);
+ break;
+
+ default:
+ g_string_append_c (str, ' ');
+ break;
+ }
+ } while (gtk_text_iter_forward_char (&iter) &&
+ (gtk_text_iter_compare (&iter, matching_line) <= 0) &&
+ (str->len < line_offset));
+
+ while (str->len < line_offset)
+ g_string_append_c (str, ' ');
+}
+
+static gboolean
+iter_ends_c89_comment (const GtkTextIter *iter)
+{
+ if (gtk_text_iter_get_char (iter) == '/')
{
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ GtkTextIter tmp;
+
+ tmp = *iter;
+
+ if (gtk_text_iter_backward_char (&tmp) &&
+ ('*' == gtk_text_iter_get_char (&tmp)))
+ return TRUE;
}
+
+ return FALSE;
}
-static void
-ide_c_indenter_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+static gboolean
+non_space_predicate (gunichar ch,
+ gpointer user_data)
+{
+ return !g_unichar_isspace (ch);
+}
+
+static gboolean
+line_is_whitespace_until (GtkTextIter *iter)
+{
+ GtkTextIter cur;
+
+ gtk_text_buffer_get_iter_at_line (gtk_text_iter_get_buffer (iter),
+ &cur,
+ gtk_text_iter_get_line (iter));
+
+ for (;
+ gtk_text_iter_compare (&cur, iter) < 0;
+ gtk_text_iter_forward_char (&cur))
+ {
+ if (!g_unichar_isspace (gtk_text_iter_get_char (&cur)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+backward_find_keyword (GtkTextIter *iter,
+ const gchar *keyword,
+ GtkTextIter *limit)
+{
+ GtkTextIter begin;
+ GtkTextIter end;
+
+ /*
+ * If we find the keyword, check to see that the character before it
+ * is either a newline or some other space character. (ie, not part of a
+ * function name like foo_do().
+ */
+ if (gtk_text_iter_backward_search (iter, keyword, GTK_TEXT_SEARCH_TEXT_ONLY,
+ &begin, &end, limit))
+ {
+ GtkTextIter copy;
+ gunichar ch;
+
+ gtk_text_iter_assign (©, &begin);
+
+ if (!gtk_text_iter_backward_char (©) ||
+ !(ch = gtk_text_iter_get_char (©)) ||
+ g_unichar_isspace (ch))
+ {
+ gtk_text_iter_assign (iter, &begin);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+backward_find_condition_keyword (GtkTextIter *iter)
+{
+ GtkTextIter line_start;
+
+ ITER_INIT_LINE_START (&line_start, iter);
+
+ if (backward_find_keyword (iter, "else if", &line_start) ||
+ backward_find_keyword (iter, "else", &line_start) ||
+ backward_find_keyword (iter, "if", &line_start) ||
+ backward_find_keyword (iter, "do", &line_start) ||
+ backward_find_keyword (iter, "while", &line_start) ||
+ backward_find_keyword (iter, "switch", &line_start) ||
+ backward_find_keyword (iter, "for", &line_start))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gchar *
+backward_last_word (GtkTextIter *iter,
+ GtkTextIter *begin)
+{
+ gtk_text_iter_assign (begin, iter);
+
+ if (gtk_text_iter_backward_word_start (begin))
+ {
+ GtkTextIter end;
+
+ gtk_text_iter_assign (&end, begin);
+
+ if (gtk_text_iter_ends_word (&end) ||
+ gtk_text_iter_forward_word_end (&end))
+ return gtk_text_iter_get_slice (begin, &end);
+ }
+
+ return NULL;
+}
+
+static gboolean
+backward_before_c89_comment (GtkTextIter *iter)
+{
+ GtkTextIter copy;
+ GtkTextIter match_start;
+ GtkTextIter match_end;
+ gunichar ch;
+
+ gtk_text_iter_assign (©, iter);
+
+ while (g_unichar_isspace (gtk_text_iter_get_char (iter)))
+ if (!gtk_text_iter_backward_char (iter))
+ GOTO (cleanup);
+
+ if (!(ch = gtk_text_iter_get_char (iter)) ||
+ (ch != '/') ||
+ !gtk_text_iter_backward_char (iter) ||
+ !(ch = gtk_text_iter_get_char (iter)) ||
+ (ch != '*') ||
+ !gtk_text_iter_backward_search (iter, "/*",
+ GTK_TEXT_SEARCH_TEXT_ONLY,
+ &match_start, &match_end, NULL) ||
+ !gtk_text_iter_backward_find_char (&match_start, non_space_predicate,
+ NULL, NULL))
+ GOTO (cleanup);
+
+ gtk_text_iter_assign (iter, &match_start);
+
+ return TRUE;
+
+cleanup:
+ gtk_text_iter_assign (iter, ©);
+
+ return FALSE;
+}
+
+static gboolean
+backward_find_matching_char (GtkTextIter *iter,
+ gunichar ch)
+{
+ GtkTextIter copy;
+ gunichar match;
+ gunichar cur;
+ guint count = 1;
+
+ switch (ch) {
+ case ')':
+ match = '(';
+ break;
+ case '}':
+ match = '{';
+ break;
+ case '[':
+ match = ']';
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gtk_text_iter_assign (©, iter);
+
+ while (gtk_text_iter_backward_char (iter))
+ {
+ cur = gtk_text_iter_get_char (iter);
+
+ if ((cur == '\'') || (cur == '"'))
+ {
+ gunichar strcur = 0;
+
+ while (gtk_text_iter_backward_char (iter))
+ {
+ strcur = gtk_text_iter_get_char (iter);
+ if (strcur == cur)
+ {
+ GtkTextIter copy2 = *iter;
+
+ /* check if the character before this is an escape char */
+ if (gtk_text_iter_backward_char (©2) &&
+ ('\\' == gtk_text_iter_get_char (©2)))
+ continue;
+
+ break;
+ }
+ }
+
+ if (strcur != cur)
+ break;
+ }
+ else if ((cur == '/') && iter_ends_c89_comment (iter))
+ {
+ GtkTextIter tmp = *iter;
+
+ if (backward_before_c89_comment (&tmp))
+ {
+ *iter = tmp;
+ cur = gtk_text_iter_get_char (iter);
+ }
+ }
+
+ if (cur == match)
+ {
+ if (--count == 0)
+ return TRUE;
+ }
+ else if (cur == ch)
+ count++;
+ }
+
+ gtk_text_iter_assign (iter, ©);
+
+ return FALSE;
+}
+
+static gboolean
+line_is_space (GtkTextIter *iter)
+{
+ GtkTextIter begin;
+
+ gtk_text_buffer_get_iter_at_line (gtk_text_iter_get_buffer (iter),
+ &begin,
+ gtk_text_iter_get_line (iter));
+
+ for (;
+ gtk_text_iter_compare (&begin, iter) < 0;
+ gtk_text_iter_forward_char (&begin))
+ {
+ if (!g_unichar_isspace (gtk_text_iter_get_char (&begin)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+starts_line_space_ok (GtkTextIter *iter)
+{
+ GtkTextIter tmp;
+
+ gtk_text_buffer_get_iter_at_line (gtk_text_iter_get_buffer (iter),
+ &tmp,
+ gtk_text_iter_get_line (iter));
+
+ for (;
+ gtk_text_iter_compare (&tmp, iter) < 0;
+ gtk_text_iter_forward_char (&tmp))
+ {
+ if (!g_unichar_isspace (gtk_text_iter_get_char (&tmp)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+backward_find_stmt_expr (GtkTextIter *iter)
+{
+ return FALSE;
+}
+
+static gboolean
+backward_to_line_first_char (GtkTextIter *iter)
+{
+ GtkTextIter tmp;
+
+ gtk_text_buffer_get_iter_at_line (gtk_text_iter_get_buffer (iter),
+ &tmp,
+ gtk_text_iter_get_line (iter));
+
+ while (gtk_text_iter_compare (&tmp, iter) <= 0)
+ {
+ gunichar ch = gtk_text_iter_get_char (&tmp);
+
+ if (!g_unichar_isspace (ch))
+ {
+ gtk_text_iter_assign (iter, &tmp);
+ return TRUE;
+ }
+
+ if (!gtk_text_iter_forward_char (&tmp))
+ break;
+ }
+
+ return FALSE;
+}
+
+/**
+ * text_iter_in_c89_comment:
+ * @location: (in): A #GtkTextIter containing the target location.
+ *
+ * The algorith for this is unfortunately trickier than one would expect.
+ * Because we could always still have context if we walk backwards that
+ * would let us know if we are in a string, we just start from the beginning
+ * of the buffer and try to skip forward until we get to our target
+ * position.
+ *
+ * Returns: %TRUE if we think we are in a c89 comment, otherwise %FALSE.
+ */
+static gboolean
+in_c89_comment (const GtkTextIter *location,
+ GtkTextIter *match_begin)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ GtkTextIter after_location;
+
+ buffer = gtk_text_iter_get_buffer (location);
+ gtk_text_buffer_get_start_iter (buffer, &iter);
+
+ after_location = *location;
+ gtk_text_iter_forward_char (&after_location);
+
+ do
+ {
+ gunichar ch;
+
+ if (gtk_text_iter_compare (&iter, location) > 0)
+ break;
+
+ ch = gtk_text_iter_get_char (&iter);
+
+ /* skip past the c89 comment */
+ if ((ch == '/') && (text_iter_peek_next_char (&iter) == '*'))
+ {
+ GtkTextIter saved = iter;
+
+ if (!gtk_text_iter_forward_chars (&iter, 2) ||
+ !gtk_text_iter_forward_search (&iter, "*/",
+ GTK_TEXT_SEARCH_TEXT_ONLY,
+ NULL, &iter, &after_location))
+ {
+ *match_begin = saved;
+ RETURN (TRUE);
+ }
+ }
+
+ /* skip past a string or character */
+ if ((ch == '\'') || (ch == '"'))
+ {
+ const gchar *match = (ch == '\'') ? "'" : "\"";
+
+ again:
+ if (!gtk_text_iter_forward_search (&iter, match,
+ GTK_TEXT_SEARCH_TEXT_ONLY,
+ NULL, NULL, NULL))
+ return FALSE;
+
+ /* this one is escaped, keep looking */
+ if (text_iter_peek_prev_char (&iter) == '\\')
+ {
+ if (!gtk_text_iter_forward_char (&iter))
+ return FALSE;
+ goto again;
+ }
+ }
+
+ /* skip past escaped character */
+ if (ch == '\\')
+ {
+ if (!gtk_text_iter_forward_char (&iter))
+ return FALSE;
+ }
+ }
+ while (gtk_text_iter_forward_char (&iter));
+
+ return FALSE;
+}
+
+static gchar *
+c_indenter_indent (IdeCIndenter *c,
+ GtkTextView *view,
+ GtkTextBuffer *buffer,
+ GtkTextIter *iter)
+{
+ GtkTextIter cur;
+ GtkTextIter match_begin;
+ gunichar ch;
+ GString *str;
+ gchar *ret = NULL;
+ gchar *last_word = NULL;
+
+ ENTRY;
+
+ g_return_val_if_fail (IDE_IS_C_INDENTER (c), NULL);
+
+ /*
+ * Save our current iter position to restore it later.
+ */
+ gtk_text_iter_assign (&cur, iter);
+
+ /*
+ * Move to before the character just inserted.
+ */
+ gtk_text_iter_backward_char (iter);
+
+ /*
+ * Create the buffer for our indentation string.
+ */
+ str = g_string_new (NULL);
+
+ /*
+ * Move backwards to the last non-space character inserted. We need to
+ * start by moving back one character to get to the pre-newline insertion
+ * point.
+ */
+ if (g_unichar_isspace (gtk_text_iter_get_char (iter)))
+ if (!gtk_text_iter_backward_find_char (iter, non_space_predicate, NULL, NULL))
+ GOTO (cleanup);
+
+ /*
+ * Get our last non \n character entered.
+ */
+ ch = gtk_text_iter_get_char (iter);
+
+ /*
+ * If we are in a c89 multi-line comment, try to match the previous comment
+ * line. Function will leave iter at original position unless it matched.
+ * If so, it will be at the beginning of the comment.
+ */
+ if (in_c89_comment (iter, &match_begin))
+ {
+ guint offset;
+
+ gtk_text_iter_assign (iter, &match_begin);
+ offset = gtk_text_iter_get_line_offset (iter);
+ build_indent (c, offset + 1, iter, str);
+ g_string_append (str, "* ");
+ GOTO (cleanup);
+ }
+
+ /*
+ * If the next thing looking backwards is a complete c89 comment, let's
+ * move the iter to before the comment so that we can work with the syntax
+ * that is before it.
+ */
+ if (backward_before_c89_comment (iter))
+ gtk_text_iter_assign (&cur, iter);
+
+ /*
+ * Get our new character as we possibely moved.
+ */
+ ch = gtk_text_iter_get_char (iter);
+
+ /*
+ * We could be:
+ * - In a parameter list for a function declaration.
+ * - In an argument list for a function call.
+ * - Defining enum fields.
+ * - XXX: bunch more.
+ */
+ if (ch == ',')
+ {
+ guint offset;
+
+ if (!backward_find_matching_char (iter, ')') &&
+ !backward_find_matching_char (iter, '}'))
+ GOTO (cleanup);
+
+ offset = gtk_text_iter_get_line_offset (iter);
+
+ if (gtk_text_iter_get_char (iter) == '(')
+ offset++;
+ else if (gtk_text_iter_get_char (iter) == '{')
+ {
+ /*
+ * Handle the case where { is not the first character,
+ * like "enum {".
+ */
+ if (backward_to_line_first_char (iter))
+ offset = gtk_text_iter_get_line_offset (iter);
+ offset += c->scope_indent;
+ }
+
+ build_indent (c, offset, iter, str);
+ GOTO (cleanup);
+ }
+
+ /*
+ * Looks like the last line was a statement or expression. Let's try to
+ * find the beginning of it.
+ */
+ if (ch == ';')
+ {
+ guint offset;
+
+ if (backward_find_stmt_expr (iter))
+ {
+ offset = gtk_text_iter_get_line_offset (iter);
+ build_indent (c, offset, iter, str);
+ GOTO (cleanup);
+ }
+ }
+
+ /*
+ * Maybe we are in a conditional.
+ *
+ * TODO: This technically isn't right since it is perfectly reasonable to
+ * end a line on a ) but not be done with the entire conditional.
+ */
+ if ((ch != ')') && backward_find_matching_char (iter, ')'))
+ {
+ guint offset;
+
+ offset = gtk_text_iter_get_line_offset (iter);
+ build_indent (c, offset + 1, iter, str);
+ GOTO (cleanup);
+ }
+
+ /*
+ * If we just ended a scope, we need to look for the matching scope
+ * before it.
+ */
+ if (ch == '}')
+ {
+ GtkTextIter copy;
+
+ gtk_text_iter_assign (©, iter);
+
+ if (gtk_text_iter_forward_char (iter))
+ {
+ guint offset = gtk_text_iter_get_line_offset (iter) - 1;
+
+ if (backward_find_matching_char (iter, '}'))
+ {
+ offset = gtk_text_iter_get_line_offset (iter);
+ offset += c->scope_indent;
+ }
+
+ build_indent (c, offset, iter, str);
+ GOTO (cleanup);
+ }
+
+ gtk_text_iter_assign (iter, ©);
+ }
+
+ /*
+ * Check to see if we just finished a conditional.
+ */
+ if (ch == ')')
+ {
+ GtkTextIter copy;
+
+ gtk_text_iter_assign (©, iter);
+
+ if (backward_find_matching_char (iter, ')') &&
+ backward_find_condition_keyword (iter))
+ {
+ guint offset = gtk_text_iter_get_line_offset (iter);
+ build_indent (c, offset + c->condition_indent, iter, str);
+ GOTO (cleanup);
+ }
+
+ gtk_text_iter_assign (iter, ©);
+ }
+
+ /*
+ * Check to see if we are after else or do. Skip if we see '{'
+ * so that we can fallback to regular scoping rules.
+ */
+ last_word = backward_last_word (iter, &match_begin);
+ if ((ch != '{') &&
+ ((g_strcmp0 (last_word, "else") == 0) ||
+ (g_strcmp0 (last_word, "do") == 0)))
+ {
+ guint offset;
+
+ if (!line_is_whitespace_until (&match_begin))
+ backward_to_line_first_char (&match_begin);
+
+ offset = gtk_text_iter_get_line_offset (&match_begin);
+ build_indent (c, offset + c->scope_indent, iter, str);
+ GOTO (cleanup);
+ }
+
+ /*
+ * Work our way back to the most recent scope. Then apply our scope
+ * indentation to that.
+ */
+ if (ch == '{' || backward_find_matching_char (iter, '}'))
+ {
+ if (line_is_space (iter))
+ {
+ guint offset;
+
+ offset = gtk_text_iter_get_line_offset (iter);
+ build_indent (c, offset + c->scope_indent, iter, str);
+ GOTO (cleanup);
+ }
+ else
+ {
+ if (backward_to_line_first_char (iter))
+ {
+ guint offset;
+
+ offset = gtk_text_iter_get_line_offset (iter);
+ build_indent (c, offset + c->scope_indent, iter, str);
+ GOTO (cleanup);
+ }
+ }
+ }
+
+cleanup:
+ gtk_text_iter_assign (iter, &cur);
+ g_free (last_word);
+
+ ret = g_string_free (str, FALSE);
+
+ RETURN (ret);
+}
+
+static gchar *
+maybe_close_comment (IdeCIndenter *c,
+ GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ GtkTextIter copy;
+ GtkTextIter begin_comment;
+ gchar *ret = NULL;
+
+ g_return_val_if_fail (IDE_IS_C_INDENTER (c), NULL);
+ g_return_val_if_fail (begin, NULL);
+ g_return_val_if_fail (end, NULL);
+
+ gtk_text_iter_assign (©, begin);
+
+ /*
+ * Walk backwards ensuring we just inserted a '/' and that it was after
+ * a '* ' sequence.
+ */
+ if (in_c89_comment (begin, &begin_comment) &&
+ gtk_text_iter_backward_char (begin) &&
+ ('/' == gtk_text_iter_get_char (begin)) &&
+ gtk_text_iter_backward_char (begin) &&
+ (' ' == gtk_text_iter_get_char (begin)) &&
+ gtk_text_iter_backward_char (begin) &&
+ ('*' == gtk_text_iter_get_char (begin)))
+ ret = g_strdup ("*/");
+ else
+ gtk_text_iter_assign (begin, ©);
+
+ return ret;
+}
+
+static gchar *
+maybe_unindent_brace (IdeCIndenter *c,
+ GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ GtkTextIter saved;
+ gchar *ret = NULL;
+
+ ENTRY;
+
+ g_return_val_if_fail (IDE_IS_C_INDENTER (c), NULL);
+ g_return_val_if_fail (begin, NULL);
+ g_return_val_if_fail (end, NULL);
+
+ gtk_text_iter_assign (&saved, begin);
+
+ if (gtk_text_iter_backward_char (begin) &&
+ gtk_text_iter_backward_char (end) &&
+ backward_find_matching_char (begin, '}') &&
+ line_is_whitespace_until (end) &&
+ ((gtk_text_iter_get_offset (begin) + 1) !=
+ gtk_text_iter_get_offset (end)))
+ {
+ GString *str;
+ guint offset;
+
+ /*
+ * Handle the case where { is not the first non-whitespace
+ * character on the line.
+ */
+ if (!starts_line_space_ok (begin))
+ backward_to_line_first_char (begin);
+
+ offset = gtk_text_iter_get_line_offset (begin);
+ str = g_string_new (NULL);
+ build_indent (c, offset, begin, str);
+ g_string_append_c (str, '}');
+
+ gtk_text_iter_assign (begin, &saved);
+ while (!gtk_text_iter_starts_line (begin))
+ gtk_text_iter_backward_char (begin);
+
+ gtk_text_iter_assign (end, &saved);
+
+ ret = g_string_free (str, FALSE);
+ }
+
+ if (!ret)
+ {
+ gtk_text_iter_assign (begin, &saved);
+ gtk_text_iter_assign (end, &saved);
+ }
+
+ RETURN (ret);
+}
+
+static gchar *
+maybe_unindent_hash (IdeCIndenter *c,
+ GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ GtkTextIter saved;
+ gchar *ret = NULL;
+
+ g_return_val_if_fail (IDE_IS_C_INDENTER (c), NULL);
+ g_return_val_if_fail (begin, NULL);
+ g_return_val_if_fail (end, NULL);
+
+ gtk_text_iter_assign (&saved, begin);
+
+ if (gtk_text_iter_backward_char (begin) &&
+ ('#' == gtk_text_iter_get_char (begin)) &&
+ line_is_whitespace_until (begin))
+ {
+ if (c->directive_indent == G_MININT)
+ {
+ while (!gtk_text_iter_starts_line (begin))
+ gtk_text_iter_backward_char (begin);
+ ret = g_strdup ("#");
+ }
+ else
+ {
+ /* TODO: Handle indent when not fully unindenting. */
+ }
+ }
+
+ if (!ret)
+ gtk_text_iter_assign (begin, &saved);
+
+ return ret;
+}
+
+static gboolean
+line_starts_with_fuzzy (const GtkTextIter *iter,
+ const gchar *prefix)
+{
+ GtkTextIter begin;
+ GtkTextIter end;
+ gboolean ret;
+ gchar *line;
+
+ ITER_INIT_LINE_START (&begin, iter);
+ ITER_INIT_LINE_START (&end, iter);
+
+ while (!gtk_text_iter_ends_line (&end))
+ if (!gtk_text_iter_forward_char (&end))
+ return FALSE;
+
+ line = g_strstrip (gtk_text_iter_get_slice (&begin, &end));
+ ret = g_str_has_prefix (line, prefix);
+ g_free (line);
+
+ return ret;
+}
+
+#if 0
+static gchar *
+maybe_space_before_paren (IdeCIndenter *c,
+ GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ GtkTextIter match_begin;
+ GtkTextIter copy;
+ gunichar ch;
+
+ g_return_val_if_fail (IDE_IS_C_INDENTER (c), NULL);
+ g_return_val_if_fail (begin, NULL);
+ g_return_val_if_fail (end, NULL);
+
+ if (!c->priv->space_before_paren)
+ return NULL;
+
+ if (in_c89_comment (begin, &match_begin))
+ return NULL;
+
+ /* ignore preprocessor #define */
+ if (line_starts_with_fuzzy (begin, "#"))
+ return NULL;
+
+ gtk_text_iter_assign (©, begin);
+
+ /*
+ * Move back to the character just inserted.
+ */
+ if (gtk_text_iter_backward_char (begin) &&
+ (ch = gtk_text_iter_get_char (begin)) &&
+ (ch == '(') &&
+ gtk_text_iter_backward_char (begin) &&
+ (ch = gtk_text_iter_get_char (begin)) &&
+ !g_unichar_isspace (ch) &&
+ g_unichar_isalnum (ch))
+ {
+ gtk_text_iter_forward_char (begin);
+ return g_strdup (" (");
+ }
+
+ gtk_text_iter_assign (begin, ©);
+
+ return NULL;
+}
+#endif
+
+static gchar *
+format_parameter (const Parameter *param,
+ guint max_type,
+ guint max_star)
+{
+ GString *str;
+ guint i;
+
+ if (param->ellipsis)
+ return g_strdup ("...");
+
+ str = g_string_new (param->type);
+
+ for (i = str->len; i < max_type; i++)
+ g_string_append_c (str, ' ');
+
+ g_string_append_c (str, ' ');
+
+ for (i = max_star; i > 0; i--)
+ {
+ if (i <= param->n_star)
+ g_string_append_c (str, '*');
+ else
+ g_string_append_c (str, ' ');
+ }
+
+ g_string_append (str, param->name);
+
+ return g_string_free (str, FALSE);
+}
+
+static gchar *
+format_parameters (GtkTextIter *begin,
+ GSList *params)
+{
+ GtkTextIter line_start;
+ GtkTextIter first_char;
+ GString *str;
+ GSList *iter;
+ gchar *slice;
+ gchar *join_str;
+ guint max_star = 0;
+ guint max_type = 0;
+
+ for (iter = params; iter; iter = iter->next)
+ {
+ Parameter *p = iter->data;
+
+ if (p->n_star)
+ max_star = MAX (max_star, p->n_star);
+ if (p->type)
+ max_type = MAX (max_type, strlen (p->type));
+ }
+
+ str = g_string_new (NULL);
+
+ ITER_INIT_LINE_START (&line_start, begin);
+
+ gtk_text_iter_assign (&first_char, begin);
+ backward_to_line_first_char (&first_char);
+
+ slice = gtk_text_iter_get_slice (&line_start, &first_char);
+ str = g_string_new (",\n");
+ g_string_append (str, slice);
+ g_free (slice);
+
+ while (gtk_text_iter_compare (&first_char, begin) < 0)
+ {
+ g_string_append (str, " ");
+ if (!gtk_text_iter_forward_char (&first_char))
+ break;
+ }
+
+ join_str = g_string_free (str, FALSE);
+ str = g_string_new (NULL);
+
+ for (iter = params; iter; iter = iter->next)
+ {
+ gchar *param_str;
+
+ if (iter != params)
+ g_string_append (str, join_str);
+
+ param_str = format_parameter (iter->data, max_type, max_star);
+ g_string_append (str, param_str);
+ }
+
+ g_free (join_str);
+
+ return g_string_free (str, FALSE);
+}
+
+static gchar *
+maybe_align_parameters (IdeCIndenter *c,
+ GtkTextIter *begin,
+ GtkTextIter *end)
{
- IdeCIndenter *self = IDE_C_INDENTER (object);
+ GtkTextIter match_begin;
+ GtkTextIter copy;
+ GSList *params = NULL;
+ gchar *ret = NULL;
+ gchar *text = NULL;
- switch (prop_id)
+ ENTRY;
+
+ g_return_val_if_fail (IDE_IS_C_INDENTER (c), NULL);
+ g_return_val_if_fail (begin, NULL);
+ g_return_val_if_fail (end, NULL);
+
+ if (in_c89_comment (begin, &match_begin))
+ RETURN (NULL);
+
+ gtk_text_iter_assign (©, begin);
+
+ if (gtk_text_iter_backward_char (begin) &&
+ backward_find_matching_char (begin, ')') &&
+ gtk_text_iter_forward_char (begin) &&
+ gtk_text_iter_backward_char (end) &&
+ (gtk_text_iter_compare (begin, end) < 0) &&
+ (text = gtk_text_iter_get_slice (begin, end)) &&
+ (params = parse_parameters (text)) &&
+ (params->next != NULL))
+ ret = format_parameters (begin, params);
+
+ g_slist_foreach (params, (GFunc)parameter_free, NULL);
+ g_slist_free (params);
+
+ if (!ret)
+ {
+ gtk_text_iter_assign (begin, ©);
+ gtk_text_iter_assign (end, ©);
+ }
+
+ g_free (text);
+
+ RETURN (ret);
+}
+
+#if 0
+static gchar *
+maybe_add_brace (IdeCIndenter *c,
+ GtkTextIter *begin,
+ GtkTextIter *end,
+ gint *cursor_offset)
+{
+ GtkTextIter iter;
+
+ gtk_text_iter_assign (&iter, begin);
+
+ if (gtk_text_iter_backward_char (&iter) &&
+ (gtk_text_iter_get_char (&iter) == '{') &&
+ (gtk_text_iter_get_char (begin) != '}'))
+ {
+ GtkTextIter copy = iter;
+
+ gtk_text_iter_assign (©, &iter);
+
+ if (gtk_text_iter_backward_word_start (©))
+ {
+ GtkTextIter copy2 = copy;
+
+ if (gtk_text_iter_forward_word_end (©2))
+ {
+ gchar *word;
+
+ word = gtk_text_iter_get_slice (©, ©2);
+
+ if ((g_strcmp0 (word, "enum") == 0) ||
+ (g_strcmp0 (word, "struct") == 0))
+ {
+ *cursor_offset = -2;
+ g_free (word);
+ return g_strdup ("};");
+ }
+
+ g_free (word);
+ }
+ }
+
+ *cursor_offset = -1;
+ return g_strdup ("}");
+ }
+
+ return NULL;
+}
+#endif
+
+static gboolean
+line_is_case (const GtkTextIter *line)
+{
+ return (line_starts_with_fuzzy (line, "case ") ||
+ line_starts_with_fuzzy (line, "default:"));
+}
+
+static gboolean
+str_maybe_label (const gchar *str)
+{
+ const gchar *ptr = str;
+
+ if (g_strcmp0 (str, "default:") == 0)
+ return FALSE;
+
+ for (; *ptr; ptr = g_utf8_next_char (ptr))
+ {
+ gunichar ch = g_utf8_get_char (ptr);
+
+ switch (ch)
+ {
+ case ':':
+ case '_':
+ break;
+ default:
+ if (!g_unichar_isalnum (ch))
+ return FALSE;
+ }
+ }
+
+ return (*str != '\0');
+}
+
+static gboolean
+line_is_label (const GtkTextIter *line)
+{
+ GtkTextIter begin;
+ GtkTextIter end;
+ gchar *text;
+ gchar **parts;
+ guint i;
+ guint count = 0;
+
+ gtk_text_iter_assign (&begin, line);
+ while (!gtk_text_iter_starts_line (&begin))
+ if (!gtk_text_iter_backward_char (&begin))
+ return FALSE;
+
+ gtk_text_iter_assign (&end, line);
+ while (!gtk_text_iter_ends_line (&end))
+ if (!gtk_text_iter_forward_char (&end))
+ return FALSE;
+
+ text = gtk_text_iter_get_slice (&begin, &end);
+ g_strdelimit (text, "\t", ' ');
+ parts = g_strsplit (text, " ", 0);
+
+ for (i = 0; parts [i]; i++)
+ {
+ g_strstrip (parts [i]);
+ if (*parts [i])
+ count++;
+ }
+
+ if (count > 1)
+ return FALSE;
+
+ count = 0;
+
+ for (i = 0; parts [i]; i++)
+ {
+ g_strstrip (parts [i]);
+ if (str_maybe_label (parts [i]))
+ count++;
+ }
+
+ g_free (text);
+ g_strfreev (parts);
+
+ return (count == 1);
+}
+
+static gchar *
+maybe_unindent_case_label (IdeCIndenter *c,
+ GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ GtkTextIter match_begin;
+ GtkTextIter iter;
+
+ ENTRY;
+
+ gtk_text_iter_assign (&iter, begin);
+
+ if (in_c89_comment (begin, &match_begin))
+ RETURN (NULL);
+
+ if (!gtk_text_iter_backward_char (&iter))
+ RETURN (NULL);
+
+ if (line_is_case (&iter))
+ {
+ if (backward_find_matching_char (&iter, '}'))
+ {
+ if (line_is_whitespace_until (&iter))
+ {
+ GString *str;
+ guint offset;
+
+ str = g_string_new (NULL);
+ offset = gtk_text_iter_get_line_offset (&iter);
+ build_indent (c, offset, &iter, str);
+ while (!gtk_text_iter_starts_line (begin))
+ gtk_text_iter_backward_char (begin);
+ gtk_text_iter_assign (end, begin);
+ while (g_unichar_isspace (gtk_text_iter_get_char (end)))
+ if (!gtk_text_iter_forward_char (end))
+ RETURN (NULL);
+ return g_string_free (str, FALSE);
+ }
+ else
+ {
+ if (backward_to_line_first_char (&iter))
+ {
+#if 0
+ TODO ("Deal with nested {");
+#endif
+ }
+ }
+ }
+ }
+ else if (line_is_label (&iter))
{
+#if 0
+ TODO ("allow configurable label indent");
+#endif
+
+ ITER_INIT_LINE_START (begin, &iter);
+ ITER_INIT_LINE_START (end, &iter);
+
+ while (g_unichar_isspace (gtk_text_iter_get_char (end)))
+ if (!gtk_text_iter_forward_char (end))
+ return NULL;
+
+ return g_strdup ("");
+ }
+
+ RETURN (NULL);
+}
+
+static gboolean
+ide_c_indenter_is_trigger (IdeIndenter *indenter,
+ GdkEventKey *event)
+{
+ switch (event->keyval)
+ {
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_Return:
+ if ((event->state & GDK_SHIFT_MASK) != 0)
+ return FALSE;
+ /* Fall through */
+
+ case GDK_KEY_braceright:
+ case GDK_KEY_colon:
+ case GDK_KEY_numbersign:
+ case GDK_KEY_parenright:
+ case GDK_KEY_slash:
+ return TRUE;
+
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ return FALSE;
}
}
+static gchar *
+ide_c_indenter_format (IdeIndenter *indenter,
+ GtkTextView *view,
+ GtkTextIter *begin,
+ GtkTextIter *end,
+ gint *cursor_offset,
+ GdkEventKey *event)
+{
+ IdeCIndenter *c = (IdeCIndenter *)indenter;
+ GtkTextIter begin_copy;
+ gchar *ret = NULL;
+ GtkTextBuffer *buffer;
+
+ g_return_val_if_fail (IDE_IS_C_INDENTER (c), NULL);
+
+ buffer = gtk_text_view_get_buffer (view);
+
+ switch (event->keyval) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ gtk_text_iter_assign (&begin_copy, begin);
+ ret = c_indenter_indent (c, view, buffer, begin);
+ gtk_text_iter_assign (begin, &begin_copy);
+
+ /*
+ * If we are inserting a newline right before a closing brace (for example
+ * after {<cursor>}, we need to indent and then maybe unindent the }.
+ */
+ if (gtk_text_iter_get_char (begin) == '}')
+ {
+ GtkTextIter iter;
+ GString *str;
+ gchar *tmp = ret;
+ guint offset = 0;
+
+ str = g_string_new (NULL);
+
+ gtk_text_iter_assign (&iter, begin);
+ if (backward_find_matching_char (&iter, '}'))
+ {
+ if (line_is_whitespace_until (&iter))
+ offset = gtk_text_iter_get_line_offset (&iter);
+ else if (backward_to_line_first_char (&iter))
+ offset = gtk_text_iter_get_line_offset (&iter);
+ build_indent (c, offset, &iter, str);
+ g_string_prepend (str, "\n");
+ g_string_prepend (str, ret);
+
+ *cursor_offset = -(str->len - strlen (ret));
+
+ ret = g_string_free (str, FALSE);
+ g_free (tmp);
+ }
+ }
+
+ break;
+
+ case GDK_KEY_braceright:
+ /*
+ * Probably need to unindent this line.
+ * TODO: Maybe overwrite character.
+ */
+ ret = maybe_unindent_brace (c, begin, end);
+ break;
+
+ case GDK_KEY_colon:
+ /*
+ * If this is a label or a case, adjust indentation.
+ */
+ ret = maybe_unindent_case_label (c, begin, end);
+ break;
+
+ case GDK_KEY_numbersign:
+ /*
+ * If this is a preprocessor directive, adjust indentation.
+ */
+ ret = maybe_unindent_hash (c, begin, end);
+ break;
+
+ case GDK_KEY_parenright:
+ /*
+ * If we are closing a function declaration, adjust the spacing of
+ * parameters so that *'s are aligned.
+ */
+ ret = maybe_align_parameters (c, begin, end);
+ break;
+
+ case GDK_KEY_slash:
+ /*
+ * Check to see if we are right after a "* " and typing "/" while inside
+ * of a multi-line comment. Probably just want to close the comment.
+ */
+ ret = maybe_close_comment (c, begin, end);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
static void
ide_c_indenter_class_init (IdeCIndenterClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ IdeIndenterClass *indenter_class = IDE_INDENTER_CLASS (klass);
- object_class->finalize = ide_c_indenter_finalize;
- object_class->get_property = ide_c_indenter_get_property;
- object_class->set_property = ide_c_indenter_set_property;
+ indenter_class->is_trigger = ide_c_indenter_is_trigger;
+ indenter_class->format = ide_c_indenter_format;
}
static void
ide_c_indenter_init (IdeCIndenter *self)
{
+ self->condition_indent = 2;
+ self->scope_indent = 2;
+ self->directive_indent = G_MININT;
+ self->space_before_paren = TRUE;
}
diff --git a/libide/c/ide-c-indenter.h b/libide/c/ide-c-indenter.h
index a7e8ce8..ec9938a 100644
--- a/libide/c/ide-c-indenter.h
+++ b/libide/c/ide-c-indenter.h
@@ -25,12 +25,7 @@ G_BEGIN_DECLS
#define IDE_TYPE_C_INDENTER (ide_c_indenter_get_type())
-G_DECLARE_DERIVABLE_TYPE (IdeCIndenter, ide_c_indenter, IDE, C_INDENTER, IdeIndenter)
-
-struct _IdeCIndenterClass
-{
- IdeIndenterClass parent;
-};
+G_DECLARE_FINAL_TYPE (IdeCIndenter, ide_c_indenter, IDE, C_INDENTER, IdeIndenter)
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]