[gnome-builder/wip/libide: 190/237] libide: used editorconfig-core-c implementation



commit d9490d95e02e3a21a51eec26296366f5826f9f9a
Author: Christian Hergert <christian hergert me>
Date:   Sat Feb 14 21:00:49 2015 -0800

    libide: used editorconfig-core-c implementation

 .gitignore                                         |    2 +
 libide/Makefile.am                                 |    8 +-
 libide/editorconfig/editorconfig-glib.c            |  118 +++++
 .../{editorconfig.h => editorconfig-glib.h}        |   12 +-
 libide/editorconfig/editorconfig.c                 |  369 -------------
 .../editorconfig/ide-editorconfig-file-settings.c  |    9 +-
 libide/editorconfig/libeditorconfig/Makefile.am    |   37 ++
 libide/editorconfig/libeditorconfig/ec_glob.c      |  367 +++++++++++++
 libide/editorconfig/libeditorconfig/ec_glob.h      |   43 ++
 libide/editorconfig/libeditorconfig/editorconfig.c |  540 ++++++++++++++++++++
 libide/editorconfig/libeditorconfig/editorconfig.h |   37 ++
 .../libeditorconfig/editorconfig/editorconfig.h    |  309 +++++++++++
 .../editorconfig/editorconfig_handle.h             |  193 +++++++
 .../libeditorconfig/editorconfig_handle.c          |  155 ++++++
 .../libeditorconfig/editorconfig_handle.h          |   89 ++++
 libide/editorconfig/libeditorconfig/global.h       |   80 +++
 libide/editorconfig/libeditorconfig/ini.c          |  200 ++++++++
 libide/editorconfig/libeditorconfig/ini.h          |   93 ++++
 libide/editorconfig/libeditorconfig/misc.c         |  250 +++++++++
 libide/editorconfig/libeditorconfig/misc.h         |   62 +++
 libide/editorconfig/libeditorconfig/utarray.h      |  232 +++++++++
 libide/ide-file-settings.h                         |    2 +-
 22 files changed, 2825 insertions(+), 382 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 65c9690..b329854 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
 *.deps
+*.gch
 *.gz
+*.la
 *.libs
 *.lo
 *.log
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 1bb5f5c..5c942ad 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -1,3 +1,5 @@
+include libide/editorconfig/libeditorconfig/Makefile.am
+
 noinst_LTLIBRARIES += libide.la
 
 libide_la_public_sources = \
@@ -134,8 +136,8 @@ libide_la_public_sources = \
 
 libide_la_SOURCES = \
        $(libide_la_public_sources) \
-       libide/editorconfig/editorconfig.c \
-       libide/editorconfig/editorconfig.h \
+       libide/editorconfig/editorconfig-glib.c \
+       libide/editorconfig/editorconfig-glib.h \
        libide/gconstructor.h \
        libide/ide-async-helper.c \
        libide/ide-async-helper.h \
@@ -151,6 +153,7 @@ libide_la_CFLAGS = \
        -I$(top_srcdir)/libide/clang \
        -I$(top_srcdir)/libide/directory \
        -I$(top_srcdir)/libide/editorconfig \
+       -I$(top_srcdir)/libide/editorconfig/libeditorconfig \
        -I$(top_srcdir)/libide/git \
        -I$(top_srcdir)/libide/gsettings \
        -I$(top_srcdir)/libide/local \
@@ -161,6 +164,7 @@ libide_la_LIBADD = \
        $(CLANG_LDFLAGS) \
        $(LIBIDE_LIBS) \
        -lclang \
+       libeditorconfig.la \
        $(NULL)
 
 
diff --git a/libide/editorconfig/editorconfig-glib.c b/libide/editorconfig/editorconfig-glib.c
new file mode 100644
index 0000000..c30a3c8
--- /dev/null
+++ b/libide/editorconfig/editorconfig-glib.c
@@ -0,0 +1,118 @@
+/* editorconfig-glib.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser 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/>.
+ */
+
+#include <editorconfig/editorconfig.h>
+
+#include "editorconfig-glib.h"
+
+static void
+_g_value_free (gpointer data)
+{
+  GValue *value = data;
+
+  g_value_unset (value);
+  g_free (value);
+}
+
+GHashTable *
+editorconfig_glib_read (GFile         *file,
+                        GCancellable  *cancellable,
+                        GError       **error)
+{
+  editorconfig_handle handle = { 0 };
+  GHashTable *ret = NULL;
+  gchar *filename = NULL;
+  gint code;
+  gint count;
+  guint i;
+
+  filename = g_file_get_path (file);
+
+  if (!filename)
+    {
+      /*
+       * This sucks, but we need to basically rewrite editorconfig library
+       * to support this. Not out of the question, but it is for today.
+       */
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_NOT_SUPPORTED,
+                   "only local files are currently supported");
+      return NULL;
+    }
+
+  handle = editorconfig_handle_init ();
+  code = editorconfig_parse (filename, handle);
+
+  switch (code)
+    {
+    case 0:
+      break;
+
+    case EDITORCONFIG_PARSE_NOT_FULL_PATH:
+    case EDITORCONFIG_PARSE_MEMORY_ERROR:
+    case EDITORCONFIG_PARSE_VERSION_TOO_NEW:
+    default:
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_FAILED,
+                   "Failed to parse editorconfig.");
+      goto cleanup;
+    }
+
+  ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _g_value_free);
+
+  count = editorconfig_handle_get_name_value_count (handle);
+
+  for (i = 0; i < count; i++)
+    {
+      GValue *value;
+      const gchar *key = NULL;
+      const gchar *valuestr = NULL;
+
+      value = g_new0 (GValue, 1);
+
+      editorconfig_handle_get_name_value (handle, i, &key, &valuestr);
+
+      if ((g_strcmp0 (key, "tab_width") == 0) ||
+          (g_strcmp0 (key, "indent_size") == 0))
+        {
+          g_value_init (value, G_TYPE_INT);
+          g_value_set_int (value, g_ascii_strtoll (valuestr, NULL, 10));
+        }
+      else if ((g_strcmp0 (key, "insert_final_newline") == 0) ||
+               (g_strcmp0 (key, "trim_trailing_whitespace") == 0))
+        {
+          g_value_init (value, G_TYPE_BOOLEAN);
+          g_value_set_boolean (value, g_str_equal (valuestr, "true"));
+        }
+      else
+        {
+          g_value_init (value, G_TYPE_STRING);
+          g_value_set_string (value, valuestr);
+        }
+
+      g_hash_table_replace (ret, g_strdup (key), value);
+    }
+
+cleanup:
+  editorconfig_handle_destroy (handle);
+  g_free (filename);
+
+  return ret;
+}
diff --git a/libide/editorconfig/editorconfig.h b/libide/editorconfig/editorconfig-glib.h
similarity index 63%
rename from libide/editorconfig/editorconfig.h
rename to libide/editorconfig/editorconfig-glib.h
index d3bda86..5f57530 100644
--- a/libide/editorconfig/editorconfig.h
+++ b/libide/editorconfig/editorconfig-glib.h
@@ -8,13 +8,13 @@
  * all present and future rights to this code under copyright law.
  */
 
-#ifndef EDITORCONFIG_H
-#define EDITORCONFIG_H
+#ifndef EDITORCONFIG_GLIB_H
+#define EDITORCONFIG_GLIB_H
 
 #include <gio/gio.h>
 
-GHashTable *editorconfig_read (GFile         *file,
-                               GCancellable  *cancellable,
-                               GError       **error);
+GHashTable *editorconfig_glib_read (GFile         *file,
+                                    GCancellable  *cancellable,
+                                    GError       **error);
 
-#endif /* EDITORCONFIG_H */
+#endif /* EDITORCONFIG_GLIB_H */
diff --git a/libide/editorconfig/ide-editorconfig-file-settings.c 
b/libide/editorconfig/ide-editorconfig-file-settings.c
index 0ec4d26..da6883b 100644
--- a/libide/editorconfig/ide-editorconfig-file-settings.c
+++ b/libide/editorconfig/ide-editorconfig-file-settings.c
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <editorconfig.h>
+#include <editorconfig-glib.h>
 #include <glib/gi18n.h>
 
 #include "ide-editorconfig-file-settings.h"
@@ -63,7 +63,7 @@ ide_editorconfig_file_settings_init_worker (GTask        *task,
   g_assert (G_IS_FILE (file));
   g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
 
-  ht = editorconfig_read (file, cancellable, &error);
+  ht = editorconfig_glib_read (file, cancellable, &error);
 
   if (!ht)
     {
@@ -82,9 +82,10 @@ ide_editorconfig_file_settings_init_worker (GTask        *task,
       if (g_str_equal (key, "indent_size"))
         g_object_set_property (source_object, "indent_width", value);
       else if (g_str_equal (key, "tab_width") ||
-               g_str_equal (key, "trim_trailing_whitespace") ||
-               g_str_equal (key, "insert_final_newline"))
+               g_str_equal (key, "trim_trailing_whitespace"))
         g_object_set_property (source_object, key, value);
+      else if (g_str_equal (key, "insert_final_newline"))
+        g_object_set_property (source_object, "insert_trailing_newline", value);
       else if (g_str_equal (key, "charset"))
         g_object_set_property (source_object, "encoding", value);
       else if (g_str_equal (key, "end_of_line"))
diff --git a/libide/editorconfig/libeditorconfig/Makefile.am b/libide/editorconfig/libeditorconfig/Makefile.am
new file mode 100644
index 0000000..79e6133
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/Makefile.am
@@ -0,0 +1,37 @@
+noinst_LTLIBRARIES += libeditorconfig.la
+
+libeditorconfig_la_SOURCES = \
+       libide/editorconfig/libeditorconfig/editorconfig.c \
+       libide/editorconfig/libeditorconfig/misc.c \
+       libide/editorconfig/libeditorconfig/ini.c \
+       libide/editorconfig/libeditorconfig/ec_glob.c \
+       libide/editorconfig/libeditorconfig/editorconfig_handle.c \
+       libide/editorconfig/libeditorconfig/editorconfig_handle.h \
+       libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h \
+       libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h \
+       libide/editorconfig/libeditorconfig/global.h \
+       libide/editorconfig/libeditorconfig/ec_glob.h \
+       libide/editorconfig/libeditorconfig/utarray.h \
+       libide/editorconfig/libeditorconfig/editorconfig.h \
+       libide/editorconfig/libeditorconfig/misc.h \
+       libide/editorconfig/libeditorconfig/ini.h \
+       $(NULL)
+
+libeditorconfig_la_LIBADD = \
+       -lpcre \
+       $(NULL)
+
+libeditorconfig_la_CFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/libide/editorconfig/libeditorconfig \
+       -D_GNU_SOURCE \
+       -DHAVE_STRCASECMP \
+       -DHAVE_STRICMP \
+       -DHAVE_STRDUP \
+       -DHAVE_STRNDUP \
+       -DUNIX \
+       -Deditorconfig_VERSION_MAJOR=0 \
+       -Deditorconfig_VERSION_MINOR=0 \
+       -Deditorconfig_VERSION_PATCH=0 \
+       -Deditorconfig_VERSION_SUFFIX=0 \
+       $(NULL)
diff --git a/libide/editorconfig/libeditorconfig/ec_glob.c b/libide/editorconfig/libeditorconfig/ec_glob.c
new file mode 100644
index 0000000..8fd4f32
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ec_glob.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2014 Hong Xu <hong AT topbug DOT net>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "global.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <pcre.h>
+
+#include "utarray.h"
+#include "misc.h"
+
+#include "ec_glob.h"
+
+typedef struct int_pair
+{
+    int     num1;
+    int     num2;
+} int_pair;
+static const UT_icd ut_int_pair_icd = {sizeof(int_pair),NULL,NULL,NULL};
+
+/* concatenate the string then move the pointer to the end */
+#define STRING_CAT(p, string, end)  do {    \
+    size_t string_len = strlen(string); \
+    if (p + string_len >= end) \
+        return -1; \
+    strcat(p, string); \
+    p += string_len; \
+} while(0)
+
+#define PATTERN_MAX  300
+/*
+ * Whether the string matches the given glob pattern
+ */
+EDITORCONFIG_LOCAL
+int ec_glob(const char *pattern, const char *string)
+{
+    size_t                    i;
+    int_pair *                p;
+    char *                    c;
+    char                      pcre_str[2 * PATTERN_MAX] = "^";
+    char *                    p_pcre;
+    char *                    pcre_str_end;
+    int                       brace_level = 0;
+    _Bool                     is_in_bracket = 0;
+    const char *              error_msg;
+    int                       erroffset;
+    pcre *                    re;
+    int                       rc;
+    int *                     pcre_result;
+    size_t                    pcre_result_len;
+    char                      l_pattern[2 * PATTERN_MAX];
+    int                       pattern_length = strlen(pattern);
+    _Bool                     are_brace_paired;
+    UT_array *                nums;     /* number ranges */
+    int                       ret = 0;
+
+    strcpy(l_pattern, pattern);
+    p_pcre = pcre_str + 1;
+    pcre_str_end = pcre_str + 2 * PATTERN_MAX;
+
+    {
+        int     left_count = 0;
+        int     right_count = 0;
+        for (c = l_pattern; *c; ++ c)
+        {
+            if (*c == '\\' && *(c+1) != '\0')
+            {
+                ++ c;
+                continue;
+            }
+
+            if (*c == '}')
+                ++ right_count;
+            if (*c == '{')
+                ++ left_count;
+        }
+
+        are_brace_paired = (right_count == left_count);
+    }
+
+    /* used to search for {num1..num2} case */
+    re = pcre_compile("^\\{[\\+\\-]?\\d+\\.\\.[\\+\\-]?\\d+\\}$", 0,
+            &error_msg, &erroffset, NULL);
+    if (!re)        /* failed to compile */
+        return -1;
+
+    utarray_new(nums, &ut_int_pair_icd);
+
+    for (c = l_pattern; *c; ++ c)
+    {
+        switch (*c)
+        {
+        case '\\':      /* also skip the next one */
+            if (*(c+1) != '\0')
+            {
+                *(p_pcre ++) = *(c++);
+                *(p_pcre ++) = *c;
+            }
+            else
+                STRING_CAT(p_pcre, "\\\\", pcre_str_end);
+
+            break;
+        case '?':
+            *(p_pcre ++) = '.';
+            break;
+        case '*':
+            if (*(c+1) == '*')      /* case of ** */
+            {
+                STRING_CAT(p_pcre, ".*", pcre_str_end);
+                ++ c;
+            }
+            else                    /* case of * */
+                STRING_CAT(p_pcre, "[^\\/]*", pcre_str_end);
+
+            break;
+        case '[':
+            if (is_in_bracket)     /* inside brackets, we really mean bracket */
+            {
+                STRING_CAT(p_pcre, "\\[", pcre_str_end);
+                break;
+            }
+
+            {
+                /* check whether we have slash within the bracket */
+                _Bool           has_slash = 0;
+                char *          cc;
+                for (cc = c; *cc && *cc != ']'; ++ cc)
+                {
+                    if (*cc == '\\' && *(cc+1) != '\0')
+                    {
+                        ++ cc;
+                        continue;
+                    }
+
+                    if (*cc == '/')
+                    {
+                        has_slash = 1;
+                        break;
+                    }
+                }
+
+                /* if we have slash in the brackets, just do it literally */
+                if (has_slash)
+                {
+                    char *           right_bracket = strchr(c, ']');
+
+                    strcat(p_pcre, "\\");
+                    strncat(p_pcre, c, right_bracket - c);
+                    strcat(p_pcre, "\\]");
+                    p_pcre += strlen(p_pcre);
+                    c = right_bracket;
+                    break;
+                }
+            }
+
+            is_in_bracket = 1;
+            if (*(c+1) == '!')     /* case of [!...] */
+            {
+                STRING_CAT(p_pcre, "[^", pcre_str_end);
+                ++ c;
+            }
+            else
+                *(p_pcre ++) = '[';
+
+            break;
+
+        case ']':
+            is_in_bracket = 0;
+            *(p_pcre ++) = *c;
+            break;
+
+        case '-':
+            if (is_in_bracket)      /* in brackets, - indicates range */
+                *(p_pcre ++) = *c;
+            else
+                STRING_CAT(p_pcre, "\\-", pcre_str_end);
+
+            break;
+        case '{':
+            if (!are_brace_paired)
+            {
+                STRING_CAT(p_pcre, "\\{", pcre_str_end);
+                break;
+            }
+
+            /* Check the case of {single}, where single can be empty */
+            {
+                char *                   cc;
+                _Bool                    is_single = 1;
+
+                for (cc = c + 1; *cc != '\0' && *cc != '}'; ++ cc)
+                {
+                    if (*cc == '\\' && *(cc+1) != '\0')
+                    {
+                        ++ cc;
+                        continue;
+                    }
+
+                    if (*cc == ',')
+                    {
+                        is_single = 0;
+                        break;
+                    }
+                }
+
+                if (*cc == '\0')
+                    is_single = 0;
+
+                if (is_single)      /* escape the { and the corresponding } */
+                {
+                    const char *        double_dots;
+                    int_pair            pair;
+                    int                 pcre_res[3];
+
+                    /* Check the case of {num1..num2} */
+                    rc = pcre_exec(re, NULL, c, (int) (cc - c + 1), 0, 0,
+                            pcre_res, 3);
+
+                    if (rc < 0)    /* not {num1..num2} case */
+                    {
+                        STRING_CAT(p_pcre, "\\{", pcre_str_end);
+
+                        memmove(cc+1, cc, strlen(cc) + 1);
+                        *cc = '\\';
+
+                        break;
+                    }
+
+                    /* Get the range */
+                    double_dots = strstr(c, "..");
+                    pair.num1 = atoi(c + 1);
+                    pair.num2 = atoi(double_dots + 2);
+
+                    utarray_push_back(nums, &pair);
+
+                    STRING_CAT(p_pcre, "([\\+\\-]?\\d+)", pcre_str_end);
+                    c = cc;
+
+                    break;
+                }
+            }
+
+            ++ brace_level;
+            STRING_CAT(p_pcre, "(?:", pcre_str_end);
+            break;
+
+        case '}':
+            if (!are_brace_paired)
+            {
+                STRING_CAT(p_pcre, "\\}", pcre_str_end);
+                break;
+            }
+
+            -- brace_level;
+            *(p_pcre ++) = ')';
+            break;
+
+        case ',':
+            if (brace_level > 0)  /* , inside {...} */
+                *(p_pcre ++) = '|';
+            else
+                STRING_CAT(p_pcre, "\\,", pcre_str_end);
+            break;
+
+        case '/':
+            // /**/ case, match both single / and /anything/
+            if (!strncmp(c, "/**/", 4))
+            {
+                STRING_CAT(p_pcre, "(\\/|\\/.*\\/)", pcre_str_end);
+                c += 3;
+            }
+            else
+                STRING_CAT(p_pcre, "\\/", pcre_str_end);
+
+            break;
+
+        default:
+            if (!isalnum(*c))
+                *(p_pcre ++) = '\\';
+
+            *(p_pcre ++) = *c;
+        }
+    }
+
+    *(p_pcre ++) = '$';
+
+    pcre_free(re); /* ^\\d+\\.\\.\\d+$ */
+
+    re = pcre_compile(pcre_str, 0, &error_msg, &erroffset, NULL);
+
+    if (!re)        /* failed to compile */
+        return -1;
+
+    pcre_result_len = 3 * (utarray_len(nums) + 1);
+    pcre_result = (int *) calloc(pcre_result_len, sizeof(int_pair));
+    rc = pcre_exec(re, NULL, string, (int) strlen(string), 0, 0,
+            pcre_result, pcre_result_len);
+
+    if (rc < 0)     /* failed to match */
+    {
+        int         ret;
+        if (rc == PCRE_ERROR_NOMATCH)
+            ret = EC_GLOB_NOMATCH;
+        else
+            ret = rc;
+
+        pcre_free(re);
+        free(pcre_result);
+        utarray_free(nums);
+
+        return ret;
+    }
+
+    /* Whether the numbers are in the desired range? */
+    for(p = (int_pair *) utarray_front(nums), i = 1; p;
+            ++ i, p = (int_pair *) utarray_next(nums, p))
+    {
+        const char * substring_start = string + pcre_result[2 * i];
+        size_t  substring_length = pcre_result[2 * i + 1] - pcre_result[2 * i];
+        char *       num_string;
+        int          num;
+
+        /* we don't consider 0digits such as 010 as matched */
+        if (*substring_start == '0')
+            break;
+
+        num_string = strndup(substring_start, substring_length);
+        num = atoi(num_string);
+        free(num_string);
+
+        if (num < p->num1 || num > p->num2) /* not matched */
+            break;
+    }
+
+    if (p != NULL)      /* numbers not matched */
+        ret = EC_GLOB_NOMATCH;
+
+    pcre_free(re);
+    free(pcre_result);
+    utarray_free(nums);
+
+    return ret;
+}
diff --git a/libide/editorconfig/libeditorconfig/ec_glob.h b/libide/editorconfig/libeditorconfig/ec_glob.h
new file mode 100644
index 0000000..d83d7ab
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ec_glob.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Hong Xu <hong AT topbug DOT net>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __EC_GLOB_H__
+#define __EC_GLOB_H__
+
+#include "global.h"
+
+#define EC_GLOB_NOMATCH  1   /* Match failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+EDITORCONFIG_LOCAL
+int ec_glob(const char * pattern, const char * string);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__EC_GLOB_H__ */
diff --git a/libide/editorconfig/libeditorconfig/editorconfig.c 
b/libide/editorconfig/libeditorconfig/editorconfig.c
new file mode 100644
index 0000000..9b5d91e
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "global.h"
+#include "editorconfig.h"
+#include "misc.h"
+#include "ini.h"
+#include "ec_glob.h"
+
+/* could be used to fast locate these properties in an
+ * array_editorconfig_name_value */
+typedef struct
+{
+    const editorconfig_name_value*        indent_style;
+    const editorconfig_name_value*        indent_size;
+    const editorconfig_name_value*        tab_width;
+} special_property_name_value_pointers;
+
+typedef struct
+{
+    editorconfig_name_value*                name_values;
+    int                                     current_value_count;
+    int                                     max_value_count;
+    special_property_name_value_pointers    spnvp;
+} array_editorconfig_name_value;
+
+typedef struct
+{
+    char*                           full_filename;
+    char*                           editorconfig_file_dir;
+    array_editorconfig_name_value   array_name_value;
+} handler_first_param;
+
+/*
+ * Set the special pointers for a name
+ */
+static void set_special_property_name_value_pointers(
+        const editorconfig_name_value* nv,
+        special_property_name_value_pointers* spnvp)
+{
+    /* set speical pointers */
+    if (!strcmp(nv->name, "indent_style"))
+        spnvp->indent_style = nv;
+    else if (!strcmp(nv->name, "indent_size"))
+        spnvp->indent_size = nv;
+    else if (!strcmp(nv->name, "tab_width"))
+        spnvp->tab_width = nv;
+}
+
+/*
+ * Set the name and value of a editorconfig_name_value structure
+ */
+static void set_name_value(editorconfig_name_value* nv, const char* name,
+        const char* value, special_property_name_value_pointers* spnvp)
+{
+    if (name)
+        nv->name = strdup(name);
+    if (value)
+        nv->value = strdup(value);
+    /* lowercase the value when the name is one of the following */
+    if (!strcmp(nv->name, "end_of_line") ||
+            !strcmp(nv->name, "indent_style") ||
+            !strcmp(nv->name, "indent_size") ||
+            !strcmp(nv->name, "insert_final_newline") ||
+            !strcmp(nv->name, "trim_trailing_whitespace") ||
+            !strcmp(nv->name, "charset"))
+        strlwr(nv->value);
+
+    /* set speical pointers */
+    set_special_property_name_value_pointers(nv, spnvp);
+}
+
+/*
+ * reset special property name value pointers
+ */
+static void reset_special_property_name_value_pointers(
+        array_editorconfig_name_value* aenv)
+{
+    int         i;
+    
+    for (i = 0; i < aenv->current_value_count; ++ i)
+        set_special_property_name_value_pointers(
+                &aenv->name_values[i], &aenv->spnvp);
+}
+
+/*
+ * Find the editorconfig_name_value from name in a editorconfig_name_value
+ * array.
+ */
+static int find_name_value_from_name(const editorconfig_name_value* env,
+        int count, const char* name)
+{
+    int         i;
+
+    for (i = 0; i < count; ++i)
+        if (!strcmp(env[i].name, name)) /* found */
+            return i;
+
+    return -1;
+}
+
+/* initialize array_editorconfig_name_value */
+static void array_editorconfig_name_value_init(
+        array_editorconfig_name_value* aenv)
+{
+    memset(aenv, 0, sizeof(array_editorconfig_name_value));
+}
+
+static int array_editorconfig_name_value_add(
+        array_editorconfig_name_value* aenv,
+        const char* name, const char* value)
+{
+#define VALUE_COUNT_INITIAL      30
+#define VALUE_COUNT_INCREASEMENT 10
+    int         name_value_pos;
+    /* always use name_lwr but not name, since property names are case
+     * insensitive */
+    char        name_lwr[MAX_PROPERTY_NAME];
+    /* For the first time we came here, aenv->name_values is NULL */
+    if (aenv->name_values == NULL) {
+        aenv->name_values = (editorconfig_name_value*)malloc(
+                sizeof(editorconfig_name_value) * VALUE_COUNT_INITIAL);
+
+        if (aenv->name_values == NULL)
+            return -1;
+
+        aenv->max_value_count = VALUE_COUNT_INITIAL;
+        aenv->current_value_count = 0;
+    }
+
+
+    /* name_lwr is the lowercase property name */
+    strlwr(strcpy(name_lwr, name));
+
+    name_value_pos = find_name_value_from_name(
+            aenv->name_values, aenv->current_value_count, name_lwr);
+
+    if (name_value_pos >= 0) { /* current name has already been used */
+        free(aenv->name_values[name_value_pos].value);
+        set_name_value(&aenv->name_values[name_value_pos],
+                (const char*)NULL, value, &aenv->spnvp);
+        return 0;
+    }
+
+    /* if the space is not enough, allocate more before add the new name and
+     * value */
+    if (aenv->current_value_count >= aenv->max_value_count) {
+
+        editorconfig_name_value*        new_values;
+        int                             new_max_value_count;
+
+        new_max_value_count = aenv->current_value_count +
+            VALUE_COUNT_INCREASEMENT;
+        new_values = (editorconfig_name_value*)realloc(aenv->name_values,
+                sizeof(editorconfig_name_value) * new_max_value_count);
+
+        if (new_values == NULL) /* error occured */
+            return -1;
+
+        aenv->name_values = new_values;
+        aenv->max_value_count = new_max_value_count;
+
+        /* reset special pointers */
+        reset_special_property_name_value_pointers(aenv);
+    }
+
+    set_name_value(&aenv->name_values[aenv->current_value_count],
+            name_lwr, value, &aenv->spnvp);
+    ++ aenv->current_value_count;
+
+    return 0;
+#undef VALUE_COUNT_INITIAL
+#undef VALUE_COUNT_INCREASEMENT
+}
+
+static void array_editorconfig_name_value_clear(
+        array_editorconfig_name_value* aenv)
+{
+    int             i;
+
+    for (i = 0; i < aenv->current_value_count; ++i) {
+        free(aenv->name_values[i].name);
+        free(aenv->name_values[i].value);
+    }
+
+    free(aenv->name_values);
+}
+
+/*
+ * Accept INI property value and store known values in handler_first_param
+ * struct.
+ */
+static int ini_handler(void* hfp, const char* section, const char* name,
+        const char* value)
+{
+    handler_first_param* hfparam = (handler_first_param*)hfp;
+    /* prepend ** to pattern */
+    char*                pattern;
+
+    /* root = true, clear all previous values */
+    if (*section == '\0' && !strcasecmp(name, "root") &&
+            !strcasecmp(value, "true")) {
+        array_editorconfig_name_value_clear(&hfparam->array_name_value);
+        array_editorconfig_name_value_init(&hfparam->array_name_value);
+        return 1;
+    }
+
+    /* pattern would be: /dir/of/editorconfig/file[double_star]/[section] if
+     * section does not contain '/', or /dir/of/editorconfig/file[section]
+     * if section starts with a '/', or /dir/of/editorconfig/file/[section] if
+     * section contains '/' but does not start with '/' */
+    pattern = (char*)malloc(
+            strlen(hfparam->editorconfig_file_dir) * sizeof(char) +
+            sizeof("**/") + strlen(section) * sizeof(char));
+    if (!pattern)
+        return 0;
+    strcpy(pattern, hfparam->editorconfig_file_dir);
+
+    if (strchr(section, '/') == NULL) /* No / is found, append '[star][star]/' */
+        strcat(pattern, "**/");
+    else if (*section != '/') /* The first char is not '/' but section contains
+                                 '/', append a '/' */
+        strcat(pattern, "/");
+
+    strcat(pattern, section);
+
+    if (ec_glob(pattern, hfparam->full_filename) == 0) {
+        if (array_editorconfig_name_value_add(&hfparam->array_name_value, name,
+                value)) {
+            free(pattern);
+            return 0;
+        }
+    }
+
+    free(pattern);
+    return 1;
+}
+
+/* 
+ * Split an absolute file path into directory and filename parts.
+ *
+ * If absolute_path does not contain a path separator, set directory and
+ * filename to NULL pointers.
+ */ 
+static void split_file_path(char** directory, char** filename,
+        const char* absolute_path)
+{
+    char* path_char = strrchr(absolute_path, '/');
+
+    if (path_char == NULL) {
+        if (directory)
+            *directory = NULL;
+        if (filename)
+            *filename = NULL;
+        return;
+    }
+
+    if (directory != NULL) {
+        *directory = strndup(absolute_path,
+                (size_t)(path_char - absolute_path));
+    }
+    if (filename != NULL) {
+        *filename = strndup(path_char+1, strlen(path_char)-1);
+    }
+}
+
+/*
+ * Return the number of slashes in given filename
+ */
+static int count_slashes(const char* filename)
+{
+    int slash_count;
+    for (slash_count = 0; *filename != '\0'; filename++) {
+        if (*filename == '/') {
+            slash_count++;
+        }
+    }
+    return slash_count;
+}
+
+/*
+ * Return an array of full filenames for files in every directory in and above
+ * the given path with the name of the relative filename given.
+ */
+static char** get_filenames(const char* path, const char* filename)
+{
+    char* currdir;
+    char* currdir1;
+    char** files;
+    int slashes = count_slashes(path);
+    int i;
+
+    files = (char**) calloc(slashes+1, sizeof(char*));
+
+    currdir = strdup(path);
+    for (i = slashes - 1; i >= 0; --i) {
+        currdir1 = currdir;
+        split_file_path(&currdir, NULL, currdir1);
+        free(currdir1);
+        files[i] = malloc(strlen(currdir) + strlen(filename) + 2);
+        strcpy(files[i], currdir);
+        strcat(files[i], "/");
+        strcat(files[i], filename);
+    }
+
+    free(currdir);
+
+    files[slashes] = NULL;
+
+    return files;
+}
+
+/*
+ * version number comparison
+ */
+static int editorconfig_compare_version(
+        const struct editorconfig_version* v0,
+        const struct editorconfig_version* v1)
+{
+    /* compare major */
+    if (v0->major > v1->major)
+        return 1;
+    else if (v0->major < v1->major)
+        return -1;
+
+    /* compare minor */
+    if (v0->minor > v1->minor)
+        return 1;
+    else if (v0->minor < v1->minor)
+        return -1;
+
+    /* compare patch */
+    if (v0->patch > v1->patch)
+        return 1;
+    else if (v0->patch < v1->patch)
+        return -1;
+
+    return 0;
+}
+
+EDITORCONFIG_EXPORT
+const char* editorconfig_get_error_msg(int err_num)
+{
+    if(err_num > 0)
+        return "Failed to parse file.";
+
+    switch(err_num) {
+    case 0:
+        return "No error occurred.";
+    case EDITORCONFIG_PARSE_NOT_FULL_PATH:
+        return "Input file must be a full path name.";
+    case EDITORCONFIG_PARSE_MEMORY_ERROR:
+        return "Memory error.";
+    case EDITORCONFIG_PARSE_VERSION_TOO_NEW:
+        return "Required version is greater than the current version.";
+    }
+
+    return "Unknown error.";
+}
+
+/* 
+ * See the header file for the use of this function
+ */
+EDITORCONFIG_EXPORT
+int editorconfig_parse(const char* full_filename, editorconfig_handle h)
+{
+    handler_first_param                 hfp;
+    char**                              config_file;
+    char**                              config_files;
+    int                                 err_num;
+    int                                 i;
+    struct editorconfig_handle*         eh = (struct editorconfig_handle*)h;
+    struct editorconfig_version         cur_ver;
+    struct editorconfig_version         tmp_ver;
+
+    /* get current version */
+    editorconfig_get_version(&cur_ver.major, &cur_ver.minor,
+            &cur_ver.patch);
+
+    /* if version is set to 0.0.0, we set it to current version */
+    if (eh->ver.major == 0 &&
+            eh->ver.minor == 0 &&
+            eh->ver.patch == 0)
+        eh->ver = cur_ver;
+
+    if (editorconfig_compare_version(&eh->ver, &cur_ver) > 0)
+        return EDITORCONFIG_PARSE_VERSION_TOO_NEW;
+
+    if (!eh->err_file) {
+        free(eh->err_file);
+        eh->err_file = NULL;
+    }
+
+    /* if eh->conf_file_name is NULL, we set ".editorconfig" as the default
+     * conf file name */
+    if (!eh->conf_file_name)
+        eh->conf_file_name = ".editorconfig";
+
+    if (eh->name_values) {
+        /* free name_values */
+        for (i = 0; i < eh->name_value_count; ++i) {
+            free(eh->name_values[i].name);
+            free(eh->name_values[i].value);
+        }
+        free(eh->name_values);
+
+        eh->name_values = NULL;
+        eh->name_value_count = 0;
+    }
+    memset(&hfp, 0, sizeof(hfp));
+
+    hfp.full_filename = strdup(full_filename);
+
+    /* return an error if file path is not absolute */
+    if (!is_file_path_absolute(full_filename)) {
+        return EDITORCONFIG_PARSE_NOT_FULL_PATH;
+    }
+
+#ifdef WIN32
+    /* replace all backslashes with slashes on Windows */
+    str_replace(hfp.full_filename, '\\', '/');
+#endif
+
+    array_editorconfig_name_value_init(&hfp.array_name_value);
+
+    config_files = get_filenames(hfp.full_filename, eh->conf_file_name);
+    for (config_file = config_files; *config_file != NULL; config_file++) {
+        split_file_path(&hfp.editorconfig_file_dir, NULL, *config_file);
+        if ((err_num = ini_parse(*config_file, ini_handler, &hfp)) != 0 &&
+                /* ignore error caused by I/O, maybe caused by non exist file */
+                err_num != -1) {
+            eh->err_file = strdup(*config_file);
+            free(*config_file);
+            free(hfp.full_filename);
+            free(hfp.editorconfig_file_dir);
+            return err_num;
+        }
+
+        free(hfp.editorconfig_file_dir);
+        free(*config_file);
+    }
+
+    /* value proprocessing */
+
+    /* For v0.9 */
+    SET_EDITORCONFIG_VERSION(&tmp_ver, 0, 9, 0);
+    if (editorconfig_compare_version(&eh->ver, &tmp_ver) >= 0) {
+    /* Set indent_size to "tab" if indent_size is not specified and
+     * indent_style is set to "tab". Only should be done after v0.9 */
+        if (hfp.array_name_value.spnvp.indent_style &&
+                !hfp.array_name_value.spnvp.indent_size &&
+                !strcmp(hfp.array_name_value.spnvp.indent_style->value, "tab"))
+            array_editorconfig_name_value_add(&hfp.array_name_value,
+                    "indent_size", "tab");
+    /* Set indent_size to tab_width if indent_size is "tab" and tab_width is
+     * specified. This behavior is specified for v0.9 and up. */
+        if (hfp.array_name_value.spnvp.indent_size &&
+            hfp.array_name_value.spnvp.tab_width &&
+            !strcmp(hfp.array_name_value.spnvp.indent_size->value, "tab"))
+        array_editorconfig_name_value_add(&hfp.array_name_value, "indent_size",
+                hfp.array_name_value.spnvp.tab_width->value);
+    }
+
+    /* Set tab_width to indent_size if indent_size is specified. If version is
+     * not less than 0.9.0, we also need to check when the indent_size is set
+     * to "tab", we should not duplicate the value to tab_width */
+    if (hfp.array_name_value.spnvp.indent_size &&
+            !hfp.array_name_value.spnvp.tab_width &&
+            (editorconfig_compare_version(&eh->ver, &tmp_ver) < 0 ||
+             strcmp(hfp.array_name_value.spnvp.indent_size->value, "tab")))
+        array_editorconfig_name_value_add(&hfp.array_name_value, "tab_width",
+                hfp.array_name_value.spnvp.indent_size->value);
+
+    eh->name_value_count = hfp.array_name_value.current_value_count;
+
+    if (eh->name_value_count == 0) {  /* no value is set, just return 0. */
+        free(hfp.full_filename);
+        free(config_files);
+        return 0;
+    }
+    eh->name_values = hfp.array_name_value.name_values;
+    eh->name_values = realloc(      /* realloc to truncate the unused spaces */
+            eh->name_values,
+            sizeof(editorconfig_name_value) * eh->name_value_count);
+    if (eh->name_values == NULL) {
+        free(hfp.full_filename);
+        return EDITORCONFIG_PARSE_MEMORY_ERROR;
+    }
+
+    free(hfp.full_filename);
+    free(config_files);
+
+    return 0;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_get_version(int* major, int* minor, int* patch)
+{
+    if (major)
+        *major = editorconfig_VERSION_MAJOR;
+    if (minor)
+        *minor = editorconfig_VERSION_MINOR;
+    if (patch)
+        *patch = editorconfig_VERSION_PATCH;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_get_version_suffix(void)
+{
+    return editorconfig_VERSION_SUFFIX;
+}
diff --git a/libide/editorconfig/libeditorconfig/editorconfig.h 
b/libide/editorconfig/libeditorconfig/editorconfig.h
new file mode 100644
index 0000000..79076c3
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EDITORCONFIG_H__
+#define __EDITORCONFIG_H__
+
+#include <editorconfig/editorconfig.h>
+
+#include "editorconfig_handle.h"
+
+typedef struct editorconfig_name_value editorconfig_name_value;
+
+#endif /* !__EDITORCONFIG_H__ */
+
diff --git a/libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h 
b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h
new file mode 100644
index 0000000..25b3a86
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2011-2013 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*!
+ * @mainpage EditorConfig C Core Documentation
+ *
+ * This is the documentation of EditorConfig C Core. In this documentation, you
+ * could find the document of the @ref editorconfig and the document of
+ * EditorConfig Core C APIs in editorconfig.h and editorconfig_handle.h.
+ */
+
+/*!
+ * @page editorconfig EditorConfig Command
+ *
+ * @section usage Usage of the `editorconfig` command line tool
+ *
+ * Usage: editorconfig <em>[OPTIONS]</em> FILEPATH1 [FILEPATH2 FILEPATH3 ...]
+ *
+ * FILEPATH can be a hyphen (-) if you want to path(s) to be read from stdin.
+ * Hyphen can also be specified with other file names. In this way, both file
+ * paths from stdin and the paths specified on the command line will be used.
+ * If more than one path specified on the command line, or the paths are
+ * reading from stdin (even only one path is read from stdin), the output
+ * format would be INI format, instead of the simple "key=value" lines.
+ *
+ * @htmlonly
+ * <table cellpadding="5" cellspacing="5">
+ *
+ * <tr>
+ * <td><em>-f</em></td>
+ * <td>Specify conf filename other than ".editorconfig".</td>
+ * </tr>
+ *
+ * <tr>
+ * <td><em>-b</em></td>
+ * <td>Specify version (used by devs to test compatibility).</td>
+ * </tr>
+ *
+ * <tr>
+ * <td><em>-h</em> OR <em>--help</em></td>
+ * <td>Print this help message.</td>
+ * </tr>
+ *
+ * <tr>
+ * <td><em>--version</em></td>
+ * <td>Display version information.</td>
+ * </tr>
+ *
+ * </table>
+ * @endhtmlonly
+ * @manonly
+ *
+ * -f             Specify conf filename other than ".editorconfig".
+ *
+ * -b             Specify version (used by devs to test compatibility).
+ *
+ * -h OR --help   Print this help message.
+ *
+ * --version      Display version information.
+ *
+ * @endmanonly
+ *
+ * @section related Related Pages
+ *
+ * @ref editorconfig-format
+ */
+
+/*!
+ * @page editorconfig-format EditorConfig File Format
+ *
+ * @section format EditorConfig File Format
+ *
+ * EditorConfig files use an INI format that is compatible with the format used
+ * by Python ConfigParser Library, but [ and ] are allowed in the section names.
+ * The section names are filepath globs, similar to the format accepted by
+ * gitignore. Forward slashes (/) are used as path separators and semicolons (;)
+ * or octothorpes (#) are used for comments. Comments should go individual lines.
+ * EditorConfig files should be UTF-8 encoded, with either CRLF or LF line
+ * separators.
+ *
+ * Filename globs containing path separators (/) match filepaths in the same
+ * way as the filename globs used by .gitignore files.  Backslashes (\\) are
+ * not allowed as path separators.
+ *
+ * A semicolon character (;) starts a line comment that terminates at the end
+ * of the line. Line comments and blank lines are ignored when parsing.
+ * Comments may be added to the ends of non-empty lines. An octothorpe
+ * character (#) may be used instead of a semicolon to denote the start of a
+ * comment.
+ *
+ * @section file-location Filename and Location
+ *
+ * When a filename is given to EditorConfig a search is performed in the
+ * directory of the given file and all parent directories for an EditorConfig
+ * file (named ".editorconfig" by default).  All found EditorConfig files are
+ * searched for sections with section names matching the given filename. The
+ * search will stop if an EditorConfig file is found with the root property set
+ * to true or when reaching the root filesystem directory.
+ *
+ * Files are read top to bottom and the most recent rules found take
+ * precedence. If multiple EditorConfig files have matching sections, the rules
+ * from the closer EditorConfig file are read last, so properties in closer
+ * files take precedence.
+ *
+ * @section patterns Wildcard Patterns
+ *
+ * Section names in EditorConfig files are filename globs that support pattern
+ * matching through Unix shell-style wildcards. These filename globs recognize
+ * the following as special characters for wildcard matching:
+ *
+ * @htmlonly
+ * <table>
+ *   <tr><td><code>*</code></td><td>Matches any string of characters, except path separators 
(<code>/</code>)</td></tr>
+ *   <tr><td><code>**</code></td><td>Matches any string of characters</td></tr>
+ *   <tr><td><code>?</code></td><td>Matches any single character</td></tr>
+ *   <tr><td><code>[seq]</code></td><td>Matches any single character in <i>seq</i></td></tr>
+ *   <tr><td><code>[!seq]</code></td><td>Matches any single character not in <i>seq</i></td></tr>
+ *   <tr><td><code>{s1,s2,s3}</code></td><td>Matches any of the strings given (separated by commas, can be 
nested)</td></tr>
+ *   <tr><td><code>{num1..num2}</code></td><td>Matches any integer numbers between num1 and num2, where num1 
and num2 can be either positive or negative</td></tr>
+ * </table>
+ * @endhtmlonly
+ * @manonly
+ * *            Matches any string of characters, except path separators (/)
+ *
+ * **           Matches any string of characters
+ *
+ * ?            Matches any single character
+ *
+ * [seq]        Matches any single character in seq
+ *
+ * [!seq]       Matches any single character not in seq
+ *
+ * {s1,s2,s3}   Matches any of the strings given (separated by commas, can be nested)
+ *
+ * {num1..num2} Matches any integer numbers between num1 and num2, where num1 and num2 can be either 
positive or negative
+ *
+ * @endmanonly
+ *
+ * The backslash character (\) can be used to escape a character so it is not interpreted as a special 
character.
+ *
+ * @section properties Supported Properties
+ *
+ * EditorConfig file sections contain properties, which are name-value pairs separated by an equal sign (=). 
EditorConfig plugins will ignore unrecognized property names and properties with invalid values.
+ *
+ * Here is the list of all property names understood by EditorConfig and all valid values for these 
properties:
+ *
+ * <ul>
+ * <li><strong>indent_style</strong>: set to "tab" or "space" to use hard tabs or soft tabs respectively. 
The values are case insensitive.</li>
+ * <li><strong>indent_size</strong>: a whole number defining the number of columns used for each indentation 
level and the width of soft tabs (when supported). If this equals to "tab", the <strong>indent_size</strong> 
will be set to the tab size, which should be tab_width if <strong>tab_width</strong> is specified, or the tab 
size set by editor if <strong>tab_width</strong> is not specified. The values are case insensitive.</li>
+ * <li><strong>tab_width</strong>: a whole number defining the number of columns used to represent a tab 
character. This defaults to the value of <strong>indent_size</strong> and should not usually need to be 
specified.</li>
+ * <li><strong>end_of_line</strong>: set to "lf", "cr", or "crlf" to control how line breaks are 
represented. The values are case insensitive.</li>
+ * <li><strong>charset</strong>: set to "latin1", "utf-8", "utf-8-bom", "utf-16be" or "utf-16le" to control 
the character set. Use of "utf-8-bom" is discouraged.</li>
+ * <li><strong>trim_trailing_whitespace</strong>:  set to "true" to remove any whitespace characters 
preceeding newline characters and "false" to ensure it doesn't.</li>
+ * <li><strong>insert_final_newline</strong>: set to "true" ensure file ends with a newline when saving and 
"false" to ensure it doesn't.</li>
+ * <li><strong>root</strong>: special property that should be specified at the top of the file outside of 
any sections. Set to "true" to stop <code>.editorconfig</code> files search on current file. The value is 
case insensitive.</li>
+ * </ul>
+ *
+ * Property names are case insensitive and all property names are lowercased when parsing.
+ */
+
+/*!
+ * @file editorconfig/editorconfig.h
+ * @brief Header file of EditorConfig.
+ *
+ * Related page: @ref editorconfig-format
+ *
+ * @author EditorConfig Team
+ */
+
+#ifndef __EDITORCONFIG_EDITORCONFIG_H__
+#define __EDITORCONFIG_EDITORCONFIG_H__
+
+/* When included from a user program, EDITORCONFIG_EXPORT may not be defined,
+ * and we define it here*/
+#ifndef EDITORCONFIG_EXPORT
+# define EDITORCONFIG_EXPORT
+#endif
+
+#include <editorconfig/editorconfig_handle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @brief Parse editorconfig files corresponding to the file path given by
+ * full_filename, and related information is input and output in h.
+ *
+ * An example is available at
+ * <a href=https://github.com/editorconfig/editorconfig-core/blob/master/src/bin/main.c>src/bin/main.c</a>
+ * in EditorConfig C Core source code.
+ *
+ * @param full_filename The full path of a file that is edited by the editor
+ * for which the parsing result is.
+ *
+ * @param h The @ref editorconfig_handle to be used and returned from this
+ * function (including the parsing result). The @ref editorconfig_handle should
+ * be created by editorconfig_handle_init().
+ *
+ * @retval 0 Everything is OK.
+ *
+ * @retval "Positive Integer" A parsing error occurs. The return value would be
+ * the line number of parsing error. err_file obtained from h by calling
+ * editorconfig_handle_get_err_file() will also be filled with the file path
+ * that caused the parsing error.
+ *
+ * @retval "Negative Integer" Some error occured. See below for the reason of
+ * the error for each return value.
+ *
+ * @retval EDITORCONFIG_PARSE_NOT_FULL_PATH The full_filename is not a full
+ * path name.
+ *
+ * @retval EDITORCONFIG_PARSE_MEMORY_ERROR A memory error occurs.
+ *
+ * @retval EDITORCONFIG_PARSE_VERSION_TOO_NEW The required version specified in
+ * @ref editorconfig_handle is greater than the current version.
+ *
+ */
+EDITORCONFIG_EXPORT
+int editorconfig_parse(const char* full_filename, editorconfig_handle h);
+
+/*!
+ * @brief Get the error message from the error number returned by
+ * editorconfig_parse().
+ *
+ * An example is available at
+ * <a href=https://github.com/editorconfig/editorconfig-core/blob/master/src/bin/main.c>src/bin/main.c</a>
+ * in EditorConfig C Core source code.
+ *
+ * @param err_num The error number that is used to obtain the error message.
+ *
+ * @return The error message corresponding to err_num.
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_get_error_msg(int err_num);
+
+/*!
+ * editorconfig_parse() return value: the full_filename parameter of
+ * editorconfig_parse() is not a full path name
+ */
+#define EDITORCONFIG_PARSE_NOT_FULL_PATH                (-2)
+/*!
+ * editorconfig_parse() return value: a memory error occurs.
+ */
+#define EDITORCONFIG_PARSE_MEMORY_ERROR                 (-3)
+/*!
+ * editorconfig_parse() return value: the required version specified in @ref
+ * editorconfig_handle is greater than the current version.
+ */
+#define EDITORCONFIG_PARSE_VERSION_TOO_NEW              (-4)
+
+/*!
+ * @brief Get the version number of EditorConfig.
+ *
+ * An example is available at
+ * <a href=https://github.com/editorconfig/editorconfig-core/blob/master/src/bin/main.c>src/bin/main.c</a>
+ * in EditorConfig C Core source code.
+ *
+ * @param major If not null, the integer pointed by major will be filled with
+ * the major version of EditorConfig.
+ *
+ * @param minor If not null, the integer pointed by minor will be filled with
+ * the minor version of EditorConfig.
+ *
+ * @param patch If not null, the integer pointed by patch will be filled
+ * with the patch version of EditorConfig.
+ *
+ * @return None.
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_get_version(int* major, int* minor, int* patch);
+
+/*!
+ * @brief Get the version suffix.
+ *
+ * @return The version suffix, such as "-development" for a development
+ * version, empty string for a stable version.
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_get_version_suffix(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__EDITORCONFIG_EDITORCONFIG_H__ */
+
diff --git a/libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h 
b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
new file mode 100644
index 0000000..bd8ee43
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig/editorconfig_handle.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*!
+ * @file editorconfig/editorconfig_handle.h
+ * @brief Header file of EditorConfig handle.
+ *
+ * @author EditorConfig Team
+ */
+
+#ifndef __EDITORCONFIG_EDITORCONFIG_HANDLE_H__
+#define __EDITORCONFIG_EDITORCONFIG_HANDLE_H__
+
+/* When included from a user program, EDITORCONFIG_EXPORT may not be defined,
+ * and we define it here*/
+#ifndef EDITORCONFIG_EXPORT
+# define EDITORCONFIG_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @brief The editorconfig handle object type
+ */
+typedef void*   editorconfig_handle;
+
+/*!
+ * @brief Create and intialize a default editorconfig_handle object.
+ *
+ * @retval NULL Failed to create the editorconfig_handle object.
+ *
+ * @retval non-NULL The created editorconfig_handle object is returned.
+ */
+EDITORCONFIG_EXPORT
+editorconfig_handle editorconfig_handle_init(void);
+
+/*!
+ * @brief Destroy an editorconfig_handle object
+ *
+ * @param h The editorconfig_handle object needs to be destroyed.
+ *
+ * @retval zero The editorconfig_handle object is destroyed successfully.
+ * 
+ * @retval non-zero Failed to destroy the editorconfig_handle object.
+ */
+EDITORCONFIG_EXPORT
+int editorconfig_handle_destroy(editorconfig_handle h);
+
+/*!
+ * @brief Get the err_file field of an editorconfig_handle object
+ *
+ * @param h The editorconfig_handle object whose err_file needs to be obtained.
+ *
+ * @retval NULL No error file exists.
+ *
+ * @retval non-NULL The pointer to the path of the file caused the parsing
+ * error is returned.
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_handle_get_err_file(editorconfig_handle h);
+
+/*!
+ * @brief Get the version fields of an editorconfig_handle object.
+ *
+ * @param h The editorconfig_handle object whose version field need to be
+ * obtained.
+ *
+ * @param major If not null, the integer pointed by major will be filled with
+ * the major version field of the editorconfig_handle object.
+ *
+ * @param minor If not null, the integer pointed by minor will be filled with
+ * the minor version field of the editorconfig_handle object.
+ *
+ * @param patch If not null, the integer pointed by patch will be filled
+ * with the patch version field of the editorconfig_handle object.
+ *
+ * @return None.
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_get_version(const editorconfig_handle h, int* major,
+        int* minor, int* patch);
+
+/*!
+ * @brief Set the version fields of an editorconfig_handle object.
+ *
+ * @param h The editorconfig_handle object whose version fields need to be set.
+ *
+ * @param major If not less than 0, the major version field will be set to
+ * major. If this parameter is less than 0, the major version field of the
+ * editorconfig_handle object will remain unchanged.
+ *
+ * @param minor If not less than 0, the minor version field will be set to
+ * minor. If this parameter is less than 0, the minor version field of the
+ * editorconfig_handle object will remain unchanged.
+ *
+ * @param patch If not less than 0, the patch version field will be set to
+ * patch. If this parameter is less than 0, the patch version field of the
+ * editorconfig_handle object will remain unchanged.
+ *
+ * @return None.
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_set_version(const editorconfig_handle h, int major,
+        int minor, int patch);
+/*!
+ * @brief Set the conf_file_name field of an editorconfig_handle object.
+ *
+ * @param h The editorconfig_handle object whose conf_file_name field needs to
+ * be set.
+ *
+ * @param conf_file_name The new value of the conf_file_name field of the
+ * editorconfig_handle object.
+ *
+ * @return None.
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_set_conf_file_name(editorconfig_handle h,
+        const char* conf_file_name);
+
+/*!
+ * @brief Get the conf_file_name field of an editorconfig_handle object.
+ *
+ * @param h The editorconfig_handle object whose conf_file_name field needs to
+ * be obtained.
+ *
+ * @return The value of the conf_file_name field of the editorconfig_handle
+ * object.
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_handle_get_conf_file_name(const editorconfig_handle h);
+
+/*!
+ * @brief Get the nth name and value fields of an editorconfig_handle object.
+ *
+ * @param h The editorconfig_handle object whose name and value fields need to
+ * be obtained.
+ *
+ * @param n The zero-based index of the name and value fields to be obtained.
+ *
+ * @param name If not null, *name will be set to point to the obtained name.
+ *
+ * @param value If not null, *value will be set to point to the obtained value.
+ *
+ * @return None.
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_get_name_value(const editorconfig_handle h, int n,
+        const char** name, const char** value);
+
+/*!
+ * @brief Get the count of name and value fields of an editorconfig_handle
+ * object.
+ *
+ * @param h The editorconfig_handle object whose count of name and value fields
+ * need to be obtained.
+ *
+ * @return the count of name and value fields of the editorconfig_handle
+ * object.
+ */
+EDITORCONFIG_EXPORT
+int editorconfig_handle_get_name_value_count(const editorconfig_handle h);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__EDITORCONFIG_EDITORCONFIG_HANDLE_H__ */
+
diff --git a/libide/editorconfig/libeditorconfig/editorconfig_handle.c 
b/libide/editorconfig/libeditorconfig/editorconfig_handle.c
new file mode 100644
index 0000000..76ea7eb
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig_handle.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "editorconfig_handle.h"
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+editorconfig_handle editorconfig_handle_init(void)
+{
+    editorconfig_handle     h;
+    
+    h = (editorconfig_handle)malloc(sizeof(struct editorconfig_handle));
+
+    if (!h)
+        return (editorconfig_handle)NULL;
+
+    memset(h, 0, sizeof(struct editorconfig_handle));
+
+    return h;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+int editorconfig_handle_destroy(editorconfig_handle h)
+{
+    int                             i;
+    struct editorconfig_handle*     eh = (struct editorconfig_handle*)h;
+
+
+    if (h == NULL)
+        return 0;
+
+    /* free name_values */
+    for (i = 0; i < eh->name_value_count; ++i) {
+        free(eh->name_values[i].name);
+        free(eh->name_values[i].value);
+    }
+    free(eh->name_values);
+
+    /* free err_file */
+    if (eh->err_file)
+        free(eh->err_file);
+
+    /* free eh itself */
+    free(eh);
+
+    return 0;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_handle_get_err_file(const editorconfig_handle h)
+{
+    return ((const struct editorconfig_handle*)h)->err_file;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_get_version(const editorconfig_handle h, int* major,
+        int* minor, int* patch)
+{
+    if (major)
+        *major = ((const struct editorconfig_handle*)h)->ver.major;
+    if (minor)
+        *minor = ((const struct editorconfig_handle*)h)->ver.minor;
+    if (patch)
+        *patch = ((const struct editorconfig_handle*)h)->ver.patch;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_set_version(editorconfig_handle h, int major,
+        int minor, int patch)
+{
+    if (major >= 0)
+        ((struct editorconfig_handle*)h)->ver.major = major;
+
+    if (minor >= 0)
+        ((struct editorconfig_handle*)h)->ver.minor = minor;
+
+    if (patch >= 0)
+        ((struct editorconfig_handle*)h)->ver.patch = minor;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+void editorconfig_handle_set_conf_file_name(editorconfig_handle h,
+        const char* conf_file_name)
+{
+    ((struct editorconfig_handle*)h)->conf_file_name = conf_file_name;
+}
+
+/*
+ * See header file
+ */
+EDITORCONFIG_EXPORT
+const char* editorconfig_handle_get_conf_file_name(const editorconfig_handle h)
+{
+    return ((const struct editorconfig_handle*)h)->conf_file_name;
+}
+
+EDITORCONFIG_EXPORT
+void editorconfig_handle_get_name_value(const editorconfig_handle h, int n,
+        const char** name, const char** value)
+{
+    struct editorconfig_name_value* name_value = &((
+                const struct editorconfig_handle*)h)->name_values[n];
+
+    if (name)
+        *name = name_value->name;
+
+    if (value)
+        *value = name_value->value;
+}
+
+EDITORCONFIG_EXPORT
+int editorconfig_handle_get_name_value_count(const editorconfig_handle h)
+{
+    return ((const struct editorconfig_handle*)h)->name_value_count;
+}
diff --git a/libide/editorconfig/libeditorconfig/editorconfig_handle.h 
b/libide/editorconfig/libeditorconfig/editorconfig_handle.h
new file mode 100644
index 0000000..812fc55
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/editorconfig_handle.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EDITORCONFIG_HANDLE_H__
+#define __EDITORCONFIG_HANDLE_H__
+
+#include "global.h"
+#include <editorconfig/editorconfig_handle.h>
+
+/*!
+ * @brief A structure containing a name and its corresponding value.
+ * @author EditorConfig Team
+ */
+struct editorconfig_name_value
+{
+    /*! EditorConfig config item's name. */ 
+    char*       name;
+    /*! EditorConfig config item's value. */ 
+    char*       value;
+};
+
+/*!
+ * @brief A structure that descripts version number.
+ * @author EditorConfig Team
+ */
+struct editorconfig_version
+{
+    /*! major version */
+    int                     major;
+    /*! minor version */
+    int                     minor;
+    /*! patch version */
+    int                     patch;
+};
+
+struct editorconfig_handle
+{
+    /*!
+     * The file name of EditorConfig conf file. If this pointer is set to NULL,
+     * the file name is set to ".editorconfig" by default.
+     */
+    const char*                         conf_file_name;
+
+    /*!
+     * When a parsing error occured, this will point to a file that caused the
+     * parsing error.
+     */
+    char*                               err_file;
+
+    /*!
+     * version number it should act as. Set this to 0.0.0 to act like the
+     * current version.
+     */
+    struct editorconfig_version         ver;
+
+    /*! Pointer to a list of editorconfig_name_value structures containing
+     * names and values of the parsed result */
+    struct editorconfig_name_value*     name_values;
+
+    /*! The total count of name_values structures pointed by name_values
+     * pointer */
+    int                                 name_value_count;
+};
+
+#endif /* !__EDITORCONFIG_HANDLE_H__ */
+
diff --git a/libide/editorconfig/libeditorconfig/global.h b/libide/editorconfig/libeditorconfig/global.h
new file mode 100644
index 0000000..56ab59d
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/global.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GLOBAL_H__
+#define __GLOBAL_H__
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Microsoft Visual C++ and some other Windows C Compilers requires exported
+ * functions in shared library to be defined with __declspec(dllexport)
+ * declarator. Also, gcc >= 4 supports hiding symbols that do not need to be
+ * exported.
+ */
+#ifdef editorconfig_shared_EXPORTS /* We are building shared lib if defined */
+# ifdef WIN32
+#  ifdef __GNUC__
+#   define EDITORCONFIG_EXPORT  __attribute__ ((dllexport))
+#  else /* __GNUC__ */
+#   define EDITORCONFIG_EXPORT __declspec(dllexport)
+#  endif /* __GNUC__ */
+# else /* WIN32 */
+#  if defined(__GNUC__) && __GNUC__ >= 4
+#   define EDITORCONFIG_EXPORT __attribute__ ((visibility ("default")))
+#   define EDITORCONFIG_LOCAL __attribute__ ((visibility ("hidden")))
+#  endif /* __GNUC__ && __GNUC >= 4 */
+# endif /* WIN32 */
+#endif /* editorconfig_shared_EXPORTS */
+
+/*
+ * For other cases, just define EDITORCONFIG_EXPORT and EDITORCONFIG_LOCAL, to
+ * make compilation successful
+ */
+#ifndef EDITORCONFIG_EXPORT
+# define EDITORCONFIG_EXPORT
+#endif
+#ifndef EDITORCONFIG_LOCAL
+# define EDITORCONFIG_LOCAL
+#endif
+
+/* a macro to set editorconfig_version struct */
+#define SET_EDITORCONFIG_VERSION(editorconfig_ver, maj, min, submin) \
+    do { \
+        (editorconfig_ver)->major = (maj); \
+        (editorconfig_ver)->minor = (min); \
+        (editorconfig_ver)->patch = (submin); \
+    } while(0)
+
+#endif /* !__GLOBAL_H__ */
+
diff --git a/libide/editorconfig/libeditorconfig/ini.c b/libide/editorconfig/libeditorconfig/ini.c
new file mode 100644
index 0000000..bf0517d
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ini.c
@@ -0,0 +1,200 @@
+/* inih -- simple .INI file parser
+
+The "inih" library is distributed under the New BSD license:
+
+Copyright (c) 2009, Brush Technology
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Brush Technology nor the names of its contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Go to the project home page for more info:
+http://code.google.com/p/inih/
+
+*/
+
+#include "global.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "ini.h"
+
+#define MAX_LINE 200
+#define MAX_SECTION MAX_SECTION_NAME
+#define MAX_NAME MAX_PROPERTY_NAME
+
+/* Strip whitespace chars off end of given string, in place. Return s. */
+static char* rstrip(char* s)
+{
+    char* p = s + strlen(s);
+    while (p > s && isspace(*--p))
+        *p = '\0';
+    return s;
+}
+
+/* Return pointer to first non-whitespace char in given string. */
+static char* lskip(const char* s)
+{
+    while (*s && isspace(*s))
+        s++;
+    return (char*)s;
+}
+
+/* Return pointer to first char c or ';' comment in given string, or pointer to
+   null at end of string if neither found. ';' must be prefixed by a whitespace
+   character to register as a comment. */
+static char* find_char_or_comment(const char* s, char c)
+{
+    int was_whitespace = 0;
+    while (*s && *s != c && !(was_whitespace && (*s == ';' || *s == '#'))) {
+        was_whitespace = isspace(*s);
+        s++;
+    }
+    return (char*)s;
+}
+
+static char* find_last_char_or_comment(const char* s, char c)
+{
+    const char* last_char = s;
+    int was_whitespace = 0;
+    while (*s && !(was_whitespace && (*s == ';' || *s == '#'))) {
+        if (*s == c)
+            last_char = s;
+        was_whitespace = isspace(*s);
+        s++;
+    }
+    return (char*)last_char;
+}
+
+/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
+static char* strncpy0(char* dest, const char* src, size_t size)
+{
+    strncpy(dest, src, size);
+    dest[size - 1] = '\0';
+    return dest;
+}
+
+/* See documentation in header file. */
+EDITORCONFIG_LOCAL
+int ini_parse_file(FILE* file,
+                   int (*handler)(void*, const char*, const char*,
+                                  const char*),
+                   void* user)
+{
+    /* Uses a fair bit of stack (use heap instead if you need to) */
+    char line[MAX_LINE];
+    char section[MAX_SECTION] = "";
+    char prev_name[MAX_NAME] = "";
+
+    char* start;
+    char* end;
+    char* name;
+    char* value;
+    int lineno = 0;
+    int error = 0;
+
+    /* Scan through file line by line */
+    while (fgets(line, sizeof(line), file) != NULL) {
+        lineno++;
+
+        start = line;
+#if INI_ALLOW_BOM
+        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
+                           (unsigned char)start[1] == 0xBB &&
+                           (unsigned char)start[2] == 0xBF) {
+            start += 3;
+        }
+#endif
+        start = lskip(rstrip(start));
+
+        if (*start == ';' || *start == '#') {
+            /* Per Python ConfigParser, allow '#' comments at start of line */
+        }
+#if INI_ALLOW_MULTILINE
+        else if (*prev_name && *start && start > line) {
+            /* Non-black line with leading whitespace, treat as continuation
+               of previous name's value (as per Python ConfigParser). */
+            if (!handler(user, section, prev_name, start) && !error)
+                error = lineno;
+        }
+#endif
+        else if (*start == '[') {
+            /* A "[section]" line */
+            end = find_last_char_or_comment(start + 1, ']');
+            if (*end == ']') {
+                *end = '\0';
+                strncpy0(section, start + 1, sizeof(section));
+                *prev_name = '\0';
+            }
+            else if (!error) {
+                /* No ']' found on section line */
+                error = lineno;
+            }
+        }
+        else if (*start && (*start != ';' || *start == '#')) {
+            /* Not a comment, must be a name[=:]value pair */
+            end = find_char_or_comment(start, '=');
+            if (*end != '=') {
+                end = find_char_or_comment(start, ':');
+            }
+            if (*end == '=' || *end == ':') {
+                *end = '\0';
+                name = rstrip(start);
+                value = lskip(end + 1);
+                end = find_char_or_comment(value, '\0');
+                if (*end == ';' || *end == '#')
+                    *end = '\0';
+                rstrip(value);
+
+                /* Valid name[=:]value pair found, call handler */
+                strncpy0(prev_name, name, sizeof(prev_name));
+                if (!handler(user, section, name, value) && !error)
+                    error = lineno;
+            }
+            else if (!error) {
+                /* No '=' or ':' found on name[=:]value line */
+                error = lineno;
+            }
+        }
+    }
+
+    return error;
+}
+
+/* See documentation in header file. */
+EDITORCONFIG_LOCAL
+int ini_parse(const char* filename,
+              int (*handler)(void*, const char*, const char*, const char*),
+              void* user)
+{
+    FILE* file;
+    int error;
+
+    file = fopen(filename, "r");
+    if (!file)
+        return -1;
+    error = ini_parse_file(file, handler, user);
+    fclose(file);
+    return error;
+}
diff --git a/libide/editorconfig/libeditorconfig/ini.h b/libide/editorconfig/libeditorconfig/ini.h
new file mode 100644
index 0000000..053db05
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/ini.h
@@ -0,0 +1,93 @@
+/* inih -- simple .INI file parser
+
+The "inih" library is distributed under the New BSD license:
+
+Copyright (c) 2009, Brush Technology
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Brush Technology nor the names of its contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Go to the project home page for more info:
+http://code.google.com/p/inih/
+
+*/
+
+#ifndef __INI_H__
+#define __INI_H__
+
+#include "global.h"
+
+/* Make this header file easier to include in C++ code */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+/* Parse given INI-style file. May have [section]s, name=value pairs
+   (whitespace stripped), and comments starting with ';' (semicolon). Section
+   is "" if name=value pair parsed before any section heading. name:value
+   pairs are also supported as a concession to Python's ConfigParser.
+
+   For each name=value pair parsed, call handler function with given user
+   pointer as well as section, name, and value (data only valid for duration
+   of handler call). Handler should return nonzero on success, zero on error.
+
+   Returns 0 on success, line number of first error on parse error (doesn't
+   stop on first error), or -1 on file open error.
+*/
+EDITORCONFIG_LOCAL
+int ini_parse(const char* filename,
+              int (*handler)(void* user, const char* section,
+                             const char* name, const char* value),
+              void* user);
+
+/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
+   close the file when it's finished -- the caller must do that. */
+EDITORCONFIG_LOCAL
+int ini_parse_file(FILE* file,
+                   int (*handler)(void* user, const char* section,
+                                  const char* name, const char* value),
+                   void* user);
+
+/* Nonzero to allow multi-line value parsing, in the style of Python's
+   ConfigParser. If allowed, ini_parse() will call the handler with the same
+   name for each subsequent line parsed. */
+#ifndef INI_ALLOW_MULTILINE
+#define INI_ALLOW_MULTILINE 0
+#endif
+
+#define MAX_SECTION_NAME 500
+#define MAX_PROPERTY_NAME 500
+
+/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
+   the file. See http://code.google.com/p/inih/issues/detail?id=21 */
+#ifndef INI_ALLOW_BOM
+#define INI_ALLOW_BOM 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INI_H__ */
diff --git a/libide/editorconfig/libeditorconfig/misc.c b/libide/editorconfig/libeditorconfig/misc.c
new file mode 100644
index 0000000..f02e3d6
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/misc.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "misc.h"
+
+#ifdef WIN32
+# include <Shlwapi.h>
+#endif
+
+#if !defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)
+/*
+ * strcasecmp function from FreeBSD
+ *
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+typedef unsigned char u_char;
+
+EDITORCONFIG_LOCAL
+int ec_strcasecmp(const char *s1, const char *s2)
+{
+    const unsigned char
+        *us1 = (const unsigned char*)s1,
+        *us2 = (const unsigned char*)s2;
+
+    while (tolower(*us1) == tolower(*us2++))
+        if (*us1++ == '\0')
+            return (0);
+    return (tolower(*us1) - tolower(*--us2));
+}
+#endif /* !HAVE_STRCASECMP && !HAVE_STRICMP */
+
+#ifndef HAVE_STRDUP
+/*
+ * strdup function from FreeBSD
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+EDITORCONFIG_LOCAL
+char* ec_strdup(const char *str)
+{
+    size_t      len;
+    char*       copy;
+
+    len = strlen(str) + 1;
+    if ((copy = malloc(len)) == NULL)
+        return (NULL);
+    memcpy(copy, str, len);
+    return (copy);
+}
+
+#endif /* !HAVE_STRDUP */
+
+
+#ifndef HAVE_STRNDUP
+/*
+ * strndup function from NetBSD
+ *
+ * $NetBSD: strndup.c,v 1.3 2007/01/14 23:41:24 cbiere Exp $ 
+ *
+ * Copyright (c) 1988, 1993
+ *  The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "global.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+EDITORCONFIG_LOCAL
+char* ec_strndup(const char* str, size_t n)
+{
+    size_t      len;
+    char*       copy;
+
+    for (len = 0; len < n && str[len]; len++)
+        continue;
+
+    if ((copy = malloc(len + 1)) == NULL)
+        return (NULL);
+    memcpy(copy, str, len);
+    copy[len] = '\0';
+    return (copy);
+}
+
+#endif /* HAVE_STRNDUP */
+
+/*
+ * replace oldc with newc in the string str
+ */
+EDITORCONFIG_LOCAL
+char* str_replace(char* str, char oldc, char newc)
+{
+    char*   p;
+
+    if (str == NULL)
+        return NULL;
+
+    for (p = str; *p != '\0'; p++)
+        if (*p == oldc)
+            *p = newc;
+
+    return str;
+}
+
+#ifndef HAVE_STRLWR
+
+#include <ctype.h>
+/*
+ * convert the string to lowercase
+ */
+EDITORCONFIG_LOCAL
+char* ec_strlwr(char* str)
+{
+    char*       p;
+
+    for (p = str; *p; ++p)
+        *p = (char)tolower((unsigned char)*p);
+
+    return str;
+}
+
+#endif /* !HAVE_STRLWR */
+
+/*
+ * is path an abosolute file path
+ */
+EDITORCONFIG_LOCAL
+_Bool is_file_path_absolute(const char* path)
+{
+    if (!path)
+        return 0;
+
+#if defined(UNIX)
+    if (*path == '/')
+        return 1;
+    return 0;
+#elif defined(WIN32)
+    return !PathIsRelative(path);
+#else
+# error "Either UNIX or WIN32 must be defined."
+#endif
+}
diff --git a/libide/editorconfig/libeditorconfig/misc.h b/libide/editorconfig/libeditorconfig/misc.h
new file mode 100644
index 0000000..5e4b463
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/misc.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011-2012 EditorConfig Team
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MISC_H__
+#define __MISC_H__
+
+#include "global.h"
+
+#include <stddef.h>
+
+#ifndef HAVE_STRCASECMP
+# ifdef HAVE_STRICMP
+#  define strcasecmp stricmp
+# else /* HAVE_STRICMP */
+EDITORCONFIG_LOCAL
+int ec_strcasecmp(const char *s1, const char *s2);
+# define strcasecmp ec_strcasecmp
+# endif /* HAVE_STRICMP */
+#endif /* !HAVE_STRCASECMP */
+#ifndef HAVE_STRDUP
+EDITORCONFIG_LOCAL
+char* ec_strdup(const char *str);
+# define strdup ec_strdup
+#endif
+#ifndef HAVE_STRNDUP
+EDITORCONFIG_LOCAL
+char* ec_strndup(const char* str, size_t n);
+# define strndup ec_strndup
+#endif
+EDITORCONFIG_LOCAL
+char* str_replace(char* str, char oldc, char newc);
+#ifndef HAVE_STRLWR
+EDITORCONFIG_LOCAL
+char* ec_strlwr(char* str);
+# define strlwr ec_strlwr
+#endif
+EDITORCONFIG_LOCAL
+_Bool is_file_path_absolute(const char* path);
+#endif /* __MISC_H__ */
diff --git a/libide/editorconfig/libeditorconfig/utarray.h b/libide/editorconfig/libeditorconfig/utarray.h
new file mode 100644
index 0000000..dcddd72
--- /dev/null
+++ b/libide/editorconfig/libeditorconfig/utarray.h
@@ -0,0 +1,232 @@
+/*
+Copyright (c) 2008-2014, Troy D. Hanson   http://troydhanson.github.com/uthash/
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* a dynamic array implementation using macros 
+ */
+#ifndef UTARRAY_H
+#define UTARRAY_H
+
+#define UTARRAY_VERSION 1.9.9
+
+#ifdef __GNUC__
+#define _UNUSED_ __attribute__ ((__unused__)) 
+#else
+#define _UNUSED_ 
+#endif
+
+#include <stddef.h>  /* size_t */
+#include <string.h>  /* memset, etc */
+#include <stdlib.h>  /* exit */
+
+#define oom() exit(-1)
+
+typedef void (ctor_f)(void *dst, const void *src);
+typedef void (dtor_f)(void *elt);
+typedef void (init_f)(void *elt);
+typedef struct {
+    size_t sz;
+    init_f *init;
+    ctor_f *copy;
+    dtor_f *dtor;
+} UT_icd;
+
+typedef struct {
+    unsigned i,n;/* i: index of next available slot, n: num slots */
+    UT_icd icd;  /* initializer, copy and destructor functions */
+    char *d;     /* n slots of size icd->sz*/
+} UT_array;
+
+#define utarray_init(a,_icd) do {                                             \
+  memset(a,0,sizeof(UT_array));                                               \
+  (a)->icd=*_icd;                                                             \
+} while(0)
+
+#define utarray_done(a) do {                                                  \
+  if ((a)->n) {                                                               \
+    if ((a)->icd.dtor) {                                                      \
+      size_t _ut_i;                                                           \
+      for(_ut_i=0; _ut_i < (a)->i; _ut_i++) {                                 \
+        (a)->icd.dtor(utarray_eltptr(a,_ut_i));                               \
+      }                                                                       \
+    }                                                                         \
+    free((a)->d);                                                             \
+  }                                                                           \
+  (a)->n=0;                                                                   \
+} while(0)
+
+#define utarray_new(a,_icd) do {                                              \
+  a=(UT_array*)malloc(sizeof(UT_array));                                      \
+  utarray_init(a,_icd);                                                       \
+} while(0)
+
+#define utarray_free(a) do {                                                  \
+  utarray_done(a);                                                            \
+  free(a);                                                                    \
+} while(0)
+
+#define utarray_reserve(a,by) do {                                            \
+  if (((a)->i+by) > ((a)->n)) {                                               \
+    while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); }     \
+    if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom();  \
+  }                                                                           \
+} while(0)
+
+#define utarray_push_back(a,p) do {                                           \
+  utarray_reserve(a,1);                                                       \
+  if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); }      \
+  else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); };              \
+} while(0)
+
+#define utarray_pop_back(a) do {                                              \
+  if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); }       \
+  else { (a)->i--; }                                                          \
+} while(0)
+
+#define utarray_extend_back(a) do {                                           \
+  utarray_reserve(a,1);                                                       \
+  if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); }            \
+  else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); }                   \
+  (a)->i++;                                                                   \
+} while(0)
+
+#define utarray_len(a) ((a)->i)
+
+#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL)
+#define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) )))
+
+#define utarray_insert(a,p,j) do {                                            \
+  if (j > (a)->i) utarray_resize(a,j);                                        \
+  utarray_reserve(a,1);                                                       \
+  if ((j) < (a)->i) {                                                         \
+    memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j),                  \
+             ((a)->i - (j))*((a)->icd.sz));                                   \
+  }                                                                           \
+  if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); }             \
+  else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); };                     \
+  (a)->i++;                                                                   \
+} while(0)
+
+#define utarray_inserta(a,w,j) do {                                           \
+  if (utarray_len(w) == 0) break;                                             \
+  if (j > (a)->i) utarray_resize(a,j);                                        \
+  utarray_reserve(a,utarray_len(w));                                          \
+  if ((j) < (a)->i) {                                                         \
+    memmove(_utarray_eltptr(a,(j)+utarray_len(w)),                            \
+            _utarray_eltptr(a,j),                                             \
+            ((a)->i - (j))*((a)->icd.sz));                                    \
+  }                                                                           \
+  if ((a)->icd.copy) {                                                        \
+    size_t _ut_i;                                                             \
+    for(_ut_i=0;_ut_i<(w)->i;_ut_i++) {                                       \
+      (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i));    \
+    }                                                                         \
+  } else {                                                                    \
+    memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0),                        \
+           utarray_len(w)*((a)->icd.sz));                                     \
+  }                                                                           \
+  (a)->i += utarray_len(w);                                                   \
+} while(0)
+
+#define utarray_resize(dst,num) do {                                          \
+  size_t _ut_i;                                                               \
+  if (dst->i > (size_t)(num)) {                                               \
+    if ((dst)->icd.dtor) {                                                    \
+      for(_ut_i=num; _ut_i < dst->i; _ut_i++) {                               \
+        (dst)->icd.dtor(utarray_eltptr(dst,_ut_i));                           \
+      }                                                                       \
+    }                                                                         \
+  } else if (dst->i < (size_t)(num)) {                                        \
+    utarray_reserve(dst,num-dst->i);                                          \
+    if ((dst)->icd.init) {                                                    \
+      for(_ut_i=dst->i; _ut_i < num; _ut_i++) {                               \
+        (dst)->icd.init(utarray_eltptr(dst,_ut_i));                           \
+      }                                                                       \
+    } else {                                                                  \
+      memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i));       \
+    }                                                                         \
+  }                                                                           \
+  dst->i = num;                                                               \
+} while(0)
+
+#define utarray_concat(dst,src) do {                                          \
+  utarray_inserta((dst),(src),utarray_len(dst));                              \
+} while(0)
+
+#define utarray_erase(a,pos,len) do {                                         \
+  if ((a)->icd.dtor) {                                                        \
+    size_t _ut_i;                                                             \
+    for(_ut_i=0; _ut_i < len; _ut_i++) {                                      \
+      (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i));                           \
+    }                                                                         \
+  }                                                                           \
+  if ((a)->i > (pos+len)) {                                                   \
+    memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len),          \
+            (((a)->i)-(pos+len))*((a)->icd.sz));                              \
+  }                                                                           \
+  (a)->i -= (len);                                                            \
+} while(0)
+
+#define utarray_renew(a,u) do {                                               \
+  if (a) utarray_clear(a); \
+  else utarray_new((a),(u));   \
+} while(0) 
+
+#define utarray_clear(a) do {                                                 \
+  if ((a)->i > 0) {                                                           \
+    if ((a)->icd.dtor) {                                                      \
+      size_t _ut_i;                                                           \
+      for(_ut_i=0; _ut_i < (a)->i; _ut_i++) {                                 \
+        (a)->icd.dtor(utarray_eltptr(a,_ut_i));                               \
+      }                                                                       \
+    }                                                                         \
+    (a)->i = 0;                                                               \
+  }                                                                           \
+} while(0)
+
+#define utarray_sort(a,cmp) do {                                              \
+  qsort((a)->d, (a)->i, (a)->icd.sz, cmp);                                    \
+} while(0)
+
+#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp)
+
+#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL)
+#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? 
_utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL))
+#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? 
_utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL))
+#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL)
+#define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - 
(char*)((a)->d))/(size_t)(a)->icd.sz) : -1)
+
+/* last we pre-define a few icd for common utarrays of ints and strings */
+static void utarray_str_cpy(void *dst, const void *src) {
+  char **_src = (char**)src, **_dst = (char**)dst;
+  *_dst = (*_src == NULL) ? NULL : strdup(*_src);
+}
+static void utarray_str_dtor(void *elt) {
+  char **eltc = (char**)elt;
+  if (*eltc) free(*eltc);
+}
+static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor};
+static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL};
+static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL};
+
+
+#endif /* UTARRAY_H */
diff --git a/libide/ide-file-settings.h b/libide/ide-file-settings.h
index 59a7c1d..4aa608a 100644
--- a/libide/ide-file-settings.h
+++ b/libide/ide-file-settings.h
@@ -56,7 +56,7 @@ void                  ide_file_settings_set_insert_trailing_newline  (IdeFileSet
                                                                       gboolean              
insert_trailing_newline);
 void                  ide_file_settings_set_newline_type             (IdeFileSettings      *self,
                                                                       GtkSourceNewlineType  newline_type);
-void                   ide_file_settings_set_right_margin_position   (IdeFileSettings      *self,
+void                  ide_file_settings_set_right_margin_position    (IdeFileSettings      *self,
                                                                       guint                 
right_margin_position);
 void                  ide_file_settings_set_tab_width                (IdeFileSettings      *self,
                                                                       guint                 tab_width);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]