[gedit/zbrown/deteplification: 1/3] deteplification: the mega commit




commit a2fb7158e6506cdeb91c82cebc29e342a460c04f
Author: Zander Brown <zbrown gnome org>
Date:   Sat Apr 10 06:06:32 2021 +0100

    deteplification: the mega commit
    
    TODO: Explain this

 build-aux/flatpak/org.gnome.gedit.yml              |   15 +-
 build-aux/snap/snapcraft.yaml                      |   27 +-
 data/org.gnome.gedit.gschema.xml.in                |    5 +
 docs/gedit-development-getting-started.md          |    8 +-
 docs/reference/api-breaks.xml                      |    7 -
 docs/reference/gedit-docs.xml                      |    1 +
 docs/reference/gedit-sections.txt                  |   36 +
 docs/reference/meson.build                         |    6 +-
 docs/roadmap.md                                    |    3 +-
 gedit/Gedit-3.0.metadata                           |    1 +
 gedit/gedit-app-osx.m                              |    4 +-
 gedit/gedit-app-private.h                          |    3 +
 gedit/gedit-app.c                                  |   54 +-
 gedit/gedit-commands-edit.c                        |   28 +-
 gedit/gedit-commands-file.c                        |   26 +-
 gedit/gedit-commands-search.c                      |    7 +-
 gedit/gedit-commands-view.c                        |   42 +-
 gedit/gedit-debug.c                                |    4 +
 gedit/gedit-debug.h                                |    2 +
 gedit/gedit-document-private.h                     |   12 +-
 gedit/gedit-document.c                             |  534 +++++++-
 gedit/gedit-document.h                             |   18 +-
 gedit/gedit-documents-panel.c                      |    3 +-
 gedit/gedit-factory.c                              |   50 -
 gedit/gedit-factory.h                              |   53 -
 gedit/gedit-file-chooser-dialog-gtk.c              |   72 +-
 gedit/gedit-file-chooser-dialog-gtk.h              |    9 +-
 gedit/gedit-file-chooser-dialog.c                  |   40 +-
 gedit/gedit-file-chooser-dialog.h                  |   17 +
 gedit/gedit-highlight-mode-dialog.c                |  102 ++
 gedit/gedit-highlight-mode-dialog.h                |   41 +
 gedit/gedit-highlight-mode-selector.c              |  375 ++++++
 gedit/gedit-highlight-mode-selector.h              |   44 +
 gedit/gedit-io-error-info-bar.c                    |  362 +++++-
 gedit/gedit-io-error-info-bar.h                    |   10 +
 gedit/gedit-metadata-manager.c                     |  650 ++++++++++
 gedit/gedit-metadata-manager.h                     |   49 +
 gedit/gedit-open-document-selector-helper.c        |  103 ++
 gedit/gedit-open-document-selector-helper.h        |  103 ++
 gedit/gedit-open-document-selector-store.c         |  820 ++++++++++++
 gedit/gedit-open-document-selector-store.h         |   68 +
 gedit/gedit-open-document-selector.c               | 1304 ++++++++++++++++++++
 gedit/gedit-open-document-selector.h               |   44 +
 gedit/gedit-pango.c                                |  230 ++++
 gedit/gedit-pango.h                                |   28 +
 gedit/gedit-preferences-dialog.c                   |  447 ++++---
 gedit/gedit-print-job.c                            |    4 +-
 gedit/gedit-progress-info-bar.c                    |  177 +++
 gedit/gedit-progress-info-bar.h                    |   53 +
 gedit/gedit-recent-osx.c                           |  249 ----
 gedit/gedit-recent-osx.h                           |   54 -
 gedit/gedit-recent.c                               |  231 +++-
 gedit/gedit-recent.h                               |   23 +-
 gedit/gedit-settings.c                             |  177 +--
 gedit/gedit-settings.h                             |    7 +-
 gedit/gedit-tab.c                                  |  115 +-
 gedit/gedit-utils.c                                |  333 ++++-
 gedit/gedit-utils.h                                |   21 +-
 gedit/gedit-view-centering.c                       |  495 ++++++++
 gedit/gedit-view-centering.h                       |   67 +
 gedit/gedit-view-frame.c                           |   37 +-
 gedit/gedit-view-frame.h                           |    4 +
 gedit/gedit-view.c                                 |  322 ++++-
 gedit/gedit-view.h                                 |   24 +-
 gedit/gedit-window-private.h                       |   15 +-
 gedit/gedit-window.c                               |  380 +++---
 gedit/gedit.c                                      |    8 +-
 gedit/meson.build                                  |   23 +-
 gedit/resources/css/gedit-style.css                |   12 +
 gedit/resources/css/gedit.adwaita.css              |   25 +
 gedit/resources/gedit.gresource.xml.in             |    4 +
 gedit/resources/ui/gedit-highlight-mode-dialog.ui  |   87 ++
 .../resources/ui/gedit-highlight-mode-selector.ui  |   83 ++
 gedit/resources/ui/gedit-open-document-selector.ui |  115 ++
 gedit/resources/ui/gedit-preferences-dialog.ui     |   30 +-
 gedit/resources/ui/gedit-progress-info-bar.ui      |   88 ++
 gedit/resources/ui/gedit-view-frame.ui             |   30 +-
 gedit/resources/ui/gedit-window.ui                 |   87 +-
 help/C/gedit-tab-groups.page                       |    4 +-
 meson.build                                        |   34 +-
 meson_options.txt                                  |    7 +
 plugins/snippets/snippets/document.py              |   10 +-
 plugins/spell/gedit-spell-plugin.c                 |    9 +-
 po/POTFILES.in                                     |    8 +-
 84 files changed, 8099 insertions(+), 1220 deletions(-)
---
diff --git a/build-aux/flatpak/org.gnome.gedit.yml b/build-aux/flatpak/org.gnome.gedit.yml
index 1438abd07..d3b535176 100644
--- a/build-aux/flatpak/org.gnome.gedit.yml
+++ b/build-aux/flatpak/org.gnome.gedit.yml
@@ -59,17 +59,12 @@ modules:
         url: https://download.gnome.org/sources/gspell/1.9/gspell-1.9.1.tar.xz
         sha256: dcbb769dfdde8e3c0a8ed3102ce7e661abbf7ddf85df08b29915e92cd723abdd
 
-  - name: amtk
-    buildsystem: meson
+  - name: uchardet
+    buildsystem: cmake-ninja
     sources:
-      - type: git
-        url: https://gitlab.gnome.org/GNOME/amtk.git
-
-  - name: tepl
-    buildsystem: meson
-    sources:
-      - type: git
-        url: https://gitlab.gnome.org/GNOME/tepl.git
+      - type: archive
+        url: https://www.freedesktop.org/software/uchardet/releases/uchardet-0.0.6.tar.xz
+        sha256: 8351328cdfbcb2432e63938721dd781eb8c11ebc56e3a89d0f84576b96002c61
 
   - name: gedit
     buildsystem: meson
diff --git a/build-aux/snap/snapcraft.yaml b/build-aux/snap/snapcraft.yaml
index fc49c3949..43db5e027 100644
--- a/build-aux/snap/snapcraft.yaml
+++ b/build-aux/snap/snapcraft.yaml
@@ -41,30 +41,6 @@ apps:
       GTK_USE_PORTAL: 1
 
 parts:
-  amtk:
-    source: https://gitlab.gnome.org/GNOME/amtk.git
-    source-type: git
-    plugin: autotools
-    configflags:
-      - --prefix=/usr
-      - --enable-introspection=no
-    organize:
-      snap/gedit/current/usr: usr
-
-  tepl:
-    after: [amtk, gtksourceview]
-    source: https://gitlab.gnome.org/GNOME/tepl.git
-    source-type: git
-    plugin: meson
-    meson-parameters:
-      - --prefix=/usr
-    organize:
-      snap/gedit/current/usr: usr
-    build-packages:
-      - libuchardet-dev
-    stage-packages:
-      - libuchardet0
-
   gtksourceview:
     source: https://gitlab.gnome.org/GNOME/gtksourceview.git
     source-type: git
@@ -94,7 +70,7 @@ parts:
        cp $SNAPCRAFT_PART_INSTALL/usr/share/vala/vapi/gtksource* /usr/share/vala/vapi
 
   gedit:
-    after: [gtksourceview, tepl]
+    after: [gtksourceview]
     source: .
     source-type: git
     parse-info: [usr/share/metainfo/org.gnome.gedit.appdata.xml]
@@ -102,6 +78,7 @@ parts:
     meson-parameters:
       - --prefix=/usr
       - -Dvala_args="--vapidir=$SNAPCRAFT_STAGE/usr/share/vala/vapi"
+
     build-environment:
       - C_INCLUDE_PATH: $SNAPCRAFT_STAGE/usr/include/gtksourceview-4
     override-build: |
diff --git a/data/org.gnome.gedit.gschema.xml.in b/data/org.gnome.gedit.gschema.xml.in
index b797d843c..59325f4ef 100644
--- a/data/org.gnome.gedit.gschema.xml.in
+++ b/data/org.gnome.gedit.gschema.xml.in
@@ -126,6 +126,11 @@
       <summary>Right Margin Position</summary>
       <description>Specifies the position of the right margin.</description>
     </key>
+    <key name="display-overview-map" type="b">
+      <default>false</default>
+      <summary>Display Overview Map</summary>
+      <description>Whether gedit should display the overview map for the document.</description>
+    </key>
     <key name="background-pattern" enum="org.gnome.gedit.BackgroundPatternType">
       <default>'none'</default>
       <summary>Document background pattern type</summary>
diff --git a/docs/gedit-development-getting-started.md b/docs/gedit-development-getting-started.md
index 4f930afc7..774bc180f 100644
--- a/docs/gedit-development-getting-started.md
+++ b/docs/gedit-development-getting-started.md
@@ -31,11 +31,9 @@ editor. To learn that widget API, read the excellent
 mostly valid). But GtkTextView is not enough for source code edition. gedit
 actually uses the
 [GtkSourceView](https://wiki.gnome.org/Projects/GtkSourceView) library, which
-contains a subclass of GtkTextView with many features useful for a text editor
-or an IDE. But GtkSourceView is not enough to have a full-blown text editor,
-gedit is actually in the process of using more features from the
-[Tepl](https://wiki.gnome.org/Projects/Tepl) library, and to further develop
-Tepl alongside gedit.
+contains a subclass of GtkTextView with syntax highlighting, a completion
+framework, the search and replace, and many other features useful for a text
+editor or an IDE.
 
 For its plugin system, gedit uses the
 [libpeas](https://wiki.gnome.org/Projects/Libpeas) library.
diff --git a/docs/reference/api-breaks.xml b/docs/reference/api-breaks.xml
index f631761a6..a239cc443 100644
--- a/docs/reference/api-breaks.xml
+++ b/docs/reference/api-breaks.xml
@@ -96,13 +96,6 @@
           <code>gedit_app_get_lockdown()</code> function has been removed.
         </para>
       </listitem>
-      <listitem>
-        <para>
-          The <code>GBOOLEAN_TO_POINTER()</code> and
-          <code>GPOINTER_TO_BOOLEAN()</code> macros have been removed from
-          <code>gedit-utils.h</code>.
-        </para>
-      </listitem>
       <listitem>
         <para>
           The <code>gedit_utils_get_current_workspace()</code>,
diff --git a/docs/reference/gedit-docs.xml b/docs/reference/gedit-docs.xml
index a0dc624cf..9e32e5469 100644
--- a/docs/reference/gedit-docs.xml
+++ b/docs/reference/gedit-docs.xml
@@ -16,6 +16,7 @@
     <xi:include href="xml/gedit-menu-extension.xml"/>
     <xi:include href="xml/gedit-message-bus.xml"/>
     <xi:include href="xml/gedit-message.xml"/>
+    <xi:include href="xml/gedit-progress-info-bar.xml"/>
     <xi:include href="xml/gedit-statusbar.xml"/>
     <xi:include href="xml/gedit-tab.xml"/>
     <xi:include href="xml/gedit-view.xml"/>
diff --git a/docs/reference/gedit-sections.txt b/docs/reference/gedit-sections.txt
index cec055fce..a71e00faa 100644
--- a/docs/reference/gedit-sections.txt
+++ b/docs/reference/gedit-sections.txt
@@ -54,7 +54,10 @@ gedit_document_new
 gedit_document_get_file
 gedit_document_get_short_name_for_display
 gedit_document_get_mime_type
+gedit_document_is_untouched
 gedit_document_is_untitled
+gedit_document_goto_line
+gedit_document_goto_line_offset
 gedit_document_set_language
 gedit_document_get_content_type
 gedit_document_get_metadata
@@ -148,6 +151,26 @@ GEDIT_MESSAGE_GET_CLASS
 GeditMessagePrivate
 </SECTION>
 
+<SECTION>
+<FILE>gedit-progress-info-bar</FILE>
+<TITLE>GeditProgressInfoBar</TITLE>
+GeditProgressInfoBar
+gedit_progress_info_bar_new
+gedit_progress_info_bar_set_icon_name
+gedit_progress_info_bar_set_markup
+gedit_progress_info_bar_set_text
+gedit_progress_info_bar_set_fraction
+gedit_progress_info_bar_pulse
+<SUBSECTION Standard>
+GEDIT_PROGRESS_INFO_BAR
+GEDIT_IS_PROGRESS_INFO_BAR
+GEDIT_TYPE_PROGRESS_INFO_BAR
+gedit_progress_info_bar_get_type
+GEDIT_PROGRESS_INFO_BAR_CLASS
+GEDIT_IS_PROGRESS_INFO_BAR_CLASS
+GEDIT_PROGRESS_INFO_BAR_GET_CLASS
+</SECTION>
+
 <SECTION>
 <FILE>gedit-statusbar</FILE>
 <TITLE>GeditStatusbar</TITLE>
@@ -199,6 +222,13 @@ GeditViewPrivate
 <TITLE>GeditView</TITLE>
 GeditView
 gedit_view_new
+gedit_view_cut_clipboard
+gedit_view_copy_clipboard
+gedit_view_paste_clipboard
+gedit_view_delete_selection
+gedit_view_select_all
+gedit_view_scroll_to_cursor
+gedit_view_set_font
 <SUBSECTION Standard>
 GEDIT_VIEW
 GEDIT_IS_VIEW
@@ -291,6 +321,7 @@ DEBUG_DOCUMENT
 DEBUG_COMMANDS
 DEBUG_APP
 DEBUG_UTILS
+DEBUG_METADATA
 gedit_debug_init
 gedit_debug
 gedit_debug_message
@@ -321,9 +352,14 @@ gedit_menu_extension_get_type
 
 <SECTION>
 <FILE>gedit-utils</FILE>
+GBOOLEAN_TO_POINTER
+GPOINTER_TO_BOOLEAN
 gedit_utils_menu_position_under_tree_view
 gedit_utils_set_atk_name_description
+gedit_warning
+gedit_utils_replace_home_dir_with_tilde
 gedit_utils_basename_for_display
+gedit_utils_decode_uri
 gedit_utils_drop_get_uris
 gedit_utils_get_compression_type_from_content_type
 gedit_utils_is_valid_location
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index 9a9c414dc..ed85f9cec 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -6,14 +6,12 @@ gio_docpath = dependency('gio-2.0').get_pkgconfig_variable('prefix') / 'share/gt
 gdk_docpath = dependency('gdk-3.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/gdk3'
 gtk_docpath = dependency('gtk+-3.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/gtk3'
 gsv_docpath = dependency('gtksourceview-4').get_pkgconfig_variable('prefix') / 
'share/gtk-doc/html/gtksourceview-4.0'
-amtk_docpath = dependency('amtk-5').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/amtk-5'
-tepl_docpath = dependency('tepl-6').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/tepl-6'
 libpeas_docpath = dependency('libpeas-1.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/libpeas'
 
 gedit_doc_dep = declare_dependency(
   link_with: libgedit_shared_lib,
   include_directories: root_include_dir,
-  dependencies: deps_basic_list,
+  dependencies: deps_basic_list + [libxml_dep],
 )
 
 gnome.gtkdoc(
@@ -30,8 +28,6 @@ gnome.gtkdoc(
     '--extra-dir=@0@'.format(gdk_docpath),
     '--extra-dir=@0@'.format(gtk_docpath),
     '--extra-dir=@0@'.format(gsv_docpath),
-    '--extra-dir=@0@'.format(amtk_docpath),
-    '--extra-dir=@0@'.format(tepl_docpath),
     '--extra-dir=@0@'.format(libpeas_docpath),
   ],
   content_files: [
diff --git a/docs/roadmap.md b/docs/roadmap.md
index 44a2f00b7..8199749b4 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -4,7 +4,8 @@ gedit roadmap
 This page contains the plans for major code changes we hope to get done in the
 future.
 
-See the [roadmap-done.md](roadmap-done.md) file for done tasks.
+See also the
+[GtkSourceView and Tepl roadmap](https://wiki.gnome.org/Projects/GtkSourceView/RoadMap).
 
 See the [NEWS file](../NEWS) for a detailed history.
 
diff --git a/gedit/Gedit-3.0.metadata b/gedit/Gedit-3.0.metadata
index e36d7cb30..1a5b45a3a 100644
--- a/gedit/Gedit-3.0.metadata
+++ b/gedit/Gedit-3.0.metadata
@@ -6,6 +6,7 @@ EncodingsComboBox cheader_filename="gedit/gedit-encodings-combo-box.h"
 MenuExtension cheader_filename="gedit/gedit-menu-extension.h"
 Message cheader_filename="gedit/gedit-message.h"
 MessageBus cheader_filename="gedit/gedit-message-bus.h"
+ProgressInfoBar cheader_filename="gedit/gedit-progress-info-bar.h"
 Statusbar cheader_filename="gedit/gedit-statusbar.h"
 Tab cheader_filename="gedit/gedit-tab.h"
 TabState cheader_filename="gedit/gedit-tab.h"
diff --git a/gedit/gedit-app-osx.m b/gedit/gedit-app-osx.m
index b02e9a28b..5df1b94da 100644
--- a/gedit/gedit-app-osx.m
+++ b/gedit/gedit-app-osx.m
@@ -31,7 +31,7 @@
 #include "gedit-debug.h"
 #include "gedit-commands.h"
 #include "gedit-commands-private.h"
-#include "gedit-recent-osx.h"
+#include "gedit-recent.h"
 #import <AppKit/AppKit.h>
 
 NSWindow *gdk_quartz_window_get_nswindow(GdkWindow *window);
@@ -286,7 +286,7 @@ gedit_app_osx_set_window_title_impl (GeditApp    *app,
                        g_free (uri);
                }
 
-               ismodified = !tepl_buffer_is_untouched (TEPL_BUFFER (document));
+               ismodified = !gedit_document_is_untouched (document);
                [native setDocumentEdited:ismodified];
        }
        else
diff --git a/gedit/gedit-app-private.h b/gedit/gedit-app-private.h
index 6e1278a3b..e9c58cc27 100644
--- a/gedit/gedit-app-private.h
+++ b/gedit/gedit-app-private.h
@@ -22,6 +22,7 @@
 #define GEDIT_APP_PRIVATE_H
 
 #include "gedit-app.h"
+#include "gedit-metadata-manager.h"
 #include "gedit-menu-extension.h"
 
 G_BEGIN_DECLS
@@ -34,6 +35,8 @@ GtkPrintSettings      *_gedit_app_get_default_print_settings  (GeditApp         *app);
 void                    _gedit_app_set_default_print_settings  (GeditApp         *app,
                                                                 GtkPrintSettings *settings);
 
+GeditMetadataManager   *_gedit_app_get_metadata_manager        (GeditApp  *app);
+
 GMenuModel             *_gedit_app_get_hamburger_menu          (GeditApp  *app);
 
 GMenuModel             *_gedit_app_get_notebook_menu           (GeditApp  *app);
diff --git a/gedit/gedit-app.c b/gedit/gedit-app.c
index 5532d5975..27d71a87a 100644
--- a/gedit/gedit-app.c
+++ b/gedit/gedit-app.c
@@ -28,8 +28,9 @@
 #include <stdlib.h>
 
 #include <glib/gi18n.h>
+#include <gio/gio.h>
 #include <libpeas/peas-extension-set.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
 
 #include "gedit-commands-private.h"
 #include "gedit-notebook.h"
@@ -44,6 +45,10 @@
 #include "gedit-preferences-dialog.h"
 #include "gedit-tab.h"
 
+#ifndef ENABLE_GVFS_METADATA
+#include "gedit-metadata-manager.h"
+#endif
+
 #define GEDIT_PAGE_SETUP_FILE          "gedit-page-setup"
 #define GEDIT_PRINT_SETTINGS_FILE      "gedit-print-settings"
 
@@ -51,6 +56,10 @@ typedef struct
 {
        GeditPluginsEngine *engine;
 
+#ifndef ENABLE_GVFS_METADATA
+       GeditMetadataManager *metadata_manager;
+#endif
+
        GtkCssProvider     *theme_provider;
 
        GtkPageSetup      *page_setup;
@@ -145,6 +154,10 @@ gedit_app_dispose (GObject *object)
 
        priv = gedit_app_get_instance_private (GEDIT_APP (object));
 
+#ifndef ENABLE_GVFS_METADATA
+       g_clear_object (&priv->metadata_manager);
+#endif
+
        g_clear_object (&priv->ui_settings);
        g_clear_object (&priv->window_settings);
 
@@ -643,6 +656,10 @@ gedit_app_startup (GApplication *application)
        GeditAppPrivate *priv;
        GtkCssProvider *css_provider;
        GtkSourceStyleSchemeManager *manager;
+#ifndef ENABLE_GVFS_METADATA
+       const gchar *cache_dir;
+       gchar *metadata_filename;
+#endif
 
        priv = gedit_app_get_instance_private (GEDIT_APP (application));
 
@@ -654,6 +671,13 @@ gedit_app_startup (GApplication *application)
 
        setup_theme_extensions (GEDIT_APP (application));
 
+#ifndef ENABLE_GVFS_METADATA
+       cache_dir = gedit_dirs_get_user_cache_dir ();
+       metadata_filename = g_build_filename (cache_dir, "gedit-metadata.xml", NULL);
+       priv->metadata_manager = gedit_metadata_manager_new (metadata_filename);
+       g_free (metadata_filename);
+#endif
+
        /* Load/init settings */
        _gedit_settings_get_singleton ();
        priv->ui_settings = g_settings_new ("org.gnome.gedit.preferences.ui");
@@ -1114,6 +1138,10 @@ gedit_app_shutdown (GApplication *app)
        save_page_setup (GEDIT_APP (app));
        save_print_settings (GEDIT_APP (app));
 
+       /* GTK+ can still hold references to some gedit objects, for example
+        * GeditDocument for the clipboard. So the metadata-manager should be
+        * shutdown after.
+        */
        G_APPLICATION_CLASS (gedit_app_parent_class)->shutdown (app);
 }
 
@@ -1253,15 +1281,10 @@ load_print_settings (GeditApp *app)
 static void
 gedit_app_init (GeditApp *app)
 {
-       TeplApplication *tepl_app;
-
        g_set_application_name ("gedit");
        gtk_window_set_default_icon_name ("org.gnome.gedit");
 
        g_application_add_main_option_entries (G_APPLICATION (app), options);
-
-       tepl_app = tepl_application_get_from_gtk_application (GTK_APPLICATION (app));
-       tepl_application_handle_metadata (tepl_app);
 }
 
 /**
@@ -1571,6 +1594,25 @@ _gedit_app_set_default_print_settings (GeditApp         *app,
        priv->print_settings = g_object_ref (settings);
 }
 
+
+GeditMetadataManager *
+_gedit_app_get_metadata_manager (GeditApp *app)
+{
+#ifndef ENABLE_GVFS_METADATA
+       GeditAppPrivate *priv;
+
+       g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
+
+       priv = gedit_app_get_instance_private (app);
+
+       return priv->metadata_manager;
+#else
+       g_assert_not_reached ();
+       return NULL;
+#endif
+}
+
+
 GMenuModel *
 _gedit_app_get_hamburger_menu (GeditApp *app)
 {
diff --git a/gedit/gedit-commands-edit.c b/gedit/gedit-commands-edit.c
index 66ea0174b..978440150 100644
--- a/gedit/gedit-commands-edit.c
+++ b/gedit/gedit-commands-edit.c
@@ -44,13 +44,13 @@ _gedit_cmd_edit_undo (GSimpleAction *action,
        gedit_debug (DEBUG_COMMANDS);
 
        active_view = gedit_window_get_active_view (window);
-       g_return_if_fail (active_view != NULL);
+       g_return_if_fail (active_view);
 
        active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
 
        gtk_source_buffer_undo (active_document);
 
-       tepl_view_scroll_to_cursor (TEPL_VIEW (active_view));
+       gedit_view_scroll_to_cursor (active_view);
 
        gtk_widget_grab_focus (GTK_WIDGET (active_view));
 }
@@ -67,13 +67,13 @@ _gedit_cmd_edit_redo (GSimpleAction *action,
        gedit_debug (DEBUG_COMMANDS);
 
        active_view = gedit_window_get_active_view (window);
-       g_return_if_fail (active_view != NULL);
+       g_return_if_fail (active_view);
 
        active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
 
        gtk_source_buffer_redo (active_document);
 
-       tepl_view_scroll_to_cursor (TEPL_VIEW (active_view));
+       gedit_view_scroll_to_cursor (active_view);
 
        gtk_widget_grab_focus (GTK_WIDGET (active_view));
 }
@@ -89,9 +89,9 @@ _gedit_cmd_edit_cut (GSimpleAction *action,
        gedit_debug (DEBUG_COMMANDS);
 
        active_view = gedit_window_get_active_view (window);
-       g_return_if_fail (active_view != NULL);
+       g_return_if_fail (active_view);
 
-       tepl_view_cut_clipboard (TEPL_VIEW (active_view));
+       gedit_view_cut_clipboard (active_view);
 
        gtk_widget_grab_focus (GTK_WIDGET (active_view));
 }
@@ -107,9 +107,9 @@ _gedit_cmd_edit_copy (GSimpleAction *action,
        gedit_debug (DEBUG_COMMANDS);
 
        active_view = gedit_window_get_active_view (window);
-       g_return_if_fail (active_view != NULL);
+       g_return_if_fail (active_view);
 
-       tepl_view_copy_clipboard (TEPL_VIEW (active_view));
+       gedit_view_copy_clipboard (active_view);
 
        gtk_widget_grab_focus (GTK_WIDGET (active_view));
 }
@@ -125,9 +125,9 @@ _gedit_cmd_edit_paste (GSimpleAction *action,
        gedit_debug (DEBUG_COMMANDS);
 
        active_view = gedit_window_get_active_view (window);
-       g_return_if_fail (active_view != NULL);
+       g_return_if_fail (active_view);
 
-       tepl_view_paste_clipboard (TEPL_VIEW (active_view));
+       gedit_view_paste_clipboard (active_view);
 
        gtk_widget_grab_focus (GTK_WIDGET (active_view));
 }
@@ -143,9 +143,9 @@ _gedit_cmd_edit_delete (GSimpleAction *action,
        gedit_debug (DEBUG_COMMANDS);
 
        active_view = gedit_window_get_active_view (window);
-       g_return_if_fail (active_view != NULL);
+       g_return_if_fail (active_view);
 
-       tepl_view_delete_selection (TEPL_VIEW (active_view));
+       gedit_view_delete_selection (active_view);
 
        gtk_widget_grab_focus (GTK_WIDGET (active_view));
 }
@@ -161,9 +161,9 @@ _gedit_cmd_edit_select_all (GSimpleAction *action,
        gedit_debug (DEBUG_COMMANDS);
 
        active_view = gedit_window_get_active_view (window);
-       g_return_if_fail (active_view != NULL);
+       g_return_if_fail (active_view);
 
-       tepl_view_select_all (TEPL_VIEW (active_view));
+       gedit_view_select_all (active_view);
 
        gtk_widget_grab_focus (GTK_WIDGET (active_view));
 }
diff --git a/gedit/gedit-commands-file.c b/gedit/gedit-commands-file.c
index 91798b95f..001899b0c 100644
--- a/gedit/gedit-commands-file.c
+++ b/gedit/gedit-commands-file.c
@@ -27,7 +27,6 @@
 #include "gedit-commands-private.h"
 
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 
 #include "gedit-app.h"
 #include "gedit-debug.h"
@@ -44,10 +43,6 @@
 #include "gedit-file-chooser-open.h"
 #include "gedit-close-confirmation-dialog.h"
 
-/* useful macro */
-#define GBOOLEAN_TO_POINTER(i) (GINT_TO_POINTER ((i) ? 2 : 1))
-#define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((GPOINTER_TO_INT(i) == 2) ? TRUE : FALSE))
-
 #define GEDIT_IS_CLOSING_ALL "gedit-is-closing-all"
 #define GEDIT_NOTEBOOK_TO_CLOSE "gedit-notebook-to-close"
 #define GEDIT_IS_QUITTING "gedit-is-quitting"
@@ -150,24 +145,26 @@ load_file_list (GeditWindow             *window,
                {
                        if (l == files)
                        {
-                               TeplView *view;
+                               GeditDocument *doc;
 
                                gedit_window_set_active_tab (window, tab);
                                jump_to = FALSE;
-                               view = TEPL_VIEW (gedit_tab_get_view (tab));
+                               doc = gedit_tab_get_document (tab);
 
                                if (line_pos > 0)
                                {
                                        if (column_pos > 0)
                                        {
-                                               tepl_view_goto_line_offset (view,
-                                                                           line_pos - 1,
-                                                                           column_pos - 1);
+                                               gedit_document_goto_line_offset (doc,
+                                                                                line_pos - 1,
+                                                                                column_pos - 1);
                                        }
                                        else
                                        {
-                                               tepl_view_goto_line (view, line_pos - 1);
+                                               gedit_document_goto_line (doc, line_pos - 1);
                                        }
+
+                                       gedit_view_scroll_to_cursor (gedit_tab_get_view (tab));
                                }
                        }
 
@@ -194,7 +191,7 @@ load_file_list (GeditWindow             *window,
 
                doc = gedit_tab_get_document (tab);
 
-               if (tepl_buffer_is_untouched (TEPL_BUFFER (doc)) &&
+               if (gedit_document_is_untouched (doc) &&
                    gedit_tab_get_state (tab) == GEDIT_TAB_STATE_NORMAL)
                {
                        _gedit_tab_load (tab,
@@ -513,7 +510,7 @@ replace_read_only_file (GtkWindow *parent,
         * though the dialog uses wrapped text, if the name doesn't contain
         * white space then the text-wrapping code is too stupid to wrap it.
         */
-       name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
+       name_for_display = gedit_utils_str_middle_truncate (parse_name, 50);
        g_free (parse_name);
 
        dialog = gtk_message_dialog_new (parent,
@@ -565,7 +562,7 @@ change_compression (GtkWindow *parent,
         * though the dialog uses wrapped text, if the name doesn't contain
         * white space then the text-wrapping code is too stupid to wrap it.
         */
-       name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
+       name_for_display = gedit_utils_str_middle_truncate (parse_name, 50);
        g_free (parse_name);
 
        if (compressed)
@@ -827,6 +824,7 @@ save_as_tab_async (GeditTab            *tab,
        /* Translators: "Save As" is the title of the file chooser window. */
        save_dialog = gedit_file_chooser_dialog_create (C_("window title", "Save As"),
                                                        GTK_WINDOW (window),
+                                                       GEDIT_FILE_CHOOSER_FLAG_SAVE,
                                                        _("_Save"),
                                                        _("_Cancel"));
 
diff --git a/gedit/gedit-commands-search.c b/gedit/gedit-commands-search.c
index 22703985e..f120b8bad 100644
--- a/gedit/gedit-commands-search.c
+++ b/gedit/gedit-commands-search.c
@@ -29,7 +29,6 @@
 #include <string.h>
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
-#include <tepl/tepl.h>
 
 #include "gedit-debug.h"
 #include "gedit-statusbar.h"
@@ -132,7 +131,7 @@ text_not_found (GeditWindow        *window,
        gchar *truncated_text;
 
        search_text = gedit_replace_dialog_get_search_text (replace_dialog);
-       truncated_text = tepl_utils_str_end_truncate (search_text, MAX_MSG_LENGTH);
+       truncated_text = gedit_utils_str_end_truncate (search_text, MAX_MSG_LENGTH);
 
        gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
                                       window->priv->generic_message_cid,
@@ -188,7 +187,7 @@ forward_search_finished (GtkSourceSearchContext *search_context,
                                              &match_start,
                                              &match_end);
 
-               tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+               gedit_view_scroll_to_cursor (view);
        }
        else
        {
@@ -294,7 +293,7 @@ backward_search_finished (GtkSourceSearchContext *search_context,
                                              &match_start,
                                              &match_end);
 
-               tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+               gedit_view_scroll_to_cursor (view);
        }
        else
        {
diff --git a/gedit/gedit-commands-view.c b/gedit/gedit-commands-view.c
index 71785b78f..369bc93b0 100644
--- a/gedit/gedit-commands-view.c
+++ b/gedit/gedit-commands-view.c
@@ -21,11 +21,16 @@
  */
 
 #include "config.h"
+
 #include "gedit-commands.h"
 #include "gedit-commands-private.h"
-#include <tepl/tepl.h>
+
+#include <gtk/gtk.h>
+
 #include "gedit-debug.h"
 #include "gedit-window.h"
+#include "gedit-highlight-mode-dialog.h"
+#include "gedit-highlight-mode-selector.h"
 
 void
 _gedit_cmd_view_focus_active (GSimpleAction *action,
@@ -121,9 +126,9 @@ _gedit_cmd_view_leave_fullscreen_mode (GSimpleAction *action,
 }
 
 static void
-language_activated_cb (TeplLanguageChooserDialog *dialog,
-                      GtkSourceLanguage         *language,
-                      GeditWindow               *window)
+language_selected_cb (GeditHighlightModeSelector *selector,
+                     GtkSourceLanguage          *language,
+                     GeditWindow                *window)
 {
        GeditDocument *active_document;
 
@@ -132,16 +137,6 @@ language_activated_cb (TeplLanguageChooserDialog *dialog,
        {
                gedit_document_set_language (active_document, language);
        }
-
-       gtk_widget_destroy (GTK_WIDGET (dialog));
-}
-
-static void
-language_chooser_dialog_response_after_cb (TeplLanguageChooserDialog *dialog,
-                                          gint                       response_id,
-                                          gpointer                   user_data)
-{
-       gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 void
@@ -150,10 +145,12 @@ _gedit_cmd_view_highlight_mode (GSimpleAction *action,
                                 gpointer       user_data)
 {
        GeditWindow *window = GEDIT_WINDOW (user_data);
-       TeplLanguageChooserDialog *dialog;
+       GeditHighlightModeDialog *dialog;
+       GeditHighlightModeSelector *selector;
        GeditDocument *active_document;
 
-       dialog = tepl_language_chooser_dialog_new (GTK_WINDOW (window));
+       dialog = GEDIT_HIGHLIGHT_MODE_DIALOG (gedit_highlight_mode_dialog_new (GTK_WINDOW (window)));
+       selector = gedit_highlight_mode_dialog_get_selector (dialog);
 
        active_document = gedit_window_get_active_document (window);
        if (active_document != NULL)
@@ -161,20 +158,15 @@ _gedit_cmd_view_highlight_mode (GSimpleAction *action,
                GtkSourceLanguage *language;
 
                language = gedit_document_get_language (active_document);
-               tepl_language_chooser_select_language (TEPL_LANGUAGE_CHOOSER (dialog), language);
+               gedit_highlight_mode_selector_select_language (selector, language);
        }
 
-       g_signal_connect_object (dialog,
-                                "language-activated",
-                                G_CALLBACK (language_activated_cb),
+       g_signal_connect_object (selector,
+                                "language-selected",
+                                G_CALLBACK (language_selected_cb),
                                 window,
                                 0);
 
-       g_signal_connect_after (dialog,
-                               "response",
-                               G_CALLBACK (language_chooser_dialog_response_after_cb),
-                               NULL);
-
        gtk_widget_show (GTK_WIDGET (dialog));
 }
 
diff --git a/gedit/gedit-debug.c b/gedit/gedit-debug.c
index 5aa82fa51..396dc140f 100644
--- a/gedit/gedit-debug.c
+++ b/gedit/gedit-debug.c
@@ -100,6 +100,10 @@ gedit_debug_init (void)
        {
                enabled_sections |= GEDIT_DEBUG_UTILS;
        }
+       if (g_getenv ("GEDIT_DEBUG_METADATA") != NULL)
+       {
+               enabled_sections |= GEDIT_DEBUG_METADATA;
+       }
 
 out:
 
diff --git a/gedit/gedit-debug.h b/gedit/gedit-debug.h
index a9d7caf37..49e5127e1 100644
--- a/gedit/gedit-debug.h
+++ b/gedit/gedit-debug.h
@@ -48,6 +48,7 @@ typedef enum {
        GEDIT_DEBUG_COMMANDS = 1 << 7,
        GEDIT_DEBUG_APP      = 1 << 8,
        GEDIT_DEBUG_UTILS    = 1 << 9,
+       GEDIT_DEBUG_METADATA = 1 << 10,
 } GeditDebugSection;
 
 #define        DEBUG_VIEW      GEDIT_DEBUG_VIEW,    __FILE__, __LINE__, G_STRFUNC
@@ -60,6 +61,7 @@ typedef enum {
 #define        DEBUG_COMMANDS  GEDIT_DEBUG_COMMANDS,__FILE__, __LINE__, G_STRFUNC
 #define        DEBUG_APP       GEDIT_DEBUG_APP,     __FILE__, __LINE__, G_STRFUNC
 #define        DEBUG_UTILS     GEDIT_DEBUG_UTILS,   __FILE__, __LINE__, G_STRFUNC
+#define        DEBUG_METADATA  GEDIT_DEBUG_METADATA,__FILE__, __LINE__, G_STRFUNC
 
 void gedit_debug_init (void);
 
diff --git a/gedit/gedit-document-private.h b/gedit/gedit-document-private.h
index 62444cc76..574c0bb89 100644
--- a/gedit/gedit-document-private.h
+++ b/gedit/gedit-document-private.h
@@ -28,9 +28,15 @@
 
 G_BEGIN_DECLS
 
-#define GEDIT_METADATA_ATTRIBUTE_POSITION "gedit-position"
-#define GEDIT_METADATA_ATTRIBUTE_ENCODING "gedit-encoding"
-#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "gedit-language"
+#ifdef G_OS_WIN32
+#define GEDIT_METADATA_ATTRIBUTE_POSITION "position"
+#define GEDIT_METADATA_ATTRIBUTE_ENCODING "encoding"
+#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "language"
+#else
+#define GEDIT_METADATA_ATTRIBUTE_POSITION "metadata::gedit-position"
+#define GEDIT_METADATA_ATTRIBUTE_ENCODING "metadata::gedit-encoding"
+#define GEDIT_METADATA_ATTRIBUTE_LANGUAGE "metadata::gedit-language"
+#endif
 
 G_GNUC_INTERNAL
 glong          _gedit_document_get_seconds_since_last_save_or_load     (GeditDocument *doc);
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 54c11a96c..4cb08ee03 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -5,7 +5,7 @@
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002-2005 Paolo Maggi
- * Copyright (C) 2014-2020 Sébastien Wilmet
+ * Copyright (C) 2014-2015 Sébastien Wilmet
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,13 +22,21 @@
  */
 
 #include "config.h"
+
 #include "gedit-document.h"
 #include "gedit-document-private.h"
+
 #include <string.h>
 #include <glib/gi18n.h>
+
+#include "gedit-app.h"
+#include "gedit-app-private.h"
 #include "gedit-settings.h"
 #include "gedit-debug.h"
 #include "gedit-utils.h"
+#include "gedit-metadata-manager.h"
+
+#define METADATA_QUERY "metadata::*"
 
 #define NO_LANGUAGE_NAME "_NORMAL_"
 
@@ -43,7 +51,11 @@ typedef struct
 {
        GtkSourceFile *file;
 
-       TeplMetadata *metadata;
+       GSettings   *editor_settings;
+
+       gint         untitled_number;
+
+       GFileInfo   *metadata_info;
 
        gchar       *content_type;
 
@@ -54,7 +66,12 @@ typedef struct
         */
        GtkSourceSearchContext *search_context;
 
+       GeditMetadataManager *metadata_manager;
+
+       guint user_action;
+
        guint language_set_by_user : 1;
+       guint use_gvfs_metadata : 1;
 
        /* The search is empty if there is no search context, or if the
         * search text is empty. It is used for the sensitivity of some menu
@@ -71,9 +88,11 @@ typedef struct
 enum
 {
        PROP_0,
+       PROP_SHORTNAME,
        PROP_CONTENT_TYPE,
        PROP_MIME_TYPE,
        PROP_EMPTY_SEARCH,
+       PROP_USE_GVFS_METADATA,
        LAST_PROP
 };
 
@@ -81,6 +100,7 @@ static GParamSpec *properties[LAST_PROP];
 
 enum
 {
+       CURSOR_MOVED,
        LOAD,
        LOADED,
        SAVE,
@@ -90,40 +110,41 @@ enum
 
 static guint document_signals[LAST_SIGNAL];
 
-G_DEFINE_TYPE_WITH_PRIVATE (GeditDocument, gedit_document, TEPL_TYPE_BUFFER)
+static GHashTable *allocated_untitled_numbers = NULL;
 
-static void
-load_metadata_from_metadata_manager (GeditDocument *doc)
+G_DEFINE_TYPE_WITH_PRIVATE (GeditDocument, gedit_document, GTK_SOURCE_TYPE_BUFFER)
+
+static gint
+get_untitled_number (void)
 {
-       GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
-       GFile *location;
+       gint i = 1;
 
-       location = gtk_source_file_get_location (priv->file);
+       if (allocated_untitled_numbers == NULL)
+               allocated_untitled_numbers = g_hash_table_new (NULL, NULL);
 
-       if (location != NULL)
+       g_return_val_if_fail (allocated_untitled_numbers != NULL, -1);
+
+       while (TRUE)
        {
-               TeplMetadataManager *manager;
+               if (g_hash_table_lookup (allocated_untitled_numbers, GINT_TO_POINTER (i)) == NULL)
+               {
+                       g_hash_table_insert (allocated_untitled_numbers,
+                                            GINT_TO_POINTER (i),
+                                            GINT_TO_POINTER (i));
 
-               manager = tepl_metadata_manager_get_singleton ();
-               tepl_metadata_manager_copy_from (manager, location, priv->metadata);
+                       return i;
+               }
+
+               ++i;
        }
 }
 
 static void
-save_metadata_into_metadata_manager (GeditDocument *doc)
+release_untitled_number (gint n)
 {
-       GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
-       GFile *location;
-
-       location = gtk_source_file_get_location (priv->file);
-
-       if (location != NULL)
-       {
-               TeplMetadataManager *manager;
+       g_return_if_fail (allocated_untitled_numbers != NULL);
 
-               manager = tepl_metadata_manager_get_singleton ();
-               tepl_metadata_manager_merge_into (manager, location, priv->metadata);
-       }
+       g_hash_table_remove (allocated_untitled_numbers, GINT_TO_POINTER (n));
 }
 
 static void
@@ -195,16 +216,17 @@ gedit_document_dispose (GObject *object)
        /* Metadata must be saved here and not in finalize because the language
         * is gone by the time finalize runs.
         */
-       if (priv->metadata != NULL)
+       if (priv->file != NULL)
        {
                save_metadata (doc);
 
-               g_object_unref (priv->metadata);
-               priv->metadata = NULL;
+               g_object_unref (priv->file);
+               priv->file = NULL;
        }
 
-       g_clear_object (&priv->file);
+       g_clear_object (&priv->metadata_info);
        g_clear_object (&priv->search_context);
+       g_clear_object (&priv->metadata_manager);
 
        G_OBJECT_CLASS (gedit_document_parent_class)->dispose (object);
 }
@@ -212,10 +234,17 @@ gedit_document_dispose (GObject *object)
 static void
 gedit_document_finalize (GObject *object)
 {
-       GeditDocumentPrivate *priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (object));
+       GeditDocumentPrivate *priv;
 
        gedit_debug (DEBUG_DOCUMENT);
 
+       priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (object));
+
+       if (priv->untitled_number > 0)
+       {
+               release_untitled_number (priv->untitled_number);
+       }
+
        g_free (priv->content_type);
 
        if (priv->time_of_last_save_or_load != NULL)
@@ -239,6 +268,10 @@ gedit_document_get_property (GObject    *object,
 
        switch (prop_id)
        {
+               case PROP_SHORTNAME:
+                       g_value_take_string (value, gedit_document_get_short_name_for_display (doc));
+                       break;
+
                case PROP_CONTENT_TYPE:
                        g_value_take_string (value, gedit_document_get_content_type (doc));
                        break;
@@ -251,6 +284,10 @@ gedit_document_get_property (GObject    *object,
                        g_value_set_boolean (value, priv->empty_search);
                        break;
 
+               case PROP_USE_GVFS_METADATA:
+                       g_value_set_boolean (value, priv->use_gvfs_metadata);
+                       break;
+
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
@@ -264,6 +301,7 @@ gedit_document_set_property (GObject      *object,
                             GParamSpec   *pspec)
 {
        GeditDocument *doc = GEDIT_DOCUMENT (object);
+       GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
 
        switch (prop_id)
        {
@@ -271,22 +309,97 @@ gedit_document_set_property (GObject      *object,
                        set_content_type (doc, g_value_get_string (value));
                        break;
 
+               case PROP_USE_GVFS_METADATA:
+                       priv->use_gvfs_metadata = g_value_get_boolean (value);
+                       break;
+
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
        }
 }
 
+static void
+gedit_document_begin_user_action (GtkTextBuffer *buffer)
+{
+       GeditDocumentPrivate *priv;
+
+       priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (buffer));
+
+       ++priv->user_action;
+
+       if (GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->begin_user_action != NULL)
+       {
+               GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->begin_user_action (buffer);
+       }
+}
+
+static void
+gedit_document_end_user_action (GtkTextBuffer *buffer)
+{
+       GeditDocumentPrivate *priv;
+
+       priv = gedit_document_get_instance_private (GEDIT_DOCUMENT (buffer));
+
+       --priv->user_action;
+
+       if (GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->end_user_action != NULL)
+       {
+               GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->end_user_action (buffer);
+       }
+}
+
+static void
+gedit_document_mark_set (GtkTextBuffer     *buffer,
+                         const GtkTextIter *iter,
+                         GtkTextMark       *mark)
+{
+       GeditDocument *doc = GEDIT_DOCUMENT (buffer);
+       GeditDocumentPrivate *priv;
+
+       priv = gedit_document_get_instance_private (doc);
+
+       if (GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->mark_set != NULL)
+       {
+               GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->mark_set (buffer, iter, mark);
+       }
+
+       if (mark == gtk_text_buffer_get_insert (buffer) && (priv->user_action == 0))
+       {
+               g_signal_emit (doc, document_signals[CURSOR_MOVED], 0);
+       }
+}
+
+static void
+gedit_document_changed (GtkTextBuffer *buffer)
+{
+       g_signal_emit (GEDIT_DOCUMENT (buffer), document_signals[CURSOR_MOVED], 0);
+
+       GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->changed (buffer);
+}
+
 static void
 gedit_document_constructed (GObject *object)
 {
        GeditDocument *doc = GEDIT_DOCUMENT (object);
+       GeditDocumentPrivate *priv;
        GeditSettings *settings;
        GSettings *editor_settings;
 
+       priv = gedit_document_get_instance_private (doc);
+
        settings = _gedit_settings_get_singleton ();
        editor_settings = _gedit_settings_peek_editor_settings (settings);
 
+       if (!priv->use_gvfs_metadata)
+       {
+               GeditMetadataManager *metadata_manager;
+
+               metadata_manager = _gedit_app_get_metadata_manager (GEDIT_APP (g_application_get_default ()));
+               g_assert (GEDIT_IS_METADATA_MANAGER (metadata_manager));
+               priv->metadata_manager = g_object_ref (metadata_manager);
+       }
+
        /* Bind construct properties. */
        g_settings_bind (editor_settings, GEDIT_SETTINGS_ENSURE_TRAILING_NEWLINE,
                         doc, "implicit-trailing-newline",
@@ -299,6 +412,7 @@ static void
 gedit_document_class_init (GeditDocumentClass *klass)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkTextBufferClass *buf_class = GTK_TEXT_BUFFER_CLASS (klass);
 
        object_class->dispose = gedit_document_dispose;
        object_class->finalize = gedit_document_finalize;
@@ -306,9 +420,26 @@ gedit_document_class_init (GeditDocumentClass *klass)
        object_class->set_property = gedit_document_set_property;
        object_class->constructed = gedit_document_constructed;
 
+       buf_class->begin_user_action = gedit_document_begin_user_action;
+       buf_class->end_user_action = gedit_document_end_user_action;
+       buf_class->mark_set = gedit_document_mark_set;
+       buf_class->changed = gedit_document_changed;
+
        klass->loaded = gedit_document_loaded_real;
        klass->saved = gedit_document_saved_real;
 
+       /**
+        * GeditDocument:shortname:
+        *
+        * The document's short name.
+        */
+       properties[PROP_SHORTNAME] =
+               g_param_spec_string ("shortname",
+                                    "Short Name",
+                                    "The document's short name",
+                                    NULL,
+                                    G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
        /**
         * GeditDocument:content-type:
         *
@@ -348,8 +479,44 @@ gedit_document_class_init (GeditDocumentClass *klass)
                                      TRUE,
                                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
+       /**
+        * GeditDocument:use-gvfs-metadata:
+        *
+        * Whether to use GVFS metadata. If %FALSE, use the gedit metadata
+        * manager that stores the metadata in an XML file in the user cache
+        * directory.
+        *
+        * <warning>
+        * The property is used internally by gedit. It must not be used in a
+        * gedit plugin. The property can be modified or removed at any time.
+        * </warning>
+        */
+       properties[PROP_USE_GVFS_METADATA] =
+               g_param_spec_boolean ("use-gvfs-metadata",
+                                     "Use GVFS metadata",
+                                     "",
+                                     TRUE,
+                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
        g_object_class_install_properties (object_class, LAST_PROP, properties);
 
+       /* This signal is used to update the cursor position in the statusbar,
+        * it's emitted either when the insert mark is moved explicitely or
+        * when the buffer changes (insert/delete).
+        * FIXME When the replace_all was implemented in gedit, this signal was
+        * not emitted during the replace_all to improve performance. Now the
+        * replace_all is implemented in GtkSourceView, so the signal is
+        * emitted.
+        */
+       document_signals[CURSOR_MOVED] =
+               g_signal_new ("cursor-moved",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GeditDocumentClass, cursor_moved),
+                             NULL, NULL, NULL,
+                             G_TYPE_NONE,
+                             0);
+
        /**
         * GeditDocument::load:
         * @document: the #GeditDocument.
@@ -632,20 +799,79 @@ on_location_changed (GtkSourceFile *file,
                     GParamSpec    *pspec,
                     GeditDocument *doc)
 {
+       GeditDocumentPrivate *priv;
+       GFile *location;
+
        gedit_debug (DEBUG_DOCUMENT);
-       load_metadata_from_metadata_manager (doc);
+
+       priv = gedit_document_get_instance_private (doc);
+
+       location = gtk_source_file_get_location (file);
+
+       if (location != NULL && priv->untitled_number > 0)
+       {
+               release_untitled_number (priv->untitled_number);
+               priv->untitled_number = 0;
+       }
+
+       g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]);
+
+       /* Load metadata for this location: we load sync since metadata is
+        * always local so it should be fast and we need the information
+        * right after the location was set.
+        * TODO: do async I/O for the metadata.
+        */
+       if (priv->use_gvfs_metadata && location != NULL)
+       {
+               GError *error = NULL;
+
+               if (priv->metadata_info != NULL)
+               {
+                       g_object_unref (priv->metadata_info);
+               }
+
+               priv->metadata_info = g_file_query_info (location,
+                                                        METADATA_QUERY,
+                                                        G_FILE_QUERY_INFO_NONE,
+                                                        NULL,
+                                                        &error);
+
+               if (error != NULL)
+               {
+                       /* Do not complain about metadata if we are opening a
+                        * non existing file.
+                        */
+                       if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_ISDIR) &&
+                           !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR) &&
+                           !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
+                           !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+                       {
+                               g_warning ("%s", error->message);
+                       }
+
+                       g_error_free (error);
+               }
+
+               if (priv->metadata_info == NULL)
+               {
+                       priv->metadata_info = g_file_info_new ();
+               }
+       }
 }
 
 static void
 gedit_document_init (GeditDocument *doc)
 {
        GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
-       TeplFile *tepl_file;
        GeditSettings *settings;
        GSettings *editor_settings;
 
        gedit_debug (DEBUG_DOCUMENT);
 
+       settings = _gedit_settings_get_singleton ();
+       editor_settings = _gedit_settings_peek_editor_settings (settings);
+
+       priv->untitled_number = get_untitled_number ();
        priv->content_type = get_default_content_type ();
        priv->language_set_by_user = FALSE;
        priv->empty_search = TRUE;
@@ -653,13 +879,7 @@ gedit_document_init (GeditDocument *doc)
        update_time_of_last_save_or_load (doc);
 
        priv->file = gtk_source_file_new ();
-       tepl_file = tepl_buffer_get_file (TEPL_BUFFER (doc));
-
-       g_object_bind_property (priv->file, "location",
-                               tepl_file, "location",
-                               G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
-
-       priv->metadata = tepl_metadata_new ();
+       priv->metadata_info = g_file_info_new ();
 
        g_signal_connect_object (priv->file,
                                 "notify::location",
@@ -667,9 +887,6 @@ gedit_document_init (GeditDocument *doc)
                                 doc,
                                 0);
 
-       settings = _gedit_settings_get_singleton ();
-       editor_settings = _gedit_settings_peek_editor_settings (settings);
-
        g_settings_bind (editor_settings, GEDIT_SETTINGS_MAX_UNDO_ACTIONS,
                         doc, "max-undo-levels",
                         G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
@@ -699,7 +916,17 @@ gedit_document_init (GeditDocument *doc)
 GeditDocument *
 gedit_document_new (void)
 {
-       return g_object_new (GEDIT_TYPE_DOCUMENT, NULL);
+       gboolean use_gvfs_metadata;
+
+#ifdef ENABLE_GVFS_METADATA
+       use_gvfs_metadata = TRUE;
+#else
+       use_gvfs_metadata = FALSE;
+#endif
+
+       return g_object_new (GEDIT_TYPE_DOCUMENT,
+                            "use-gvfs-metadata", use_gvfs_metadata,
+                            NULL);
 }
 
 static gchar *
@@ -814,17 +1041,19 @@ set_content_type (GeditDocument *doc,
 gchar *
 _gedit_document_get_uri_for_display (GeditDocument *doc)
 {
-       TeplFile *file;
+       GeditDocumentPrivate *priv;
        GFile *location;
 
        g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), g_strdup (""));
 
-       file = tepl_buffer_get_file (TEPL_BUFFER (doc));
-       location = tepl_file_get_location (file);
+       priv = gedit_document_get_instance_private (doc);
+
+       location = gtk_source_file_get_location (priv->file);
 
        if (location == NULL)
        {
-               return tepl_file_get_short_name (file);
+               return g_strdup_printf (_("Untitled Document %d"),
+                                       priv->untitled_number);
        }
        else
        {
@@ -841,12 +1070,24 @@ _gedit_document_get_uri_for_display (GeditDocument *doc)
 gchar *
 gedit_document_get_short_name_for_display (GeditDocument *doc)
 {
-       TeplFile *file;
+       GeditDocumentPrivate *priv;
+       GFile *location;
 
        g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), g_strdup (""));
 
-       file = tepl_buffer_get_file (TEPL_BUFFER (doc));
-       return tepl_file_get_short_name (file);
+       priv = gedit_document_get_instance_private (doc);
+
+       location = gtk_source_file_get_location (priv->file);
+
+       if (location == NULL)
+       {
+               return g_strdup_printf (_("Untitled Document %d"),
+                                       priv->untitled_number);
+       }
+       else
+       {
+               return gedit_utils_basename_for_display (location);
+       }
 }
 
 gchar *
@@ -1032,15 +1273,31 @@ gedit_document_saved_real (GeditDocument *doc)
                                 doc);
 }
 
+gboolean
+gedit_document_is_untouched (GeditDocument *doc)
+{
+       GeditDocumentPrivate *priv;
+       GFile *location;
+
+       g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE);
+
+       priv = gedit_document_get_instance_private (doc);
+
+       location = gtk_source_file_get_location (priv->file);
+
+       return location == NULL && !gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc));
+}
+
 gboolean
 gedit_document_is_untitled (GeditDocument *doc)
 {
-       TeplFile *file;
+       GeditDocumentPrivate *priv;
 
        g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE);
 
-       file = tepl_buffer_get_file (TEPL_BUFFER (doc));
-       return tepl_file_get_location (file) == NULL;
+       priv = gedit_document_get_instance_private (doc);
+
+       return gtk_source_file_get_location (priv->file) == NULL;
 }
 
 /*
@@ -1072,6 +1329,51 @@ _gedit_document_needs_saving (GeditDocument *doc)
        return (externally_modified || deleted) && !priv->create;
 }
 
+/* If @line is bigger than the lines of the document, the cursor is moved
+ * to the last line and FALSE is returned.
+ */
+gboolean
+gedit_document_goto_line (GeditDocument *doc,
+                         gint           line)
+{
+       GtkTextIter iter;
+
+       gedit_debug (DEBUG_DOCUMENT);
+
+       g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
+       g_return_val_if_fail (line >= -1, FALSE);
+
+       gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc),
+                                         &iter,
+                                         line);
+
+       gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
+
+       return gtk_text_iter_get_line (&iter) == line;
+}
+
+gboolean
+gedit_document_goto_line_offset (GeditDocument *doc,
+                                gint           line,
+                                gint           line_offset)
+{
+       GtkTextIter iter;
+
+       g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
+       g_return_val_if_fail (line >= -1, FALSE);
+       g_return_val_if_fail (line_offset >= -1, FALSE);
+
+       gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER (doc),
+                                                &iter,
+                                                line,
+                                                line_offset);
+
+       gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
+
+       return (gtk_text_iter_get_line (&iter) == line &&
+               gtk_text_iter_get_line_offset (&iter) == line_offset);
+}
+
 /**
  * gedit_document_set_language:
  * @doc:
@@ -1130,6 +1432,64 @@ _gedit_document_get_seconds_since_last_save_or_load (GeditDocument *doc)
        return n_microseconds / (1000 * 1000);
 }
 
+static gchar *
+get_metadata_from_metadata_manager (GeditDocument *doc,
+                                   const gchar   *key)
+{
+       GeditDocumentPrivate *priv;
+       GFile *location;
+
+       priv = gedit_document_get_instance_private (doc);
+
+       location = gtk_source_file_get_location (priv->file);
+
+       if (location != NULL)
+       {
+               return gedit_metadata_manager_get (priv->metadata_manager, location, key);
+       }
+
+       return NULL;
+}
+
+static gchar *
+get_metadata_from_gvfs (GeditDocument *doc,
+                       const gchar   *key)
+{
+       GeditDocumentPrivate *priv;
+
+       priv = gedit_document_get_instance_private (doc);
+
+       if (priv->metadata_info != NULL &&
+           g_file_info_has_attribute (priv->metadata_info, key) &&
+           g_file_info_get_attribute_type (priv->metadata_info, key) == G_FILE_ATTRIBUTE_TYPE_STRING)
+       {
+               return g_strdup (g_file_info_get_attribute_string (priv->metadata_info, key));
+       }
+
+       return NULL;
+}
+
+static void
+set_gvfs_metadata (GFileInfo   *info,
+                  const gchar *key,
+                  const gchar *value)
+{
+       g_return_if_fail (G_IS_FILE_INFO (info));
+
+       if (value != NULL)
+       {
+               g_file_info_set_attribute_string (info, key, value);
+       }
+       else
+       {
+               /* Unset the key */
+               g_file_info_set_attribute (info,
+                                          key,
+                                          G_FILE_ATTRIBUTE_TYPE_INVALID,
+                                          NULL);
+       }
+}
+
 /**
  * gedit_document_get_metadata:
  * @doc: a #GeditDocument
@@ -1150,12 +1510,12 @@ gedit_document_get_metadata (GeditDocument *doc,
 
        priv = gedit_document_get_instance_private (doc);
 
-       if (priv->metadata == NULL)
+       if (priv->use_gvfs_metadata)
        {
-               return NULL;
+               return get_metadata_from_gvfs (doc, key);
        }
 
-       return tepl_metadata_get (priv->metadata, key);
+       return get_metadata_from_metadata_manager (doc, key);
 }
 
 /**
@@ -1173,30 +1533,84 @@ gedit_document_set_metadata (GeditDocument *doc,
                             ...)
 {
        GeditDocumentPrivate *priv;
-       va_list var_args;
+       GFile *location;
        const gchar *key;
+       va_list var_args;
+       GFileInfo *info = NULL;
 
        g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
        g_return_if_fail (first_key != NULL);
 
        priv = gedit_document_get_instance_private (doc);
 
-       if (priv->metadata == NULL)
+       location = gtk_source_file_get_location (priv->file);
+
+       /* With the metadata manager, can't set metadata for untitled documents.
+        * With GVFS metadata, if the location is NULL the metadata is stored in
+        * priv->metadata_info, so that it can be saved later if the document is
+        * saved.
+        */
+       if (!priv->use_gvfs_metadata && location == NULL)
        {
                return;
        }
 
+       if (priv->use_gvfs_metadata)
+       {
+               info = g_file_info_new ();
+       }
+
        va_start (var_args, first_key);
 
-       for (key = first_key; key != NULL; key = va_arg (var_args, const gchar *))
+       for (key = first_key; key; key = va_arg (var_args, const gchar *))
        {
                const gchar *value = va_arg (var_args, const gchar *);
-               tepl_metadata_set (priv->metadata, key, value);
+
+               if (priv->use_gvfs_metadata)
+               {
+                       set_gvfs_metadata (info, key, value);
+                       set_gvfs_metadata (priv->metadata_info, key, value);
+               }
+               else
+               {
+                       gedit_metadata_manager_set (priv->metadata_manager, location, key, value);
+               }
        }
 
        va_end (var_args);
 
-       save_metadata_into_metadata_manager (doc);
+       if (priv->use_gvfs_metadata && location != NULL)
+       {
+               GError *error = NULL;
+
+               /* We save synchronously since metadata is always local so it
+                * should be fast. Moreover this function can be called on
+                * application shutdown, when the main loop has already exited,
+                * so an async operation would not terminate.
+                * https://bugzilla.gnome.org/show_bug.cgi?id=736591
+                */
+               g_file_set_attributes_from_info (location,
+                                                info,
+                                                G_FILE_QUERY_INFO_NONE,
+                                                NULL,
+                                                &error);
+
+               if (error != NULL)
+               {
+                       /* Do not complain about metadata if we are closing a
+                        * document for a non existing file.
+                        */
+                       if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
+                           !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+                       {
+                               g_warning ("Set document metadata failed: %s", error->message);
+                       }
+
+                       g_error_free (error);
+               }
+       }
+
+       g_clear_object (&info);
 }
 
 static void
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index 901d02dc0..ed52a42fb 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -5,7 +5,7 @@
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002-2005 Paolo Maggi
- * Copyright (C) 2014-2020 Sébastien Wilmet
+ * Copyright (C) 2014 Sébastien Wilmet
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,19 +24,20 @@
 #ifndef GEDIT_DOCUMENT_H
 #define GEDIT_DOCUMENT_H
 
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
 
 G_BEGIN_DECLS
 
 #define GEDIT_TYPE_DOCUMENT (gedit_document_get_type())
 
-G_DECLARE_DERIVABLE_TYPE (GeditDocument, gedit_document, GEDIT, DOCUMENT, TeplBuffer)
+G_DECLARE_DERIVABLE_TYPE (GeditDocument, gedit_document, GEDIT, DOCUMENT, GtkSourceBuffer)
 
 struct _GeditDocumentClass
 {
-       TeplBufferClass parent_class;
+       GtkSourceBufferClass parent_class;
 
        /* Signals */
+       void (* cursor_moved)           (GeditDocument *document);
 
        void (* load)                   (GeditDocument *document);
 
@@ -57,8 +58,17 @@ gchar                *gedit_document_get_content_type                (GeditDocument       
*doc);
 
 gchar          *gedit_document_get_mime_type                   (GeditDocument       *doc);
 
+gboolean        gedit_document_is_untouched                    (GeditDocument       *doc);
+
 gboolean        gedit_document_is_untitled                     (GeditDocument       *doc);
 
+gboolean        gedit_document_goto_line                       (GeditDocument       *doc,
+                                                               gint                 line);
+
+gboolean        gedit_document_goto_line_offset                (GeditDocument       *doc,
+                                                                gint                 line,
+                                                                gint                 line_offset);
+
 void            gedit_document_set_language                    (GeditDocument       *doc,
                                                                 GtkSourceLanguage   *lang);
 GtkSourceLanguage
diff --git a/gedit/gedit-documents-panel.c b/gedit/gedit-documents-panel.c
index 98d84a98f..8033f944e 100644
--- a/gedit/gedit-documents-panel.c
+++ b/gedit/gedit-documents-panel.c
@@ -23,7 +23,6 @@
 #include "gedit-documents-panel.h"
 
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 
 #include "gedit-debug.h"
 #include "gedit-document.h"
@@ -447,7 +446,7 @@ doc_get_name (GeditDocument *doc)
        name = gedit_document_get_short_name_for_display (doc);
 
        /* Truncate the name so it doesn't get insanely wide. */
-       docname = tepl_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
+       docname = gedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
 
        g_free (name);
 
diff --git a/gedit/gedit-file-chooser-dialog-gtk.c b/gedit/gedit-file-chooser-dialog-gtk.c
index 4b8b4dbb0..17671ff3e 100644
--- a/gedit/gedit-file-chooser-dialog-gtk.c
+++ b/gedit/gedit-file-chooser-dialog-gtk.c
@@ -192,6 +192,12 @@ chooser_show (GeditFileChooserDialog *dialog)
        gtk_widget_grab_focus (GTK_WIDGET (dialog));
 }
 
+static void
+chooser_hide (GeditFileChooserDialog *dialog)
+{
+       gtk_widget_hide (GTK_WIDGET (dialog));
+}
+
 static void
 chooser_destroy (GeditFileChooserDialog *dialog)
 {
@@ -211,6 +217,26 @@ chooser_get_window (GeditFileChooserDialog *dialog)
        return GTK_WINDOW (dialog);
 }
 
+static void
+chooser_add_pattern_filter (GeditFileChooserDialog *dialog,
+                            const gchar            *name,
+                            const gchar            *pattern)
+{
+       GtkFileFilter *filter;
+
+       filter = gtk_file_filter_new ();
+
+       gtk_file_filter_set_name (filter, name);
+       gtk_file_filter_add_pattern (filter, pattern);
+
+       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+       if (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == NULL)
+       {
+               gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
+       }
+}
+
 static void
 gedit_file_chooser_dialog_gtk_chooser_init (gpointer g_iface,
                                             gpointer iface_data)
@@ -229,9 +255,11 @@ gedit_file_chooser_dialog_gtk_chooser_init (gpointer g_iface,
        iface->get_file = chooser_get_file;
        iface->set_do_overwrite_confirmation = chooser_set_do_overwrite_confirmation;
        iface->show = chooser_show;
+       iface->hide = chooser_hide;
        iface->destroy = chooser_destroy;
        iface->set_modal = chooser_set_modal;
        iface->get_window = chooser_get_window;
+       iface->add_pattern_filter = chooser_add_pattern_filter;
 }
 
 static void
@@ -253,7 +281,8 @@ gedit_file_chooser_dialog_gtk_class_init (GeditFileChooserDialogGtkClass *klass)
 }
 
 static void
-create_option_menu (GeditFileChooserDialogGtk *dialog)
+create_option_menu (GeditFileChooserDialogGtk *dialog,
+                    GeditFileChooserFlags      flags)
 {
        GtkWidget *label;
        GtkWidget *menu;
@@ -262,7 +291,7 @@ create_option_menu (GeditFileChooserDialogGtk *dialog)
        label = gtk_label_new_with_mnemonic (_("C_haracter Encoding:"));
        gtk_widget_set_halign (label, GTK_ALIGN_START);
 
-       save_mode = TRUE;
+       save_mode = (flags & GEDIT_FILE_CHOOSER_FLAG_SAVE) != 0;
        menu = gedit_encodings_combo_box_new (save_mode);
 
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu);
@@ -374,13 +403,18 @@ create_newline_combo (GeditFileChooserDialogGtk *dialog)
 }
 
 static void
-create_extra_widget (GeditFileChooserDialogGtk *dialog)
+create_extra_widget (GeditFileChooserDialogGtk *dialog,
+                     GeditFileChooserFlags      flags)
 {
        dialog->extra_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
        gtk_widget_show (dialog->extra_widget);
 
-       create_option_menu (dialog);
-       create_newline_combo (dialog);
+       create_option_menu (dialog, flags);
+
+       if ((flags & GEDIT_FILE_CHOOSER_FLAG_SAVE) != 0)
+       {
+               create_newline_combo (dialog);
+       }
 
        gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), dialog->extra_widget);
 }
@@ -421,21 +455,35 @@ gedit_file_chooser_dialog_gtk_init (GeditFileChooserDialogGtk *dialog)
 }
 
 GeditFileChooserDialog *
-gedit_file_chooser_dialog_gtk_create (const gchar *title,
-                                     GtkWindow   *parent,
-                                     const gchar *accept_label,
-                                     const gchar *cancel_label)
+gedit_file_chooser_dialog_gtk_create (const gchar           *title,
+                                     GtkWindow             *parent,
+                                     GeditFileChooserFlags  flags,
+                                     const gchar           *accept_label,
+                                     const gchar           *cancel_label)
 {
        GeditFileChooserDialogGtk *result;
+       GtkFileChooserAction action;
+       gboolean select_multiple;
+
+       if ((flags & GEDIT_FILE_CHOOSER_FLAG_SAVE) != 0)
+       {
+               action = GTK_FILE_CHOOSER_ACTION_SAVE;
+               select_multiple = FALSE;
+       }
+       else
+       {
+               action = GTK_FILE_CHOOSER_ACTION_OPEN;
+               select_multiple = TRUE;
+       }
 
        result = g_object_new (GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK,
                               "title", title,
                               "local-only", FALSE,
-                              "action", GTK_FILE_CHOOSER_ACTION_SAVE,
-                              "select-multiple", FALSE,
+                              "action", action,
+                              "select-multiple", select_multiple,
                               NULL);
 
-       create_extra_widget (result);
+       create_extra_widget (result, flags);
 
        g_signal_connect (result,
                          "notify::action",
diff --git a/gedit/gedit-file-chooser-dialog-gtk.h b/gedit/gedit-file-chooser-dialog-gtk.h
index 0bf6a0d41..40726af54 100644
--- a/gedit/gedit-file-chooser-dialog-gtk.h
+++ b/gedit/gedit-file-chooser-dialog-gtk.h
@@ -33,10 +33,11 @@ G_DECLARE_FINAL_TYPE (GeditFileChooserDialogGtk, gedit_file_chooser_dialog_gtk,
                      GEDIT, FILE_CHOOSER_DIALOG_GTK,
                      GtkFileChooserDialog)
 
-GeditFileChooserDialog *       gedit_file_chooser_dialog_gtk_create    (const gchar *title,
-                                                                        GtkWindow   *parent,
-                                                                        const gchar *accept_label,
-                                                                        const gchar *cancel_label);
+GeditFileChooserDialog *       gedit_file_chooser_dialog_gtk_create    (const gchar           *title,
+                                                                        GtkWindow             *parent,
+                                                                        GeditFileChooserFlags  flags,
+                                                                        const gchar           *accept_label,
+                                                                        const gchar           *cancel_label);
 
 G_END_DECLS
 
diff --git a/gedit/gedit-file-chooser-dialog.c b/gedit/gedit-file-chooser-dialog.c
index 56edbae3b..b4ce2fd9e 100644
--- a/gedit/gedit-file-chooser-dialog.c
+++ b/gedit/gedit-file-chooser-dialog.c
@@ -62,13 +62,15 @@ gedit_file_chooser_dialog_default_init (GeditFileChooserDialogInterface *iface)
 }
 
 GeditFileChooserDialog *
-gedit_file_chooser_dialog_create (const gchar *title,
-                                 GtkWindow   *parent,
-                                 const gchar *accept_label,
-                                 const gchar *cancel_label)
+gedit_file_chooser_dialog_create (const gchar           *title,
+                                 GtkWindow             *parent,
+                                 GeditFileChooserFlags  flags,
+                                 const gchar           *accept_label,
+                                 const gchar           *cancel_label)
 {
        return gedit_file_chooser_dialog_gtk_create (title,
                                                     parent,
+                                                    flags,
                                                     accept_label,
                                                     cancel_label);
 }
@@ -211,6 +213,19 @@ gedit_file_chooser_dialog_show (GeditFileChooserDialog *dialog)
        iface->show (dialog);
 }
 
+void
+gedit_file_chooser_dialog_hide (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogInterface *iface;
+
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
+
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->hide != NULL);
+
+       iface->hide (dialog);
+}
+
 void
 gedit_file_chooser_dialog_destroy (GeditFileChooserDialog *dialog)
 {
@@ -255,4 +270,21 @@ gedit_file_chooser_dialog_get_window (GeditFileChooserDialog *dialog)
        return NULL;
 }
 
+void
+gedit_file_chooser_dialog_add_pattern_filter (GeditFileChooserDialog   *dialog,
+                                              const gchar              *name,
+                                              const gchar              *pattern)
+{
+       GeditFileChooserDialogInterface *iface;
+
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
+
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+
+       if (iface->add_pattern_filter)
+       {
+               iface->add_pattern_filter (dialog, name, pattern);
+       }
+}
+
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-chooser-dialog.h b/gedit/gedit-file-chooser-dialog.h
index b759c6566..633950e05 100644
--- a/gedit/gedit-file-chooser-dialog.h
+++ b/gedit/gedit-file-chooser-dialog.h
@@ -64,6 +64,7 @@ struct _GeditFileChooserDialogInterface
                                         gboolean                overwrite_confirmation);
 
        void    (*show)                 (GeditFileChooserDialog *dialog);
+       void    (*hide)                 (GeditFileChooserDialog *dialog);
 
        void    (*destroy)              (GeditFileChooserDialog *dialog);
 
@@ -72,11 +73,22 @@ struct _GeditFileChooserDialogInterface
 
        GtkWindow *
                (*get_window)           (GeditFileChooserDialog *dialog);
+
+       void    (*add_pattern_filter)   (GeditFileChooserDialog *dilaog,
+                                        const gchar            *name,
+                                        const gchar            *pattern);
 };
 
+typedef enum
+{
+       GEDIT_FILE_CHOOSER_FLAG_SAVE = 1 << 0,
+       GEDIT_FILE_CHOOSER_FLAG_OPEN = 1 << 1
+} GeditFileChooserFlags;
+
 GeditFileChooserDialog *
                gedit_file_chooser_dialog_create                (const gchar              *title,
                                                                 GtkWindow                *parent,
+                                                                GeditFileChooserFlags     flags,
                                                                 const gchar              *accept_label,
                                                                 const gchar              *cancel_label);
 
@@ -110,12 +122,17 @@ void               gedit_file_chooser_dialog_set_do_overwrite_confirmation (
                                                                 gboolean                  
overwrite_confirmation);
 
 void            gedit_file_chooser_dialog_show                 (GeditFileChooserDialog   *dialog);
+void            gedit_file_chooser_dialog_hide                 (GeditFileChooserDialog   *dialog);
 
 void            gedit_file_chooser_dialog_set_modal            (GeditFileChooserDialog   *dialog,
                                                                 gboolean                  is_modal);
 
 GtkWindow      *gedit_file_chooser_dialog_get_window           (GeditFileChooserDialog   *dialog);
 
+void            gedit_file_chooser_dialog_add_pattern_filter   (GeditFileChooserDialog   *dialog,
+                                                                const gchar              *name,
+                                                                const gchar              *pattern);
+
 G_END_DECLS
 
 #endif /* GEDIT_FILE_CHOOSER_DIALOG_H */
diff --git a/gedit/gedit-highlight-mode-dialog.c b/gedit/gedit-highlight-mode-dialog.c
new file mode 100644
index 000000000..a0661bfc3
--- /dev/null
+++ b/gedit/gedit-highlight-mode-dialog.c
@@ -0,0 +1,102 @@
+/*
+ * gedit-highlight-mode-dialog.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-highlight-mode-dialog.h"
+
+struct _GeditHighlightModeDialog
+{
+       GtkDialog parent_instance;
+
+       GeditHighlightModeSelector *selector;
+       gulong on_language_selected_id;
+};
+
+G_DEFINE_TYPE (GeditHighlightModeDialog, gedit_highlight_mode_dialog, GTK_TYPE_DIALOG)
+
+static void
+gedit_highlight_mode_dialog_response (GtkDialog *dialog,
+                                      gint       response_id)
+{
+       GeditHighlightModeDialog *dlg = GEDIT_HIGHLIGHT_MODE_DIALOG (dialog);
+
+       if (response_id == GTK_RESPONSE_OK)
+       {
+               g_signal_handler_block (dlg->selector, dlg->on_language_selected_id);
+               gedit_highlight_mode_selector_activate_selected_language (dlg->selector);
+               g_signal_handler_unblock (dlg->selector, dlg->on_language_selected_id);
+       }
+
+       gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+on_language_selected (GeditHighlightModeSelector *sel,
+                      GtkSourceLanguage          *language,
+                      GeditHighlightModeDialog   *dlg)
+{
+       g_signal_handler_block (dlg->selector, dlg->on_language_selected_id);
+       gedit_highlight_mode_selector_activate_selected_language (dlg->selector);
+       g_signal_handler_unblock (dlg->selector, dlg->on_language_selected_id);
+
+       gtk_widget_destroy (GTK_WIDGET (dlg));
+}
+
+static void
+gedit_highlight_mode_dialog_class_init (GeditHighlightModeDialogClass *klass)
+{
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+       GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+
+       dialog_class->response = gedit_highlight_mode_dialog_response;
+
+       /* Bind class to template */
+       gtk_widget_class_set_template_from_resource (widget_class,
+                                                    "/org/gnome/gedit/ui/gedit-highlight-mode-dialog.ui");
+       gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeDialog, selector);
+}
+
+static void
+gedit_highlight_mode_dialog_init (GeditHighlightModeDialog *dlg)
+{
+       gtk_widget_init_template (GTK_WIDGET (dlg));
+       gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK);
+
+       dlg->on_language_selected_id = g_signal_connect (dlg->selector, "language-selected",
+                                                        G_CALLBACK (on_language_selected), dlg);
+}
+
+GtkWidget *
+gedit_highlight_mode_dialog_new (GtkWindow *parent)
+{
+       return GTK_WIDGET (g_object_new (GEDIT_TYPE_HIGHLIGHT_MODE_DIALOG,
+                                        "transient-for", parent,
+                                        "use-header-bar", TRUE,
+                                        NULL));
+}
+
+GeditHighlightModeSelector *
+gedit_highlight_mode_dialog_get_selector (GeditHighlightModeDialog *dlg)
+{
+       g_return_val_if_fail (GEDIT_IS_HIGHLIGHT_MODE_DIALOG (dlg), NULL);
+
+       return dlg->selector;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-highlight-mode-dialog.h b/gedit/gedit-highlight-mode-dialog.h
new file mode 100644
index 000000000..57d406bb3
--- /dev/null
+++ b/gedit/gedit-highlight-mode-dialog.h
@@ -0,0 +1,41 @@
+/*
+ * gedit-highlight-mode-dialog.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef GEDIT_HIGHLIGHT_MODE_DIALOG_H
+#define GEDIT_HIGHLIGHT_MODE_DIALOG_H
+
+#include "gedit-highlight-mode-selector.h"
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_HIGHLIGHT_MODE_DIALOG (gedit_highlight_mode_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditHighlightModeDialog, gedit_highlight_mode_dialog, GEDIT, HIGHLIGHT_MODE_DIALOG, 
GtkDialog)
+
+GtkWidget                  *gedit_highlight_mode_dialog_new             (GtkWindow *parent);
+
+GeditHighlightModeSelector *gedit_highlight_mode_dialog_get_selector    (GeditHighlightModeDialog *dlg);
+
+G_END_DECLS
+
+#endif /* GEDIT_HIGHLIGHT_MODE_DIALOG_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-highlight-mode-selector.c b/gedit/gedit-highlight-mode-selector.c
new file mode 100644
index 000000000..cb6bd466f
--- /dev/null
+++ b/gedit/gedit-highlight-mode-selector.c
@@ -0,0 +1,375 @@
+/*
+ * gedit-highlight-mode-selector.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-highlight-mode-selector.h"
+#include <glib/gi18n.h>
+
+enum
+{
+       COLUMN_NAME,
+       COLUMN_LANG,
+       N_COLUMNS
+};
+
+struct _GeditHighlightModeSelector
+{
+       GtkGrid parent_instance;
+
+       GtkWidget *treeview;
+       GtkWidget *entry;
+       GtkListStore *liststore;
+       GtkTreeModelFilter *treemodelfilter;
+       GtkTreeSelection *treeview_selection;
+};
+
+/* Signals */
+enum
+{
+       LANGUAGE_SELECTED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GeditHighlightModeSelector, gedit_highlight_mode_selector, GTK_TYPE_GRID)
+
+static void
+gedit_highlight_mode_selector_language_selected (GeditHighlightModeSelector *widget,
+                                                 GtkSourceLanguage          *language)
+{
+}
+
+static void
+gedit_highlight_mode_selector_class_init (GeditHighlightModeSelectorClass *klass)
+{
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       signals[LANGUAGE_SELECTED] =
+               g_signal_new_class_handler ("language-selected",
+                                           G_TYPE_FROM_CLASS (klass),
+                                           G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                           G_CALLBACK (gedit_highlight_mode_selector_language_selected),
+                                           NULL, NULL, NULL,
+                                           G_TYPE_NONE,
+                                           1,
+                                           GTK_SOURCE_TYPE_LANGUAGE);
+
+       /* Bind class to template */
+       gtk_widget_class_set_template_from_resource (widget_class,
+                                                    "/org/gnome/gedit/ui/gedit-highlight-mode-selector.ui");
+       gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, treeview);
+       gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, entry);
+       gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, liststore);
+       gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, treemodelfilter);
+       gtk_widget_class_bind_template_child (widget_class, GeditHighlightModeSelector, treeview_selection);
+}
+
+static gboolean
+visible_func (GtkTreeModel               *model,
+              GtkTreeIter                *iter,
+              GeditHighlightModeSelector *selector)
+{
+       const gchar *entry_text;
+       gchar *name;
+       gchar *name_normalized;
+       gchar *name_casefolded;
+       gchar *text_normalized;
+       gchar *text_casefolded;
+       gboolean visible = FALSE;
+
+       entry_text = gtk_entry_get_text (GTK_ENTRY (selector->entry));
+
+       if (*entry_text == '\0')
+       {
+               return TRUE;
+       }
+
+       gtk_tree_model_get (model, iter, COLUMN_NAME, &name, -1);
+
+       name_normalized = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
+       g_free (name);
+
+       name_casefolded = g_utf8_casefold (name_normalized, -1);
+       g_free (name_normalized);
+
+       text_normalized = g_utf8_normalize (entry_text, -1, G_NORMALIZE_ALL);
+       text_casefolded = g_utf8_casefold (text_normalized, -1);
+       g_free (text_normalized);
+
+       if (strstr (name_casefolded, text_casefolded) != NULL)
+       {
+               visible = TRUE;
+       }
+
+       g_free (name_casefolded);
+       g_free (text_casefolded);
+
+       return visible;
+}
+
+static void
+on_entry_activate (GtkEntry                   *entry,
+                   GeditHighlightModeSelector *selector)
+{
+       gedit_highlight_mode_selector_activate_selected_language (selector);
+}
+
+static void
+on_entry_changed (GtkEntry                   *entry,
+                  GeditHighlightModeSelector *selector)
+{
+       GtkTreeIter iter;
+
+       gtk_tree_model_filter_refilter (selector->treemodelfilter);
+
+       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+       {
+               gtk_tree_selection_select_iter (selector->treeview_selection, &iter);
+       }
+}
+
+static gboolean
+move_selection (GeditHighlightModeSelector *selector,
+                gint                      howmany)
+{
+       GtkTreeIter iter;
+       GtkTreePath *path;
+       gint *indices;
+       gint ret = FALSE;
+
+       if (!gtk_tree_selection_get_selected (selector->treeview_selection, NULL, &iter) &&
+           !gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+       {
+               return FALSE;
+       }
+
+       path = gtk_tree_model_get_path (GTK_TREE_MODEL (selector->treemodelfilter), &iter);
+       indices = gtk_tree_path_get_indices (path);
+
+       if (indices)
+       {
+               gint num;
+               gint idx;
+               GtkTreePath *new_path;
+
+               idx = indices[0];
+               num = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (selector->treemodelfilter), NULL);
+
+               if ((idx + howmany) < 0)
+               {
+                       idx = 0;
+               }
+               else if ((idx + howmany) >= num)
+               {
+                       idx = num - 1;
+               }
+               else
+               {
+                       idx = idx + howmany;
+               }
+
+               new_path = gtk_tree_path_new_from_indices (idx, -1);
+               gtk_tree_selection_select_path (selector->treeview_selection, new_path);
+               gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (selector->treeview),
+                                             new_path, NULL, TRUE, 0.5, 0);
+               gtk_tree_path_free (new_path);
+
+               ret = TRUE;
+       }
+
+       gtk_tree_path_free (path);
+
+       return ret;
+}
+
+static gboolean
+on_entry_key_press_event (GtkWidget                  *entry,
+                          GdkEventKey                *event,
+                          GeditHighlightModeSelector *selector)
+{
+       if (event->keyval == GDK_KEY_Down)
+       {
+               return move_selection (selector, 1);
+       }
+       else if (event->keyval == GDK_KEY_Up)
+       {
+               return move_selection (selector, -1);
+       }
+       else if (event->keyval == GDK_KEY_Page_Down)
+       {
+               return move_selection (selector, 5);
+       }
+       else if (event->keyval == GDK_KEY_Page_Up)
+       {
+               return move_selection (selector, -5);
+       }
+
+       return FALSE;
+}
+
+static void
+on_row_activated (GtkTreeView                *tree_view,
+                  GtkTreePath                *path,
+                  GtkTreeViewColumn          *column,
+                  GeditHighlightModeSelector *selector)
+{
+       gedit_highlight_mode_selector_activate_selected_language (selector);
+}
+
+static void
+gedit_highlight_mode_selector_init (GeditHighlightModeSelector *selector)
+{
+       GtkSourceLanguageManager *lm;
+       const gchar * const *ids;
+       gint i;
+       GtkTreeIter iter;
+
+       selector = gedit_highlight_mode_selector_get_instance_private (selector);
+
+       gtk_widget_init_template (GTK_WIDGET (selector));
+
+       gtk_tree_model_filter_set_visible_func (selector->treemodelfilter,
+                                               (GtkTreeModelFilterVisibleFunc)visible_func,
+                                               selector,
+                                               NULL);
+
+       g_signal_connect (selector->entry, "activate",
+                         G_CALLBACK (on_entry_activate), selector);
+       g_signal_connect (selector->entry, "changed",
+                         G_CALLBACK (on_entry_changed), selector);
+       g_signal_connect (selector->entry, "key-press-event",
+                         G_CALLBACK (on_entry_key_press_event), selector);
+
+       g_signal_connect (selector->treeview, "row-activated",
+                         G_CALLBACK (on_row_activated), selector);
+
+       /* Populate tree model */
+       gtk_list_store_append (selector->liststore, &iter);
+       gtk_list_store_set (selector->liststore, &iter,
+                           COLUMN_NAME, _("Plain Text"),
+                           COLUMN_LANG, NULL,
+                           -1);
+
+       lm = gtk_source_language_manager_get_default ();
+       ids = gtk_source_language_manager_get_language_ids (lm);
+
+       for (i = 0; ids[i] != NULL; i++)
+       {
+               GtkSourceLanguage *lang;
+
+               lang = gtk_source_language_manager_get_language (lm, ids[i]);
+
+               if (!gtk_source_language_get_hidden (lang))
+               {
+                       gtk_list_store_append (selector->liststore, &iter);
+                       gtk_list_store_set (selector->liststore, &iter,
+                                           COLUMN_NAME, gtk_source_language_get_name (lang),
+                                           COLUMN_LANG, lang,
+                                           -1);
+               }
+       }
+
+       /* select first item */
+       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+       {
+               gtk_tree_selection_select_iter (selector->treeview_selection, &iter);
+       }
+}
+
+GeditHighlightModeSelector *
+gedit_highlight_mode_selector_new ()
+{
+       return g_object_new (GEDIT_TYPE_HIGHLIGHT_MODE_SELECTOR, NULL);
+}
+
+void
+gedit_highlight_mode_selector_select_language (GeditHighlightModeSelector *selector,
+                                             GtkSourceLanguage        *language)
+{
+       GtkTreeIter iter;
+
+       g_return_if_fail (GEDIT_IS_HIGHLIGHT_MODE_SELECTOR (selector));
+
+       if (language == NULL)
+       {
+               return;
+       }
+
+       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (selector->treemodelfilter), &iter))
+       {
+               do
+               {
+                       GtkSourceLanguage *lang;
+
+                       gtk_tree_model_get (GTK_TREE_MODEL (selector->treemodelfilter),
+                                           &iter,
+                                           COLUMN_LANG, &lang,
+                                           -1);
+
+                       if (lang != NULL)
+                       {
+                               gboolean equal = (lang == language);
+
+                               g_object_unref (lang);
+
+                               if (equal)
+                               {
+                                       GtkTreePath *path;
+
+                                       path = gtk_tree_model_get_path (GTK_TREE_MODEL 
(selector->treemodelfilter), &iter);
+
+                                       gtk_tree_selection_select_iter (selector->treeview_selection, &iter);
+                                       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (selector->treeview),
+                                                                     path, NULL, TRUE, 0.5, 0);
+                                       gtk_tree_path_free (path);
+                                       break;
+                               }
+                       }
+               }
+               while (gtk_tree_model_iter_next (GTK_TREE_MODEL (selector->treemodelfilter), &iter));
+       }
+}
+
+void
+gedit_highlight_mode_selector_activate_selected_language (GeditHighlightModeSelector *selector)
+{
+       GtkSourceLanguage *lang;
+       GtkTreeIter iter;
+
+       g_return_if_fail (GEDIT_IS_HIGHLIGHT_MODE_SELECTOR (selector));
+
+       if (!gtk_tree_selection_get_selected (selector->treeview_selection, NULL, &iter))
+       {
+               return;
+       }
+
+       gtk_tree_model_get (GTK_TREE_MODEL (selector->treemodelfilter), &iter,
+                           COLUMN_LANG, &lang,
+                           -1);
+
+       g_signal_emit (G_OBJECT (selector), signals[LANGUAGE_SELECTED], 0, lang);
+
+       if (lang != NULL)
+       {
+               g_object_unref (lang);
+       }
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-highlight-mode-selector.h b/gedit/gedit-highlight-mode-selector.h
new file mode 100644
index 000000000..dc19e3cc4
--- /dev/null
+++ b/gedit/gedit-highlight-mode-selector.h
@@ -0,0 +1,44 @@
+/*
+ * gedit-highlight-mode-selector.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2013 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_HIGHLIGHT_MODE_SELECTOR_H
+#define GEDIT_HIGHLIGHT_MODE_SELECTOR_H
+
+#include <gtksourceview/gtksource.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_HIGHLIGHT_MODE_SELECTOR (gedit_highlight_mode_selector_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditHighlightModeSelector, gedit_highlight_mode_selector, GEDIT, 
HIGHLIGHT_MODE_SELECTOR, GtkGrid)
+
+GeditHighlightModeSelector *gedit_highlight_mode_selector_new             (void);
+
+void                        gedit_highlight_mode_selector_select_language (GeditHighlightModeSelector 
*selector,
+                                                                           GtkSourceLanguage          
*language);
+
+void                        gedit_highlight_mode_selector_activate_selected_language
+                                                                          (GeditHighlightModeSelector 
*selector);
+
+G_END_DECLS
+
+#endif /* GEDIT_HIGHLIGHT_MODE_SELECTOR_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-io-error-info-bar.c b/gedit/gedit-io-error-info-bar.c
index 77ca04d7b..21e27e459 100644
--- a/gedit/gedit-io-error-info-bar.c
+++ b/gedit/gedit-io-error-info-bar.c
@@ -23,9 +23,16 @@
  */
 
 #include "gedit-io-error-info-bar.h"
+
+#include <errno.h>
+#include <string.h>
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
+#include <gio/gio.h>
+
 #include "gedit-encodings-combo-box.h"
+#include "gedit-settings.h"
+#include "gedit-utils.h"
+#include "gedit-document.h"
 
 #define MAX_URI_IN_DIALOG_LENGTH 50
 
@@ -220,7 +227,7 @@ parse_gio_error (gint          code,
                                        uri = g_file_get_uri (location);
                                }
 
-                               if (uri && tepl_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
+                               if (uri && gedit_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
                                {
                                        if (hn != NULL)
                                        {
@@ -323,8 +330,8 @@ gedit_unrecoverable_reverting_error_info_bar_new (GFile        *location,
         * though the dialog uses wrapped text, if the URI doesn't contain
         * white space then the text-wrapping code is too stupid to wrap it.
         */
-       temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
-                                                              MAX_URI_IN_DIALOG_LENGTH);
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
        g_free (full_formatted_uri);
 
        uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -534,8 +541,8 @@ gedit_io_loading_error_info_bar_new (GFile                   *location,
         * though the dialog uses wrapped text, if the URI doesn't contain
         * white space then the text-wrapping code is too stupid to wrap it.
         */
-       temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
-                                                              MAX_URI_IN_DIALOG_LENGTH);
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
        g_free (full_formatted_uri);
 
        uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -655,8 +662,8 @@ gedit_conversion_error_while_saving_info_bar_new (GFile                   *locat
         * though the dialog uses wrapped text, if the URI doesn't contain
         * white space then the text-wrapping code is too stupid to wrap it.
         */
-       temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
-                                                              MAX_URI_IN_DIALOG_LENGTH);
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
        g_free (full_formatted_uri);
 
        uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -700,6 +707,88 @@ gedit_conversion_error_info_bar_get_encoding (GtkWidget *info_bar)
        return NULL;
 }
 
+GtkWidget *
+gedit_file_already_open_warning_info_bar_new (GFile *location)
+{
+       GtkWidget *info_bar;
+       GtkWidget *hbox_content;
+       GtkWidget *vbox;
+       gchar *primary_markup;
+       gchar *secondary_markup;
+       GtkWidget *primary_label;
+       GtkWidget *secondary_label;
+       gchar *primary_text;
+       const gchar *secondary_text;
+       gchar *full_formatted_uri;
+       gchar *uri_for_display;
+       gchar *temp_uri_for_display;
+
+       g_return_val_if_fail (G_IS_FILE (location), NULL);
+
+       full_formatted_uri = g_file_get_parse_name (location);
+
+       /* Truncate the URI so it doesn't get insanely wide. Note that even
+        * though the dialog uses wrapped text, if the URI doesn't contain
+        * white space then the text-wrapping code is too stupid to wrap it.
+        */
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
+       g_free (full_formatted_uri);
+
+       uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+       g_free (temp_uri_for_display);
+
+       info_bar = gtk_info_bar_new ();
+       gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+       /* Translators: the access key chosen for this string should be
+        different from other main menu access keys (Open, Edit, View...) */
+                                _("Edit Any_way"),
+                                GTK_RESPONSE_YES);
+       gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+       /* Translators: the access key chosen for this string should be
+        different from other main menu access keys (Open, Edit, View...) */
+                                _("D_on’t Edit"),
+                                GTK_RESPONSE_CANCEL);
+       gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+                                      GTK_MESSAGE_WARNING);
+
+       hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+       gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
+
+       primary_text = g_strdup_printf (_("This file “%s” is already open in another window."), 
uri_for_display);
+       g_free (uri_for_display);
+
+       primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
+       g_free (primary_text);
+       primary_label = gtk_label_new (primary_markup);
+       g_free (primary_markup);
+       gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
+       gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+       gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
+       gtk_widget_set_can_focus (primary_label, TRUE);
+       gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+
+       secondary_text = _("Do you want to edit it anyway?");
+       secondary_markup = g_strdup_printf ("<small>%s</small>",
+                                           secondary_text);
+       secondary_label = gtk_label_new (secondary_markup);
+       g_free (secondary_markup);
+       gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
+       gtk_widget_set_can_focus (secondary_label, TRUE);
+       gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+       gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+       gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
+
+       gtk_widget_show_all (hbox_content);
+       set_contents (info_bar, hbox_content);
+
+       return info_bar;
+}
+
 GtkWidget *
 gedit_externally_modified_saving_error_info_bar_new (GFile        *location,
                                                     const GError *error)
@@ -728,8 +817,8 @@ gedit_externally_modified_saving_error_info_bar_new (GFile        *location,
         * though the dialog uses wrapped text, if the URI doesn't contain
         * white space then the text-wrapping code is too stupid to wrap it.
         */
-       temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
-                                                              MAX_URI_IN_DIALOG_LENGTH);
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
        g_free (full_formatted_uri);
 
        uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -788,6 +877,110 @@ gedit_externally_modified_saving_error_info_bar_new (GFile        *location,
        return info_bar;
 }
 
+GtkWidget *
+gedit_no_backup_saving_error_info_bar_new (GFile        *location,
+                                          const GError *error)
+{
+       GtkWidget *info_bar;
+       GtkWidget *hbox_content;
+       GtkWidget *vbox;
+       gchar *primary_markup;
+       gchar *secondary_markup;
+       GtkWidget *primary_label;
+       GtkWidget *secondary_label;
+       gchar *primary_text;
+       const gchar *secondary_text;
+       gchar *full_formatted_uri;
+       gchar *uri_for_display;
+       gchar *temp_uri_for_display;
+       gboolean create_backup_copy;
+       GSettings *editor_settings;
+
+       g_return_val_if_fail (G_IS_FILE (location), NULL);
+       g_return_val_if_fail (error != NULL, NULL);
+       g_return_val_if_fail (error->domain == G_IO_ERROR &&
+                             error->code == G_IO_ERROR_CANT_CREATE_BACKUP, NULL);
+
+       full_formatted_uri = g_file_get_parse_name (location);
+
+       /* Truncate the URI so it doesn't get insanely wide. Note that even
+        * though the dialog uses wrapped text, if the URI doesn't contain
+        * white space then the text-wrapping code is too stupid to wrap it.
+        */
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
+       g_free (full_formatted_uri);
+
+       uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+       g_free (temp_uri_for_display);
+
+       info_bar = gtk_info_bar_new ();
+
+       gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+                                _("S_ave Anyway"),
+                                GTK_RESPONSE_YES);
+       gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+                                _("D_on’t Save"),
+                                GTK_RESPONSE_CANCEL);
+       gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+                                      GTK_MESSAGE_WARNING);
+
+       hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+       gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
+
+       editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
+
+       create_backup_copy = g_settings_get_boolean (editor_settings,
+                                                    GEDIT_SETTINGS_CREATE_BACKUP_COPY);
+       g_object_unref (editor_settings);
+
+       /* FIXME: review this messages */
+       if (create_backup_copy)
+       {
+               primary_text = g_strdup_printf (_("Could not create a backup file while saving “%s”"),
+                                               uri_for_display);
+       }
+       else
+       {
+               primary_text = g_strdup_printf (_("Could not create a temporary backup file while saving 
“%s”"),
+                                               uri_for_display);
+       }
+
+       g_free (uri_for_display);
+
+       primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
+       g_free (primary_text);
+       primary_label = gtk_label_new (primary_markup);
+       g_free (primary_markup);
+       gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
+       gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+       gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
+       gtk_widget_set_can_focus (primary_label, TRUE);
+       gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+
+       secondary_text = _("Could not back up the old copy of the file before saving the new one. "
+                          "You can ignore this warning and save the file anyway, but if an error "
+                          "occurs while saving, you could lose the old copy of the file. Save anyway?");
+       secondary_markup = g_strdup_printf ("<small>%s</small>",
+                                           secondary_text);
+       secondary_label = gtk_label_new (secondary_markup);
+       g_free (secondary_markup);
+       gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
+       gtk_widget_set_can_focus (secondary_label, TRUE);
+       gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+       gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+       gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
+
+       gtk_widget_show_all (hbox_content);
+       set_contents (info_bar, hbox_content);
+
+       return info_bar;
+}
+
 GtkWidget *
 gedit_unrecoverable_saving_error_info_bar_new (GFile        *location,
                                               const GError *error)
@@ -812,8 +1005,8 @@ gedit_unrecoverable_saving_error_info_bar_new (GFile        *location,
         * though the dialog uses wrapped text, if the URI doesn't contain
         * white space then the text-wrapping code is too stupid to wrap it.
         */
-       temp_uri_for_display = tepl_utils_str_middle_truncate (full_formatted_uri,
-                                                              MAX_URI_IN_DIALOG_LENGTH);
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
        g_free (full_formatted_uri);
 
        uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
@@ -917,4 +1110,149 @@ gedit_unrecoverable_saving_error_info_bar_new (GFile        *location,
        return info_bar;
 }
 
+GtkWidget *
+gedit_externally_modified_info_bar_new (GFile    *location,
+                                       gboolean  document_modified)
+{
+       gchar *full_formatted_uri;
+       gchar *uri_for_display;
+       gchar *temp_uri_for_display;
+       gchar *primary_text;
+       GtkWidget *info_bar;
+
+       g_return_val_if_fail (G_IS_FILE (location), NULL);
+
+       full_formatted_uri = g_file_get_parse_name (location);
+
+       /* Truncate the URI so it doesn't get insanely wide. Note that even
+        * though the dialog uses wrapped text, if the URI doesn't contain
+        * white space then the text-wrapping code is too stupid to wrap it.
+        */
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
+       g_free (full_formatted_uri);
+
+       uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+       g_free (temp_uri_for_display);
+
+       primary_text = g_strdup_printf (_("The file “%s” changed on disk."),
+                                       uri_for_display);
+       g_free (uri_for_display);
+
+       info_bar = gtk_info_bar_new ();
+
+       if (document_modified)
+       {
+               GtkWidget *box;
+               GtkWidget *button;
+               button = gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+                                                 _("Drop Changes and _Reload"),
+                                                 GTK_RESPONSE_OK);
+               box = gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar));
+               gtk_button_box_set_child_non_homogeneous (GTK_BUTTON_BOX (box),
+                                                         button,
+                                                         TRUE);
+       }
+       else
+       {
+               gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+                                        _("_Reload"),
+                                        GTK_RESPONSE_OK);
+       }
+
+       gtk_info_bar_set_show_close_button (GTK_INFO_BAR (info_bar), TRUE);
+       gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+                                      GTK_MESSAGE_WARNING);
+
+       set_info_bar_text (info_bar,
+                          primary_text,
+                          NULL);
+
+       g_free (primary_text);
+
+       return info_bar;
+}
+
+GtkWidget *
+gedit_invalid_character_info_bar_new (GFile *location)
+{
+       GtkWidget *info_bar;
+       GtkWidget *hbox_content;
+       GtkWidget *vbox;
+       GtkWidget *primary_label;
+       GtkWidget *secondary_label;
+       gchar *primary_markup;
+       gchar *secondary_markup;
+       gchar *primary_text;
+       gchar *full_formatted_uri;
+       gchar *uri_for_display;
+       gchar *temp_uri_for_display;
+       const gchar *secondary_text;
+
+       g_return_val_if_fail (G_IS_FILE (location), NULL);
+
+       full_formatted_uri = g_file_get_parse_name (location);
+
+       /* Truncate the URI so it doesn't get insanely wide. Note that even
+        * though the dialog uses wrapped text, if the URI doesn't contain
+        * white space then the text-wrapping code is too stupid to wrap it.
+        */
+       temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri,
+                                                               MAX_URI_IN_DIALOG_LENGTH);
+       g_free (full_formatted_uri);
+
+       uri_for_display = g_markup_escape_text (temp_uri_for_display, -1);
+       g_free (temp_uri_for_display);
+
+       info_bar = gtk_info_bar_new ();
+
+       gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+                                _("S_ave Anyway"),
+                                GTK_RESPONSE_YES);
+       gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+                                _("D_on’t Save"),
+                                GTK_RESPONSE_CANCEL);
+       gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+                                      GTK_MESSAGE_WARNING);
+
+       hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+       gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
+
+       primary_text = g_strdup_printf (_("Some invalid chars have been detected while saving “%s”"),
+                                       uri_for_display);
+
+       g_free (uri_for_display);
+
+       primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
+       g_free (primary_text);
+       primary_label = gtk_label_new (primary_markup);
+       g_free (primary_markup);
+       gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
+       gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+       gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
+       gtk_widget_set_can_focus (primary_label, TRUE);
+       gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+
+       secondary_text = _("If you continue saving this file you can corrupt the document. "
+                          " Save anyway?");
+       secondary_markup = g_strdup_printf ("<small>%s</small>",
+                                           secondary_text);
+       secondary_label = gtk_label_new (secondary_markup);
+       g_free (secondary_markup);
+       gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
+       gtk_widget_set_can_focus (secondary_label, TRUE);
+       gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+       gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+       gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
+
+       gtk_widget_show_all (hbox_content);
+       set_contents (info_bar, hbox_content);
+
+       return info_bar;
+}
+
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-io-error-info-bar.h b/gedit/gedit-io-error-info-bar.h
index 12780f7ae..9784652c7 100644
--- a/gedit/gedit-io-error-info-bar.h
+++ b/gedit/gedit-io-error-info-bar.h
@@ -39,12 +39,22 @@ GtkWidget   *gedit_conversion_error_while_saving_info_bar_new       (GFile
 const GtkSourceEncoding
                *gedit_conversion_error_info_bar_get_encoding           (GtkWidget           *info_bar);
 
+GtkWidget      *gedit_file_already_open_warning_info_bar_new           (GFile               *location);
+
 GtkWidget      *gedit_externally_modified_saving_error_info_bar_new    (GFile               *location,
                                                                         const GError        *error);
 
+GtkWidget      *gedit_no_backup_saving_error_info_bar_new               (GFile               *location,
+                                                                         const GError        *error);
+
 GtkWidget      *gedit_unrecoverable_saving_error_info_bar_new          (GFile               *location,
                                                                         const GError        *error);
 
+GtkWidget      *gedit_externally_modified_info_bar_new                 (GFile               *location,
+                                                                        gboolean             
document_modified);
+
+GtkWidget      *gedit_invalid_character_info_bar_new                   (GFile               *location);
+
 G_END_DECLS
 
 #endif  /* GEDIT_IO_ERROR_INFO_BAR_H  */
diff --git a/gedit/gedit-metadata-manager.c b/gedit/gedit-metadata-manager.c
new file mode 100644
index 000000000..8f858b286
--- /dev/null
+++ b/gedit/gedit-metadata-manager.c
@@ -0,0 +1,650 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gedit-metadata-manager.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2003-2007  Paolo Maggi
+ * Copyright (C) 2019 Canonical LTD
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 "gedit-metadata-manager.h"
+#include <libxml/xmlreader.h>
+#include "gedit-debug.h"
+
+/*
+#define GEDIT_METADATA_VERBOSE_DEBUG   1
+*/
+
+#define MAX_ITEMS 50
+
+typedef struct _Item Item;
+
+struct _Item
+{
+       /* Time of last access in seconds since January 1, 1970 UTC. */
+       gint64           atime;
+
+       GHashTable      *values;
+};
+
+struct _GeditMetadataManager
+{
+       GObject parent_instance;
+
+       /* It is true if the file has been read. */
+       gboolean         values_loaded;
+
+       guint            timeout_id;
+
+       GHashTable      *items;
+
+       gchar           *metadata_filename;
+};
+
+enum
+{
+       PROP_0,
+       PROP_METADATA_FILENAME,
+       LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+G_DEFINE_TYPE (GeditMetadataManager, gedit_metadata_manager, G_TYPE_OBJECT);
+
+static gboolean gedit_metadata_manager_save (GeditMetadataManager *self);
+
+static void
+item_free (gpointer data)
+{
+       Item *item;
+
+       g_return_if_fail (data != NULL);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+       gedit_debug (DEBUG_METADATA);
+#endif
+
+       item = (Item *)data;
+
+       if (item->values != NULL)
+               g_hash_table_destroy (item->values);
+
+       g_free (item);
+}
+
+static void
+gedit_metadata_manager_arm_timeout (GeditMetadataManager *self)
+{
+       if (self->timeout_id == 0)
+       {
+               self->timeout_id =
+                       g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
+                                                   2,
+                                                   (GSourceFunc)gedit_metadata_manager_save,
+                                                   self,
+                                                   NULL);
+       }
+}
+
+static void
+gedit_metadata_manager_parse_item (GeditMetadataManager *self,
+                                  xmlDocPtr             doc,
+                                  xmlNodePtr            cur)
+{
+       Item *item;
+
+       xmlChar *uri;
+       xmlChar *atime;
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+       gedit_debug (DEBUG_METADATA);
+#endif
+
+       if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
+                       return;
+
+       uri = xmlGetProp (cur, (const xmlChar *)"uri");
+       if (uri == NULL)
+               return;
+
+       atime = xmlGetProp (cur, (const xmlChar *)"atime");
+       if (atime == NULL)
+       {
+               xmlFree (uri);
+               return;
+       }
+
+       item = g_new0 (Item, 1);
+
+       item->atime = g_ascii_strtoll ((char *)atime, NULL, 0);
+
+       item->values = g_hash_table_new_full (g_str_hash,
+                                             g_str_equal,
+                                             g_free,
+                                             g_free);
+
+       cur = cur->xmlChildrenNode;
+
+       while (cur != NULL)
+       {
+               if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
+               {
+                       xmlChar *key;
+                       xmlChar *value;
+
+                       key = xmlGetProp (cur, (const xmlChar *)"key");
+                       value = xmlGetProp (cur, (const xmlChar *)"value");
+
+                       if ((key != NULL) && (value != NULL))
+                       {
+                               g_hash_table_insert (item->values,
+                                                    g_strdup ((gchar *)key),
+                                                    g_strdup ((gchar *)value));
+                       }
+
+                       if (key != NULL)
+                               xmlFree (key);
+                       if (value != NULL)
+                               xmlFree (value);
+               }
+
+               cur = cur->next;
+       }
+
+       g_hash_table_insert (self->items,
+                            g_strdup ((gchar *)uri),
+                            item);
+
+       xmlFree (uri);
+       xmlFree (atime);
+}
+
+/* Returns FALSE in case of error. */
+static gboolean
+gedit_metadata_manager_load_values (GeditMetadataManager *self)
+{
+       xmlDocPtr doc;
+       xmlNodePtr cur;
+
+       gedit_debug (DEBUG_METADATA);
+
+       g_return_val_if_fail (self != NULL, FALSE);
+       g_return_val_if_fail (self->values_loaded == FALSE, FALSE);
+
+       self->values_loaded = TRUE;
+
+       xmlKeepBlanksDefault (0);
+
+       if (self->metadata_filename == NULL)
+       {
+               return FALSE;
+       }
+
+       /* TODO: avoid races */
+       if (!g_file_test (self->metadata_filename, G_FILE_TEST_EXISTS))
+       {
+               return TRUE;
+       }
+
+       doc = xmlParseFile (self->metadata_filename);
+
+       if (doc == NULL)
+       {
+               return FALSE;
+       }
+
+       cur = xmlDocGetRootElement (doc);
+       if (cur == NULL)
+       {
+               g_message ("The metadata file '%s' is empty",
+                          g_path_get_basename (self->metadata_filename));
+               xmlFreeDoc (doc);
+
+               return TRUE;
+       }
+
+       if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
+       {
+               g_message ("File '%s' is of the wrong type",
+                          g_path_get_basename (self->metadata_filename));
+               xmlFreeDoc (doc);
+
+               return FALSE;
+       }
+
+       cur = xmlDocGetRootElement (doc);
+       cur = cur->xmlChildrenNode;
+
+       while (cur != NULL)
+       {
+               gedit_metadata_manager_parse_item (self, doc, cur);
+
+               cur = cur->next;
+       }
+
+       xmlFreeDoc (doc);
+
+       return TRUE;
+}
+
+/**
+ * gedit_metadata_manager_get:
+ * @self: a #GeditMetadataManager.
+ * @location: a #GFile.
+ * @key: a key.
+ *
+ * Gets the value associated with the specified @key for the file @location.
+ */
+gchar *
+gedit_metadata_manager_get (GeditMetadataManager *self,
+                           GFile                *location,
+                           const gchar          *key)
+{
+       Item *item;
+       gchar *value;
+       gchar *uri;
+
+       g_return_val_if_fail (GEDIT_IS_METADATA_MANAGER (self), NULL);
+       g_return_val_if_fail (G_IS_FILE (location), NULL);
+       g_return_val_if_fail (key != NULL, NULL);
+
+       uri = g_file_get_uri (location);
+
+       gedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
+
+       if (!self->values_loaded)
+       {
+               gboolean res;
+
+               res = gedit_metadata_manager_load_values (self);
+
+               if (!res)
+               {
+                       g_free (uri);
+                       return NULL;
+               }
+       }
+
+       item = (Item *)g_hash_table_lookup (self->items, uri);
+
+       g_free (uri);
+
+       if (item == NULL)
+               return NULL;
+
+       item->atime = g_get_real_time () / 1000;
+
+       if (item->values == NULL)
+               return NULL;
+
+       value = g_hash_table_lookup (item->values, key);
+
+       if (value == NULL)
+               return NULL;
+       else
+               return g_strdup (value);
+}
+
+/**
+ * gedit_metadata_manager_set:
+ * @self: a #GeditMetadataManager.
+ * @location: a #GFile.
+ * @key: a key.
+ * @value: the value associated with the @key.
+ *
+ * Sets the @key to contain the given @value for the file @location.
+ */
+void
+gedit_metadata_manager_set (GeditMetadataManager *self,
+                           GFile                *location,
+                           const gchar          *key,
+                           const gchar          *value)
+{
+       Item *item;
+       gchar *uri;
+
+       g_return_if_fail (GEDIT_IS_METADATA_MANAGER (self));
+       g_return_if_fail (G_IS_FILE (location));
+       g_return_if_fail (key != NULL);
+
+       uri = g_file_get_uri (location);
+
+       gedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
+
+       if (!self->values_loaded)
+       {
+               gboolean ok;
+
+               ok = gedit_metadata_manager_load_values (self);
+
+               if (!ok)
+               {
+                       g_free (uri);
+                       return;
+               }
+       }
+
+       item = (Item *)g_hash_table_lookup (self->items, uri);
+
+       if (item == NULL)
+       {
+               item = g_new0 (Item, 1);
+
+               g_hash_table_insert (self->items,
+                                    g_strdup (uri),
+                                    item);
+       }
+
+       if (item->values == NULL)
+       {
+                item->values = g_hash_table_new_full (g_str_hash,
+                                                      g_str_equal,
+                                                      g_free,
+                                                      g_free);
+       }
+
+       if (value != NULL)
+       {
+               g_hash_table_insert (item->values,
+                                    g_strdup (key),
+                                    g_strdup (value));
+       }
+       else
+       {
+               g_hash_table_remove (item->values,
+                                    key);
+       }
+
+       item->atime = g_get_real_time () / 1000;
+
+       g_free (uri);
+
+       gedit_metadata_manager_arm_timeout (self);
+}
+
+static void
+save_values (const gchar *key, const gchar *value, xmlNodePtr parent)
+{
+       xmlNodePtr xml_node;
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+       gedit_debug (DEBUG_METADATA);
+#endif
+
+       g_return_if_fail (key != NULL);
+
+       if (value == NULL)
+               return;
+
+       xml_node = xmlNewChild (parent,
+                               NULL,
+                               (const xmlChar *)"entry",
+                               NULL);
+
+       xmlSetProp (xml_node,
+                   (const xmlChar *)"key",
+                   (const xmlChar *)key);
+       xmlSetProp (xml_node,
+                   (const xmlChar *)"value",
+                   (const xmlChar *)value);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+       gedit_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value);
+#endif
+}
+
+static void
+save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
+{
+       xmlNodePtr xml_node;
+       const Item *item = (const Item *)data;
+       gchar *atime;
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+       gedit_debug (DEBUG_METADATA);
+#endif
+
+       g_return_if_fail (key != NULL);
+
+       if (item == NULL)
+               return;
+
+       xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
+
+       xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+       gedit_debug_message (DEBUG_METADATA, "uri: %s", key);
+#endif
+
+       atime = g_strdup_printf ("%" G_GINT64_FORMAT, item->atime);
+       xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
+
+#ifdef GEDIT_METADATA_VERBOSE_DEBUG
+       gedit_debug_message (DEBUG_METADATA, "atime: %s", atime);
+#endif
+
+       g_free (atime);
+
+       g_hash_table_foreach (item->values,
+                             (GHFunc)save_values,
+                             xml_node);
+}
+
+static const gchar *
+gedit_metadata_manager_get_oldest (GeditMetadataManager *self)
+{
+       GHashTableIter iter;
+       gpointer key, value, key_to_remove = NULL;
+       const Item *item_to_remove = NULL;
+
+       g_hash_table_iter_init (&iter, self->items);
+       while (g_hash_table_iter_next (&iter, &key, &value))
+       {
+               const Item *item = (const Item *) value;
+
+               if (key_to_remove == NULL)
+               {
+                       key_to_remove = key;
+                       item_to_remove = item;
+               }
+               else
+               {
+                       g_return_val_if_fail (item_to_remove != NULL, NULL);
+
+                       if (item->atime < item_to_remove->atime)
+                               key_to_remove = key;
+               }
+       }
+
+       return key_to_remove;
+}
+
+static void
+gedit_metadata_manager_resize_items (GeditMetadataManager *self)
+{
+       while (g_hash_table_size (self->items) > MAX_ITEMS)
+       {
+               const gchar *key_to_remove;
+
+               key_to_remove = gedit_metadata_manager_get_oldest (self);
+               g_return_if_fail (key_to_remove != NULL);
+               g_hash_table_remove (self->items,
+                                    key_to_remove);
+       }
+}
+
+static gboolean
+gedit_metadata_manager_save (GeditMetadataManager *self)
+{
+       xmlDocPtr  doc;
+       xmlNodePtr root;
+
+       gedit_debug (DEBUG_METADATA);
+
+       self->timeout_id = 0;
+
+       gedit_metadata_manager_resize_items (self);
+
+       xmlIndentTreeOutput = TRUE;
+
+       doc = xmlNewDoc ((const xmlChar *)"1.0");
+       if (doc == NULL)
+               return TRUE;
+
+       /* Create metadata root */
+       root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
+       xmlDocSetRootElement (doc, root);
+
+       g_hash_table_foreach (self->items,
+                             (GHFunc)save_item,
+                             root);
+
+       /* FIXME: lock file - Paolo */
+       if (self->metadata_filename != NULL)
+       {
+               gchar *cache_dir;
+               int res;
+
+               /* make sure the cache dir exists */
+               cache_dir = g_path_get_dirname (self->metadata_filename);
+               res = g_mkdir_with_parents (cache_dir, 0755);
+               if (res != -1)
+               {
+                       xmlSaveFormatFile (self->metadata_filename,
+                                          doc,
+                                          1);
+               }
+
+               g_free (cache_dir);
+       }
+
+       xmlFreeDoc (doc);
+
+       gedit_debug_message (DEBUG_METADATA, "DONE");
+
+       return FALSE;
+}
+
+static void
+gedit_metadata_manager_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+       GeditMetadataManager *self = GEDIT_METADATA_MANAGER (object);
+
+       switch (prop_id)
+       {
+       case PROP_METADATA_FILENAME:
+               g_value_set_string (value, self->metadata_filename);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+
+static void
+gedit_metadata_manager_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+       GeditMetadataManager *self = GEDIT_METADATA_MANAGER (object);
+
+       switch (prop_id)
+       {
+       case PROP_METADATA_FILENAME:
+               self->metadata_filename = g_value_dup_string (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+gedit_metadata_manager_init (GeditMetadataManager *self)
+{
+       gedit_debug (DEBUG_METADATA);
+
+       self->values_loaded = FALSE;
+
+       self->items =
+               g_hash_table_new_full (g_str_hash,
+                                      g_str_equal,
+                                      g_free,
+                                      item_free);
+}
+
+static void
+gedit_metadata_manager_dispose (GObject *object)
+{
+       GeditMetadataManager *self = GEDIT_METADATA_MANAGER (object);
+
+       gedit_debug (DEBUG_METADATA);
+
+       if (self->timeout_id)
+       {
+               g_source_remove (self->timeout_id);
+               self->timeout_id = 0;
+               gedit_metadata_manager_save (self);
+       }
+
+       if (self->items != NULL)
+               g_hash_table_destroy (self->items);
+
+       g_free (self->metadata_filename);
+}
+
+static void
+gedit_metadata_manager_class_init (GeditMetadataManagerClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->dispose = gedit_metadata_manager_dispose;
+       object_class->get_property = gedit_metadata_manager_get_property;
+       object_class->set_property = gedit_metadata_manager_set_property;
+
+       /**
+        * GeditMetadataManager:metadata-filename:
+        *
+        * The filename where the metadata is stored.
+        */
+       properties[PROP_METADATA_FILENAME] =
+               g_param_spec_string ("metadata-filename",
+                                     "Metadata filename",
+                                     "The filename where the metadata is stored",
+                                     NULL,
+                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+       g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+GeditMetadataManager *
+gedit_metadata_manager_new (const gchar *metadata_filename)
+{
+       gedit_debug (DEBUG_METADATA);
+
+       return g_object_new (GEDIT_TYPE_METADATA_MANAGER,
+                            "metadata-filename", metadata_filename,
+                            NULL);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-metadata-manager.h b/gedit/gedit-metadata-manager.h
new file mode 100644
index 000000000..49c2f05bf
--- /dev/null
+++ b/gedit/gedit-metadata-manager.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gedit-metadata-manager.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2003  Paolo Maggi
+ * Copyright (C) 2019  Canonical LTD
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_METADATA_MANAGER_H
+#define GEDIT_METADATA_MANAGER_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_METADATA_MANAGER (gedit_metadata_manager_get_type())
+
+G_DECLARE_FINAL_TYPE (GeditMetadataManager, gedit_metadata_manager, GEDIT, METADATA_MANAGER, GObject)
+
+GeditMetadataManager *gedit_metadata_manager_new       (const gchar *metadata_filename);
+
+gchar               *gedit_metadata_manager_get        (GeditMetadataManager *self,
+                                                        GFile                *location,
+                                                        const gchar          *key);
+
+void                 gedit_metadata_manager_set        (GeditMetadataManager *self,
+                                                        GFile                *location,
+                                                        const gchar          *key,
+                                                        const gchar          *value);
+
+G_END_DECLS
+
+#endif /* GEDIT_METADATA_MANAGER_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-helper.c b/gedit/gedit-open-document-selector-helper.c
new file mode 100644
index 000000000..369d12ea2
--- /dev/null
+++ b/gedit/gedit-open-document-selector-helper.c
@@ -0,0 +1,103 @@
+/*
+ * gedit-open-document-selector-helper.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-open-document-selector-helper.h"
+
+void
+gedit_open_document_selector_debug_print_list (const gchar *title,
+                                               GList       *fileitem_list)
+{
+       FileItem *item;
+       GList *l;
+       glong time_sec;
+       glong time_usec;
+
+       g_print ("%s\n", title);
+
+       for (l = fileitem_list; l != NULL; l = l->next)
+       {
+               item = (FileItem *)l->data;
+               time_sec = item->access_time.tv_sec;
+               time_usec = item->access_time.tv_usec;
+
+               g_print ("%ld:%ld uri:%s (%s %s)\n",
+                        time_sec,
+                        time_usec,
+                        item->uri,
+                        item->name,
+                        item->path);
+       }
+}
+
+FileItem *
+gedit_open_document_selector_create_fileitem_item (void)
+{
+       FileItem *item;
+
+       item = g_slice_new0 (FileItem);
+
+       return item;
+}
+
+void
+gedit_open_document_selector_free_fileitem_item (FileItem *item)
+{
+       g_free (item->uri);
+       g_free (item->name);
+       g_free (item->path);
+
+       g_slice_free (FileItem, item);
+}
+
+FileItem *
+gedit_open_document_selector_copy_fileitem_item (FileItem *item)
+{
+       FileItem *new_item;
+
+       new_item = gedit_open_document_selector_create_fileitem_item ();
+
+       new_item->uri = g_strdup (item->uri);
+       new_item->name = g_strdup (item->name);
+       new_item->path = g_strdup (item->path);
+       new_item->access_time = item->access_time;
+
+       return new_item;
+}
+
+inline GList *
+gedit_open_document_selector_copy_file_items_list (const GList *file_items_list)
+{
+       GList *new_file_items_list;
+
+       new_file_items_list = g_list_copy_deep ((GList *)file_items_list,
+                                               (GCopyFunc)gedit_open_document_selector_copy_fileitem_item,
+                                               NULL);
+
+       return new_file_items_list;
+}
+
+inline void
+gedit_open_document_selector_free_file_items_list (GList *file_items_list)
+{
+       g_list_free_full (file_items_list,
+                         (GDestroyNotify)gedit_open_document_selector_free_fileitem_item);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-helper.h b/gedit/gedit-open-document-selector-helper.h
new file mode 100644
index 000000000..6feb65408
--- /dev/null
+++ b/gedit/gedit-open-document-selector-helper.h
@@ -0,0 +1,103 @@
+/*
+ * gedit-open-document-selector-helper.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H
+
+#include "gedit-open-document-selector.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+       gchar *uri;
+       gchar *name;
+       gchar *path;
+       GTimeVal access_time;
+} FileItem;
+
+typedef enum
+{
+       GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST = 0,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_HOME_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_DESKTOP_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_LOCAL_BOOKMARKS_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_FILE_BROWSER_ROOT_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_ACTIVE_DOC_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_CURRENT_DOCS_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS
+} ListType;
+
+/* Use #if 1 and rebuild to activate selector debugging and timing */
+#if 0
+#define DEBUG_OPEN_DOCUMENT_SELECTOR
+#endif
+
+#ifdef DEBUG_OPEN_DOCUMENT_SELECTOR
+G_GNUC_UNUSED static const gchar *list_type_string[] =
+{
+       "RECENT_FILES_LIST",
+       "HOME_DIR_LIST",
+       "DESKTOP_DIR_LIST",
+       "LOCAL_BOOKMARKS_DIR_LIST",
+       "FILE_BROWSER_ROOT_DIR_LIST",
+       "ACTIVE_DOC_DIR_LIST",
+       "CURRENT_DOCS_LIST"
+};
+
+#define DEBUG_SELECTOR(x) do { x; } while (0)
+#define DEBUG_SELECTOR_TIMER_DECL G_GNUC_UNUSED GTimer *debug_timer;
+#define DEBUG_SELECTOR_TIMER_NEW debug_timer = g_timer_new ();
+#define DEBUG_SELECTOR_TIMER_DESTROY g_timer_destroy (debug_timer);
+#define DEBUG_SELECTOR_TIMER_GET g_timer_elapsed (debug_timer, NULL)
+#else
+#define DEBUG_SELECTOR(x)
+#define DEBUG_SELECTOR_TIMER_DECL
+#define DEBUG_SELECTOR_TIMER_NEW
+#define DEBUG_SELECTOR_TIMER_DESTROY
+#define DEBUG_SELECTOR_TIMER_GET
+#endif
+
+typedef struct
+{
+       GeditOpenDocumentSelector *selector;
+       ListType type;
+} PushMessage;
+
+void            gedit_open_document_selector_debug_print_list          (const gchar *title,
+                                                                         GList       *fileitem_list);
+
+GList          *gedit_open_document_selector_copy_file_items_list      (const GList *file_items_list);
+
+void            gedit_open_document_selector_free_file_items_list      (GList *file_items_list);
+
+FileItem       *gedit_open_document_selector_create_fileitem_item      (void);
+
+void            gedit_open_document_selector_free_fileitem_item        (FileItem *item);
+
+FileItem       *gedit_open_document_selector_copy_fileitem_item        (FileItem *item);
+
+G_END_DECLS
+
+#endif /* GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-store.c b/gedit/gedit-open-document-selector-store.c
new file mode 100644
index 000000000..e3454f12c
--- /dev/null
+++ b/gedit/gedit-open-document-selector-store.c
@@ -0,0 +1,820 @@
+/*
+ * gedit-open-document-selector-store.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* You need to call gedit_open_document_selector_store_get_default()
+ * to get a singleton #GeditOpenDocumentSelectorStore object.
+ * #GeditOpenDocumentSelectorStore is responsible of managing
+ * the recent files list and computing others lists.
+ *
+ * The lists returned are lists of FileItem structs.
+ *
+ * #GeditOpenDocumentSelectorStore is destroyed automaticly at
+ * the end of your application.
+ *
+ * Call gedit_open_document_selector_store_update_list_async() with
+ * the corresponding ListType, then in your callback, call
+ * gedit_open_document_selector_store_update_list_finish() to get
+ * in return the list of FileItem structs.
+ *
+ * The recent files list can be filtered by calling
+ * gedit_open_document_selector_store_set_filter()
+ * and you can get the actual filter by calling
+ * gedit_open_document_selector_store_get_filter()
+ * ( this is in addition to the text mime type filter)
+ *
+ * The recent files list is not capped by Gedit settings like
+ * in gedit_recent_get_items() but you still can get the limit
+ * by calling gedit_open_document_selector_store_get_recent_limit().
+ *
+ * The original setting is stored in gsettings at :
+ * org.gnome.gedit.preferences.ui
+ * with the key : max-recents
+ */
+
+#include "gedit-open-document-selector-store.h"
+
+#include <time.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "gedit-recent.h"
+#include "gedit-utils.h"
+#include "gedit-window.h"
+#include "gedit-debug.h"
+
+struct _GeditOpenDocumentSelectorStore
+{
+       GObject                   parent_instance;
+
+       GSource                  *recent_source;
+
+       GeditRecentConfiguration  recent_config;
+       gchar                    *filter;
+       GList                    *recent_items;
+       gint                      recent_config_limit;
+       gboolean                  recent_items_need_update;
+};
+
+G_LOCK_DEFINE_STATIC (recent_files_filter_lock);
+
+G_DEFINE_TYPE (GeditOpenDocumentSelectorStore, gedit_open_document_selector_store, G_TYPE_OBJECT)
+
+G_DEFINE_QUARK (gedit-open-document-selector-store-error-quark,
+                gedit_open_document_selector_store_error)
+
+static GList *
+get_current_docs_list (GeditOpenDocumentSelectorStore *selector_store G_GNUC_UNUSED,
+                       GeditOpenDocumentSelector      *selector)
+{
+       GeditWindow *window;
+       GList *docs;
+       GList *l;
+       GFile *file;
+       GFileInfo *info;
+       FileItem *item;
+       GList *file_items_list = NULL;
+
+       window = gedit_open_document_selector_get_window (selector);
+
+       docs = gedit_window_get_documents (window);
+       for (l = docs; l != NULL; l = l->next)
+       {
+               file = gtk_source_file_get_location (gedit_document_get_file (l->data));
+               if (file == NULL)
+               {
+                       /* In case of not saved docs */
+                       continue;
+               }
+
+               info = g_file_query_info (file,
+                                         "time::access,time::access-usec",
+                                         G_FILE_QUERY_INFO_NONE,
+                                         NULL,
+                                         NULL);
+               if (info == NULL)
+               {
+                       continue;
+               }
+
+               item = gedit_open_document_selector_create_fileitem_item ();
+
+               item->access_time.tv_sec = g_file_info_get_attribute_uint64 (info, "time::access");
+               item->access_time.tv_usec = g_file_info_get_attribute_uint32 (info, "time::access-usec");
+               item->uri = g_file_get_uri (file);
+
+               file_items_list = g_list_prepend (file_items_list, item);
+
+               g_object_unref (info);
+       }
+
+       g_list_free (docs);
+       return file_items_list;
+}
+
+/* Notice that a content-type attribute must have been query to work */
+static gboolean
+check_mime_type (GFileInfo *info)
+{
+       const gchar *content_type;
+       G_GNUC_UNUSED gchar *mime_type;
+
+       content_type = g_file_info_get_attribute_string (info, "standard::fast-content-type");
+       if (content_type == NULL)
+       {
+               return FALSE;
+       }
+
+#ifdef G_OS_WIN32
+       if (g_content_type_is_a (content_type, "text"))
+       {
+               return TRUE;
+       }
+
+       mime_type = g_content_type_get_mime_type (content_type);
+       if (mime_type == NULL)
+       {
+               return FALSE;
+       }
+
+       if (g_strcmp0 (mime_type, "text/plain") == 0)
+       {
+               g_free (mime_type);
+               return TRUE;
+       }
+
+       g_free (mime_type);
+#else
+       if (g_content_type_is_a (content_type, "text/plain"))
+       {
+               return TRUE;
+       }
+#endif
+       return FALSE;
+}
+
+static GList *
+get_children_from_dir (GeditOpenDocumentSelectorStore *selector_store G_GNUC_UNUSED,
+                       GFile                          *dir)
+{
+       GList *file_items_list = NULL;
+       GFileEnumerator *file_enum;
+       GFileInfo *info;
+       GFileType filetype;
+       GFile *file;
+       FileItem *item;
+       gboolean is_text;
+       gboolean is_correct_type;
+
+       g_return_val_if_fail (G_IS_FILE (dir), NULL);
+
+       file_enum = g_file_enumerate_children (dir,
+                                              "standard::name,"
+                                              "standard::type,"
+                                              "standard::fast-content-type,"
+                                              "time::access,time::access-usec",
+                                              G_FILE_QUERY_INFO_NONE,
+                                              NULL,
+                                              NULL);
+       if (file_enum == NULL)
+       {
+               return NULL;
+       }
+
+       while ((info = g_file_enumerator_next_file (file_enum, NULL, NULL)))
+       {
+               filetype = g_file_info_get_file_type (info);
+               is_text = check_mime_type (info);
+               is_correct_type = (filetype == G_FILE_TYPE_REGULAR ||
+                                  filetype == G_FILE_TYPE_SYMBOLIC_LINK ||
+                                  filetype == G_FILE_TYPE_SHORTCUT);
+
+               if (is_text &&
+                   is_correct_type &&
+                   (file = g_file_enumerator_get_child (file_enum, info)) != NULL)
+               {
+                       item = gedit_open_document_selector_create_fileitem_item ();
+                       item->uri = g_file_get_uri (file);
+
+                       item->access_time.tv_sec = g_file_info_get_attribute_uint64 (info, "time::access");
+                       item->access_time.tv_usec = g_file_info_get_attribute_uint32 (info, 
"time::access-usec");
+
+                       file_items_list = g_list_prepend (file_items_list, item);
+                       g_object_unref (file);
+               }
+
+               g_object_unref (info);
+       }
+
+       g_file_enumerator_close (file_enum, NULL, NULL);
+       g_object_unref (file_enum);
+
+       return file_items_list;
+}
+
+static GList *
+get_active_doc_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                         GeditOpenDocumentSelector      *selector)
+{
+       GeditWindow *window;
+       GeditDocument *active_doc;
+       GtkSourceFile *source_file;
+       GList *file_items_list = NULL;
+
+       window = gedit_open_document_selector_get_window (selector);
+
+       active_doc = gedit_window_get_active_document (window);
+
+       if (active_doc == NULL)
+       {
+               return NULL;
+       }
+
+       source_file = gedit_document_get_file (active_doc);
+       if (gtk_source_file_is_local (source_file))
+       {
+               GFile *location;
+               GFile *parent_dir;
+
+               location = gtk_source_file_get_location (source_file);
+               parent_dir = g_file_get_parent (location);
+
+               if (parent_dir != NULL)
+               {
+                       file_items_list = get_children_from_dir (selector_store, parent_dir);
+                       g_object_unref (parent_dir);
+               }
+       }
+
+       return file_items_list;
+}
+
+static GFile *
+get_file_browser_root (GeditOpenDocumentSelectorStore *selector_store G_GNUC_UNUSED,
+                       GeditOpenDocumentSelector      *selector)
+{
+       GeditWindow *window;
+       GeditMessageBus *bus;
+       GeditMessage *msg;
+       GFile *root = NULL;
+
+       window = gedit_open_document_selector_get_window (selector);
+
+       bus = gedit_window_get_message_bus (window);
+       if (gedit_message_bus_is_registered (bus, "/plugins/filebrowser", "get_root"))
+       {
+               msg = gedit_message_bus_send_sync (bus, "/plugins/filebrowser", "get_root", NULL, NULL);
+               g_object_get (msg, "location", &root, NULL);
+               g_object_unref (msg);
+       }
+
+       return root;
+}
+
+static GList *
+get_file_browser_root_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                                GeditOpenDocumentSelector      *selector)
+{
+       GFile *root;
+       GList *file_items_list = NULL;
+
+       root = get_file_browser_root (selector_store, selector);
+       if (root != NULL && g_file_is_native (root))
+       {
+               file_items_list = get_children_from_dir (selector_store, root);
+       }
+
+       g_clear_object (&root);
+       return file_items_list;
+}
+
+/* Taken and adapted from gtk+ gtkbookmarksmanager.c */
+static GList *
+read_bookmarks_file (GFile *file)
+{
+       gchar *contents;
+       gchar **lines, *space;
+       GList *uri_list = NULL;
+       gint i;
+
+       if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL))
+       {
+               return NULL;
+       }
+
+       lines = g_strsplit (contents, "\n", -1);
+
+       for (i = 0; lines[i]; i++)
+       {
+               if (*lines[i] == '\0')
+               {
+                       continue;
+               }
+
+               if (!g_utf8_validate (lines[i], -1, NULL))
+               {
+                       continue;
+               }
+
+               if ((space = strchr (lines[i], ' ')) != NULL)
+               {
+                       space[0] = '\0';
+               }
+
+               uri_list = g_list_prepend (uri_list, g_strdup (lines[i]));
+       }
+
+       g_strfreev (lines);
+       g_free (contents);
+
+       return uri_list;
+}
+
+static GList *
+get_local_bookmarks_list (GeditOpenDocumentSelectorStore *selector_store,
+                          GeditOpenDocumentSelector      *selector G_GNUC_UNUSED)
+{
+       GList *bookmarks_uri_list = NULL;
+       GList *file_items_list = NULL;
+       GList *new_file_items_list = NULL;
+       GFile *bookmarks_file;
+       GFile *file;
+       gchar *filename;
+       GList *l;
+
+       filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
+       bookmarks_file = g_file_new_for_path (filename);
+       g_free (filename);
+
+       bookmarks_uri_list = read_bookmarks_file (bookmarks_file);
+       g_object_unref (bookmarks_file);
+
+       for (l = bookmarks_uri_list; l != NULL; l = l->next)
+       {
+               file = g_file_new_for_uri (l->data);
+               if (g_file_is_native (file))
+               {
+                       new_file_items_list = get_children_from_dir (selector_store, file);
+                       file_items_list = g_list_concat (file_items_list, new_file_items_list);
+               }
+
+               g_object_unref (file);
+       }
+
+       g_list_free_full (bookmarks_uri_list, g_free);
+       return file_items_list;
+}
+
+/* Taken and adapted from gtk+ gtkplacessidebar.c */
+static gboolean
+path_is_home_dir (const gchar *path)
+{
+       GFile *home_dir;
+       GFile *location;
+       const gchar *home_path;
+       gboolean res;
+
+       home_path = g_get_home_dir ();
+       if (home_path == NULL)
+       {
+               return FALSE;
+       }
+
+       home_dir = g_file_new_for_path (home_path);
+       location = g_file_new_for_path (path);
+       res = g_file_equal (home_dir, location);
+
+       g_object_unref (home_dir);
+       g_object_unref (location);
+
+       return res;
+}
+
+static GList *
+get_desktop_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                      GeditOpenDocumentSelector      *selector G_GNUC_UNUSED)
+{
+       GList *file_items_list = NULL;
+       const gchar *desktop_dir_name;
+       gchar *desktop_uri;
+       GFile *desktop_file;
+
+       desktop_dir_name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
+
+       /* "To disable a directory, point it to the homedir."
+        * See http://freedesktop.org/wiki/Software/xdg-user-dirs
+        */
+       if (path_is_home_dir (desktop_dir_name))
+       {
+               return NULL;
+       }
+
+       desktop_uri = g_strconcat ("file://", desktop_dir_name, NULL);
+       desktop_file = g_file_new_for_uri (desktop_uri);
+       file_items_list = get_children_from_dir (selector_store, desktop_file);
+
+       g_free (desktop_uri);
+       g_object_unref (desktop_file);
+
+       return file_items_list;
+}
+
+static GList *
+get_home_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                   GeditOpenDocumentSelector      *selector G_GNUC_UNUSED)
+{
+       GList *file_items_list = NULL;
+       const gchar *home_name;
+       gchar *home_uri;
+       GFile *home_file;
+
+       home_name = g_get_home_dir ();
+       if (home_name == NULL)
+       {
+               return NULL;
+       }
+
+       home_uri = g_strconcat ("file://", home_name, NULL);
+       home_file = g_file_new_for_uri (home_uri);
+       file_items_list = get_children_from_dir (selector_store, home_file);
+
+       g_free (home_uri);
+       g_object_unref (home_file);
+
+       return file_items_list;
+}
+
+static GList *
+convert_recent_item_list_to_fileitem_list (GList *uri_list)
+{
+       GList *l;
+       GList *fileitem_list = NULL;
+
+       for (l = uri_list; l != NULL; l = l->next)
+       {
+               gchar *uri;
+               FileItem *item;
+
+               uri = g_strdup (gtk_recent_info_get_uri (l->data));
+
+               item = gedit_open_document_selector_create_fileitem_item ();
+               item->uri = uri;
+
+               item->access_time.tv_sec = gtk_recent_info_get_visited (l->data);
+               item->access_time.tv_usec = 0;
+
+               fileitem_list = g_list_prepend (fileitem_list, item);
+       }
+
+       fileitem_list = g_list_reverse (fileitem_list);
+       return fileitem_list;
+}
+
+static GList *
+get_recent_files_list (GeditOpenDocumentSelectorStore *selector_store,
+                       GeditOpenDocumentSelector      *selector G_GNUC_UNUSED)
+{
+       GList *recent_items_list;
+       GList *file_items_list;
+
+       G_LOCK (recent_files_filter_lock);
+       recent_items_list = gedit_recent_get_items (&selector_store->recent_config);
+       G_UNLOCK (recent_files_filter_lock);
+
+       file_items_list = convert_recent_item_list_to_fileitem_list (recent_items_list);
+       g_list_free_full (recent_items_list, (GDestroyNotify)gtk_recent_info_unref);
+
+       return file_items_list;
+}
+
+static void
+update_list_cb (GeditOpenDocumentSelectorStore *selector_store,
+                GAsyncResult                   *res,
+                gpointer                        user_data G_GNUC_UNUSED)
+{
+       GList *list;
+       GError *error;
+       PushMessage *message;
+       ListType type;
+
+       list = gedit_open_document_selector_store_update_list_finish (selector_store, res, &error);
+
+       message = g_task_get_task_data (G_TASK (res));
+       type = message->type;
+
+       switch (type)
+       {
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST:
+                       gedit_open_document_selector_free_file_items_list (selector_store->recent_items);
+                       selector_store->recent_items = list;
+
+                       DEBUG_SELECTOR (g_print ("\tStore(%p): update_list_cb: type:%s, length:%i\n",
+                                                selector_store, list_type_string[type], g_list_length 
(list)););
+
+                       break;
+               default:
+                       break;
+       }
+}
+
+static void
+on_recent_manager_changed (GtkRecentManager *manager G_GNUC_UNUSED,
+                           gpointer          user_data)
+{
+       GeditOpenDocumentSelectorStore *selector_store = GEDIT_OPEN_DOCUMENT_SELECTOR_STORE (user_data);
+
+       selector_store->recent_items_need_update = TRUE;
+       gedit_open_document_selector_store_update_list_async (selector_store,
+                                                             NULL,
+                                                             NULL,
+                                                             (GAsyncReadyCallback)update_list_cb,
+                                                             GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST,
+                                                             NULL);
+}
+
+static void
+gedit_open_document_selector_store_dispose (GObject *object)
+{
+       GeditOpenDocumentSelectorStore *selector_store = GEDIT_OPEN_DOCUMENT_SELECTOR_STORE (object);
+
+       gedit_recent_configuration_destroy (&selector_store->recent_config);
+
+       g_clear_pointer (&selector_store->recent_source, g_source_destroy);
+       g_clear_pointer (&selector_store->filter, g_free);
+
+       if (selector_store->recent_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector_store->recent_items);
+               selector_store->recent_items = NULL;
+       }
+
+       G_OBJECT_CLASS (gedit_open_document_selector_store_parent_class)->dispose (object);
+}
+
+static void
+gedit_open_document_selector_store_class_init (GeditOpenDocumentSelectorStoreClass *klass)
+{
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+       gobject_class->dispose = gedit_open_document_selector_store_dispose;
+}
+
+/* The order of functions pointers must be the same as in
+ * ListType enum define in ./gedit-open-document-selector-helper.h
+ */
+static GList * (*list_func [])(GeditOpenDocumentSelectorStore *selector_store,
+                               GeditOpenDocumentSelector      *selector) =
+{
+       get_recent_files_list,
+       get_home_dir_list,
+       get_desktop_dir_list,
+       get_local_bookmarks_list,
+       get_file_browser_root_dir_list,
+       get_active_doc_dir_list,
+       get_current_docs_list
+};
+
+static gboolean
+update_recent_list (gpointer user_data)
+{
+       GeditOpenDocumentSelectorStore *selector_store;
+       GeditOpenDocumentSelector *selector;
+       PushMessage *message;
+       /* The type variable is only used when debug code activated */
+       G_GNUC_UNUSED ListType type;
+       GList *file_items_list;
+       GTask *task = G_TASK(user_data);
+
+       selector_store = g_task_get_source_object (task);
+       message = g_task_get_task_data (task);
+       selector = message->selector;
+       type = message->type;
+
+       DEBUG_SELECTOR_TIMER_DECL
+       DEBUG_SELECTOR_TIMER_NEW
+       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: type:%s\n",
+                                selector, list_type_string[type]););
+
+       /* Update the recent list only when it changes, copy otherwise but keep it the first time */
+       if (selector_store->recent_items != NULL && selector_store->recent_items_need_update == FALSE)
+       {
+               file_items_list = gedit_open_document_selector_copy_file_items_list 
(selector_store->recent_items);
+
+               DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: recent list copy\n", selector););
+       }
+       else
+       {
+               selector_store->recent_items_need_update = FALSE;
+               file_items_list = get_recent_files_list (selector_store, selector);
+
+               DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: recent list compute\n", selector););
+
+               if (selector_store->recent_items == NULL)
+               {
+                       selector_store->recent_items = gedit_open_document_selector_copy_file_items_list 
(file_items_list);
+               }
+       }
+
+       g_task_return_pointer (task,
+                              file_items_list,
+                              (GDestroyNotify)gedit_open_document_selector_free_file_items_list);
+
+       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: type:%s, time:%lf\n",
+                                selector, list_type_string[type], DEBUG_SELECTOR_TIMER_GET););
+       DEBUG_SELECTOR_TIMER_DESTROY
+
+        selector_store->recent_source = NULL;
+       return G_SOURCE_REMOVE;
+}
+
+static void
+update_list_dispatcher (GTask        *task,
+                        gpointer      source_object,
+                        gpointer      task_data,
+                        GCancellable *cancellable G_GNUC_UNUSED)
+{
+       GeditOpenDocumentSelectorStore *selector_store = source_object;
+       GeditOpenDocumentSelector *selector;
+       PushMessage *message;
+       ListType type;
+       GList *file_items_list;
+
+       message = task_data;
+       selector = message->selector;
+       type = message->type;
+
+       DEBUG_SELECTOR_TIMER_DECL
+       DEBUG_SELECTOR_TIMER_NEW
+       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: Thread:%p, type:%s\n",
+                                selector, g_thread_self (), list_type_string[type]););
+
+       if (type >= GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS)
+       {
+               g_task_return_new_error (task,
+                                        GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_ERROR, TYPE_OUT_OF_RANGE,
+                                        "List Type out of range");
+               g_object_unref (task);
+               return;
+       }
+
+       /* Here we call the corresponding list creator function */
+       file_items_list = (*list_func[type]) (selector_store, selector);
+
+       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: Thread:%p, type:%s, time:%lf\n",
+                                selector, g_thread_self (), list_type_string[type], 
DEBUG_SELECTOR_TIMER_GET););
+       DEBUG_SELECTOR_TIMER_DESTROY
+
+       g_task_return_pointer (task,
+                              file_items_list,
+                              (GDestroyNotify)gedit_open_document_selector_free_file_items_list);
+}
+
+GList *
+gedit_open_document_selector_store_update_list_finish (GeditOpenDocumentSelectorStore  
*open_document_selector_store,
+                                                       GAsyncResult                    *result,
+                                                       GError                         **error)
+{
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (open_document_selector_store), NULL);
+       g_return_val_if_fail (g_task_is_valid (result, open_document_selector_store), NULL);
+
+       return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+void
+gedit_open_document_selector_store_update_list_async (GeditOpenDocumentSelectorStore *selector_store,
+                                                      GeditOpenDocumentSelector      *selector,
+                                                      GCancellable                   *cancellable,
+                                                      GAsyncReadyCallback             callback,
+                                                      ListType                        type,
+                                                      gpointer                        user_data)
+{
+       GTask *task;
+       PushMessage *message;
+
+       g_return_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store));
+       g_return_if_fail (selector == NULL || GEDIT_IS_OPEN_DOCUMENT_SELECTOR (selector));
+
+       message = g_new (PushMessage, 1);
+       message->selector = selector;
+       message->type = type;
+
+       task = g_task_new (selector_store, cancellable, callback, user_data);
+       g_task_set_source_tag (task, gedit_open_document_selector_store_update_list_async);
+       g_task_set_priority (task, G_PRIORITY_DEFAULT);
+       g_task_set_task_data (task, message, (GDestroyNotify)g_free);
+
+       if (type == GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST &&
+           selector_store->recent_source == NULL)
+       {
+               selector_store->recent_source = g_idle_source_new ();
+               g_task_attach_source (task, selector_store->recent_source, update_recent_list);
+       }
+       else
+       {
+               g_task_run_in_thread (task, update_list_dispatcher);
+       }
+
+       g_object_unref (task);
+}
+
+static void
+gedit_open_document_selector_store_init (GeditOpenDocumentSelectorStore *selector_store)
+{
+       gedit_recent_configuration_init_default (&selector_store->recent_config);
+
+       /* We remove the recent files limit since we need the whole list but
+        * we back it up as gedit_open_document_selector_store_get_recent_limit
+        * use it
+        */
+       selector_store->recent_config_limit = selector_store->recent_config.limit;
+       selector_store->recent_config.limit = -1;
+
+       g_signal_connect_object (selector_store->recent_config.manager,
+                                "changed",
+                                G_CALLBACK (on_recent_manager_changed),
+                                selector_store,
+                                0);
+
+       selector_store->recent_items_need_update = TRUE;
+}
+
+gint
+gedit_open_document_selector_store_get_recent_limit (GeditOpenDocumentSelectorStore *selector_store)
+{
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store), -1);
+
+       return selector_store->recent_config_limit;
+}
+
+void
+gedit_open_document_selector_store_set_filter (GeditOpenDocumentSelectorStore *selector_store,
+                                               const gchar                    *filter)
+{
+       gchar *old_filter;
+
+       g_return_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store));
+       g_return_if_fail (filter != NULL);
+
+       G_LOCK (recent_files_filter_lock);
+
+       old_filter = selector_store->filter;
+       selector_store->filter = g_strdup (filter);
+
+       G_UNLOCK (recent_files_filter_lock);
+       g_free (old_filter);
+}
+
+gchar *
+gedit_open_document_selector_store_get_filter (GeditOpenDocumentSelectorStore *selector_store)
+{
+       gchar *recent_filter;
+
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store), NULL);
+
+       G_LOCK (recent_files_filter_lock);
+       recent_filter = g_strdup (selector_store->filter);
+       G_UNLOCK (recent_files_filter_lock);
+
+       return recent_filter;
+}
+
+/* Gets a unique instance of #GeditOpenDocumentSelectorStore
+ *
+ * Returns: (transfer none): A unique #GeditOpenDocumentSelectorStore.
+ * Do not ref or unref it, it will be destroyed at the end of the application.
+ */
+GeditOpenDocumentSelectorStore *
+gedit_open_document_selector_store_get_default (void)
+{
+       static GeditOpenDocumentSelectorStore *instance;
+
+       if (instance == NULL)
+       {
+               instance = g_object_new (GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE, NULL);
+               g_object_add_weak_pointer (G_OBJECT (instance), (gpointer) &instance);
+       }
+
+       return instance;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-store.h b/gedit/gedit-open-document-selector-store.h
new file mode 100644
index 000000000..d1e17a908
--- /dev/null
+++ b/gedit/gedit-open-document-selector-store.h
@@ -0,0 +1,68 @@
+/*
+ * gedit-open-document-selector-store.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H
+
+#include "gedit-open-document-selector-helper.h"
+#include "gedit-open-document-selector.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE (gedit_open_document_selector_store_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditOpenDocumentSelectorStore, gedit_open_document_selector_store, GEDIT, 
OPEN_DOCUMENT_SELECTOR_STORE, GObject)
+
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_ERROR gedit_open_document_selector_store_error_quark ()
+
+typedef enum
+{
+       TYPE_OUT_OF_RANGE
+} GeditOpenDocumentSelectorStoreError;
+
+GQuark                          gedit_open_document_selector_store_error_quark                         
(void);
+
+gint                            gedit_open_document_selector_store_get_recent_limit                    
(GeditOpenDocumentSelectorStore *store);
+
+void                            gedit_open_document_selector_store_set_filter                          
(GeditOpenDocumentSelectorStore *store,
+                                                                                                         
const gchar                    *filter);
+
+gchar                          *gedit_open_document_selector_store_get_filter                          
(GeditOpenDocumentSelectorStore *store);
+
+GList                          *gedit_open_document_selector_store_update_list_finish                  
(GeditOpenDocumentSelectorStore  *open_document_selector_store,
+                                                                                                         
GAsyncResult                    *res,
+                                                                                                         
GError                         **error);
+
+void                           gedit_open_document_selector_store_update_list_async                    
(GeditOpenDocumentSelectorStore *open_document_selector_store,
+                                                                                                         
GeditOpenDocumentSelector      *open_document_selector,
+                                                                                                         
GCancellable                   *cancellable,
+                                                                                                         
GAsyncReadyCallback             callback,
+                                                                                                         
ListType                        type,
+                                                                                                         
gpointer                        user_data);
+
+GeditOpenDocumentSelectorStore *gedit_open_document_selector_store_get_default                         
(void);
+
+G_END_DECLS
+
+#endif /* GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H */
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector.c b/gedit/gedit-open-document-selector.c
new file mode 100644
index 000000000..f67a6ba6d
--- /dev/null
+++ b/gedit/gedit-open-document-selector.c
@@ -0,0 +1,1304 @@
+/*
+ * gedit-open-document-selector.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-open-document-selector.h"
+#include "gedit-open-document-selector-store.h"
+#include "gedit-open-document-selector-helper.h"
+
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include "gedit-recent.h"
+#include "gedit-utils.h"
+#include "gedit-window.h"
+#include "gedit-debug.h"
+
+struct _GeditOpenDocumentSelector
+{
+       GtkBox parent_instance;
+
+       GeditWindow *window;
+       GtkWidget *search_entry;
+
+       GtkWidget *open_button;
+       GtkWidget *treeview;
+       GtkListStore *liststore;
+       GtkCellRenderer *name_renderer;
+       GtkCellRenderer *path_renderer;
+       GtkWidget *placeholder_box;
+       GtkWidget *scrolled_window;
+
+       guint populate_listbox_id;
+
+       GdkRGBA name_label_color;
+       PangoFontDescription *name_font;
+       GdkRGBA path_label_color;
+       PangoFontDescription *path_font;
+       gchar *match_markup_color;
+
+       GeditOpenDocumentSelectorStore *selector_store;
+       GList *recent_items;
+       GList *home_dir_items;
+       GList *desktop_dir_items;
+       GList *local_bookmarks_dir_items;
+       GList *file_browser_root_items;
+       GList *active_doc_dir_items;
+       GList *current_docs_items;
+       GList *all_items;
+};
+
+typedef enum
+{
+       SELECTOR_TAG_NONE,
+       SELECTOR_TAG_MATCH
+} SelectorTag;
+
+enum
+{
+       NAME_COLUMN,
+       PATH_COLUMN,
+       URI_COLUMN,
+       N_COLUMNS
+};
+
+enum
+{
+       PROP_0,
+       PROP_WINDOW,
+       LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+enum
+{
+       SELECTOR_FILE_ACTIVATED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* Value 0xFF is reserved to mark the end of the array */
+#define BYTE_ARRAY_END 0xFF
+
+#define OPEN_DOCUMENT_SELECTOR_WIDTH 400
+#define OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS 10
+
+G_DEFINE_TYPE (GeditOpenDocumentSelector, gedit_open_document_selector, GTK_TYPE_BOX)
+
+static inline const guint8 *
+get_byte_run (const guint8 *byte_array,
+              gsize        *count,
+              SelectorTag  *tag)
+{
+       guint8 tag_found;
+       gsize c = 1;
+
+       tag_found = *byte_array++;
+
+       while ( *byte_array != BYTE_ARRAY_END && *byte_array == tag_found)
+       {
+               c++;
+               byte_array++;
+       }
+
+       *count = c;
+       *tag = tag_found;
+
+       return ( *byte_array != BYTE_ARRAY_END) ? byte_array : NULL;
+}
+
+static gchar*
+get_markup_from_tagged_byte_array (GeditOpenDocumentSelector *selector,
+                                   const gchar               *str,
+                                   const guint8              *byte_array)
+{
+       gchar *txt;
+       GString *string;
+       gchar *result_str;
+       SelectorTag tag;
+       gsize count;
+
+       string = g_string_sized_new (255);
+
+       while (TRUE)
+       {
+               byte_array = get_byte_run (byte_array, &count, &tag);
+               txt = g_markup_escape_text (str, count);
+               if (tag == SELECTOR_TAG_MATCH)
+               {
+                       g_string_append (string, selector->match_markup_color);
+                       g_string_append (string, txt);
+                       g_string_append (string, "</span>");
+               }
+               else
+               {
+                       g_string_append (string, txt);
+               }
+
+               g_free (txt);
+
+               if (!byte_array)
+               {
+                       break;
+               }
+
+               str = (const gchar *)((gsize)str + count);
+       }
+
+       result_str = g_string_free (string, FALSE);
+       return result_str;
+}
+
+static guint8 *
+get_tagged_byte_array (const gchar *uri,
+                       GRegex      *filter_regex)
+{
+       guint8 *byte_array;
+       gsize uri_len;
+       GMatchInfo *match_info;
+       gboolean no_match = TRUE;
+
+       g_return_val_if_fail (uri != NULL, NULL);
+
+       uri_len = strlen (uri);
+       byte_array = g_malloc0 (uri_len + 1);
+       byte_array[uri_len] = BYTE_ARRAY_END;
+
+       if (g_regex_match (filter_regex, uri, 0, &match_info) == TRUE)
+       {
+               while (g_match_info_matches (match_info) == TRUE)
+               {
+                       guint8 *p;
+                       gint match_len;
+                       gint start_pos;
+                       gint end_pos;
+
+                       if (g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos) == TRUE)
+                       {
+                               match_len = end_pos - start_pos;
+                               no_match = FALSE;
+
+                               p = (guint8 *)((gsize)byte_array + start_pos);
+                               memset (p, SELECTOR_TAG_MATCH, match_len);
+                       }
+
+                       g_match_info_next (match_info, NULL);
+               }
+       }
+
+       g_match_info_free (match_info);
+
+       if (no_match)
+       {
+               g_free (byte_array);
+               return NULL;
+       }
+
+       return byte_array;
+}
+
+static void
+get_markup_for_path_and_name (GeditOpenDocumentSelector  *selector,
+                              GRegex                     *filter_regex,
+                              const gchar                *src_path,
+                              const gchar                *src_name,
+                              gchar                     **dst_path,
+                              gchar                     **dst_name)
+{
+       gchar *filename;
+       gsize path_len;
+       gsize name_len;
+       gsize path_separator_len;
+       guint8 *byte_array;
+       guint8 *path_byte_array;
+       guint8 *name_byte_array;
+
+       filename = g_build_filename (src_path, src_name, NULL);
+
+       path_len = g_utf8_strlen (src_path, -1);
+       name_len = g_utf8_strlen (src_name, -1);
+       path_separator_len = g_utf8_strlen (filename, -1) - ( path_len + name_len);
+
+       byte_array = get_tagged_byte_array (filename, filter_regex);
+       if (byte_array)
+       {
+               path_byte_array = g_memdup (byte_array, path_len + 1);
+               path_byte_array[path_len] = BYTE_ARRAY_END;
+
+               /* name_byte_array is part of byte_array, so released with it */
+               name_byte_array = (guint8 *)((gsize)byte_array + path_len + path_separator_len);
+
+               *dst_path = get_markup_from_tagged_byte_array (selector, src_path, path_byte_array);
+               *dst_name = get_markup_from_tagged_byte_array (selector, src_name, name_byte_array);
+
+               g_free (byte_array);
+               g_free (path_byte_array);
+       }
+       else
+       {
+               *dst_path = g_strdup (src_path);
+               *dst_name = g_strdup (src_name);
+       }
+
+       g_free (filename);
+}
+
+static void
+create_row (GeditOpenDocumentSelector *selector,
+            const FileItem            *item,
+            GRegex                    *filter_regex)
+{
+       GtkTreeIter iter;
+       gchar *uri;
+       gchar *dst_path;
+       gchar *dst_name;
+
+       uri =item->uri;
+
+       if (filter_regex)
+       {
+               get_markup_for_path_and_name (selector,
+                                             filter_regex,
+                                             (const gchar *)item->path,
+                                             (const gchar *)item->name,
+                                             &dst_path,
+                                             &dst_name);
+       }
+       else
+       {
+               dst_path = g_markup_escape_text (item->path, -1);
+               dst_name = g_markup_escape_text (item->name, -1);
+       }
+
+       gtk_list_store_append (selector->liststore, &iter);
+       gtk_list_store_set (selector->liststore, &iter,
+                           URI_COLUMN, uri,
+                           NAME_COLUMN, dst_name,
+                           PATH_COLUMN, dst_path,
+                           -1);
+
+       g_free (dst_path);
+       g_free (dst_name);
+}
+
+static gint
+sort_items_by_mru (FileItem *a,
+                   FileItem *b,
+                   gpointer  unused G_GNUC_UNUSED)
+{
+       glong diff;
+
+       g_assert (a != NULL && b != NULL);
+       diff = b->access_time.tv_sec - a->access_time.tv_sec;
+
+       if (diff == 0)
+       {
+               return (b->access_time.tv_usec - a->access_time.tv_usec);
+       }
+       else
+       {
+               return diff;
+       }
+}
+
+static GList *
+compute_all_items_list (GeditOpenDocumentSelector *selector)
+{
+       GList *recent_items;
+       GList *home_dir_items;
+       GList *desktop_dir_items;
+       GList *local_bookmarks_dir_items;
+       GList *file_browser_root_items;
+       GList *active_doc_dir_items;
+       GList *current_docs_items;
+       GList *all_items = NULL;
+
+       /* Copy/concat the whole list */
+       recent_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)selector->recent_items);
+       home_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)selector->home_dir_items);
+       desktop_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)selector->desktop_dir_items);
+       local_bookmarks_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)selector->local_bookmarks_dir_items);
+       file_browser_root_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)selector->file_browser_root_items);
+       active_doc_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)selector->active_doc_dir_items);
+       current_docs_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)selector->current_docs_items);
+
+       if (selector->all_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->all_items);
+               selector->all_items = NULL;
+       }
+
+       all_items = g_list_concat (all_items, recent_items);
+       all_items = g_list_concat (all_items, home_dir_items);
+       all_items = g_list_concat (all_items, desktop_dir_items);
+       all_items = g_list_concat (all_items, local_bookmarks_dir_items);
+       all_items = g_list_concat (all_items, file_browser_root_items);
+       all_items = g_list_concat (all_items, active_doc_dir_items);
+       all_items = g_list_concat (all_items, current_docs_items);
+
+       return all_items;
+}
+
+static GList *
+clamp_recent_items_list (GList *recent_items,
+                         gint   limit)
+{
+       GList *recent_items_capped = NULL;
+       GList *l;
+       FileItem *item;
+
+       l = recent_items;
+       while (limit > 0 && l != NULL)
+       {
+               item = gedit_open_document_selector_copy_fileitem_item (l->data);
+               recent_items_capped = g_list_prepend (recent_items_capped, item);
+               l = l->next;
+               limit -= 1;
+       }
+
+       recent_items_capped = g_list_reverse (recent_items_capped);
+       return recent_items_capped;
+}
+
+/* Setup the fileitem, depending uri's scheme
+ * Return a string to search in.
+ */
+static gchar *
+fileitem_setup (FileItem *item)
+{
+       gchar *scheme;
+       gchar *filename;
+       gchar *normalized_filename = NULL;
+       gchar *candidate = NULL;
+       gchar *path;
+       gchar *name;
+
+       scheme = g_uri_parse_scheme (item->uri);
+       if (g_strcmp0 (scheme, "file") == 0)
+       {
+               filename = g_filename_from_uri ((const gchar *)item->uri, NULL, NULL);
+               if (filename)
+               {
+                       path = g_path_get_dirname (filename);
+                       item->path = g_filename_to_utf8 (path, -1, NULL, NULL, NULL);
+                       g_free (path);
+
+                       name = g_path_get_basename (filename);
+                       item->name = g_filename_to_utf8 (name, -1, NULL, NULL, NULL);
+                       g_free (name);
+
+                       normalized_filename = g_utf8_normalize (filename, -1, G_NORMALIZE_ALL);
+                       g_free (filename);
+               }
+       }
+       else
+       {
+               GFile *file;
+               gchar *parse_name;
+
+               file = g_file_new_for_uri (item->uri);
+               item->path = gedit_utils_location_get_dirname_for_display (file);
+               item->name  = gedit_utils_basename_for_display (file);
+               parse_name = g_file_get_parse_name (file);
+               g_object_unref (file);
+
+               normalized_filename = g_utf8_normalize (parse_name, -1, G_NORMALIZE_ALL);
+               g_free (parse_name);
+       }
+
+        if (normalized_filename)
+       {
+               candidate = g_utf8_casefold (normalized_filename, -1);
+               g_free (normalized_filename);
+       }
+
+       g_free (scheme);
+
+       return candidate;
+}
+
+static inline gboolean
+is_filter_in_candidate (const gchar *candidate,
+                        const gchar *filter)
+{
+       gchar *candidate_fold;
+       gboolean ret;
+
+       g_assert (candidate != NULL);
+       g_assert (filter != NULL);
+
+       candidate_fold = g_utf8_casefold (candidate, -1);
+       ret = (strstr (candidate_fold, filter) != NULL);
+
+       g_free (candidate_fold);
+       return ret;
+}
+
+/* If filter == NULL then items are
+ * not checked against the filter.
+ */
+static GList *
+fileitem_list_filter (GList       *items,
+                      const gchar *filter)
+{
+       GList *new_items = NULL;
+       GList *l;
+       gchar *filter_fold = NULL;
+
+       if (filter != NULL)
+               filter_fold = g_utf8_casefold (filter, -1);
+
+       for (l = items; l != NULL; l = l->next)
+       {
+               FileItem *item;
+               gchar *candidate;
+
+               item = l->data;
+               candidate = fileitem_setup (item);
+               if (candidate != NULL)
+               {
+                       if (filter == NULL || is_filter_in_candidate (candidate, filter_fold))
+                       {
+                               new_items = g_list_prepend (new_items,
+                                                           gedit_open_document_selector_copy_fileitem_item 
(item));
+                       }
+
+                       g_free (candidate);
+               }
+       }
+
+       g_free (filter_fold);
+       new_items = g_list_reverse (new_items);
+       return new_items;
+}
+
+/* Remove duplicated, the HEAD of the list never change,
+ * the list passed in is modified.
+ */
+static void
+fileitem_list_remove_duplicates (GList *items)
+{
+       GList *l;
+       G_GNUC_UNUSED GList *dummy_ptr;
+
+       l = items;
+       while (l != NULL)
+       {
+               gchar *l_uri, *l1_uri;
+               GList *l1;
+
+               if ((l1 = l->next) == NULL)
+               {
+                       break;
+               }
+
+               l_uri = ((FileItem *)l->data)->uri;
+               l1_uri = ((FileItem *)l1->data)->uri;
+               if (g_strcmp0 (l_uri, l1_uri) == 0)
+               {
+                       gedit_open_document_selector_free_fileitem_item ((FileItem *)l1->data);
+                       dummy_ptr = g_list_delete_link (items, l1);
+               }
+               else
+               {
+                       l = l->next;
+               }
+       }
+}
+
+static gboolean
+real_populate_liststore (gpointer data)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (data);
+       GeditOpenDocumentSelectorStore *selector_store;
+       GList *l;
+       GList *filter_items = NULL;
+       gchar *filter;
+       GRegex *filter_regex = NULL;
+
+       DEBUG_SELECTOR_TIMER_DECL
+       DEBUG_SELECTOR_TIMER_NEW
+
+       gtk_list_store_clear (selector->liststore);
+
+       selector_store = selector->selector_store;
+       filter = gedit_open_document_selector_store_get_filter (selector_store);
+       if (filter && *filter != '\0')
+       {
+               DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: all lists\n", selector););
+
+               filter_items = fileitem_list_filter (selector->all_items, (const gchar *)filter);
+               filter_items = g_list_sort_with_data (filter_items, (GCompareDataFunc)sort_items_by_mru, 
NULL);
+               fileitem_list_remove_duplicates (filter_items);
+
+               filter_regex = g_regex_new (filter, G_REGEX_CASELESS, 0, NULL);
+       }
+       else
+       {
+               gint recent_limit;
+               GList *recent_items;
+
+               DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: recent files list\n", selector););
+
+               recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
+
+               if (recent_limit > 0 )
+               {
+                       recent_items = fileitem_list_filter (selector->recent_items, NULL);
+                       filter_items = clamp_recent_items_list (recent_items, recent_limit);
+                       gedit_open_document_selector_free_file_items_list (recent_items);
+               }
+               else
+               {
+                       filter_items = fileitem_list_filter (selector->recent_items, NULL);
+               }
+       }
+
+       g_free (filter);
+
+       DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: length:%i\n",
+                                selector, g_list_length (filter_items)););
+
+       /* Show the placeholder if no results, show the treeview otherwise */
+       gtk_widget_set_visible (selector->scrolled_window, (filter_items != NULL));
+       gtk_widget_set_visible (selector->placeholder_box, (filter_items == NULL));
+
+       for (l = filter_items; l != NULL; l = l->next)
+       {
+               FileItem *item;
+
+               item = l->data;
+               create_row (selector, (const FileItem *)item, filter_regex);
+       }
+
+       if (filter_regex)
+       {
+               g_regex_unref (filter_regex);
+       }
+
+       gedit_open_document_selector_free_file_items_list (filter_items);
+
+       DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: time:%lf\n\n",
+                                 selector, DEBUG_SELECTOR_TIMER_GET););
+       DEBUG_SELECTOR_TIMER_DESTROY
+
+       selector->populate_listbox_id = 0;
+       return G_SOURCE_REMOVE;
+}
+
+static void
+populate_liststore (GeditOpenDocumentSelector *selector)
+{
+       /* Populate requests are compressed */
+       if (selector->populate_listbox_id != 0)
+       {
+               DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: idle\n", selector););
+               return;
+       }
+
+       DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: scheduled\n", selector););
+       selector->populate_listbox_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
+                                                                  real_populate_liststore,
+                                                                  selector,
+                                                                  NULL);
+}
+
+static gboolean
+on_treeview_key_press (GtkTreeView               *treeview,
+                       GdkEventKey               *event,
+                       GeditOpenDocumentSelector *selector)
+{
+       guint keyval;
+       gboolean is_control_pressed;
+       GtkTreeSelection *tree_selection;
+       GtkTreePath *root_path;
+       GdkModifierType modifiers;
+
+       if (gdk_event_get_keyval ((GdkEvent *)event, &keyval) == TRUE)
+       {
+               tree_selection = gtk_tree_view_get_selection (treeview);
+               root_path = gtk_tree_path_new_from_string ("0");
+
+               modifiers = gtk_accelerator_get_default_mod_mask ();
+               is_control_pressed = (event->state & modifiers) == GDK_CONTROL_MASK;
+
+               if ((keyval == GDK_KEY_Up || keyval == GDK_KEY_KP_Up) &&
+                   !is_control_pressed)
+               {
+                       if (gtk_tree_selection_path_is_selected (tree_selection, root_path))
+                       {
+                               gtk_tree_selection_unselect_all (tree_selection);
+                               gtk_widget_grab_focus (selector->search_entry);
+
+                               return GDK_EVENT_STOP;
+                       }
+               }
+       }
+
+       return GDK_EVENT_PROPAGATE;
+}
+
+static void
+on_entry_changed (GtkEntry                  *entry,
+                  GeditOpenDocumentSelector *selector)
+{
+       const gchar *entry_text;
+
+       entry_text = gtk_entry_get_text (entry);
+       gedit_open_document_selector_store_set_filter (selector->selector_store,
+                                                      entry_text);
+
+       if (gtk_widget_get_mapped ( GTK_WIDGET (selector)))
+       {
+               populate_liststore (selector);
+       }
+}
+
+static void
+on_entry_activated (GtkEntry                  *entry,
+                    GeditOpenDocumentSelector *selector)
+{
+       const gchar *entry_text;
+       GtkTreeSelection *selection;
+       gchar *uri;
+       GFile *file;
+       gchar *scheme;
+
+       entry_text = gtk_entry_get_text (entry);
+       scheme = g_uri_parse_scheme (entry_text);
+       if (!scheme)
+       {
+               const gchar *home_dir = g_get_home_dir ();
+
+               if ( home_dir != NULL && g_str_has_prefix (entry_text, "~/"))
+               {
+                       uri = g_strconcat ("file://", home_dir, "/", entry_text + 2, NULL);
+               }
+               else
+               {
+                       uri = g_strconcat ("file://", entry_text, NULL);
+               }
+       }
+       else
+       {
+               g_free (scheme);
+               uri = g_strdup (entry_text);
+       }
+
+       file = g_file_new_for_uri (uri);
+       if (g_file_query_exists (file, NULL))
+       {
+               DEBUG_SELECTOR (g_print ("Selector(%p): search entry activated : loading '%s'\n",
+                                        selector, uri););
+
+               gtk_entry_set_text (entry, "");
+               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->treeview));
+               gtk_tree_selection_unselect_all (selection);
+
+               g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
+       }
+
+       g_object_unref (file);
+}
+
+static void
+gedit_open_document_selector_dispose (GObject *object)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+       if (selector->populate_listbox_id != 0)
+       {
+               g_source_remove (selector->populate_listbox_id);
+               selector->populate_listbox_id = 0;
+       }
+
+       g_clear_pointer (&selector->name_font, pango_font_description_free);
+       g_clear_pointer (&selector->path_font, pango_font_description_free);
+       g_clear_pointer (&selector->match_markup_color, g_free);
+
+       if (selector->recent_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->recent_items);
+               selector->recent_items = NULL;
+       }
+
+       if (selector->home_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->home_dir_items);
+               selector->home_dir_items = NULL;
+       }
+
+       if (selector->desktop_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->desktop_dir_items);
+               selector->desktop_dir_items = NULL;
+       }
+
+       if (selector->local_bookmarks_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->local_bookmarks_dir_items);
+               selector->local_bookmarks_dir_items = NULL;
+       }
+
+       if (selector->file_browser_root_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->file_browser_root_items);
+               selector->file_browser_root_items = NULL;
+       }
+
+       if (selector->active_doc_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->active_doc_dir_items);
+               selector->active_doc_dir_items = NULL;
+       }
+
+       if (selector->current_docs_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->current_docs_items);
+               selector->current_docs_items = NULL;
+       }
+
+       if (selector->all_items)
+       {
+               gedit_open_document_selector_free_file_items_list (selector->all_items);
+               selector->all_items = NULL;
+       }
+
+       G_OBJECT_CLASS (gedit_open_document_selector_parent_class)->dispose (object);
+}
+
+static void
+on_row_activated (GtkTreeView               *treeview,
+                  GtkTreePath               *path,
+                  GtkTreeViewColumn         *column G_GNUC_UNUSED,
+                  GeditOpenDocumentSelector *selector)
+{
+       GtkTreeModel *liststore = GTK_TREE_MODEL (selector->liststore);
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
+       gchar *uri;
+
+       g_return_if_fail (gtk_tree_model_get_iter (liststore, &iter, path));
+       gtk_tree_model_get (liststore, &iter,
+                           URI_COLUMN, &uri,
+                           -1);
+
+       selection = gtk_tree_view_get_selection (treeview);
+       gtk_tree_selection_unselect_all (selection);
+
+       /* Leak of uri */
+       g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
+}
+
+static void
+update_list_cb (GeditOpenDocumentSelectorStore *selector_store,
+                GAsyncResult                   *res,
+                gpointer                        user_data G_GNUC_UNUSED)
+{
+       GList *list;
+       GError *error;
+       PushMessage *message;
+       ListType type;
+       GeditOpenDocumentSelector *selector;
+
+       list = gedit_open_document_selector_store_update_list_finish (selector_store, res, &error);
+       message = g_task_get_task_data (G_TASK (res));
+       selector = message->selector;
+       type = message->type;
+
+       DEBUG_SELECTOR (g_print ("Selector(%p): update_list_cb - type:%s, length:%i\n",
+                                selector, list_type_string[type], g_list_length (list)););
+
+       switch (type)
+       {
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST:
+                       gedit_open_document_selector_free_file_items_list (selector->recent_items);
+                       selector->recent_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_HOME_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (selector->home_dir_items);
+                       selector->home_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_DESKTOP_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (selector->desktop_dir_items);
+                       selector->desktop_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_LOCAL_BOOKMARKS_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list 
(selector->local_bookmarks_dir_items);
+                       selector->local_bookmarks_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_FILE_BROWSER_ROOT_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (selector->file_browser_root_items);
+                       selector->file_browser_root_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_ACTIVE_DOC_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (selector->active_doc_dir_items);
+                       selector->active_doc_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_CURRENT_DOCS_LIST:
+                       gedit_open_document_selector_free_file_items_list (selector->current_docs_items);
+                       selector->current_docs_items = list;
+                       break;
+
+               default:
+                       g_return_if_reached ();
+       }
+
+       selector->all_items = compute_all_items_list (selector);
+       populate_liststore (selector);
+}
+
+static void
+gedit_open_document_selector_constructed (GObject *object)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+       G_OBJECT_CLASS (gedit_open_document_selector_parent_class)->constructed (object);
+
+       DEBUG_SELECTOR (g_print ("Selector(%p): constructed - ask recent file list\n", selector););
+
+       gedit_open_document_selector_store_update_list_async (selector->selector_store,
+                                                             selector,
+                                                             NULL,
+                                                             (GAsyncReadyCallback)update_list_cb,
+                                                             GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST,
+                                                             selector);
+}
+
+static void
+gedit_open_document_selector_mapped (GtkWidget *widget)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (widget);
+       ListType list_number;
+
+       /* We update all the lists */
+       DEBUG_SELECTOR (g_print ("Selector(%p): mapped - ask all lists\n", selector););
+
+       for (list_number = 0; list_number < GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS; 
list_number++)
+       {
+               gedit_open_document_selector_store_update_list_async (selector->selector_store,
+                                                                     selector,
+                                                                     NULL,
+                                                                     (GAsyncReadyCallback)update_list_cb,
+                                                                     list_number,
+                                                                     selector);
+       }
+
+       GTK_WIDGET_CLASS (gedit_open_document_selector_parent_class)->map (widget);
+}
+
+static GtkSizeRequestMode
+gedit_open_document_selector_get_request_mode (GtkWidget *widget G_GNUC_UNUSED)
+{
+       return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
+static void
+gedit_open_document_selector_get_preferred_width (GtkWidget *widget G_GNUC_UNUSED,
+                                                  gint      *minimum_width,
+                                                  gint      *natural_width)
+{
+       *minimum_width = *natural_width = OPEN_DOCUMENT_SELECTOR_WIDTH;
+}
+
+static void
+gedit_open_document_selector_set_property (GObject      *object,
+                                           guint         prop_id,
+                                           const GValue *value,
+                                           GParamSpec   *pspec)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+       switch (prop_id)
+       {
+               case PROP_WINDOW:
+                       selector->window = g_value_get_object (value);
+                       break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
+gedit_open_document_selector_get_property (GObject    *object,
+                                           guint       prop_id,
+                                           GValue     *value,
+                                           GParamSpec *pspec)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+       switch (prop_id)
+       {
+               case PROP_WINDOW:
+                       g_value_set_object (value, selector->window);
+                       break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
+gedit_open_document_selector_file_activated (GeditOpenDocumentSelector *selector G_GNUC_UNUSED,
+                                             const gchar               *uri      G_GNUC_UNUSED)
+{
+       /* Do nothing in the default handler */
+}
+
+static void
+gedit_open_document_selector_class_init (GeditOpenDocumentSelectorClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       object_class->constructed = gedit_open_document_selector_constructed;
+       object_class->dispose = gedit_open_document_selector_dispose;
+
+       object_class->get_property = gedit_open_document_selector_get_property;
+       object_class->set_property = gedit_open_document_selector_set_property;
+
+       widget_class->get_request_mode = gedit_open_document_selector_get_request_mode;
+       widget_class->get_preferred_width = gedit_open_document_selector_get_preferred_width;
+       widget_class->map = gedit_open_document_selector_mapped;
+
+       properties[PROP_WINDOW] =
+               g_param_spec_object ("window",
+                                    "Window",
+                                    "The GeditWindow this GeditOpenDocumentSelector is associated with",
+                                    GEDIT_TYPE_WINDOW,
+                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+       g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+       signals[SELECTOR_FILE_ACTIVATED] =
+               g_signal_new_class_handler ("file-activated",
+                                           G_TYPE_FROM_CLASS (klass),
+                                           G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                           G_CALLBACK (gedit_open_document_selector_file_activated),
+                                           NULL, NULL, NULL,
+                                           G_TYPE_NONE,
+                                           1,
+                                           G_TYPE_STRING);
+
+       gtk_widget_class_set_template_from_resource (widget_class,
+                                                    "/org/gnome/gedit/ui/gedit-open-document-selector.ui");
+
+       gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, open_button);
+       gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, treeview);
+       gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, placeholder_box);
+       gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, scrolled_window);
+       gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, search_entry);
+}
+
+static void
+on_treeview_allocate (GtkWidget                 *widget     G_GNUC_UNUSED,
+                      GdkRectangle              *allocation G_GNUC_UNUSED,
+                      GeditOpenDocumentSelector *selector)
+{
+       GeditOpenDocumentSelectorStore *selector_store;
+       GtkStyleContext *context;
+       gint name_renderer_natural_size;
+       gint path_renderer_natural_size;
+       GtkBorder padding;
+       gint ypad;
+       gint limit_capped;
+       gint treeview_height;
+       gint grid_line_width;
+       gint row_height;
+       gint recent_limit;
+
+       selector_store = selector->selector_store;
+
+       context = gtk_widget_get_style_context (selector->treeview);
+       gtk_style_context_get_padding (context,
+                                      gtk_style_context_get_state (context),
+                                      &padding);
+
+       /* Treeview height computation */
+       gtk_cell_renderer_get_preferred_height (selector->name_renderer,
+                                               selector->treeview,
+                                               NULL,
+                                               &name_renderer_natural_size);
+
+       gtk_cell_renderer_get_preferred_height (selector->path_renderer,
+                                               selector->treeview,
+                                               NULL,
+                                               &path_renderer_natural_size);
+
+       gtk_cell_renderer_get_padding (selector->name_renderer, NULL, &ypad);
+       gtk_widget_style_get (selector->treeview, "grid-line-width", &grid_line_width, NULL);
+
+       recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
+
+       limit_capped = (recent_limit > 0 ) ? MIN (recent_limit, OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS) :
+                                            OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS;
+
+       row_height = name_renderer_natural_size +
+                    path_renderer_natural_size +
+                    2 * (padding.top + padding.bottom) +
+                    ypad +
+                    grid_line_width;
+
+       treeview_height = row_height * limit_capped;
+       gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (selector->scrolled_window),
+                                                   treeview_height);
+       gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (selector->scrolled_window),
+                                                   treeview_height);
+
+       gtk_widget_set_size_request (selector->placeholder_box, -1, treeview_height);
+}
+
+static inline gchar *
+rgba_to_hex8 (GdkRGBA *rgba)
+{
+       guint red = (guint)(0.5 + CLAMP (rgba->red, 0.0, 1.0) * 255.0);
+       guint green = (guint)(0.5 + CLAMP (rgba->green, 0.0, 1.0) * 255.0);
+       guint blue = (guint)(0.5 + CLAMP (rgba->blue, 0.0, 1.0) * 255.0);
+       guint alpha = (guint)(0.5 + CLAMP (rgba->alpha, 0.0, 1.0) * 255.0);
+       gchar *str = g_strdup_printf ("#%02X%02X%02X%02X", red, green, blue, alpha);
+
+       return str;
+}
+
+static void
+on_treeview_style_updated (GtkWidget                 *widget,
+                           GeditOpenDocumentSelector *selector)
+{
+       GtkStyleContext *context;
+       GdkRGBA match_foreground_rgba = {0.0, 0.0, 0.0, 0.0};
+       GdkRGBA match_background_rgba = {0.0, 0.0, 0.0, 0.0};
+       gchar *match_foreground_hex8;
+       gchar *match_background_hex8;
+
+       context = gtk_widget_get_style_context (widget);
+
+       /* Name label foreground and font size styling */
+       gtk_style_context_save (context);
+       gtk_style_context_add_class (context, "open-document-selector-name-label");
+
+       gtk_style_context_get_color (context,
+                                    gtk_style_context_get_state (context),
+                                    &selector->name_label_color);
+
+       g_clear_pointer (&selector->name_font, pango_font_description_free);
+       gtk_style_context_get (context,
+                              gtk_style_context_get_state (context),
+                              "font", &selector->name_font,
+                              NULL);
+
+       gtk_style_context_restore (context);
+
+       /* Path label foreground and font size styling */
+       gtk_style_context_save (context);
+       gtk_style_context_add_class (context, "open-document-selector-path-label");
+
+       gtk_style_context_get_color (context,
+                                    gtk_style_context_get_state (context),
+                                    &selector->path_label_color);
+
+       g_clear_pointer (&selector->path_font, pango_font_description_free);
+       gtk_style_context_get (context,
+                              gtk_style_context_get_state (context),
+                              "font", &selector->path_font,
+                              NULL);
+
+       gtk_style_context_restore (context);
+
+       /* Match styling */
+       gtk_style_context_save (context);
+       gtk_style_context_add_class (context, "open-document-selector-match");
+
+       gtk_style_context_get_color (context,
+                                    gtk_style_context_get_state (context),
+                                    &match_foreground_rgba);
+
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+       gtk_style_context_get_background_color (context,
+                                               gtk_style_context_get_state (context),
+                                               &match_background_rgba);
+       G_GNUC_END_IGNORE_DEPRECATIONS;
+
+       gtk_style_context_restore (context);
+       g_free (selector->match_markup_color);
+
+       match_foreground_hex8 = rgba_to_hex8 (&match_foreground_rgba);
+       match_background_hex8 = rgba_to_hex8 (&match_background_rgba);
+
+       selector->match_markup_color = g_strdup_printf ("<span weight =\"heavy\" foreground =\"%s\" 
background =\"%s\">",
+                                                       match_foreground_hex8,
+                                                       match_background_hex8);
+
+       g_free (match_foreground_hex8);
+       g_free (match_background_hex8);
+}
+
+static void
+name_renderer_datafunc (GtkTreeViewColumn         *column        G_GNUC_UNUSED,
+                        GtkCellRenderer           *name_renderer G_GNUC_UNUSED,
+                        GtkTreeModel              *liststore     G_GNUC_UNUSED,
+                        GtkTreeIter               *iter          G_GNUC_UNUSED,
+                        GeditOpenDocumentSelector *selector)
+{
+       g_object_set (selector->name_renderer, "foreground-rgba", &selector->name_label_color, NULL);
+       g_object_set (selector->name_renderer, "font-desc", selector->name_font, NULL);
+}
+
+static void
+path_renderer_datafunc (GtkTreeViewColumn         *column        G_GNUC_UNUSED,
+                        GtkCellRenderer           *path_renderer G_GNUC_UNUSED,
+                        GtkTreeModel              *liststore     G_GNUC_UNUSED,
+                        GtkTreeIter               *iter          G_GNUC_UNUSED,
+                        GeditOpenDocumentSelector *selector)
+{
+       g_object_set (selector->path_renderer, "foreground-rgba", &selector->path_label_color, NULL);
+       g_object_set (selector->path_renderer, "font-desc", selector->path_font, NULL);
+}
+
+static void
+setup_treeview (GeditOpenDocumentSelector *selector)
+{
+       GtkTreeViewColumn *column;
+       GtkCellArea *cell_area;
+       GtkStyleContext *context;
+
+       gtk_tree_view_set_model (GTK_TREE_VIEW (selector->treeview), GTK_TREE_MODEL (selector->liststore));
+       g_object_unref(GTK_TREE_MODEL (selector->liststore));
+
+       selector->name_renderer = gtk_cell_renderer_text_new ();
+       selector->path_renderer = gtk_cell_renderer_text_new ();
+
+       g_object_set (selector->name_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+       g_object_set (selector->path_renderer, "ellipsize", PANGO_ELLIPSIZE_START, NULL);
+
+       column = gtk_tree_view_column_new ();
+       gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+
+       gtk_tree_view_column_pack_start (column, selector->name_renderer, TRUE);
+       gtk_tree_view_column_pack_start (column, selector->path_renderer, TRUE);
+
+       gtk_tree_view_column_set_attributes (column, selector->name_renderer, "markup", NAME_COLUMN, NULL);
+       gtk_tree_view_column_set_attributes (column, selector->path_renderer, "markup", PATH_COLUMN, NULL);
+
+       gtk_tree_view_append_column (GTK_TREE_VIEW (selector->treeview), column);
+       cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
+       gtk_orientable_set_orientation (GTK_ORIENTABLE (cell_area), GTK_ORIENTATION_VERTICAL);
+
+       context = gtk_widget_get_style_context (selector->treeview);
+       gtk_style_context_add_class (context, "open-document-selector-treeview");
+
+       gtk_tree_view_column_set_cell_data_func (column,
+                                                selector->name_renderer,
+                                                (GtkTreeCellDataFunc)name_renderer_datafunc,
+                                                selector,
+                                                NULL);
+
+       gtk_tree_view_column_set_cell_data_func (column,
+                                                selector->path_renderer,
+                                                (GtkTreeCellDataFunc)path_renderer_datafunc,
+                                                selector,
+                                                NULL);
+}
+
+static void
+gedit_open_document_selector_init (GeditOpenDocumentSelector *selector)
+{
+       gedit_debug (DEBUG_WINDOW);
+
+       gtk_widget_init_template (GTK_WIDGET (selector));
+
+       selector->selector_store = gedit_open_document_selector_store_get_default ();
+
+       selector->liststore = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+       setup_treeview (selector);
+
+       g_signal_connect (selector->search_entry,
+                         "changed",
+                         G_CALLBACK (on_entry_changed),
+                         selector);
+
+       g_signal_connect (selector->search_entry,
+                         "activate",
+                         G_CALLBACK (on_entry_activated),
+                         selector);
+
+       g_signal_connect (selector->treeview,
+                         "row-activated",
+                         G_CALLBACK (on_row_activated),
+                         selector);
+
+       g_signal_connect (selector->treeview,
+                         "size-allocate",
+                         G_CALLBACK (on_treeview_allocate),
+                         selector);
+
+       g_signal_connect (selector->treeview,
+                         "key-press-event",
+                         G_CALLBACK (on_treeview_key_press),
+                         selector);
+
+       g_signal_connect (selector->treeview,
+                         "style-updated",
+                         G_CALLBACK (on_treeview_style_updated),
+                         selector);
+}
+
+GeditOpenDocumentSelector *
+gedit_open_document_selector_new (GeditWindow *window)
+{
+       g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
+
+       return g_object_new (GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR,
+                            "window", window,
+                            NULL);
+}
+
+GeditWindow *
+gedit_open_document_selector_get_window (GeditOpenDocumentSelector *selector)
+{
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR (selector), NULL);
+
+       return selector->window;
+}
+
+GtkWidget *
+gedit_open_document_selector_get_search_entry (GeditOpenDocumentSelector *selector)
+{
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR (selector), NULL);
+
+       return selector->search_entry;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector.h b/gedit/gedit-open-document-selector.h
new file mode 100644
index 000000000..b4d50cefd
--- /dev/null
+++ b/gedit/gedit-open-document-selector.h
@@ -0,0 +1,44 @@
+/*
+ * gedit-open-document-selector.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_H
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_H
+
+#include <glib-object.h>
+#include "gedit-window.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR (gedit_open_document_selector_get_type ())
+
+G_DECLARE_FINAL_TYPE (GeditOpenDocumentSelector, gedit_open_document_selector, GEDIT, 
OPEN_DOCUMENT_SELECTOR, GtkBox)
+
+GeditOpenDocumentSelector      *gedit_open_document_selector_new               (GeditWindow               
*window);
+
+GeditWindow                    *gedit_open_document_selector_get_window        (GeditOpenDocumentSelector 
*selector);
+
+GtkWidget                      *gedit_open_document_selector_get_search_entry  (GeditOpenDocumentSelector 
*selector);
+
+G_END_DECLS
+
+#endif /* GEDIT_OPEN_DOCUMENT_SELECTOR_H */
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-pango.c b/gedit/gedit-pango.c
new file mode 100644
index 000000000..0488bbcd2
--- /dev/null
+++ b/gedit/gedit-pango.c
@@ -0,0 +1,230 @@
+/* gedit-pango.c
+ *
+ * This file is a copy of pango_font_description_to_css from gtk gtkfontbutton.c
+ *
+ * Copyright (C) 2016 Matthias Clasen <mclasen redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "gedit-pango"
+
+#include "config.h"
+
+#include "gedit-pango.h"
+
+#if PANGO_VERSION_CHECK (1, 44, 0)
+static void
+add_css_variations (GString    *s,
+                    const char *variations)
+{
+  const char *p;
+  const char *sep = "";
+
+  if (variations == NULL || variations[0] == '\0')
+    {
+      g_string_append (s, "normal");
+      return;
+    }
+
+  p = variations;
+  while (p && *p)
+    {
+      const char *start;
+      const char *end, *end2;
+      double value;
+      char name[5];
+
+      while (g_ascii_isspace (*p)) p++;
+
+      start = p;
+      end = strchr (p, ',');
+      if (end && (end - p < 6))
+        goto skip;
+
+      name[0] = p[0];
+      name[1] = p[1];
+      name[2] = p[2];
+      name[3] = p[3];
+      name[4] = '\0';
+
+      p += 4;
+      while (g_ascii_isspace (*p)) p++;
+      if (*p == '=') p++;
+
+      if (p - start < 5)
+        goto skip;
+
+      value = g_ascii_strtod (p, (char **) &end2);
+
+      while (end2 && g_ascii_isspace (*end2)) end2++;
+
+      if (end2 && (*end2 != ',' && *end2 != '\0'))
+        goto skip;
+
+      g_string_append_printf (s, "%s\"%s\" %g", sep, name, value);
+      sep = ", ";
+
+skip:
+      p = end ? end + 1 : NULL;
+    }
+}
+#endif
+
+/**
+ * gedit_pango_font_description_to_css:
+ *
+ * This function will generate CSS suitable for Gtk's CSS engine
+ * based on the properties of the #PangoFontDescription.
+ *
+ * Returns: (transfer full): A newly allocated string containing the
+ *    CSS describing the font description.
+ */
+gchar *
+gedit_pango_font_description_to_css (const PangoFontDescription *desc)
+{
+  GString *s;
+  PangoFontMask set;
+
+  s = g_string_new ("");
+
+  set = pango_font_description_get_set_fields (desc);
+  if (set & PANGO_FONT_MASK_FAMILY)
+    {
+      g_string_append (s, "font-family: ");
+      g_string_append (s, pango_font_description_get_family (desc));
+      g_string_append (s, "; ");
+    }
+  if (set & PANGO_FONT_MASK_STYLE)
+    {
+      switch (pango_font_description_get_style (desc))
+        {
+        case PANGO_STYLE_NORMAL:
+          g_string_append (s, "font-style: normal; ");
+          break;
+        case PANGO_STYLE_OBLIQUE:
+          g_string_append (s, "font-style: oblique; ");
+          break;
+        case PANGO_STYLE_ITALIC:
+          g_string_append (s, "font-style: italic; ");
+          break;
+        default:
+          break;
+        }
+    }
+  if (set & PANGO_FONT_MASK_VARIANT)
+    {
+      switch (pango_font_description_get_variant (desc))
+        {
+        case PANGO_VARIANT_NORMAL:
+          g_string_append (s, "font-variant: normal; ");
+          break;
+        case PANGO_VARIANT_SMALL_CAPS:
+          g_string_append (s, "font-variant: small-caps; ");
+          break;
+        default:
+          break;
+        }
+    }
+  if (set & PANGO_FONT_MASK_WEIGHT)
+    {
+      switch (pango_font_description_get_weight (desc))
+        {
+        case PANGO_WEIGHT_THIN:
+          g_string_append (s, "font-weight: 100; ");
+          break;
+        case PANGO_WEIGHT_ULTRALIGHT:
+          g_string_append (s, "font-weight: 200; ");
+          break;
+        case PANGO_WEIGHT_LIGHT:
+        case PANGO_WEIGHT_SEMILIGHT:
+          g_string_append (s, "font-weight: 300; ");
+          break;
+        case PANGO_WEIGHT_BOOK:
+        case PANGO_WEIGHT_NORMAL:
+          g_string_append (s, "font-weight: 400; ");
+          break;
+        case PANGO_WEIGHT_MEDIUM:
+          g_string_append (s, "font-weight: 500; ");
+          break;
+        case PANGO_WEIGHT_SEMIBOLD:
+          g_string_append (s, "font-weight: 600; ");
+          break;
+        case PANGO_WEIGHT_BOLD:
+          g_string_append (s, "font-weight: 700; ");
+          break;
+        case PANGO_WEIGHT_ULTRABOLD:
+          g_string_append (s, "font-weight: 800; ");
+          break;
+        case PANGO_WEIGHT_HEAVY:
+        case PANGO_WEIGHT_ULTRAHEAVY:
+          g_string_append (s, "font-weight: 900; ");
+          break;
+        default:
+          break;
+        }
+    }
+  if (set & PANGO_FONT_MASK_STRETCH)
+    {
+      switch (pango_font_description_get_stretch (desc))
+        {
+        case PANGO_STRETCH_ULTRA_CONDENSED:
+          g_string_append (s, "font-stretch: ultra-condensed; ");
+          break;
+        case PANGO_STRETCH_EXTRA_CONDENSED:
+          g_string_append (s, "font-stretch: extra-condensed; ");
+          break;
+        case PANGO_STRETCH_CONDENSED:
+          g_string_append (s, "font-stretch: condensed; ");
+          break;
+        case PANGO_STRETCH_SEMI_CONDENSED:
+          g_string_append (s, "font-stretch: semi-condensed; ");
+          break;
+        case PANGO_STRETCH_NORMAL:
+          g_string_append (s, "font-stretch: normal; ");
+          break;
+        case PANGO_STRETCH_SEMI_EXPANDED:
+          g_string_append (s, "font-stretch: semi-expanded; ");
+          break;
+        case PANGO_STRETCH_EXPANDED:
+          g_string_append (s, "font-stretch: expanded; ");
+          break;
+        case PANGO_STRETCH_EXTRA_EXPANDED:
+          break;
+        case PANGO_STRETCH_ULTRA_EXPANDED:
+          g_string_append (s, "font-stretch: ultra-expanded; ");
+          break;
+        default:
+          break;
+        }
+    }
+  if (set & PANGO_FONT_MASK_SIZE)
+    {
+      g_string_append_printf (s, "font-size: %dpt; ", pango_font_description_get_size (desc) / PANGO_SCALE);
+    }
+
+#if PANGO_VERSION_CHECK (1, 44, 0)
+  if (set & PANGO_FONT_MASK_VARIATIONS)
+    {
+      const char *variations;
+
+      g_string_append (s, "font-variation-settings: ");
+      variations = pango_font_description_get_variations (desc);
+      add_css_variations (s, variations);
+      g_string_append (s, "; ");
+    }
+#endif
+
+  return g_string_free (s, FALSE);
+}
diff --git a/gedit/gedit-pango.h b/gedit/gedit-pango.h
new file mode 100644
index 000000000..8c800d502
--- /dev/null
+++ b/gedit/gedit-pango.h
@@ -0,0 +1,28 @@
+/* gedit-pango.h
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_PANGO_H
+#define GEDIT_PANGO_H
+
+#include <pango/pango.h>
+
+G_BEGIN_DECLS
+
+gchar *gedit_pango_font_description_to_css (const PangoFontDescription *font_desc);
+
+G_END_DECLS
+
+#endif /* GEDIT_PANGO_H */
diff --git a/gedit/gedit-preferences-dialog.c b/gedit/gedit-preferences-dialog.c
index 016baf189..ec3f53a3d 100644
--- a/gedit/gedit-preferences-dialog.c
+++ b/gedit/gedit-preferences-dialog.c
@@ -23,14 +23,22 @@
 
 #include "gedit-preferences-dialog.h"
 
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
 #include <libpeas-gtk/peas-gtk.h>
 
+#include "gedit-utils.h"
 #include "gedit-debug.h"
+#include "gedit-document.h"
 #include "gedit-dirs.h"
 #include "gedit-settings.h"
+#include "gedit-utils.h"
+#include "gedit-file-chooser-dialog.h"
 
 /*
  * gedit-preferences dialog is a singleton since we don't
@@ -83,9 +91,11 @@ struct _GeditPreferencesDialog
        GtkWidget       *schemes_list;
        GtkWidget       *install_scheme_button;
        GtkWidget       *uninstall_scheme_button;
+       GtkWidget       *schemes_scrolled_window;
        GtkWidget       *schemes_toolbar;
-       GtkFileChooserNative *
-                        install_scheme_file_chooser;
+
+       GeditFileChooserDialog *
+                        install_scheme_file_schooser;
 
        /* Tabs */
        GtkWidget       *tabs_width_spinbutton;
@@ -105,6 +115,7 @@ struct _GeditPreferencesDialog
 
        GtkWidget       *display_line_numbers_checkbutton;
        GtkWidget       *display_statusbar_checkbutton;
+       GtkWidget       *display_overview_map_checkbutton;
        GtkWidget       *display_grid_checkbutton;
 
        /* Right margin */
@@ -170,6 +181,7 @@ gedit_preferences_dialog_class_init (GeditPreferencesDialogClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, 
display_line_numbers_checkbutton);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, 
display_statusbar_checkbutton);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, display_grid_checkbutton);
+       gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, 
display_overview_map_checkbutton);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, right_margin_checkbutton);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, 
right_margin_position_grid);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, 
right_margin_position_spinbutton);
@@ -187,6 +199,7 @@ gedit_preferences_dialog_class_init (GeditPreferencesDialogClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, font_button);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, font_grid);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_list);
+       gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_scrolled_window);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, install_scheme_button);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, uninstall_scheme_button);
        gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_toolbar);
@@ -386,6 +399,11 @@ setup_view_page (GeditPreferencesDialog *dlg)
                         dlg->display_statusbar_checkbutton,
                         "active",
                         G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+       g_settings_bind (dlg->editor,
+                        GEDIT_SETTINGS_DISPLAY_OVERVIEW_MAP,
+                        dlg->display_overview_map_checkbutton,
+                        "active",
+                        G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
        g_settings_bind (dlg->editor,
                         GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN,
                         dlg->right_margin_checkbutton,
@@ -434,7 +452,7 @@ setup_font_colors_page_font_section (GeditPreferencesDialog *dlg)
 
        /* Get values */
        settings = _gedit_settings_get_singleton ();
-       system_font = _gedit_settings_get_system_font (settings);
+       system_font = gedit_settings_get_system_font (settings);
 
        label = g_strdup_printf(_("_Use the system fixed width font (%s)"),
                                system_font);
@@ -462,172 +480,255 @@ setup_font_colors_page_font_section (GeditPreferencesDialog *dlg)
 }
 
 static void
-update_style_scheme_buttons_sensisitivity (GeditPreferencesDialog *dlg)
+set_buttons_sensisitivity_according_to_scheme (GeditPreferencesDialog *dlg,
+                                               GtkSourceStyleScheme   *scheme)
 {
-       GtkSourceStyleScheme *selected_style_scheme;
        gboolean editable = FALSE;
 
-       selected_style_scheme = gtk_source_style_scheme_chooser_get_style_scheme 
(GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list));
-
-       if (selected_style_scheme != NULL)
+       if (scheme != NULL)
        {
                const gchar *filename;
 
-               filename = gtk_source_style_scheme_get_filename (selected_style_scheme);
+               filename = gtk_source_style_scheme_get_filename (scheme);
                if (filename != NULL)
                {
                        editable = g_str_has_prefix (filename, gedit_dirs_get_user_styles_dir ());
                }
        }
 
-       gtk_widget_set_sensitive (dlg->uninstall_scheme_button, editable);
+       gtk_widget_set_sensitive (dlg->uninstall_scheme_button,
+                                 editable);
 }
 
 static void
-style_scheme_notify_cb (GtkSourceStyleSchemeChooser *chooser,
-                       GParamSpec                  *pspec,
-                       GeditPreferencesDialog      *dlg)
+style_scheme_changed (GtkSourceStyleSchemeChooser *chooser,
+                      GParamSpec                  *pspec,
+                      GeditPreferencesDialog      *dlg)
 {
-       update_style_scheme_buttons_sensisitivity (dlg);
+       GtkSourceStyleScheme *scheme;
+       const gchar *id;
+
+       scheme = gtk_source_style_scheme_chooser_get_style_scheme (chooser);
+       id = gtk_source_style_scheme_get_id (scheme);
+
+       g_settings_set_string (dlg->editor, GEDIT_SETTINGS_SCHEME, id);
+       set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
 }
 
-static GFile *
-get_user_style_scheme_destination_file (GFile *src_file)
+static GtkSourceStyleScheme *
+get_default_color_scheme (GeditPreferencesDialog *dlg)
 {
-       gchar *basename;
-       const gchar *styles_dir;
-       GFile *dest_file;
+       GtkSourceStyleSchemeManager *manager;
+       GtkSourceStyleScheme *scheme = NULL;
+       gchar *pref_id;
 
-       basename = g_file_get_basename (src_file);
-       g_return_val_if_fail (basename != NULL, NULL);
+       manager = gtk_source_style_scheme_manager_get_default ();
 
-       styles_dir = gedit_dirs_get_user_styles_dir ();
-       dest_file = g_file_new_build_filename (styles_dir, basename, NULL);
+       pref_id = g_settings_get_string (dlg->editor,
+                                        GEDIT_SETTINGS_SCHEME);
 
-       g_free (basename);
-       return dest_file;
+       scheme = gtk_source_style_scheme_manager_get_scheme (manager,
+                                                            pref_id);
+       g_free (pref_id);
+
+       if (scheme == NULL)
+       {
+               /* Fall-back to classic style scheme */
+               scheme = gtk_source_style_scheme_manager_get_scheme (manager,
+                                                                    "classic");
+       }
+
+       return scheme;
 }
 
-/* Returns: whether @src_file has been correctly copied to @dest_file. */
+/*
+ * file_copy:
+ * @name: a pointer to a %NULL-terminated string, that names
+ * the file to be copied, in the GLib file name encoding
+ * @dest_name: a pointer to a %NULL-terminated string, that is the
+ * name for the destination file, in the GLib file name encoding
+ * @error: return location for a #GError, or %NULL
+ *
+ * Copies file @name to @dest_name.
+ *
+ * If the call was successful, it returns %TRUE. If the call was not
+ * successful, it returns %FALSE and sets @error. The error domain
+ * is #G_FILE_ERROR. Possible error
+ * codes are those in the #GFileError enumeration.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ */
 static gboolean
-copy_file (GFile   *src_file,
-          GFile   *dest_file,
-          GError **error)
+file_copy (const gchar  *name,
+          const gchar  *dest_name,
+          GError      **error)
 {
-       if (g_file_equal (src_file, dest_file))
+       gchar *contents;
+       gsize length;
+       gchar *dest_dir;
+
+       /* FIXME - Paolo (Aug. 13, 2007):
+        * Since the style scheme files are relatively small, we can implement
+        * file copy getting all the content of the source file in a buffer and
+        * then write the content to the destination file. In this way we
+        * can use the g_file_get_contents and g_file_set_contents and avoid to
+        * write custom code to copy the file (with sane error management).
+        * If needed we can improve this code later. */
+
+       g_return_val_if_fail (name != NULL, FALSE);
+       g_return_val_if_fail (dest_name != NULL, FALSE);
+       g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+       /* Note: we allow to copy a file to itself since this is not a problem
+        * in our use case */
+
+       /* Ensure the destination directory exists */
+       dest_dir = g_path_get_dirname (dest_name);
+
+       errno = 0;
+       if (g_mkdir_with_parents (dest_dir, 0755) != 0)
        {
+               gint save_errno = errno;
+               gchar *display_filename = g_filename_display_name (dest_dir);
+
+               g_set_error (error,
+                            G_FILE_ERROR,
+                            g_file_error_from_errno (save_errno),
+                            _("Directory “%s” could not be created: g_mkdir_with_parents() failed: %s"),
+                            display_filename,
+                            g_strerror (save_errno));
+
+               g_free (dest_dir);
+               g_free (display_filename);
+
                return FALSE;
        }
 
-       if (!tepl_utils_create_parent_directories (dest_file, NULL, error))
+       g_free (dest_dir);
+
+       if (!g_file_get_contents (name, &contents, &length, error))
+               return FALSE;
+
+       if (!g_file_set_contents (dest_name, contents, length, error))
        {
+               g_free (contents);
                return FALSE;
        }
 
-       return g_file_copy (src_file,
-                           dest_file,
-                           G_FILE_COPY_OVERWRITE | G_FILE_COPY_TARGET_DEFAULT_PERMS,
-                           NULL, /* cancellable */
-                           NULL, NULL, /* progress callback */
-                           error);
+       g_free (contents);
+
+       return TRUE;
 }
 
-/* Get the style scheme ID of @user_style_scheme_file if it has been correctly
- * installed and @user_style_scheme_file is a valid style scheme file.
+/*
+ * install_style_scheme:
+ * @manager: a #GtkSourceStyleSchemeManager
+ * @fname: the file name of the style scheme to be installed
+ *
+ * Install a new user scheme.
+ * This function copies @fname in #GEDIT_STYLES_DIR and ask the style manager to
+ * recompute the list of available style schemes. It then checks if a style
+ * scheme with the right file name exists.
+ *
+ * If the call was succesful, it returns the id of the installed scheme
+ * otherwise %NULL.
+ *
+ * Return value: the id of the installed scheme, %NULL otherwise.
  */
-static const gchar *
-get_style_scheme_id_after_installing_user_style_scheme (GFile *user_style_scheme_file)
+static GtkSourceStyleScheme *
+install_style_scheme (const gchar *fname)
 {
        GtkSourceStyleSchemeManager *manager;
-       const gchar * const *scheme_ids;
-       gint i;
+       gchar *new_file_name = NULL;
+       gchar *dirname;
+       const gchar *styles_dir;
+       GError *error = NULL;
+       gboolean copied = FALSE;
+       const gchar * const *ids;
+
+       g_return_val_if_fail (fname != NULL, NULL);
 
        manager = gtk_source_style_scheme_manager_get_default ();
-       gtk_source_style_scheme_manager_force_rescan (manager);
 
-       scheme_ids = gtk_source_style_scheme_manager_get_scheme_ids (manager);
+       dirname = g_path_get_dirname (fname);
+       styles_dir = gedit_dirs_get_user_styles_dir ();
 
-       for (i = 0; scheme_ids != NULL && scheme_ids[i] != NULL; i++)
+       if (strcmp (dirname, styles_dir) != 0)
        {
-               const gchar *cur_scheme_id = scheme_ids[i];
-               GtkSourceStyleScheme *scheme;
-               const gchar *filename;
-               GFile *scheme_file;
+               gchar *basename;
 
-               scheme = gtk_source_style_scheme_manager_get_scheme (manager, cur_scheme_id);
-               filename = gtk_source_style_scheme_get_filename (scheme);
-               if (filename == NULL)
-               {
-                       continue;
-               }
+               basename = g_path_get_basename (fname);
+               new_file_name = g_build_filename (styles_dir, basename, NULL);
+               g_free (basename);
 
-               scheme_file = g_file_new_for_path (filename);
-               if (g_file_equal (scheme_file, user_style_scheme_file))
+               /* Copy the style scheme file into GEDIT_STYLES_DIR */
+               if (!file_copy (fname, new_file_name, &error))
                {
-                       g_object_unref (scheme_file);
-                       return cur_scheme_id;
+                       g_free (new_file_name);
+                       g_free (dirname);
+
+                       g_message ("Cannot install style scheme:\n%s",
+                                  error->message);
+
+                       g_error_free (error);
+
+                       return NULL;
                }
 
-               g_object_unref (scheme_file);
+               copied = TRUE;
+       }
+       else
+       {
+               new_file_name = g_strdup (fname);
        }
 
-       return NULL;
-}
-
-/* Returns: (nullable): the installed style scheme ID, or %NULL on failure. */
-static const gchar *
-install_style_scheme (GFile   *src_file,
-                     GError **error)
-{
-       GFile *dest_file;
-       gboolean copied;
-       const gchar *installed_style_scheme_id = NULL;
-       GError *my_error = NULL;
+       g_free (dirname);
 
-       g_return_val_if_fail (G_IS_FILE (src_file), NULL);
-       g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+       /* Reload the available style schemes */
+       gtk_source_style_scheme_manager_force_rescan (manager);
 
-       dest_file = get_user_style_scheme_destination_file (src_file);
-       g_return_val_if_fail (dest_file != NULL, NULL);
+       /* Check the new style scheme has been actually installed */
+       ids = gtk_source_style_scheme_manager_get_scheme_ids (manager);
 
-       copied = copy_file (src_file, dest_file, &my_error);
-       if (my_error != NULL)
+       while (*ids != NULL)
        {
-               g_propagate_error (error, my_error);
-               g_object_unref (dest_file);
-               return NULL;
-       }
+               GtkSourceStyleScheme *scheme;
+               const gchar *filename;
 
-       installed_style_scheme_id = get_style_scheme_id_after_installing_user_style_scheme (dest_file);
+               scheme = gtk_source_style_scheme_manager_get_scheme (manager, *ids);
 
-       if (installed_style_scheme_id == NULL && copied)
-       {
-               /* The style scheme has not been correctly installed. */
-               g_file_delete (dest_file, NULL, &my_error);
-               if (my_error != NULL)
-               {
-                       gchar *dest_file_parse_name = g_file_get_parse_name (dest_file);
+               filename = gtk_source_style_scheme_get_filename (scheme);
 
-                       g_warning ("Failed to delete the file “%s”: %s",
-                                  dest_file_parse_name,
-                                  my_error->message);
+               if (filename && (strcmp (filename, new_file_name) == 0))
+               {
+                       /* The style scheme has been correctly installed */
+                       g_free (new_file_name);
 
-                       g_free (dest_file_parse_name);
-                       g_clear_error (&my_error);
+                       return scheme;
                }
+               ++ids;
        }
 
-       g_object_unref (dest_file);
-       return installed_style_scheme_id;
+       /* The style scheme has not been correctly installed */
+       if (copied)
+               g_unlink (new_file_name);
+
+       g_free (new_file_name);
+
+       return NULL;
 }
 
-/*
+/**
  * uninstall_style_scheme:
+ * @manager: a #GtkSourceStyleSchemeManager
  * @scheme: a #GtkSourceStyleScheme
  *
  * Uninstall a user scheme.
  *
- * Returns: %TRUE on success, %FALSE otherwise.
+ * If the call was succesful, it returns %TRUE
+ * otherwise %FALSE.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
  */
 static gboolean
 uninstall_style_scheme (GtkSourceStyleScheme *scheme)
@@ -653,94 +754,92 @@ uninstall_style_scheme (GtkSourceStyleScheme *scheme)
 }
 
 static void
-add_scheme_chooser_response_cb (GtkFileChooserNative   *chooser,
-                               gint                    response_id,
-                               GeditPreferencesDialog *dialog)
+add_scheme_chooser_response_cb (GeditFileChooserDialog *chooser,
+                               gint                    res_id,
+                               GeditPreferencesDialog *dlg)
 {
        GFile *file;
-       const gchar *scheme_id;
-       GeditSettings *settings;
-       GSettings *editor_settings;
-       GError *error = NULL;
+       gchar *filename;
+       GtkSourceStyleScheme *scheme;
 
-       if (response_id != GTK_RESPONSE_ACCEPT)
+       if (res_id != GTK_RESPONSE_ACCEPT)
        {
+               gedit_file_chooser_dialog_hide (chooser);
                return;
        }
 
-       file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
+       file = gedit_file_chooser_dialog_get_file (chooser);
+
        if (file == NULL)
        {
                return;
        }
 
-       scheme_id = install_style_scheme (file, &error);
+       filename = g_file_get_path (file);
        g_object_unref (file);
 
-       if (scheme_id == NULL)
+       if (filename == NULL)
        {
-               if (error != NULL)
-               {
-                       tepl_utils_show_warning_dialog (GTK_WINDOW (dialog),
-                                                       _("The selected color scheme cannot be installed: 
%s"),
-                                                       error->message);
-               }
-               else
-               {
-                       tepl_utils_show_warning_dialog (GTK_WINDOW (dialog),
-                                                       _("The selected color scheme cannot be installed."));
-               }
+               return;
+       }
+
+       gedit_file_chooser_dialog_hide (chooser);
+
+       scheme = install_style_scheme (filename);
+       g_free (filename);
+
+       if (scheme == NULL)
+       {
+               gedit_warning (GTK_WINDOW (dlg),
+                              _("The selected color scheme cannot be installed."));
 
-               g_clear_error (&error);
                return;
        }
 
-       settings = _gedit_settings_get_singleton ();
-       editor_settings = _gedit_settings_peek_editor_settings (settings);
-       g_settings_set_string (editor_settings, GEDIT_SETTINGS_SCHEME, scheme_id);
+       g_settings_set_string (dlg->editor, GEDIT_SETTINGS_SCHEME,
+                              gtk_source_style_scheme_get_id (scheme));
+
+       set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
 }
 
 static void
 install_scheme_clicked (GtkButton              *button,
-                       GeditPreferencesDialog *dialog)
+                       GeditPreferencesDialog *dlg)
 {
-       GtkFileChooserNative *chooser;
-       GtkFileFilter *scheme_filter;
-       GtkFileFilter *all_filter;
+       GeditFileChooserDialog *chooser;
 
-       if (dialog->install_scheme_file_chooser != NULL)
+       if (dlg->install_scheme_file_schooser != NULL)
        {
-               gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog->install_scheme_file_chooser));
+               gedit_file_chooser_dialog_show (dlg->install_scheme_file_schooser);
                return;
        }
 
-       chooser = gtk_file_chooser_native_new (_("Add Color Scheme"),
-                                              GTK_WINDOW (dialog),
-                                              GTK_FILE_CHOOSER_ACTION_OPEN,
-                                              _("_Add Scheme"),
-                                              _("_Cancel"));
+       chooser = gedit_file_chooser_dialog_create (_("Add Scheme"),
+                                                   GTK_WINDOW (dlg),
+                                                   GEDIT_FILE_CHOOSER_FLAG_OPEN,
+                                                   _("_Cancel"),
+                                                   _("A_dd Scheme"));
 
        /* Filters */
-       scheme_filter = gtk_file_filter_new ();
-       gtk_file_filter_set_name (scheme_filter, _("Color Scheme Files"));
-       gtk_file_filter_add_pattern (scheme_filter, "*.xml");
-       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), scheme_filter);
-
-       all_filter = gtk_file_filter_new ();
-       gtk_file_filter_set_name (all_filter, _("All Files"));
-       gtk_file_filter_add_pattern (all_filter, "*");
-       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), all_filter);
+       gedit_file_chooser_dialog_add_pattern_filter (chooser,
+                                                     _("Color Scheme Files"),
+                                                     "*.xml");
 
-       gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), scheme_filter);
+       gedit_file_chooser_dialog_add_pattern_filter (chooser,
+                                                     _("All Files"),
+                                                     "*");
 
        g_signal_connect (chooser,
                          "response",
                          G_CALLBACK (add_scheme_chooser_response_cb),
-                         dialog);
+                         dlg);
 
-       g_set_weak_pointer (&dialog->install_scheme_file_chooser, chooser);
+       dlg->install_scheme_file_schooser = chooser;
 
-       gtk_native_dialog_show (GTK_NATIVE_DIALOG (chooser));
+       g_object_add_weak_pointer (G_OBJECT (chooser),
+                                  (gpointer) &dlg->install_scheme_file_schooser);
+
+       gedit_file_chooser_dialog_show (chooser);
 }
 
 static void
@@ -748,33 +847,14 @@ uninstall_scheme_clicked (GtkButton              *button,
                          GeditPreferencesDialog *dlg)
 {
        GtkSourceStyleScheme *scheme;
-       GtkSourceStyleScheme *new_selected_scheme;
 
        scheme = gtk_source_style_scheme_chooser_get_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER 
(dlg->schemes_list));
 
-       if (scheme == NULL)
-       {
-               return;
-       }
-
        if (!uninstall_style_scheme (scheme))
        {
-               tepl_utils_show_warning_dialog (GTK_WINDOW (dlg),
-                                               _("Could not remove color scheme “%s”."),
-                                               gtk_source_style_scheme_get_name (scheme));
-               return;
-       }
-
-       new_selected_scheme = gtk_source_style_scheme_chooser_get_style_scheme 
(GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list));
-       if (new_selected_scheme == NULL)
-       {
-               GeditSettings *settings;
-               GSettings *editor_settings;
-
-               settings = _gedit_settings_get_singleton ();
-               editor_settings = _gedit_settings_peek_editor_settings (settings);
-
-               g_settings_reset (editor_settings, GEDIT_SETTINGS_SCHEME);
+               gedit_warning (GTK_WINDOW (dlg),
+                              _("Could not remove color scheme “%s”."),
+                              gtk_source_style_scheme_get_name (scheme));
        }
 }
 
@@ -782,13 +862,14 @@ static void
 setup_font_colors_page_style_scheme_section (GeditPreferencesDialog *dlg)
 {
        GtkStyleContext *context;
-       GeditSettings *settings;
-       GSettings *editor_settings;
+       GtkSourceStyleScheme *scheme;
 
        gedit_debug (DEBUG_PREFS);
 
-       /* junction between the schemes list and the toolbar */
-       context = gtk_widget_get_style_context (dlg->schemes_list);
+       scheme = get_default_color_scheme (dlg);
+
+       /* junction between the scrolled window and the toolbar */
+       context = gtk_widget_get_style_context (dlg->schemes_scrolled_window);
        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
        context = gtk_widget_get_style_context (dlg->schemes_toolbar);
        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
@@ -796,7 +877,7 @@ setup_font_colors_page_style_scheme_section (GeditPreferencesDialog *dlg)
        /* Connect signals */
        g_signal_connect (dlg->schemes_list,
                          "notify::style-scheme",
-                         G_CALLBACK (style_scheme_notify_cb),
+                         G_CALLBACK (style_scheme_changed),
                          dlg);
        g_signal_connect (dlg->install_scheme_button,
                          "clicked",
@@ -807,13 +888,11 @@ setup_font_colors_page_style_scheme_section (GeditPreferencesDialog *dlg)
                          G_CALLBACK (uninstall_scheme_clicked),
                          dlg);
 
-       settings = _gedit_settings_get_singleton ();
-       editor_settings = _gedit_settings_peek_editor_settings (settings);
-       g_settings_bind (editor_settings, GEDIT_SETTINGS_SCHEME,
-                        dlg->schemes_list, "tepl-style-scheme-id",
-                        G_SETTINGS_BIND_DEFAULT);
+       gtk_source_style_scheme_chooser_set_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list),
+                                                         scheme);
 
-       update_style_scheme_buttons_sensisitivity (dlg);
+       /* Set initial widget sensitivity */
+       set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
 }
 
 static void
diff --git a/gedit/gedit-print-job.c b/gedit/gedit-print-job.c
index 6083669f9..e6c1dcdcb 100644
--- a/gedit/gedit-print-job.c
+++ b/gedit/gedit-print-job.c
@@ -23,7 +23,7 @@
 #include "gedit-print-job.h"
 
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
 
 #include "gedit-debug.h"
 #include "gedit-document-private.h"
@@ -535,7 +535,7 @@ create_compositor (GeditPrintJob *job)
                gchar *left;
 
                doc_name = _gedit_document_get_uri_for_display (GEDIT_DOCUMENT (buf));
-               name_to_display = tepl_utils_str_middle_truncate (doc_name, 60);
+               name_to_display = gedit_utils_str_middle_truncate (doc_name, 60);
 
                left = g_strdup_printf (_("File: %s"), name_to_display);
 
diff --git a/gedit/gedit-progress-info-bar.c b/gedit/gedit-progress-info-bar.c
new file mode 100644
index 000000000..d547189fb
--- /dev/null
+++ b/gedit/gedit-progress-info-bar.c
@@ -0,0 +1,177 @@
+/*
+ * gedit-progress-info-bar.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 "gedit-progress-info-bar.h"
+#include <glib/gi18n.h>
+
+enum {
+       PROP_0,
+       PROP_HAS_CANCEL_BUTTON,
+       LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+struct _GeditProgressInfoBar
+{
+       GtkInfoBar parent_instance;
+
+       GtkWidget *image;
+       GtkWidget *label;
+       GtkWidget *progress;
+};
+
+G_DEFINE_TYPE (GeditProgressInfoBar, gedit_progress_info_bar, GTK_TYPE_INFO_BAR)
+
+static void
+gedit_progress_info_bar_set_has_cancel_button (GeditProgressInfoBar *bar,
+                                              gboolean              has_button)
+{
+       if (has_button)
+       {
+               gtk_info_bar_add_button (GTK_INFO_BAR (bar), _("_Cancel"), GTK_RESPONSE_CANCEL);
+       }
+}
+
+static void
+gedit_progress_info_bar_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+       GeditProgressInfoBar *bar;
+
+       bar = GEDIT_PROGRESS_INFO_BAR (object);
+
+       switch (prop_id)
+       {
+               case PROP_HAS_CANCEL_BUTTON:
+                       gedit_progress_info_bar_set_has_cancel_button (bar,
+                                                                      g_value_get_boolean (value));
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
+gedit_progress_info_bar_class_init (GeditProgressInfoBarClass *klass)
+{
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       gobject_class->set_property = gedit_progress_info_bar_set_property;
+
+       properties[PROP_HAS_CANCEL_BUTTON] =
+                g_param_spec_boolean ("has-cancel-button",
+                                      "Has Cancel Button",
+                                      "If the message bar has a cancel button",
+                                      TRUE,
+                                      G_PARAM_WRITABLE |
+                                      G_PARAM_CONSTRUCT_ONLY |
+                                      G_PARAM_STATIC_STRINGS);
+
+       g_object_class_install_properties (gobject_class, LAST_PROP, properties);
+
+       /* Bind class to template */
+       gtk_widget_class_set_template_from_resource (widget_class,
+                                                    "/org/gnome/gedit/ui/gedit-progress-info-bar.ui");
+       gtk_widget_class_bind_template_child (widget_class, GeditProgressInfoBar, image);
+       gtk_widget_class_bind_template_child (widget_class, GeditProgressInfoBar, label);
+       gtk_widget_class_bind_template_child (widget_class, GeditProgressInfoBar, progress);
+}
+
+static void
+gedit_progress_info_bar_init (GeditProgressInfoBar *bar)
+{
+       gtk_widget_init_template (GTK_WIDGET (bar));
+}
+
+GtkWidget *
+gedit_progress_info_bar_new (const gchar *icon_name,
+                            const gchar *markup,
+                            gboolean     has_cancel)
+{
+       GeditProgressInfoBar *bar;
+
+       g_return_val_if_fail (icon_name != NULL, NULL);
+       g_return_val_if_fail (markup != NULL, NULL);
+
+       bar = GEDIT_PROGRESS_INFO_BAR (g_object_new (GEDIT_TYPE_PROGRESS_INFO_BAR,
+                                                    "has-cancel-button", has_cancel,
+                                                    NULL));
+
+       gedit_progress_info_bar_set_icon_name (bar, icon_name);
+       gedit_progress_info_bar_set_markup (bar, markup);
+
+       return GTK_WIDGET (bar);
+}
+
+void
+gedit_progress_info_bar_set_icon_name (GeditProgressInfoBar *bar,
+                                      const gchar          *icon_name)
+{
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+       g_return_if_fail (icon_name != NULL);
+
+       gtk_image_set_from_icon_name (GTK_IMAGE (bar->image),
+                                     icon_name,
+                                     GTK_ICON_SIZE_SMALL_TOOLBAR);
+}
+
+void
+gedit_progress_info_bar_set_markup (GeditProgressInfoBar *bar,
+                                   const gchar          *markup)
+{
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+       g_return_if_fail (markup != NULL);
+
+       gtk_label_set_markup (GTK_LABEL (bar->label), markup);
+}
+
+void
+gedit_progress_info_bar_set_text (GeditProgressInfoBar *bar,
+                                 const gchar          *text)
+{
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+       g_return_if_fail (text != NULL);
+
+       gtk_label_set_text (GTK_LABEL (bar->label), text);
+}
+
+void
+gedit_progress_info_bar_set_fraction (GeditProgressInfoBar *bar,
+                                     gdouble               fraction)
+{
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+
+       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (bar->progress), fraction);
+}
+
+void
+gedit_progress_info_bar_pulse (GeditProgressInfoBar *bar)
+{
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (bar));
+
+       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (bar->progress));
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-progress-info-bar.h b/gedit/gedit-progress-info-bar.h
new file mode 100644
index 000000000..0d820d8e4
--- /dev/null
+++ b/gedit/gedit-progress-info-bar.h
@@ -0,0 +1,53 @@
+/*
+ * gedit-progress-info-bar.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GEDIT_PROGRESS_INFO_BAR_H
+#define GEDIT_PROGRESS_INFO_BAR_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_PROGRESS_INFO_BAR (gedit_progress_info_bar_get_type ())
+G_DECLARE_FINAL_TYPE (GeditProgressInfoBar, gedit_progress_info_bar, GEDIT, PROGRESS_INFO_BAR, GtkInfoBar)
+
+GtkWidget      *gedit_progress_info_bar_new                    (const gchar          *icon_name,
+                                                                const gchar          *markup,
+                                                                gboolean              has_cancel);
+
+void            gedit_progress_info_bar_set_icon_name          (GeditProgressInfoBar *bar,
+                                                                const gchar          *icon_name);
+
+void            gedit_progress_info_bar_set_markup             (GeditProgressInfoBar *bar,
+                                                                const gchar          *markup);
+
+void            gedit_progress_info_bar_set_text               (GeditProgressInfoBar *bar,
+                                                                const gchar          *text);
+
+void            gedit_progress_info_bar_set_fraction           (GeditProgressInfoBar *bar,
+                                                                gdouble               fraction);
+
+void            gedit_progress_info_bar_pulse                  (GeditProgressInfoBar *bar);
+
+G_END_DECLS
+
+#endif  /* GEDIT_PROGRESS_INFO_BAR_H  */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-recent.c b/gedit/gedit-recent.c
index b1535d057..2a0063306 100644
--- a/gedit/gedit-recent.c
+++ b/gedit/gedit-recent.c
@@ -24,7 +24,7 @@
 void
 gedit_recent_add_document (GeditDocument *document)
 {
-       TeplFile *file;
+       GtkSourceFile *file;
        GFile *location;
        GtkRecentManager *recent_manager;
        GtkRecentData recent_data;
@@ -33,8 +33,8 @@ gedit_recent_add_document (GeditDocument *document)
 
        g_return_if_fail (GEDIT_IS_DOCUMENT (document));
 
-       file = tepl_buffer_get_file (TEPL_BUFFER (document));
-       location = tepl_file_get_location (file);
+       file = gedit_document_get_file (document);
+       location = gtk_source_file_get_location (file);
 
        if (location == NULL)
        {
@@ -89,4 +89,229 @@ gedit_recent_remove_if_local (GFile *location)
        }
 }
 
+static gint
+sort_recent_items_mru (GtkRecentInfo *a,
+                       GtkRecentInfo *b,
+                       gpointer       unused)
+{
+       g_assert (a != NULL && b != NULL);
+       return gtk_recent_info_get_modified (b) - gtk_recent_info_get_modified (a);
+}
+
+static void
+populate_filter_info (GtkRecentInfo        *info,
+                      GtkRecentFilterInfo  *filter_info,
+                      GtkRecentFilterFlags  needed)
+{
+       filter_info->uri = gtk_recent_info_get_uri (info);
+       filter_info->mime_type = gtk_recent_info_get_mime_type (info);
+
+       filter_info->contains = GTK_RECENT_FILTER_URI | GTK_RECENT_FILTER_MIME_TYPE;
+
+       if (needed & GTK_RECENT_FILTER_DISPLAY_NAME)
+       {
+               filter_info->display_name = gtk_recent_info_get_display_name (info);
+               filter_info->contains |= GTK_RECENT_FILTER_DISPLAY_NAME;
+       }
+       else
+       {
+               filter_info->uri = NULL;
+       }
+
+       if (needed & GTK_RECENT_FILTER_APPLICATION)
+       {
+               filter_info->applications = (const gchar **) gtk_recent_info_get_applications (info, NULL);
+               filter_info->contains |= GTK_RECENT_FILTER_APPLICATION;
+       }
+       else
+       {
+               filter_info->applications = NULL;
+       }
+
+       if (needed & GTK_RECENT_FILTER_GROUP)
+       {
+               filter_info->groups = (const gchar **) gtk_recent_info_get_groups (info, NULL);
+               filter_info->contains |= GTK_RECENT_FILTER_GROUP;
+       }
+       else
+       {
+               filter_info->groups = NULL;
+       }
+
+       if (needed & GTK_RECENT_FILTER_AGE)
+       {
+               filter_info->age = gtk_recent_info_get_age (info);
+               filter_info->contains |= GTK_RECENT_FILTER_AGE;
+       }
+       else
+       {
+               filter_info->age = -1;
+       }
+}
+
+/* The GeditRecentConfiguration struct is allocated and owned by the caller */
+void
+gedit_recent_configuration_init_default (GeditRecentConfiguration *config)
+{
+       config->manager = gtk_recent_manager_get_default ();
+
+       if (config->filter != NULL)
+       {
+               g_object_unref (config->filter);
+       }
+
+       config->filter = gtk_recent_filter_new ();
+       gtk_recent_filter_add_application (config->filter, g_get_application_name ());
+       gtk_recent_filter_add_mime_type (config->filter, "text/plain");
+       g_object_ref_sink (config->filter);
+
+       config->limit = 5;
+       config->show_not_found = TRUE;
+       config->show_private = FALSE;
+       config->local_only = FALSE;
+
+       config->substring_filter = NULL;
+}
+
+/* The GeditRecentConfiguration struct is owned and destroyed by the caller */
+void
+gedit_recent_configuration_destroy (GeditRecentConfiguration *config)
+{
+       g_clear_object (&config->filter);
+       config->manager = NULL;
+
+       g_clear_pointer (&config->substring_filter, (GDestroyNotify)g_free);
+}
+
+GList *
+gedit_recent_get_items (GeditRecentConfiguration *config)
+{
+       GtkRecentFilterFlags needed;
+       GList *items;
+       GList *retitems = NULL;
+       gint length;
+       char *substring_filter = NULL;
+
+       if (config->limit == 0)
+       {
+               return NULL;
+       }
+
+       items = gtk_recent_manager_get_items (config->manager);
+
+       if (!items)
+       {
+               return NULL;
+       }
+
+       needed = gtk_recent_filter_get_needed (config->filter);
+       if (config->substring_filter && *config->substring_filter != '\0')
+       {
+               gchar *filter_normalized;
+
+               filter_normalized = g_utf8_normalize (config->substring_filter, -1, G_NORMALIZE_ALL);
+               substring_filter = g_utf8_casefold (filter_normalized, -1);
+               g_free (filter_normalized);
+       }
+
+       while (items)
+       {
+               GtkRecentInfo *info;
+               GtkRecentFilterInfo filter_info;
+               gboolean is_filtered;
+
+               info = items->data;
+               is_filtered = FALSE;
+
+               if (config->local_only && !gtk_recent_info_is_local (info))
+               {
+                       is_filtered = TRUE;
+               }
+               else if (!config->show_private && gtk_recent_info_get_private_hint (info))
+               {
+                       is_filtered = TRUE;
+               }
+               else if (!config->show_not_found && !gtk_recent_info_exists (info))
+               {
+                       is_filtered = TRUE;
+               }
+               else
+               {
+                       if (substring_filter)
+                       {
+                               gchar *uri_normalized;
+                               gchar *uri_casefolded;
+
+                               uri_normalized = g_utf8_normalize (gtk_recent_info_get_uri_display (info), 
-1, G_NORMALIZE_ALL);
+                               uri_casefolded = g_utf8_casefold (uri_normalized, -1);
+                               g_free (uri_normalized);
+
+                               if (strstr (uri_casefolded, substring_filter) == NULL)
+                               {
+                                       is_filtered = TRUE;
+                               }
+
+                               g_free (uri_casefolded);
+                       }
+
+                       if (!is_filtered)
+                       {
+                               populate_filter_info (info, &filter_info, needed);
+                               is_filtered = !gtk_recent_filter_filter (config->filter, &filter_info);
+
+                               /* these we own */
+                               if (filter_info.applications)
+                               {
+                                       g_strfreev ((gchar **) filter_info.applications);
+                               }
+
+                               if (filter_info.groups)
+                               {
+                                       g_strfreev ((gchar **) filter_info.groups);
+                               }
+                       }
+               }
+
+               if (!is_filtered)
+               {
+                       retitems = g_list_prepend (retitems, info);
+               }
+               else
+               {
+                       gtk_recent_info_unref (info);
+               }
+
+               items = g_list_delete_link (items, items);
+       }
+
+       g_free (substring_filter);
+
+       if (!retitems)
+       {
+               return NULL;
+       }
+
+       retitems = g_list_sort_with_data (retitems, (GCompareDataFunc) sort_recent_items_mru, NULL);
+       length = g_list_length (retitems);
+
+       if ((config->limit != -1) && (length > config->limit))
+       {
+               GList *clamp, *l;
+
+               clamp = g_list_nth (retitems, config->limit - 1);
+
+               if (!clamp)
+               {
+                       return retitems;
+               }
+
+               l = clamp->next;
+               clamp->next = NULL;
+
+               g_list_free_full (l, (GDestroyNotify) gtk_recent_info_unref);
+       }
+
+       return retitems;
+}
+
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-recent.h b/gedit/gedit-recent.h
index 068d89c72..5c72837ed 100644
--- a/gedit/gedit-recent.h
+++ b/gedit/gedit-recent.h
@@ -27,12 +27,29 @@
 
 G_BEGIN_DECLS
 
-void   gedit_recent_add_document       (GeditDocument *document);
+typedef struct
+{
+       GtkRecentManager *manager;
+       GtkRecentFilter *filter;
 
-void   gedit_recent_remove_if_local    (GFile *location);
+       gint limit;
+       gchar *substring_filter;
+
+       guint show_private : 1;
+       guint show_not_found : 1;
+       guint local_only : 1;
+} GeditRecentConfiguration;
+
+void            gedit_recent_add_document               (GeditDocument            *document);
+
+void            gedit_recent_remove_if_local            (GFile                    *location);
+
+void            gedit_recent_configuration_init_default (GeditRecentConfiguration *config);
+void            gedit_recent_configuration_destroy      (GeditRecentConfiguration *config);
+GList          *gedit_recent_get_items                  (GeditRecentConfiguration *config);
 
 G_END_DECLS
 
-#endif /* GEDIT_RECENT_H */
+#endif  /* GEDIT_RECENT_H  */
 
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-settings.c b/gedit/gedit-settings.c
index a762a1dc2..6fa300f29 100644
--- a/gedit/gedit-settings.c
+++ b/gedit/gedit-settings.c
@@ -37,13 +37,7 @@ struct _GeditSettings
        GSettings *settings_file_chooser_state;
 };
 
-enum
-{
-       SIGNAL_FONTS_CHANGED,
-       N_SIGNALS
-};
-
-static guint signals[N_SIGNALS];
+/* GeditSettings is a singleton. */
 static GeditSettings *singleton = NULL;
 
 G_DEFINE_TYPE (GeditSettings, gedit_settings, G_TYPE_OBJECT)
@@ -81,46 +75,92 @@ gedit_settings_class_init (GeditSettingsClass *klass)
 
        object_class->dispose = gedit_settings_dispose;
        object_class->finalize = gedit_settings_finalize;
+}
 
-       /* This signal is emitted when the return value of
-        * _gedit_settings_get_selected_font() has potentially changed.
-        */
-       signals[SIGNAL_FONTS_CHANGED] =
-               g_signal_new ("fonts-changed",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_FIRST,
-                             0,
-                             NULL, NULL, NULL,
-                             G_TYPE_NONE, 0);
+static void
+set_font (GeditSettings *self,
+         const gchar   *font)
+{
+       guint tabs_size;
+       GList *views;
+       GList *l;
+
+       tabs_size = g_settings_get_uint (self->settings_editor, GEDIT_SETTINGS_TABS_SIZE);
+
+       views = gedit_app_get_views (GEDIT_APP (g_application_get_default ()));
+
+       for (l = views; l != NULL; l = l->next)
+       {
+               /* Note: we use def=FALSE to avoid GeditView to query dconf. */
+               gedit_view_set_font (GEDIT_VIEW (l->data), FALSE, font);
+
+               /* FIXME: setting the tab width seems unrelated to set_font(). */
+               gtk_source_view_set_tab_width (GTK_SOURCE_VIEW (l->data), tabs_size);
+       }
+
+       g_list_free (views);
 }
 
 static void
-system_font_changed_cb (GSettings     *settings,
+on_system_font_changed (GSettings     *settings,
                        const gchar   *key,
                        GeditSettings *self)
 {
-       if (g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT))
+
+       gboolean use_default_font;
+
+       use_default_font = g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT);
+
+       if (use_default_font)
        {
-               g_signal_emit (self, signals[SIGNAL_FONTS_CHANGED], 0);
+               gchar *font;
+
+               font = g_settings_get_string (settings, key);
+               set_font (self, font);
+               g_free (font);
        }
 }
 
 static void
-use_default_font_changed_cb (GSettings     *settings,
+on_use_default_font_changed (GSettings     *settings,
                             const gchar   *key,
                             GeditSettings *self)
 {
-       g_signal_emit (self, signals[SIGNAL_FONTS_CHANGED], 0);
+       gboolean use_default_font;
+       gchar *font;
+
+       use_default_font = g_settings_get_boolean (settings, key);
+
+       if (use_default_font)
+       {
+               font = g_settings_get_string (self->settings_interface, GEDIT_SETTINGS_SYSTEM_FONT);
+       }
+       else
+       {
+               font = g_settings_get_string (self->settings_editor, GEDIT_SETTINGS_EDITOR_FONT);
+       }
+
+       set_font (self, font);
+
+       g_free (font);
 }
 
 static void
-editor_font_changed_cb (GSettings     *settings,
+on_editor_font_changed (GSettings     *settings,
                        const gchar   *key,
                        GeditSettings *self)
 {
-       if (!g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT))
+       gboolean use_default_font;
+
+       use_default_font = g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT);
+
+       if (!use_default_font)
        {
-               g_signal_emit (self, signals[SIGNAL_FONTS_CHANGED], 0);
+               gchar *font;
+
+               font = g_settings_get_string (settings, key);
+               set_font (self, font);
+               g_free (font);
        }
 }
 
@@ -207,47 +247,43 @@ on_syntax_highlighting_changed (GSettings     *settings,
 static void
 gedit_settings_init (GeditSettings *self)
 {
-       self->settings_interface = g_settings_new ("org.gnome.desktop.interface");
-
        self->settings_editor = g_settings_new ("org.gnome.gedit.preferences.editor");
        self->settings_ui = g_settings_new ("org.gnome.gedit.preferences.ui");
        self->settings_file_chooser_state = g_settings_new ("org.gnome.gedit.state.file-chooser");
 
-       g_signal_connect_object (self->settings_interface,
-                                "changed::" GEDIT_SETTINGS_SYSTEM_FONT,
-                                G_CALLBACK (system_font_changed_cb),
-                                self,
-                                0);
-
-       g_signal_connect_object (self->settings_editor,
-                                "changed::" GEDIT_SETTINGS_USE_DEFAULT_FONT,
-                                G_CALLBACK (use_default_font_changed_cb),
-                                self,
-                                0);
-
-       g_signal_connect_object (self->settings_editor,
-                                "changed::" GEDIT_SETTINGS_EDITOR_FONT,
-                                G_CALLBACK (editor_font_changed_cb),
-                                self,
-                                0);
-
-       g_signal_connect_object (self->settings_editor,
-                                "changed::auto-save",
-                                G_CALLBACK (on_auto_save_changed),
-                                self,
-                                0);
-
-       g_signal_connect_object (self->settings_editor,
-                                "changed::auto-save-interval",
-                                G_CALLBACK (on_auto_save_interval_changed),
-                                self,
-                                0);
-
-       g_signal_connect_object (self->settings_editor,
-                                "changed::syntax-highlighting",
-                                G_CALLBACK (on_syntax_highlighting_changed),
-                                self,
-                                0);
+       self->settings_interface = g_settings_new ("org.gnome.desktop.interface");
+
+       g_signal_connect (self->settings_interface,
+                         "changed::monospace-font-name",
+                         G_CALLBACK (on_system_font_changed),
+                         self);
+
+       /* editor changes */
+
+       g_signal_connect (self->settings_editor,
+                         "changed::use-default-font",
+                         G_CALLBACK (on_use_default_font_changed),
+                         self);
+
+       g_signal_connect (self->settings_editor,
+                         "changed::editor-font",
+                         G_CALLBACK (on_editor_font_changed),
+                         self);
+
+       g_signal_connect (self->settings_editor,
+                         "changed::auto-save",
+                         G_CALLBACK (on_auto_save_changed),
+                         self);
+
+       g_signal_connect (self->settings_editor,
+                         "changed::auto-save-interval",
+                         G_CALLBACK (on_auto_save_interval_changed),
+                         self);
+
+       g_signal_connect (self->settings_editor,
+                         "changed::syntax-highlighting",
+                         G_CALLBACK (on_syntax_highlighting_changed),
+                         self);
 }
 
 GeditSettings *
@@ -292,24 +328,11 @@ _gedit_settings_peek_file_chooser_state_settings (GeditSettings *self)
 }
 
 gchar *
-_gedit_settings_get_system_font (GeditSettings *self)
+gedit_settings_get_system_font (GeditSettings *self)
 {
        g_return_val_if_fail (GEDIT_IS_SETTINGS (self), NULL);
 
-       return g_settings_get_string (self->settings_interface, GEDIT_SETTINGS_SYSTEM_FONT);
-}
-
-gchar *
-_gedit_settings_get_selected_font (GeditSettings *self)
-{
-       g_return_val_if_fail (GEDIT_IS_SETTINGS (self), NULL);
-
-       if (g_settings_get_boolean (self->settings_editor, GEDIT_SETTINGS_USE_DEFAULT_FONT))
-       {
-               return _gedit_settings_get_system_font (self);
-       }
-
-       return g_settings_get_string (self->settings_editor, GEDIT_SETTINGS_EDITOR_FONT);
+       return g_settings_get_string (self->settings_interface, "monospace-font-name");
 }
 
 static gboolean
diff --git a/gedit/gedit-settings.h b/gedit/gedit-settings.h
index a7993d5d1..a2fe9e47b 100644
--- a/gedit/gedit-settings.h
+++ b/gedit/gedit-settings.h
@@ -43,11 +43,7 @@ GSettings *  _gedit_settings_peek_editor_settings                    (GeditSettings *self);
 G_GNUC_INTERNAL
 GSettings *    _gedit_settings_peek_file_chooser_state_settings        (GeditSettings *self);
 
-G_GNUC_INTERNAL
-gchar *                _gedit_settings_get_system_font                         (GeditSettings *self);
-
-G_GNUC_INTERNAL
-gchar *                _gedit_settings_get_selected_font                       (GeditSettings *self);
+gchar *                gedit_settings_get_system_font                          (GeditSettings *self);
 
 GSList *       gedit_settings_get_candidate_encodings                  (gboolean *default_candidates);
 
@@ -73,6 +69,7 @@ GSList *      gedit_settings_get_candidate_encodings                  (gboolean 
*default_candidates)
 #define GEDIT_SETTINGS_RESTORE_CURSOR_POSITION         "restore-cursor-position"
 #define GEDIT_SETTINGS_SYNTAX_HIGHLIGHTING             "syntax-highlighting"
 #define GEDIT_SETTINGS_SEARCH_HIGHLIGHTING             "search-highlighting"
+#define GEDIT_SETTINGS_DISPLAY_OVERVIEW_MAP            "display-overview-map"
 #define GEDIT_SETTINGS_BACKGROUND_PATTERN              "background-pattern"
 #define GEDIT_SETTINGS_STATUSBAR_VISIBLE               "statusbar-visible"
 #define GEDIT_SETTINGS_SIDE_PANEL_VISIBLE              "side-panel-visible"
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index 8bff54690..45e80c828 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -24,7 +24,6 @@
 
 #include <stdlib.h>
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 
 #include "gedit-app.h"
 #include "gedit-app-private.h"
@@ -33,6 +32,7 @@
 #include "gedit-io-error-info-bar.h"
 #include "gedit-print-job.h"
 #include "gedit-print-preview.h"
+#include "gedit-progress-info-bar.h"
 #include "gedit-debug.h"
 #include "gedit-document.h"
 #include "gedit-document-private.h"
@@ -577,9 +577,9 @@ document_location_notify_handler (GtkSourceFile *file,
 }
 
 static void
-document_shortname_notify_handler (TeplFile   *file,
-                                  GParamSpec *pspec,
-                                  GeditTab   *tab)
+document_shortname_notify_handler (GeditDocument *document,
+                                  GParamSpec    *pspec,
+                                  GeditTab      *tab)
 {
        gedit_debug (DEBUG_TAB);
 
@@ -737,7 +737,7 @@ load_cancelled (GtkWidget *bar,
 {
        LoaderData *data = g_task_get_task_data (loading_task);
 
-       g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (data->tab->info_bar));
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (data->tab->info_bar));
 
        g_cancellable_cancel (g_task_get_cancellable (loading_task));
        remove_tab (data->tab);
@@ -768,7 +768,7 @@ static void
 show_loading_info_bar (GTask *loading_task)
 {
        LoaderData *data = g_task_get_task_data (loading_task);
-       TeplProgressInfoBar *bar;
+       GtkWidget *bar;
        GeditDocument *doc;
        gchar *name;
        gchar *dirname = NULL;
@@ -796,7 +796,7 @@ show_loading_info_bar (GTask *loading_task)
        {
                gchar *str;
 
-               str = tepl_utils_str_middle_truncate (name, MAX_MSG_LENGTH);
+               str = gedit_utils_str_middle_truncate (name, MAX_MSG_LENGTH);
                g_free (name);
                name = str;
        }
@@ -815,8 +815,8 @@ show_loading_info_bar (GTask *loading_task)
                         * we have a title long 99 + 20, but I think it's a rare enough
                         * case to be acceptable. It's justa darn title afterall :)
                         */
-                       dirname = tepl_utils_str_middle_truncate (str,
-                                                                 MAX (20, MAX_MSG_LENGTH - len));
+                       dirname = gedit_utils_str_middle_truncate (str,
+                                                                  MAX (20, MAX_MSG_LENGTH - len));
                        g_free (str);
                }
        }
@@ -841,7 +841,7 @@ show_loading_info_bar (GTask *loading_task)
                        msg = g_strdup_printf (_("Reverting %s"), name_markup);
                }
 
-               bar = tepl_progress_info_bar_new ("document-revert", msg, TRUE);
+               bar = gedit_progress_info_bar_new ("document-revert", msg, TRUE);
        }
        else
        {
@@ -861,7 +861,7 @@ show_loading_info_bar (GTask *loading_task)
                        msg = g_strdup_printf (_("Loading %s"), name_markup);
                }
 
-               bar = tepl_progress_info_bar_new ("document-open", msg, TRUE);
+               bar = gedit_progress_info_bar_new ("document-open", msg, TRUE);
        }
 
        g_signal_connect_object (bar,
@@ -870,7 +870,7 @@ show_loading_info_bar (GTask *loading_task)
                                 loading_task,
                                 0);
 
-       set_info_bar (data->tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
+       set_info_bar (data->tab, bar, GTK_RESPONSE_NONE);
 
        g_free (msg);
        g_free (name);
@@ -882,7 +882,7 @@ static void
 show_saving_info_bar (GTask *saving_task)
 {
        GeditTab *tab = g_task_get_source_object (saving_task);
-       TeplProgressInfoBar *bar;
+       GtkWidget *bar;
        GeditDocument *doc;
        gchar *short_name;
        gchar *from;
@@ -910,7 +910,7 @@ show_saving_info_bar (GTask *saving_task)
         */
        if (len > MAX_MSG_LENGTH)
        {
-               from = tepl_utils_str_middle_truncate (short_name, MAX_MSG_LENGTH);
+               from = gedit_utils_str_middle_truncate (short_name, MAX_MSG_LENGTH);
                g_free (short_name);
        }
        else
@@ -924,7 +924,7 @@ show_saving_info_bar (GTask *saving_task)
 
                from = short_name;
                to = g_file_get_parse_name (location);
-               str = tepl_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
+               str = gedit_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
                g_free (to);
 
                to = str;
@@ -946,9 +946,9 @@ show_saving_info_bar (GTask *saving_task)
                msg = g_strdup_printf (_("Saving %s"), from_markup);
        }
 
-       bar = tepl_progress_info_bar_new ("document-save", msg, FALSE);
+       bar = gedit_progress_info_bar_new ("document-save", msg, FALSE);
 
-       set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
+       set_info_bar (tab, bar, GTK_RESPONSE_NONE);
 
        g_free (msg);
        g_free (to);
@@ -961,7 +961,7 @@ info_bar_set_progress (GeditTab *tab,
                       goffset   size,
                       goffset   total_size)
 {
-       TeplProgressInfoBar *progress_info_bar;
+       GeditProgressInfoBar *progress_info_bar;
 
        if (tab->info_bar == NULL)
        {
@@ -970,23 +970,23 @@ info_bar_set_progress (GeditTab *tab,
 
        gedit_debug_message (DEBUG_TAB, "%" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT, size, total_size);
 
-       g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (tab->info_bar));
 
-       progress_info_bar = TEPL_PROGRESS_INFO_BAR (tab->info_bar);
+       progress_info_bar = GEDIT_PROGRESS_INFO_BAR (tab->info_bar);
 
        if (total_size != 0)
        {
                gdouble frac = (gdouble)size / (gdouble)total_size;
 
-               tepl_progress_info_bar_set_fraction (progress_info_bar, frac);
+               gedit_progress_info_bar_set_fraction (progress_info_bar, frac);
        }
        else if (size != 0)
        {
-               tepl_progress_info_bar_pulse (progress_info_bar);
+               gedit_progress_info_bar_pulse (progress_info_bar);
        }
        else
        {
-               tepl_progress_info_bar_set_fraction (progress_info_bar, 0);
+               gedit_progress_info_bar_set_fraction (progress_info_bar, 0);
        }
 }
 
@@ -1045,7 +1045,7 @@ scroll_to_cursor (GeditTab *tab)
        GeditView *view;
 
        view = gedit_tab_get_view (tab);
-       tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+       gedit_view_scroll_to_cursor (view);
 
        tab->idle_scroll = 0;
        return G_SOURCE_REMOVE;
@@ -1129,9 +1129,9 @@ invalid_character_info_bar_response (GtkWidget *info_bar,
 }
 
 static void
-cant_create_backup_error_info_bar_response (GtkWidget *info_bar,
-                                           gint       response_id,
-                                           GTask     *saving_task)
+no_backup_error_info_bar_response (GtkWidget *info_bar,
+                                  gint       response_id,
+                                  GTask     *saving_task)
 {
        if (response_id == GTK_RESPONSE_YES)
        {
@@ -1237,7 +1237,7 @@ externally_modified_notification_info_bar_response (GtkWidget *info_bar,
 static void
 display_externally_modified_notification (GeditTab *tab)
 {
-       TeplInfoBar *info_bar;
+       GtkWidget *info_bar;
        GeditDocument *doc;
        GtkSourceFile *file;
        GFile *location;
@@ -1251,9 +1251,9 @@ display_externally_modified_notification (GeditTab *tab)
        g_return_if_fail (location != NULL);
 
        document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc));
-       info_bar = tepl_io_error_info_bar_externally_modified (location, document_modified);
+       info_bar = gedit_externally_modified_info_bar_new (location, document_modified);
 
-       set_info_bar (tab, GTK_WIDGET (info_bar), GTK_RESPONSE_OK);
+       set_info_bar (tab, info_bar, GTK_RESPONSE_OK);
 
        g_signal_connect (info_bar,
                          "response",
@@ -1318,7 +1318,6 @@ gedit_tab_init (GeditTab *tab)
        GeditDocument *doc;
        GeditView *view;
        GtkSourceFile *file;
-       TeplFile *tepl_file;
 
        tab->state = GEDIT_TAB_STATE_NORMAL;
 
@@ -1349,7 +1348,6 @@ gedit_tab_init (GeditTab *tab)
        g_object_set_data (G_OBJECT (doc), GEDIT_TAB_KEY, tab);
 
        file = gedit_document_get_file (doc);
-       tepl_file = tepl_buffer_get_file (TEPL_BUFFER (doc));
 
        g_signal_connect_object (file,
                                 "notify::location",
@@ -1357,11 +1355,10 @@ gedit_tab_init (GeditTab *tab)
                                 tab,
                                 0);
 
-       g_signal_connect_object (tepl_file,
-                                "notify::short-name",
-                                G_CALLBACK (document_shortname_notify_handler),
-                                tab,
-                                0);
+       g_signal_connect (doc,
+                         "notify::shortname",
+                         G_CALLBACK (document_shortname_notify_handler),
+                         tab);
 
        g_signal_connect (doc,
                          "modified_changed",
@@ -1445,7 +1442,7 @@ _gedit_tab_get_name (GeditTab *tab)
        name = gedit_document_get_short_name_for_display (doc);
 
        /* Truncate the name so it doesn't get insanely wide. */
-       docname = tepl_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
+       docname = gedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
 
        if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
        {
@@ -1478,7 +1475,7 @@ _gedit_tab_get_tooltip (GeditTab *tab)
        uri = _gedit_document_get_uri_for_display (doc);
        g_return_val_if_fail (uri != NULL, NULL);
 
-       ruri =  tepl_utils_replace_home_dir_with_tilde (uri);
+       ruri =  gedit_utils_replace_home_dir_with_tilde (uri);
        g_free (uri);
 
        ruri_markup = g_markup_printf_escaped ("<i>%s</i>", ruri);
@@ -1644,11 +1641,9 @@ goto_line (GTask *loading_task)
        /* Move the cursor at the requested line if any. */
        if (data->line_pos > 0)
        {
-               TeplView *view = TEPL_VIEW (gedit_tab_get_view (data->tab));
-
-               tepl_view_goto_line_offset (view,
-                                           data->line_pos - 1,
-                                           MAX (0, data->column_pos - 1));
+               gedit_document_goto_line_offset (doc,
+                                                data->line_pos - 1,
+                                                MAX (0, data->column_pos - 1));
                return;
        }
 
@@ -1764,18 +1759,18 @@ successful_load (GTask *loading_task)
        if (!gtk_source_file_is_readonly (file) &&
            file_already_opened (doc, location))
        {
-               TeplInfoBar *info_bar;
+               GtkWidget *info_bar;
 
                set_editable (data->tab, FALSE);
 
-               info_bar = tepl_io_error_info_bar_file_already_open (location);
+               info_bar = gedit_file_already_open_warning_info_bar_new (location);
 
                g_signal_connect (info_bar,
                                  "response",
                                  G_CALLBACK (file_already_open_warning_info_bar_response),
                                  data->tab);
 
-               set_info_bar (data->tab, GTK_WIDGET (info_bar), GTK_RESPONSE_CANCEL);
+               set_info_bar (data->tab, info_bar, GTK_RESPONSE_CANCEL);
        }
 
        /* When loading from stdin, the contents may not be saved, so set the
@@ -2406,12 +2401,12 @@ save_cb (GtkSourceFileSaver *saver,
                         error->code == G_IO_ERROR_CANT_CREATE_BACKUP)
                {
                        /* This error is recoverable */
-                       info_bar = GTK_WIDGET (tepl_io_error_info_bar_cant_create_backup (location, error));
+                       info_bar = gedit_no_backup_saving_error_info_bar_new (location, error);
                        g_return_if_fail (info_bar != NULL);
 
                        g_signal_connect (info_bar,
                                          "response",
-                                         G_CALLBACK (cant_create_backup_error_info_bar_response),
+                                         G_CALLBACK (no_backup_error_info_bar_response),
                                          saving_task);
                }
                else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
@@ -2420,7 +2415,7 @@ save_cb (GtkSourceFileSaver *saver,
                        /* If we have any invalid char in the document we must warn the user
                         * as it can make the document useless if it is saved.
                         */
-                       info_bar = GTK_WIDGET (tepl_io_error_info_bar_invalid_characters (location));
+                       info_bar = gedit_invalid_character_info_bar_new (location);
                        g_return_if_fail (info_bar != NULL);
 
                        g_signal_connect (info_bar,
@@ -2802,15 +2797,15 @@ printing_cb (GeditPrintJob       *job,
             GeditPrintJobStatus  status,
             GeditTab            *tab)
 {
-       g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
+       g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (tab->info_bar));
 
        gtk_widget_show (tab->info_bar);
 
-       tepl_progress_info_bar_set_text (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
-                                        gedit_print_job_get_status_string (job));
+       gedit_progress_info_bar_set_text (GEDIT_PROGRESS_INFO_BAR (tab->info_bar),
+                                         gedit_print_job_get_status_string (job));
 
-       tepl_progress_info_bar_set_fraction (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
-                                            gedit_print_job_get_progress (job));
+       gedit_progress_info_bar_set_fraction (GEDIT_PROGRESS_INFO_BAR (tab->info_bar),
+                                             gedit_print_job_get_progress (job));
 }
 
 static void
@@ -2920,19 +2915,21 @@ print_cancelled (GtkWidget *bar,
 static void
 add_printing_info_bar (GeditTab *tab)
 {
-       TeplProgressInfoBar *bar;
+       GtkWidget *bar;
 
-       bar = tepl_progress_info_bar_new ("document-print", NULL, TRUE);
+       bar = gedit_progress_info_bar_new ("document-print",
+                                          "",
+                                          TRUE);
 
        g_signal_connect (bar,
                          "response",
                          G_CALLBACK (print_cancelled),
                          tab);
 
-       set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
+       set_info_bar (tab, bar, GTK_RESPONSE_NONE);
 
        /* hide until we start printing */
-       gtk_widget_hide (GTK_WIDGET (bar));
+       gtk_widget_hide (bar);
 }
 
 void
diff --git a/gedit/gedit-utils.c b/gedit/gedit-utils.c
index 9fc9e4fb0..ae7e92156 100644
--- a/gedit/gedit-utils.c
+++ b/gedit/gedit-utils.c
@@ -23,7 +23,6 @@
 #include "gedit-utils.h"
 #include <string.h>
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 #include "gedit-debug.h"
 
 gboolean
@@ -87,6 +86,122 @@ gedit_utils_set_atk_name_description (GtkWidget   *widget,
                atk_object_set_description (aobj, description);
 }
 
+void
+gedit_warning (GtkWindow *parent, const gchar *format, ...)
+{
+       va_list         args;
+       gchar          *str;
+       GtkWidget      *dialog;
+       GtkWindowGroup *wg = NULL;
+
+       g_return_if_fail (format != NULL);
+
+       if (parent != NULL)
+               wg = gtk_window_get_group (parent);
+
+       va_start (args, format);
+       str = g_strdup_vprintf (format, args);
+       va_end (args);
+
+       dialog = gtk_message_dialog_new_with_markup (
+                       parent,
+                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                       GTK_MESSAGE_ERROR,
+                       GTK_BUTTONS_OK,
+                       "%s", str);
+
+       g_free (str);
+
+       if (wg != NULL)
+               gtk_window_group_add_window (wg, GTK_WINDOW (dialog));
+
+       gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+       gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+       g_signal_connect (G_OBJECT (dialog),
+                         "response",
+                         G_CALLBACK (gtk_widget_destroy),
+                         NULL);
+
+       gtk_widget_show (dialog);
+}
+
+/* the following functions are taken from eel */
+
+static gchar *
+gedit_utils_str_truncate (const gchar *string,
+                         guint        truncate_length,
+                         gboolean     middle)
+{
+       GString     *truncated;
+       guint        length;
+       guint        n_chars;
+       guint        num_left_chars;
+       guint        right_offset;
+       guint        delimiter_length;
+       const gchar *delimiter = "\342\200\246";
+
+       g_return_val_if_fail (string != NULL, NULL);
+
+       length = strlen (string);
+
+       g_return_val_if_fail (g_utf8_validate (string, length, NULL), NULL);
+
+       /* It doesnt make sense to truncate strings to less than
+        * the size of the delimiter plus 2 characters (one on each
+        * side)
+        */
+       delimiter_length = g_utf8_strlen (delimiter, -1);
+       if (truncate_length < (delimiter_length + 2))
+       {
+               return g_strdup (string);
+       }
+
+       n_chars = g_utf8_strlen (string, length);
+
+       /* Make sure the string is not already small enough. */
+       if (n_chars <= truncate_length)
+       {
+               return g_strdup (string);
+       }
+
+       /* Find the 'middle' where the truncation will occur. */
+       if (middle)
+       {
+               num_left_chars = (truncate_length - delimiter_length) / 2;
+               right_offset = n_chars - truncate_length + num_left_chars + delimiter_length;
+
+               truncated = g_string_new_len (string,
+                                             g_utf8_offset_to_pointer (string, num_left_chars) - string);
+               g_string_append (truncated, delimiter);
+               g_string_append (truncated, g_utf8_offset_to_pointer (string, right_offset));
+       }
+       else
+       {
+               num_left_chars = truncate_length - delimiter_length;
+               truncated = g_string_new_len (string,
+                                             g_utf8_offset_to_pointer (string, num_left_chars) - string);
+               g_string_append (truncated, delimiter);
+       }
+
+       return g_string_free (truncated, FALSE);
+}
+
+gchar *
+gedit_utils_str_middle_truncate (const gchar *string,
+                                guint        truncate_length)
+{
+       return gedit_utils_str_truncate (string, truncate_length, TRUE);
+}
+
+gchar *
+gedit_utils_str_end_truncate (const gchar *string,
+                             guint        truncate_length)
+{
+       return gedit_utils_str_truncate (string, truncate_length, FALSE);
+}
+
 static gchar *
 uri_get_dirname (const gchar *uri)
 {
@@ -106,7 +221,7 @@ uri_get_dirname (const gchar *uri)
                return NULL;
        }
 
-       res = tepl_utils_replace_home_dir_with_tilde (str);
+       res = gedit_utils_replace_home_dir_with_tilde (str);
 
        g_free (str);
 
@@ -149,10 +264,10 @@ gedit_utils_location_get_dirname_for_display (GFile *location)
                g_object_unref (mount);
 
                /* obtain the "path" part of the uri */
-               tepl_utils_decode_uri (uri,
-                                      NULL, NULL,
-                                      NULL, NULL,
-                                      &path);
+               gedit_utils_decode_uri (uri,
+                                       NULL, NULL,
+                                       NULL, NULL,
+                                       &path);
 
                if (path == NULL)
                {
@@ -187,6 +302,51 @@ gedit_utils_location_get_dirname_for_display (GFile *location)
        return res;
 }
 
+gchar *
+gedit_utils_replace_home_dir_with_tilde (const gchar *uri)
+{
+       gchar *tmp;
+       gchar *home;
+
+       g_return_val_if_fail (uri != NULL, NULL);
+
+       /* Note that g_get_home_dir returns a const string */
+       tmp = (gchar *)g_get_home_dir ();
+
+       if (tmp == NULL)
+               return g_strdup (uri);
+
+       home = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
+       if (home == NULL)
+               return g_strdup (uri);
+
+       if (strcmp (uri, home) == 0)
+       {
+               g_free (home);
+
+               return g_strdup ("~/");
+       }
+
+       tmp = home;
+       home = g_strdup_printf ("%s/", tmp);
+       g_free (tmp);
+
+       if (g_str_has_prefix (uri, home))
+       {
+               gchar *res;
+
+               res = g_strdup_printf ("~/%s", uri + strlen (home));
+
+               g_free (home);
+
+               return res;
+       }
+
+       g_free (home);
+
+       return g_strdup (uri);
+}
+
 static gboolean
 is_valid_scheme_character (gchar c)
 {
@@ -353,7 +513,7 @@ gedit_utils_basename_for_display (GFile *location)
                }
        }
        else if (g_file_has_parent (location, NULL) ||
-                !tepl_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
+                 !gedit_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
        {
                /* For remote files with a parent (so not just http://foo.com)
                   or remote file for which the decoding of the host name fails,
@@ -438,6 +598,165 @@ gedit_utils_drop_get_uris (GtkSelectionData *selection_data)
        return uri_list;
 }
 
+static void
+null_ptr (gchar **ptr)
+{
+       if (ptr)
+               *ptr = NULL;
+}
+
+/**
+ * gedit_utils_decode_uri:
+ * @uri: the uri to decode
+ * @scheme: (out) (allow-none): return value pointer for the uri's
+ * scheme (e.g. http, sftp, ...), or %NULL
+ * @user: (out) (allow-none): return value pointer for the uri user info, or %NULL
+ * @port: (out) (allow-none): return value pointer for the uri port, or %NULL
+ * @host: (out) (allow-none): return value pointer for the uri host, or %NULL
+ * @path: (out) (allow-none): return value pointer for the uri path, or %NULL
+ *
+ * Parse and break an uri apart in its individual components like the uri
+ * scheme, user info, port, host and path. The return value pointer can be
+ * %NULL to ignore certain parts of the uri. If the function returns %TRUE, then
+ * all return value pointers should be freed using g_free
+ *
+ * Return value: %TRUE if the uri could be properly decoded, %FALSE otherwise.
+ */
+gboolean
+gedit_utils_decode_uri (const gchar  *uri,
+                       gchar       **scheme,
+                       gchar       **user,
+                       gchar       **host,
+                       gchar       **port,
+                       gchar       **path)
+{
+       /* Largely copied from glib/gio/gdummyfile.c:_g_decode_uri. This
+        * functionality should be in glib/gio, but for now we implement it
+        * ourselves (see bug #546182) */
+
+       const char *p, *in, *hier_part_start, *hier_part_end;
+       char *out;
+       char c;
+
+       /* From RFC 3986 Decodes:
+        * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+        */
+
+       p = uri;
+
+       null_ptr (scheme);
+       null_ptr (user);
+       null_ptr (port);
+       null_ptr (host);
+       null_ptr (path);
+
+       /* Decode scheme:
+        * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+        */
+
+       if (!g_ascii_isalpha (*p))
+               return FALSE;
+
+       while (1)
+       {
+               c = *p++;
+
+               if (c == ':')
+                       break;
+
+               if (!(g_ascii_isalnum(c) ||
+                     c == '+' ||
+                     c == '-' ||
+                     c == '.'))
+               {
+                       return FALSE;
+               }
+       }
+
+       if (scheme)
+       {
+               *scheme = g_malloc (p - uri);
+               out = *scheme;
+
+               for (in = uri; in < p - 1; in++)
+               {
+                       *out++ = g_ascii_tolower (*in);
+               }
+
+               *out = '\0';
+       }
+
+       hier_part_start = p;
+       hier_part_end = p + strlen (p);
+
+       if (hier_part_start[0] == '/' && hier_part_start[1] == '/')
+       {
+               const char *authority_start, *authority_end;
+               const char *userinfo_start, *userinfo_end;
+               const char *host_start, *host_end;
+               const char *port_start;
+
+               authority_start = hier_part_start + 2;
+               /* authority is always followed by / or nothing */
+               authority_end = memchr (authority_start, '/', hier_part_end - authority_start);
+
+               if (authority_end == NULL)
+                       authority_end = hier_part_end;
+
+               /* 3.2:
+                * authority = [ userinfo "@" ] host [ ":" port ]
+                */
+
+               userinfo_end = memchr (authority_start, '@', authority_end - authority_start);
+
+               if (userinfo_end)
+               {
+                       userinfo_start = authority_start;
+
+                       if (user)
+                               *user = g_uri_unescape_segment (userinfo_start, userinfo_end, NULL);
+
+                       if (user && *user == NULL)
+                       {
+                               if (scheme)
+                                       g_free (*scheme);
+
+                               return FALSE;
+                       }
+
+                       host_start = userinfo_end + 1;
+               }
+               else
+               {
+                       host_start = authority_start;
+               }
+
+               port_start = memchr (host_start, ':', authority_end - host_start);
+
+               if (port_start)
+               {
+                       host_end = port_start++;
+
+                       if (port)
+                               *port = g_strndup (port_start, authority_end - port_start);
+               }
+               else
+               {
+                       host_end = authority_end;
+               }
+
+               if (host)
+                       *host = g_strndup (host_start, host_end - host_start);
+
+               hier_part_start = authority_end;
+       }
+
+       if (path)
+               *path = g_uri_unescape_segment (hier_part_start, hier_part_end, "/");
+
+       return TRUE;
+}
+
 GtkSourceCompressionType
 gedit_utils_get_compression_type_from_content_type (const gchar *content_type)
 {
diff --git a/gedit/gedit-utils.h b/gedit/gedit-utils.h
index a6b423db0..64af070d2 100644
--- a/gedit/gedit-utils.h
+++ b/gedit/gedit-utils.h
@@ -27,19 +27,38 @@
 
 G_BEGIN_DECLS
 
+/* useful macro */
+#define GBOOLEAN_TO_POINTER(i) (GINT_TO_POINTER ((i) ? 2 : 1))
+#define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((GPOINTER_TO_INT(i) == 2) ? TRUE : FALSE))
+
 gboolean                   gedit_utils_menu_position_under_tree_view          (GtkTreeView     *tree_view,
                                                                                GdkRectangle    *rect);
 
+gchar                     *gedit_utils_str_middle_truncate                    (const gchar     *string,
+                                                                               guint            
truncate_length);
+gchar                     *gedit_utils_str_end_truncate                       (const gchar     *string,
+                                                                               guint            
truncate_length);
 void                       gedit_utils_set_atk_name_description               (GtkWidget       *widget,
                                                                                const gchar     *name,
                                                                                const gchar     *description);
+void                       gedit_warning                                      (GtkWindow      *parent,
+                                                                               const gchar    *format,
+                                                                               ...) G_GNUC_PRINTF(2, 3);
 
-gchar                     *gedit_utils_location_get_dirname_for_display       (GFile *location);
+gchar                     *gedit_utils_location_get_dirname_for_display       (GFile          *location);
+gchar                     *gedit_utils_replace_home_dir_with_tilde            (const gchar    *uri);
 
 gboolean                   gedit_utils_is_valid_location                      (GFile *location);
 
 gchar                     *gedit_utils_basename_for_display                   (GFile *location);
 
+gboolean                   gedit_utils_decode_uri                             (const gchar  *uri,
+                                                                               gchar       **scheme,
+                                                                               gchar       **user,
+                                                                               gchar       **host,
+                                                                               gchar       **port,
+                                                                               gchar       **path);
+
 /* Turns data from a drop into a list of well formatted uris */
 gchar                    **gedit_utils_drop_get_uris                          (GtkSelectionData     
*selection_data);
 
diff --git a/gedit/gedit-view-centering.c b/gedit/gedit-view-centering.c
new file mode 100644
index 000000000..f9c742076
--- /dev/null
+++ b/gedit/gedit-view-centering.c
@@ -0,0 +1,495 @@
+/*
+ * gedit-view-centering.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ *
+ * Gedit is free software; you can redistribute this file 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.
+ *
+ * Gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Based on Christian Hergert's prototype.
+ */
+
+#include "gedit-view-centering.h"
+
+#include <gtksourceview/gtksource.h>
+
+#include "gedit-view.h"
+#include "gedit-debug.h"
+
+struct _GeditViewCenteringPrivate
+{
+       GtkWidget *box;
+       GtkWidget *scrolled_window;
+       GtkWidget *sourceview;
+       GtkWidget *spacer;
+
+       GtkStyleContext *view_context;
+       GdkRGBA view_background;
+       GdkRGBA view_line_margin_fg;
+       GdkRGBA view_margin_background;
+       guint view_text_width;
+
+       guint centered : 1;
+       guint view_background_set : 1;
+       guint view_line_margin_fg_set : 1;
+       guint view_margin_background_set : 1;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GeditViewCentering, gedit_view_centering, GTK_TYPE_BIN)
+
+#define STYLE_TEXT                     "text"
+#define STYLE_RIGHT_MARGIN             "right-margin"
+
+#define RIGHT_MARGIN_LINE_ALPHA                40
+#define RIGHT_MARGIN_OVERLAY_ALPHA     15
+
+static gboolean
+get_style (GtkSourceStyleScheme *scheme,
+          const gchar          *style_id,
+          const gchar          *attribute,
+          GdkRGBA              *color)
+{
+       GtkSourceStyle *style;
+       gchar *style_string;
+
+       style = gtk_source_style_scheme_get_style (scheme, style_id);
+       if (!style)
+       {
+               return FALSE;
+       }
+
+       g_object_get (style, attribute, &style_string, NULL);
+       if (style_string)
+       {
+               gdk_rgba_parse (color, style_string);
+               g_free (style_string);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void
+get_spacer_colors (GeditViewCentering   *container,
+                  GtkSourceStyleScheme *scheme)
+{
+       GeditViewCenteringPrivate *priv = container->priv;
+
+       if (scheme)
+       {
+               priv->view_background_set = get_style (scheme,
+                                                      STYLE_TEXT, "background",
+                                                      &priv->view_background);
+
+               priv->view_line_margin_fg_set = get_style (scheme,
+                                                          STYLE_RIGHT_MARGIN, "foreground",
+                                                          &priv->view_line_margin_fg);
+               priv->view_line_margin_fg.alpha = RIGHT_MARGIN_LINE_ALPHA / 255.0;
+
+               priv->view_margin_background_set = get_style (scheme,
+                                                             STYLE_RIGHT_MARGIN, "background",
+                                                             &priv->view_margin_background);
+               priv->view_margin_background.alpha = RIGHT_MARGIN_OVERLAY_ALPHA / 255.0;
+       }
+}
+
+/* FIXME: when GeditViewCentering will be transfered to GtkSourceView,
+ * this method will be replaced by a call to a new method called
+ * gtk_source_view_get_right_margin_pixel_position ()
+ */
+static guint
+_gedit_view_centering_get_right_margin_pixel_position (GeditViewCentering *container)
+{
+       GeditViewCenteringPrivate *priv;
+       gchar *str;
+       PangoFontDescription *font_desc;
+       PangoLayout *layout;
+       guint right_margin_position;
+       gint width = 0;
+
+       g_return_val_if_fail (GEDIT_IS_VIEW_CENTERING (container), 0);
+
+       priv = container->priv;
+
+       right_margin_position = gtk_source_view_get_right_margin_position (GTK_SOURCE_VIEW 
(priv->sourceview));
+
+       gtk_style_context_save (priv->view_context);
+       gtk_style_context_set_state (priv->view_context, GTK_STATE_FLAG_NORMAL);
+       gtk_style_context_get (priv->view_context,
+                              gtk_style_context_get_state (priv->view_context),
+                              GTK_STYLE_PROPERTY_FONT, &font_desc,
+                              NULL);
+       gtk_style_context_restore (priv->view_context);
+
+       str = g_strnfill (right_margin_position, '_');
+       layout = gtk_widget_create_pango_layout (GTK_WIDGET (priv->sourceview), str);
+       g_free (str);
+
+       pango_layout_set_font_description (layout, font_desc);
+       pango_font_description_free (font_desc);
+       pango_layout_get_pixel_size (layout, &width, NULL);
+
+       g_object_unref (G_OBJECT (layout));
+
+       return width;
+}
+
+static void
+on_view_right_margin_visibility_changed (GeditView          *view,
+                                        GParamSpec         *pspec,
+                                        GeditViewCentering *container)
+{
+       GeditViewCenteringPrivate *priv = container->priv;
+       gboolean visibility;
+
+       visibility = gtk_source_view_get_show_right_margin (GTK_SOURCE_VIEW (priv->sourceview));
+
+       gtk_widget_set_visible (GTK_WIDGET (container->priv->spacer), visibility && priv->centered);
+}
+
+static void
+on_view_right_margin_position_changed (GeditView          *view,
+                                      GParamSpec         *pspec,
+                                      GeditViewCentering *container)
+{
+       GeditViewCenteringPrivate *priv = container->priv;
+       gboolean visibility;
+
+       priv->view_text_width = _gedit_view_centering_get_right_margin_pixel_position (container);
+
+       visibility = gtk_source_view_get_show_right_margin (GTK_SOURCE_VIEW (priv->sourceview));
+
+       if (visibility)
+       {
+               gtk_widget_queue_resize (priv->spacer);
+       }
+}
+
+static void
+on_view_context_changed (GtkStyleContext    *stylecontext,
+                        GeditViewCentering *container)
+{
+       GeditViewCenteringPrivate *priv = container->priv;
+       GtkTextBuffer *buffer;
+       GtkSourceStyleScheme *scheme;
+       gboolean visibility;
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->sourceview));
+       scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (buffer));
+       get_spacer_colors (container, scheme);
+
+       priv->view_text_width = _gedit_view_centering_get_right_margin_pixel_position (container);
+
+       visibility = gtk_source_view_get_show_right_margin (GTK_SOURCE_VIEW (priv->sourceview));
+
+       if (visibility)
+       {
+               gtk_widget_queue_resize (priv->spacer);
+       }
+}
+
+static gboolean
+on_spacer_draw (GeditViewCentering *container,
+               cairo_t            *cr,
+               GtkDrawingArea     *spacer)
+{
+       GeditViewCenteringPrivate *priv = container->priv;
+       GtkStyleContext *context;
+       guint width, height;
+
+       if (!container->priv->sourceview)
+       {
+               return FALSE;
+       }
+
+       width = gtk_widget_get_allocated_width (GTK_WIDGET (spacer));
+       height = gtk_widget_get_allocated_height (GTK_WIDGET (spacer));
+
+       context = gtk_widget_get_style_context (GTK_WIDGET (spacer));
+       gtk_style_context_save (context);
+       gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
+       gtk_render_background (context, cr, 0, 0, width, height);
+       gtk_style_context_restore (context);
+
+       cairo_set_line_width (cr, 1.0);
+
+       if (priv->view_background_set)
+       {
+               gdk_cairo_set_source_rgba (cr, &container->priv->view_background);
+               cairo_rectangle (cr, 0, 0, width, height);
+               cairo_fill (cr);
+       }
+
+       if (priv->view_margin_background_set)
+       {
+               gdk_cairo_set_source_rgba (cr, &container->priv->view_margin_background);
+               cairo_rectangle (cr, 0, 0, width, height);
+               cairo_fill (cr);
+       }
+
+       if (priv->view_line_margin_fg_set)
+       {
+               gdk_cairo_set_source_rgba (cr, &container->priv->view_line_margin_fg);
+               cairo_move_to (cr, width - 0.5, 0);
+               cairo_line_to (cr, width - 0.5, height);
+               cairo_stroke (cr);
+       }
+
+       return FALSE;
+}
+
+static void
+gedit_view_centering_remove (GtkContainer *container,
+                            GtkWidget    *child)
+{
+       GeditViewCenteringPrivate *priv;
+
+       g_assert (GEDIT_IS_VIEW_CENTERING (container));
+
+       priv = GEDIT_VIEW_CENTERING (container)->priv;
+
+       if (priv->sourceview == child)
+       {
+               gtk_container_remove (GTK_CONTAINER (priv->scrolled_window), priv->sourceview);
+               g_object_remove_weak_pointer (G_OBJECT (priv->sourceview), (gpointer *)&priv->sourceview);
+               priv->sourceview = NULL;
+               priv->view_context = NULL;
+       }
+       else
+       {
+               GTK_CONTAINER_CLASS (gedit_view_centering_parent_class)->remove (container, child);
+       }
+}
+
+static void
+gedit_view_centering_add (GtkContainer *container,
+                         GtkWidget    *child)
+{
+       GeditViewCenteringPrivate *priv;
+       GtkTextBuffer *buffer;
+       GtkSourceStyleScheme *scheme;
+
+       g_assert (GEDIT_IS_VIEW_CENTERING (container));
+
+       priv = GEDIT_VIEW_CENTERING (container)->priv;
+
+       if (GEDIT_IS_VIEW (child))
+       {
+               if (priv->sourceview)
+               {
+                       gedit_view_centering_remove (container, priv->sourceview);
+               }
+
+               priv->sourceview = child;
+               g_object_add_weak_pointer (G_OBJECT (child), (gpointer *)&priv->sourceview);
+               gtk_container_add (GTK_CONTAINER (priv->scrolled_window), child);
+
+               priv->view_context = gtk_widget_get_style_context (child);
+
+               buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->sourceview));
+               scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (buffer));
+               get_spacer_colors (GEDIT_VIEW_CENTERING (container), scheme);
+
+               g_signal_connect (priv->sourceview,
+                                 "notify::right-margin-position",
+                                 G_CALLBACK (on_view_right_margin_position_changed),
+                                 container);
+
+               g_signal_connect (priv->sourceview,
+                                 "notify::show-right-margin",
+                                 G_CALLBACK (on_view_right_margin_visibility_changed),
+                                 container);
+
+               g_signal_connect (priv->view_context,
+                                 "changed",
+                                 G_CALLBACK (on_view_context_changed),
+                                 container);
+
+               gtk_widget_queue_resize (GTK_WIDGET (container));
+       }
+       else
+       {
+               GTK_CONTAINER_CLASS (gedit_view_centering_parent_class)->add (container, child);
+       }
+}
+
+static gboolean
+on_spacer_scroll_event (GtkWidget          *widget,
+                       GdkEvent           *event,
+                       GeditViewCentering *container)
+{
+       GdkEventScroll *new_scroll_event;
+
+       new_scroll_event = (GdkEventScroll *)gdk_event_copy (event);
+       g_object_unref (new_scroll_event->window);
+
+       new_scroll_event->window = g_object_ref (gtk_widget_get_window (container->priv->sourceview));
+       new_scroll_event->send_event = TRUE;
+
+       new_scroll_event->x = 0;
+       new_scroll_event->y = 0;
+       new_scroll_event->x_root = 0;
+       new_scroll_event->y_root = 0;
+
+       gtk_main_do_event ((GdkEvent *)new_scroll_event);
+       gdk_event_free ((GdkEvent *)new_scroll_event);
+
+       return TRUE;
+}
+
+static void
+gedit_view_centering_size_allocate (GtkWidget     *widget,
+                                   GtkAllocation *alloc)
+{
+       GeditViewCenteringPrivate *priv;
+       GtkTextView *view;
+       gint container_width;
+       gint gutter_width;
+       gint text_width;
+       gint spacer_width;
+       gint current_spacer_width;
+       GdkWindow *gutter_window;
+
+       g_assert (GEDIT_IS_VIEW_CENTERING (widget));
+
+       priv = GEDIT_VIEW_CENTERING (widget)->priv;
+
+       view = GTK_TEXT_VIEW (priv->sourceview);
+
+       if (view)
+       {
+               container_width = alloc->width;
+
+               gutter_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_LEFT);
+               gutter_width = (gutter_window) ? gdk_window_get_width (gutter_window) : 0;
+
+               text_width = priv->view_text_width;
+               spacer_width = MAX (0, container_width - text_width - gutter_width) / 2;
+
+               g_object_get(priv->spacer, "width-request", &current_spacer_width, NULL);
+
+               if (current_spacer_width != spacer_width)
+               {
+                       g_object_set(priv->spacer, "width-request", spacer_width, NULL);
+               }
+       }
+
+       GTK_WIDGET_CLASS (gedit_view_centering_parent_class)->size_allocate (widget, alloc);
+}
+
+static void
+gedit_view_centering_finalize (GObject *object)
+{
+       GeditViewCentering *container = GEDIT_VIEW_CENTERING (object);
+       GeditViewCenteringPrivate *priv = container->priv;
+
+       if (priv->sourceview)
+       {
+               gedit_view_centering_remove (GTK_CONTAINER (container), priv->sourceview);
+       }
+
+       G_OBJECT_CLASS (gedit_view_centering_parent_class)->finalize (object);
+}
+
+static void
+gedit_view_centering_class_init (GeditViewCenteringClass *klass)
+{
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+       GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+       gobject_class->finalize = gedit_view_centering_finalize;
+
+       widget_class->size_allocate = gedit_view_centering_size_allocate;
+
+       container_class->add = gedit_view_centering_add;
+       container_class->remove = gedit_view_centering_remove;
+}
+
+static void
+gedit_view_centering_init (GeditViewCentering *container)
+{
+       GeditViewCenteringPrivate *priv;
+
+       container->priv = gedit_view_centering_get_instance_private (container);
+       priv = container->priv;
+       priv->view_text_width = 0;
+
+       priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+       priv->spacer = gtk_drawing_area_new ();
+       priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+
+       gtk_container_add (GTK_CONTAINER (container), priv->box);
+       gtk_box_pack_start (GTK_BOX (priv->box), priv->spacer, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (priv->box), priv->scrolled_window, TRUE, TRUE, 0);
+
+       gtk_widget_set_no_show_all (GTK_WIDGET (priv->spacer), TRUE);
+       gtk_widget_show_all (GTK_WIDGET (priv->box));
+
+       g_signal_connect_swapped (priv->spacer, "draw",
+                                 G_CALLBACK (on_spacer_draw),
+                                 container);
+
+       gtk_widget_add_events(GTK_WIDGET(priv->spacer), GDK_SCROLL_MASK);
+       g_signal_connect (priv->spacer, "scroll-event",
+                         G_CALLBACK (on_spacer_scroll_event),
+                         container);
+}
+
+/**
+ * gedit_view_centering_set_centered:
+ * @container: a #GeditViewCentering.
+ * @centered: whether to center the sourceview child or not.
+ *
+ * If @centered is %TRUE, the sourceview child is centered
+ * horizontally on the #GeditViewCentering container.
+ **/
+void
+gedit_view_centering_set_centered (GeditViewCentering *container,
+                                  gboolean            centered)
+{
+       g_return_if_fail (GEDIT_IS_VIEW_CENTERING (container));
+
+       container->priv->centered = centered != FALSE;
+
+       on_view_right_margin_visibility_changed (GEDIT_VIEW (container->priv->sourceview), NULL, container);
+}
+
+/**
+ * gedit_view_centering_get_centered:
+ * @container: a #GeditViewCentering.
+ *
+ * Return whether the #GtkSourceView child is centered or not.
+ *
+ * Return value: %TRUE if the #GtkSourceView child is centered
+ * horizontally on the #GeditViewCentering container.
+ **/
+gboolean
+gedit_view_centering_get_centered (GeditViewCentering *container)
+{
+       g_return_val_if_fail (GEDIT_IS_VIEW_CENTERING (container), FALSE);
+
+       return container->priv->centered;
+}
+
+GeditViewCentering *
+gedit_view_centering_new (void)
+{
+       return g_object_new (GEDIT_TYPE_VIEW_CENTERING,
+                            NULL);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-view-centering.h b/gedit/gedit-view-centering.h
new file mode 100644
index 000000000..1d7218969
--- /dev/null
+++ b/gedit/gedit-view-centering.h
@@ -0,0 +1,67 @@
+/*
+ * gedit-view-centering.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Sébastien Lafargue
+ * Copyright (C) 2015 - Sébastien Wilmet
+ *
+ * Gedit is free software; you can redistribute this file 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.
+ *
+ * Gedit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef GEDIT_VIEW_CENTERING_H
+#define GEDIT_VIEW_CENTERING_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_VIEW_CENTERING              (gedit_view_centering_get_type())
+#define GEDIT_VIEW_CENTERING(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_VIEW_CENTERING, GeditViewCentering))
+#define GEDIT_VIEW_CENTERING_CONST(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_VIEW_CENTERING, GeditViewCentering const))
+#define GEDIT_VIEW_CENTERING_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_VIEW_CENTERING, 
GeditViewCenteringClass))
+#define GEDIT_IS_VIEW_CENTERING(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GEDIT_TYPE_VIEW_CENTERING))
+#define GEDIT_IS_VIEW_CENTERING_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_VIEW_CENTERING))
+#define GEDIT_VIEW_CENTERING_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_VIEW_CENTERING, 
GeditViewCenteringClass))
+
+typedef struct _GeditViewCentering             GeditViewCentering;
+typedef struct _GeditViewCenteringClass                GeditViewCenteringClass;
+typedef struct _GeditViewCenteringPrivate      GeditViewCenteringPrivate;
+
+struct _GeditViewCentering
+{
+       GtkBin parent;
+
+       GeditViewCenteringPrivate *priv;
+};
+
+struct _GeditViewCenteringClass
+{
+       GtkBinClass parent_class;
+};
+
+GType                  gedit_view_centering_get_type                   (void) G_GNUC_CONST;
+
+GeditViewCentering *   gedit_view_centering_new                        (void);
+
+void                   gedit_view_centering_set_centered               (GeditViewCentering *container,
+                                                                        gboolean            centered);
+
+gboolean               gedit_view_centering_get_centered               (GeditViewCentering *container);
+
+G_END_DECLS
+
+#endif /* GEDIT_VIEW_CENTERING_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-view-frame.c b/gedit/gedit-view-frame.c
index f41734c47..67c067a41 100644
--- a/gedit/gedit-view-frame.c
+++ b/gedit/gedit-view-frame.c
@@ -3,7 +3,7 @@
  * This file is part of gedit
  *
  * Copyright (C) 2010 - Ignacio Casal Quinteiro
- * Copyright (C) 2013, 2019 - Sébastien Wilmet
+ * Copyright (C) 2013 - Sébastien Wilmet
  *
  * gedit is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
 #include <glib/gi18n.h>
 #include <stdlib.h>
 
+#include "gedit-view-centering.h"
 #include "gedit-debug.h"
 #include "gedit-utils.h"
 #include "gedit-settings.h"
@@ -53,7 +54,11 @@ struct _GeditViewFrame
 {
        GtkOverlay parent_instance;
 
+       GSettings *editor_settings;
+
        GeditView *view;
+       GeditViewCentering *view_centering;
+       GtkFrame *map_frame;
 
        SearchMode search_mode;
 
@@ -159,6 +164,7 @@ gedit_view_frame_dispose (GObject *object)
                gtk_source_file_set_mount_operation_factory (file, NULL, NULL, NULL);
        }
 
+       g_clear_object (&frame->editor_settings);
        g_clear_object (&frame->entry_tag);
        g_clear_object (&frame->search_settings);
        g_clear_object (&frame->old_search_settings);
@@ -213,7 +219,7 @@ hide_search_widget (GeditViewFrame *frame,
                                                  frame->start_mark);
                gtk_text_buffer_place_cursor (buffer, &iter);
 
-               tepl_view_scroll_to_cursor (TEPL_VIEW (frame->view));
+               gedit_view_scroll_to_cursor (frame->view);
        }
 
        if (frame->start_mark != NULL)
@@ -297,7 +303,7 @@ finish_search (GeditViewFrame    *frame,
 
        if (found || (entry_text[0] == '\0'))
        {
-               tepl_view_scroll_to_cursor (TEPL_VIEW (frame->view));
+               gedit_view_scroll_to_cursor (frame->view);
 
                set_search_state (frame, SEARCH_STATE_NORMAL);
        }
@@ -1061,6 +1067,7 @@ update_goto_line (GeditViewFrame *frame)
        gchar **split_text = NULL;
        const gchar *text;
        GtkTextIter iter;
+       GeditDocument *doc;
 
        entry_text = gtk_entry_get_text (GTK_ENTRY (frame->search_entry));
 
@@ -1116,8 +1123,11 @@ update_goto_line (GeditViewFrame *frame)
 
        g_strfreev (split_text);
 
-       moved = tepl_view_goto_line (TEPL_VIEW (frame->view), line);
-       moved_offset = tepl_view_goto_line_offset (TEPL_VIEW (frame->view), line, line_offset);
+       doc = get_document (frame);
+       moved = gedit_document_goto_line (doc, line);
+       moved_offset = gedit_document_goto_line_offset (doc, line, line_offset);
+
+       gedit_view_scroll_to_cursor (frame->view);
 
        if (!moved || !moved_offset)
        {
@@ -1428,6 +1438,8 @@ gedit_view_frame_class_init (GeditViewFrameClass *klass)
        gtk_widget_class_set_template_from_resource (widget_class,
                                                     "/org/gnome/gedit/ui/gedit-view-frame.ui");
        gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, view);
+       gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, view_centering);
+       gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, map_frame);
        gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, revealer);
        gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, search_entry);
        gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, go_up_button);
@@ -1454,6 +1466,13 @@ gedit_view_frame_init (GeditViewFrame *frame)
 
        gtk_widget_init_template (GTK_WIDGET (frame));
 
+       frame->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
+       g_settings_bind (frame->editor_settings,
+                        GEDIT_SETTINGS_DISPLAY_OVERVIEW_MAP,
+                        frame->map_frame,
+                        "visible",
+                        G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
+
        doc = get_document (frame);
        file = gedit_document_get_file (doc);
 
@@ -1551,6 +1570,14 @@ gedit_view_frame_new (void)
        return g_object_new (GEDIT_TYPE_VIEW_FRAME, NULL);
 }
 
+GeditViewCentering *
+gedit_view_frame_get_view_centering (GeditViewFrame *frame)
+{
+       g_return_val_if_fail (GEDIT_IS_VIEW_FRAME (frame), NULL);
+
+       return frame->view_centering;
+}
+
 GeditView *
 gedit_view_frame_get_view (GeditViewFrame *frame)
 {
diff --git a/gedit/gedit-view-frame.h b/gedit/gedit-view-frame.h
index 78ac469d1..d2e550840 100644
--- a/gedit/gedit-view-frame.h
+++ b/gedit/gedit-view-frame.h
@@ -24,6 +24,7 @@
 #include <gtk/gtk.h>
 #include "gedit-document.h"
 #include "gedit-view.h"
+#include "gedit-view-centering.h"
 
 G_BEGIN_DECLS
 
@@ -32,6 +33,9 @@ G_DECLARE_FINAL_TYPE (GeditViewFrame, gedit_view_frame, GEDIT, VIEW_FRAME, GtkOv
 
 GeditViewFrame *gedit_view_frame_new                   (void);
 
+GeditViewCentering
+               *gedit_view_frame_get_view_centering    (GeditViewFrame *frame);
+
 GeditView      *gedit_view_frame_get_view              (GeditViewFrame *frame);
 
 void            gedit_view_frame_popup_search          (GeditViewFrame *frame);
diff --git a/gedit/gedit-view.c b/gedit/gedit-view.c
index 0c730c989..035e599ab 100644
--- a/gedit/gedit-view.c
+++ b/gedit/gedit-view.c
@@ -24,16 +24,21 @@
 #include "gedit-view-activatable.h"
 #include "gedit-plugins-engine.h"
 #include "gedit-debug.h"
+#include "gedit-pango.h"
 #include "gedit-utils.h"
 #include "gedit-settings.h"
 
+#define GEDIT_VIEW_SCROLL_MARGIN 0.02
+
 struct _GeditViewPrivate
 {
+       GeditDocument *current_document;
        PeasExtensionSet *extensions;
 
        gchar *direct_save_uri;
 
-       TeplSignalGroup *file_signal_group;
+       GtkCssProvider *css_provider;
+       PangoFontDescription *font_desc;
 };
 
 enum
@@ -50,7 +55,7 @@ enum
 
 static guint signals[N_SIGNALS];
 
-G_DEFINE_TYPE_WITH_PRIVATE (GeditView, gedit_view, TEPL_TYPE_VIEW)
+G_DEFINE_TYPE_WITH_PRIVATE (GeditView, gedit_view, GTK_SOURCE_TYPE_VIEW)
 
 static void
 update_editable (GeditView *view)
@@ -73,23 +78,46 @@ file_read_only_notify_cb (GtkSourceFile *file,
        update_editable (view);
 }
 
+static void
+current_document_removed (GeditView *view)
+{
+       if (view->priv->current_document != NULL)
+       {
+               GtkSourceFile *file;
+
+               file = gedit_document_get_file (view->priv->current_document);
+
+               g_signal_handlers_disconnect_by_func (file,
+                                                     file_read_only_notify_cb,
+                                                     view);
+
+               g_object_unref (view->priv->current_document);
+               view->priv->current_document = NULL;
+       }
+}
+
 static void
 buffer_changed (GeditView *view)
 {
-       GeditDocument *doc;
        GtkSourceFile *file;
+       GtkTextBuffer *buffer;
 
-       doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
-       file = gedit_document_get_file (doc);
+       current_document_removed (view);
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       if (!GEDIT_IS_DOCUMENT (buffer))
+       {
+               return;
+       }
 
-       tepl_signal_group_clear (&view->priv->file_signal_group);
-       view->priv->file_signal_group = tepl_signal_group_new (G_OBJECT (file));
+       view->priv->current_document = g_object_ref (GEDIT_DOCUMENT (buffer));
 
-       tepl_signal_group_add (view->priv->file_signal_group,
-                              g_signal_connect (file,
-                                                "notify::read-only",
-                                                G_CALLBACK (file_read_only_notify_cb),
-                                                view));
+       file = gedit_document_get_file (view->priv->current_document);
+       g_signal_connect_object (file,
+                                "notify::read-only",
+                                G_CALLBACK (file_read_only_notify_cb),
+                                view,
+                                0);
 
        update_editable (view);
 }
@@ -106,7 +134,7 @@ static void
 gedit_view_init (GeditView *view)
 {
        GtkTargetList *target_list;
-       GtkStyleContext *style_context;
+       GtkStyleContext *context;
 
        gedit_debug (DEBUG_VIEW);
 
@@ -140,8 +168,13 @@ gedit_view_init (GeditView *view)
                          NULL);
 
        /* CSS stuff */
-       style_context = gtk_widget_get_style_context (GTK_WIDGET (view));
-       gtk_style_context_add_class (style_context, "gedit-view");
+       context = gtk_widget_get_style_context (GTK_WIDGET (view));
+       gtk_style_context_add_class (context, "gedit-view");
+
+       view->priv->css_provider = gtk_css_provider_new ();
+       gtk_style_context_add_provider (context,
+                                       GTK_STYLE_PROVIDER (view->priv->css_provider),
+                                       GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 }
 
 static void
@@ -150,7 +183,8 @@ gedit_view_dispose (GObject *object)
        GeditView *view = GEDIT_VIEW (object);
 
        g_clear_object (&view->priv->extensions);
-       tepl_signal_group_clear (&view->priv->file_signal_group);
+
+       current_document_removed (view);
 
        /* Disconnect notify buffer because the destroy of the textview will set
         * the buffer to NULL, and we call get_buffer in the notify which would
@@ -160,26 +194,10 @@ gedit_view_dispose (GObject *object)
         */
        g_signal_handlers_disconnect_by_func (view, buffer_notify_cb, NULL);
 
-       G_OBJECT_CLASS (gedit_view_parent_class)->dispose (object);
-}
-
-static void
-update_font (GeditView *view)
-{
-       GeditSettings *settings;
-       gchar *selected_font;
-
-       settings = _gedit_settings_get_singleton ();
-       selected_font = _gedit_settings_get_selected_font (settings);
-       tepl_utils_override_font (GTK_WIDGET (view), selected_font);
-       g_free (selected_font);
-}
+       g_clear_object (&view->priv->css_provider);
+       g_clear_pointer (&view->priv->font_desc, pango_font_description_free);
 
-static void
-fonts_changed_cb (GeditSettings *settings,
-                 GeditView     *view)
-{
-       update_font (view);
+       G_OBJECT_CLASS (gedit_view_parent_class)->dispose (object);
 }
 
 static void
@@ -188,18 +206,27 @@ gedit_view_constructed (GObject *object)
        GeditView *view = GEDIT_VIEW (object);
        GeditSettings *settings;
        GSettings *editor_settings;
+       gboolean use_default_font;
 
        G_OBJECT_CLASS (gedit_view_parent_class)->constructed (object);
 
        settings = _gedit_settings_get_singleton ();
        editor_settings = _gedit_settings_peek_editor_settings (settings);
 
-       update_font (view);
-       g_signal_connect_object (settings,
-                                "fonts-changed",
-                                G_CALLBACK (fonts_changed_cb),
-                                view,
-                                0);
+       use_default_font = g_settings_get_boolean (editor_settings, GEDIT_SETTINGS_USE_DEFAULT_FONT);
+
+       if (use_default_font)
+       {
+               gedit_view_set_font (view, TRUE, NULL);
+       }
+       else
+       {
+               gchar *editor_font;
+
+               editor_font = g_settings_get_string (editor_settings, GEDIT_SETTINGS_EDITOR_FONT);
+               gedit_view_set_font (view, FALSE, editor_font);
+               g_free (editor_font);
+       }
 
        g_settings_bind (editor_settings, GEDIT_SETTINGS_DISPLAY_LINE_NUMBERS,
                         view, "show-line-numbers",
@@ -720,4 +747,217 @@ gedit_view_new (GeditDocument *doc)
                             NULL);
 }
 
+void
+gedit_view_cut_clipboard (GeditView *view)
+{
+       GtkTextBuffer *buffer;
+       GtkClipboard *clipboard;
+
+       gedit_debug (DEBUG_VIEW);
+
+       g_return_if_fail (GEDIT_IS_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
+                                             GDK_SELECTION_CLIPBOARD);
+
+       gtk_text_buffer_cut_clipboard (buffer,
+                                      clipboard,
+                                      gtk_text_view_get_editable (GTK_TEXT_VIEW (view)));
+
+       gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+                                     gtk_text_buffer_get_insert (buffer),
+                                     GEDIT_VIEW_SCROLL_MARGIN,
+                                     FALSE,
+                                     0.0,
+                                     0.0);
+}
+
+void
+gedit_view_copy_clipboard (GeditView *view)
+{
+       GtkTextBuffer *buffer;
+       GtkClipboard *clipboard;
+
+       gedit_debug (DEBUG_VIEW);
+
+       g_return_if_fail (GEDIT_IS_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
+                                             GDK_SELECTION_CLIPBOARD);
+
+       gtk_text_buffer_copy_clipboard (buffer, clipboard);
+
+       /* on copy do not scroll, we are already on screen */
+}
+
+void
+gedit_view_paste_clipboard (GeditView *view)
+{
+       GtkTextBuffer *buffer;
+       GtkClipboard *clipboard;
+
+       gedit_debug (DEBUG_VIEW);
+
+       g_return_if_fail (GEDIT_IS_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
+                                             GDK_SELECTION_CLIPBOARD);
+
+       gtk_text_buffer_paste_clipboard (buffer,
+                                        clipboard,
+                                        NULL,
+                                        gtk_text_view_get_editable (GTK_TEXT_VIEW (view)));
+
+       gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+                                     gtk_text_buffer_get_insert (buffer),
+                                     GEDIT_VIEW_SCROLL_MARGIN,
+                                     FALSE,
+                                     0.0,
+                                     0.0);
+}
+
+/**
+ * gedit_view_delete_selection:
+ * @view: a #GeditView
+ *
+ * Deletes the text currently selected in the #GtkTextBuffer associated
+ * to the view and scroll to the cursor position.
+ */
+void
+gedit_view_delete_selection (GeditView *view)
+{
+       GtkTextBuffer *buffer;
+
+       gedit_debug (DEBUG_VIEW);
+
+       g_return_if_fail (GEDIT_IS_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       gtk_text_buffer_delete_selection (buffer,
+                                         TRUE,
+                                         gtk_text_view_get_editable (GTK_TEXT_VIEW (view)));
+
+       gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+                                     gtk_text_buffer_get_insert (buffer),
+                                     GEDIT_VIEW_SCROLL_MARGIN,
+                                     FALSE,
+                                     0.0,
+                                     0.0);
+}
+
+/**
+ * gedit_view_select_all:
+ * @view: a #GeditView
+ *
+ * Selects all the text.
+ */
+void
+gedit_view_select_all (GeditView *view)
+{
+       GtkTextBuffer *buffer;
+       GtkTextIter start;
+       GtkTextIter end;
+
+       gedit_debug (DEBUG_VIEW);
+
+       g_return_if_fail (GEDIT_IS_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       gtk_text_buffer_get_bounds (buffer, &start, &end);
+       gtk_text_buffer_select_range (buffer, &start, &end);
+}
+
+/**
+ * gedit_view_scroll_to_cursor:
+ * @view: a #GeditView
+ *
+ * Scrolls the @view to the cursor position.
+ */
+void
+gedit_view_scroll_to_cursor (GeditView *view)
+{
+       GtkTextBuffer *buffer;
+
+       gedit_debug (DEBUG_VIEW);
+
+       g_return_if_fail (GEDIT_IS_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
+                                     gtk_text_buffer_get_insert (buffer),
+                                     0.25,
+                                     FALSE,
+                                     0.0,
+                                     0.0);
+}
+
+static void
+update_css_provider (GeditView *view)
+{
+       gchar *str;
+       gchar *css;
+
+       g_assert (GEDIT_IS_VIEW (view));
+       g_assert (view->priv->font_desc != NULL);
+
+       str = gedit_pango_font_description_to_css (view->priv->font_desc);
+       css = g_strdup_printf ("textview { %s }", str ? str : "");
+       gtk_css_provider_load_from_data (view->priv->css_provider, css, -1, NULL);
+
+       g_free (css);
+       g_free (str);
+}
+
+/**
+ * gedit_view_set_font:
+ * @view: a #GeditView
+ * @default_font: whether to reset to the default font
+ * @font_name: the name of the font to use
+ *
+ * If @default_font is #TRUE, resets the font of the @view to the default font.
+ * Otherwise sets it to @font_name.
+ */
+void
+gedit_view_set_font (GeditView   *view,
+                    gboolean     default_font,
+                    const gchar *font_name)
+{
+       gedit_debug (DEBUG_VIEW);
+
+       g_return_if_fail (GEDIT_IS_VIEW (view));
+
+       g_clear_pointer (&view->priv->font_desc, pango_font_description_free);
+
+       if (default_font)
+       {
+               GeditSettings *settings;
+               gchar *font;
+
+               settings = _gedit_settings_get_singleton ();
+               font = gedit_settings_get_system_font (settings);
+
+               view->priv->font_desc = pango_font_description_from_string (font);
+               g_free (font);
+       }
+       else
+       {
+               g_return_if_fail (font_name != NULL);
+
+               view->priv->font_desc = pango_font_description_from_string (font_name);
+       }
+
+       g_return_if_fail (view->priv->font_desc != NULL);
+
+       update_css_provider (view);
+}
+
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-view.h b/gedit/gedit-view.h
index c05d68553..7f2ae3ae2 100644
--- a/gedit/gedit-view.h
+++ b/gedit/gedit-view.h
@@ -22,8 +22,10 @@
 #ifndef GEDIT_VIEW_H
 #define GEDIT_VIEW_H
 
+#include <gtk/gtk.h>
+
 #include <gedit/gedit-document.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
 
 G_BEGIN_DECLS
 
@@ -40,7 +42,7 @@ typedef struct _GeditViewPrivate      GeditViewPrivate;
 
 struct _GeditView
 {
-       TeplView view;
+       GtkSourceView view;
 
        /*< private >*/
        GeditViewPrivate *priv;
@@ -48,7 +50,7 @@ struct _GeditView
 
 struct _GeditViewClass
 {
-       TeplViewClass parent_class;
+       GtkSourceViewClass parent_class;
 
        void    (*drop_uris)    (GeditView  *view,
                                 gchar     **uri_list);
@@ -60,6 +62,22 @@ GType                gedit_view_get_type             (void);
 
 GtkWidget *    gedit_view_new                  (GeditDocument *doc);
 
+void           gedit_view_cut_clipboard        (GeditView *view);
+
+void           gedit_view_copy_clipboard       (GeditView *view);
+
+void           gedit_view_paste_clipboard      (GeditView *view);
+
+void           gedit_view_delete_selection     (GeditView *view);
+
+void           gedit_view_select_all           (GeditView *view);
+
+void           gedit_view_scroll_to_cursor     (GeditView *view);
+
+void           gedit_view_set_font             (GeditView   *view,
+                                                gboolean     default_font,
+                                                const gchar *font_name);
+
 G_END_DECLS
 
 #endif /* GEDIT_VIEW_H */
diff --git a/gedit/gedit-window-private.h b/gedit/gedit-window-private.h
index 60f8ba706..380f6bdc5 100644
--- a/gedit/gedit-window-private.h
+++ b/gedit/gedit-window-private.h
@@ -27,6 +27,7 @@
 #include "gedit-message-bus.h"
 #include "gedit-settings.h"
 #include "gedit-multi-notebook.h"
+#include "gedit-open-document-selector.h"
 
 G_BEGIN_DECLS
 
@@ -53,12 +54,15 @@ struct _GeditWindowPrivate
        PeasExtensionSet *extensions;
 
        /* Widgets for fullscreen mode */
+       GtkWidget      *fullscreen_controls;
        GtkWidget      *fullscreen_eventbox;
-       GtkRevealer    *fullscreen_revealer;
        GtkWidget      *fullscreen_headerbar;
-       GtkWidget      *fullscreen_new_button;
        GtkMenuButton  *fullscreen_gear_button;
-       GtkMenuButton  *fullscreen_open_recent_button;
+
+       GtkWidget       *fullscreen_new_button;
+       GtkWidget       *fullscreen_open_button;
+       GtkWidget       *fullscreen_open_document_popover;
+       GeditOpenDocumentSelector *fullscreen_open_document_selector;
 
        /* statusbar and context ids for statusbar messages */
        GtkWidget      *statusbar;
@@ -79,7 +83,10 @@ struct _GeditWindowPrivate
        GtkWidget      *side_headerbar;
        GtkWidget      *headerbar;
 
-       GtkWidget      *new_button;
+       GtkWidget       *open_document_popover;
+       GtkWidget       *new_button;
+       GtkWidget       *open_button;
+       GeditOpenDocumentSelector *open_document_selector;
 
        GtkMenuButton  *gear_button;
 
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index 2f9a2076f..b08a1dbcc 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -28,11 +28,11 @@
 
 #include <glib/gi18n.h>
 #include <libpeas/peas-extension-set.h>
-#include <tepl/tepl.h>
 
 #include "gedit-window-private.h"
 #include "gedit-app.h"
 #include "gedit-app-private.h"
+#include "gedit-recent.h"
 #include "gedit-notebook.h"
 #include "gedit-notebook-popup-menu.h"
 #include "gedit-multi-notebook.h"
@@ -40,6 +40,7 @@
 #include "gedit-tab.h"
 #include "gedit-tab-private.h"
 #include "gedit-view-frame.h"
+#include "gedit-view-centering.h"
 #include "gedit-utils.h"
 #include "gedit-commands.h"
 #include "gedit-commands-private.h"
@@ -54,6 +55,11 @@
 #include "gedit-status-menu-button.h"
 #include "gedit-settings.h"
 #include "gedit-menu-stack-switcher.h"
+#include "gedit-highlight-mode-selector.h"
+#include "gedit-open-document-selector.h"
+
+#define TAB_WIDTH_DATA "GeditWindowTabWidthData"
+#define FULLSCREEN_ANIMATION_SPEED 500
 
 enum
 {
@@ -158,9 +164,9 @@ save_window_state (GtkWidget *widget)
        GeditWindow *window = GEDIT_WINDOW (widget);
 
        if ((window->priv->window_state &
-            (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
+           (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
        {
-               gtk_window_get_size (GTK_WINDOW (widget), &window->priv->width, &window->priv->height);
+                gtk_window_get_size (GTK_WINDOW (widget), &window->priv->width, &window->priv->height);
 
                g_settings_set (window->priv->window_settings, GEDIT_SETTINGS_WINDOW_SIZE,
                                "(ii)", window->priv->width, window->priv->height);
@@ -231,8 +237,6 @@ gedit_window_dispose (GObject *object)
         */
        remove_actions (window);
 
-       window->priv->fullscreen_open_recent_button = NULL;
-
        G_OBJECT_CLASS (gedit_window_parent_class)->dispose (object);
 }
 
@@ -247,6 +251,22 @@ gedit_window_finalize (GObject *object)
        G_OBJECT_CLASS (gedit_window_parent_class)->finalize (object);
 }
 
+/* Center the view when the window is in fullscreen mode. */
+static void
+update_view_centering (GeditTab *tab,
+                      gpointer  user_data)
+{
+       GeditViewFrame *view_frame;
+       GeditViewCentering *view_centering;
+       gboolean is_fullscreen;
+
+       view_frame = _gedit_tab_get_view_frame (tab);
+       view_centering = gedit_view_frame_get_view_centering (view_frame);
+
+       is_fullscreen = GPOINTER_TO_BOOLEAN (user_data);
+       gedit_view_centering_set_centered (view_centering, is_fullscreen);
+}
+
 static void
 update_fullscreen (GeditWindow *window,
                    gboolean     is_fullscreen)
@@ -267,6 +287,10 @@ update_fullscreen (GeditWindow *window,
                }
        }
 
+       gedit_multi_notebook_foreach_tab (window->priv->multi_notebook,
+                                         (GtkCallback)update_view_centering,
+                                         GBOOLEAN_TO_POINTER (is_fullscreen));
+
 #ifndef OS_OSX
        if (is_fullscreen)
        {
@@ -312,7 +336,7 @@ gedit_window_configure_event (GtkWidget         *widget,
 
        if (gtk_widget_get_realized (widget) &&
            (window->priv->window_state &
-            (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
+           (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
        {
                save_window_state (widget);
        }
@@ -454,6 +478,7 @@ gedit_window_class_init (GeditWindowClass *klass)
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_headerbar);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, headerbar);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, new_button);
+       gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, open_button);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, gear_button);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, hpaned);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_panel);
@@ -466,10 +491,11 @@ gedit_window_class_init (GeditWindowClass *klass)
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, language_button);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, tab_width_button);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, line_col_button);
+       gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_controls);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_eventbox);
-       gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_revealer);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_headerbar);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_new_button);
+       gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_open_button);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, fullscreen_gear_button);
 }
 
@@ -765,8 +791,48 @@ update_actions_sensitivity (GeditWindow *window)
 }
 
 static void
-language_chooser_show_cb (TeplLanguageChooser *language_chooser,
-                         GeditWindow         *window)
+on_recent_chooser_item_activated (GeditOpenDocumentSelector *open_document_selector,
+                                  gchar                     *uri,
+                                  GeditWindow               *window)
+{
+       GFile *location;
+       GeditView *active_view;
+
+       g_return_if_fail (GEDIT_WINDOW (window));
+       g_return_if_fail (GEDIT_OPEN_DOCUMENT_SELECTOR (open_document_selector));
+
+       /* TODO: get_current_file when exists */
+       location = g_file_new_for_uri (uri);
+
+       if (location)
+       {
+               GSList *locations = NULL;
+               GSList *loaded = NULL;
+
+               locations = g_slist_prepend (locations, (gpointer) location);
+               loaded = gedit_commands_load_locations (window, locations, NULL, 0, 0);
+
+               /* if it doesn't contain just 1 element */
+               if (!loaded || loaded->next)
+               {
+                       gedit_recent_remove_if_local (location);
+               }
+
+               g_slist_free (locations);
+               g_slist_free (loaded);
+
+               g_object_unref (location);
+       }
+
+       /* Needed to close the popover when activating the same
+        * document as the current one */
+       active_view = gedit_window_get_active_view (window);
+       gtk_widget_grab_focus (GTK_WIDGET (active_view));
+}
+
+static void
+language_selector_show_cb (GeditHighlightModeSelector *selector,
+                          GeditWindow                *window)
 {
        GeditDocument *active_document;
 
@@ -776,14 +842,14 @@ language_chooser_show_cb (TeplLanguageChooser *language_chooser,
                GtkSourceLanguage *language;
 
                language = gedit_document_get_language (active_document);
-               tepl_language_chooser_select_language (language_chooser, language);
+               gedit_highlight_mode_selector_select_language (selector, language);
        }
 }
 
 static void
-language_activated_cb (TeplLanguageChooser *language_chooser,
-                      GtkSourceLanguage   *language,
-                      GeditWindow         *window)
+language_selected_cb (GeditHighlightModeSelector *selector,
+                     GtkSourceLanguage          *language,
+                     GeditWindow                *window)
 {
        GeditDocument *active_document;
 
@@ -793,13 +859,13 @@ language_activated_cb (TeplLanguageChooser *language_chooser,
                gedit_document_set_language (active_document, language);
        }
 
-       gtk_widget_hide (window->priv->language_popover);
+       gtk_widget_hide (GTK_WIDGET (window->priv->language_popover));
 }
 
 static void
 setup_statusbar (GeditWindow *window)
 {
-       TeplLanguageChooserWidget *language_chooser;
+       GeditHighlightModeSelector *selector;
 
        gedit_debug (DEBUG_WINDOW);
 
@@ -829,20 +895,20 @@ setup_statusbar (GeditWindow *window)
        gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->language_button),
                                     window->priv->language_popover);
 
-       language_chooser = tepl_language_chooser_widget_new ();
+       selector = gedit_highlight_mode_selector_new ();
 
-       g_signal_connect (language_chooser,
+       g_signal_connect (selector,
                          "show",
-                         G_CALLBACK (language_chooser_show_cb),
+                         G_CALLBACK (language_selector_show_cb),
                          window);
 
-       g_signal_connect (language_chooser,
-                         "language-activated",
-                         G_CALLBACK (language_activated_cb),
+       g_signal_connect (selector,
+                         "language-selected",
+                         G_CALLBACK (language_selected_cb),
                          window);
 
-       gtk_container_add (GTK_CONTAINER (window->priv->language_popover), GTK_WIDGET (language_chooser));
-       gtk_widget_show (GTK_WIDGET (language_chooser));
+       gtk_container_add (GTK_CONTAINER (window->priv->language_popover), GTK_WIDGET (selector));
+       gtk_widget_show (GTK_WIDGET (selector));
 }
 
 static GeditWindow *
@@ -1044,8 +1110,8 @@ set_title (GeditWindow *window)
        {
                gchar *tmp;
 
-               tmp = tepl_utils_str_middle_truncate (name,
-                                                     MAX_TITLE_LENGTH);
+               tmp = gedit_utils_str_middle_truncate (name,
+                                                      MAX_TITLE_LENGTH);
                g_free (name);
                name = tmp;
        }
@@ -1063,8 +1129,8 @@ set_title (GeditWindow *window)
                         * we have a title long 99 + 20, but I think it's a rare enough
                         * case to be acceptable. It's justa darn title afterall :)
                         */
-                       dirname = tepl_utils_str_middle_truncate (str,
-                                                                 MAX (20, MAX_TITLE_LENGTH - len));
+                       dirname = gedit_utils_str_middle_truncate (str,
+                                                                  MAX (20, MAX_TITLE_LENGTH - len));
                        g_free (str);
                }
        }
@@ -1690,88 +1756,84 @@ drop_uris_cb (GtkWidget    *widget,
        load_uris_from_drop (window, uri_list);
 }
 
-static void
-update_fullscreen_revealer_state (GeditWindow *window)
+static gboolean
+on_fullscreen_controls_enter_notify_event (GtkWidget        *widget,
+                                           GdkEventCrossing *event,
+                                           GeditWindow      *window)
 {
-       gboolean open_recent_menu_is_active;
-       gboolean hamburger_menu_is_active;
+       window->priv->in_fullscreen_eventbox = TRUE;
 
-       open_recent_menu_is_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON 
(window->priv->fullscreen_open_recent_button));
-       hamburger_menu_is_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON 
(window->priv->fullscreen_gear_button));
+       gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), TRUE);
 
-       gtk_revealer_set_reveal_child (window->priv->fullscreen_revealer,
-                                      (window->priv->in_fullscreen_eventbox ||
-                                       open_recent_menu_is_active ||
-                                       hamburger_menu_is_active));
+       return FALSE;
 }
 
 static gboolean
-on_fullscreen_eventbox_enter_notify_event (GtkWidget        *fullscreen_eventbox,
-                                          GdkEventCrossing *event,
-                                          GeditWindow      *window)
+real_fullscreen_controls_leave_notify_event (gpointer data)
 {
-       window->priv->in_fullscreen_eventbox = TRUE;
-       update_fullscreen_revealer_state (window);
+       GeditWindow *window = GEDIT_WINDOW (data);
+       gboolean hamburger_menu_state;
+       gboolean fullscreen_open_button_state;
 
-       return GDK_EVENT_PROPAGATE;
-}
+       hamburger_menu_state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON 
(window->priv->fullscreen_gear_button));
+       fullscreen_open_button_state =
+                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON 
(window->priv->fullscreen_open_button));
 
-static gboolean
-on_fullscreen_eventbox_leave_notify_event (GtkWidget        *fullscreen_eventbox,
-                                          GdkEventCrossing *event,
-                                          GeditWindow      *window)
-{
-       if (-1.0 <= event->y && event->y <= 0.0)
-       {
-               /* Ignore the event.
-                *
-                * Leave notify events are received with -1 <= y <= 0
-                * coordinates, although the GeditWindow is in fullscreen mode
-                * and when there are no screens above (it's maybe a bug in an
-                * underlying library).
-                * If we hide the headerbar when those events happen, then it
-                * makes the headerbar to be shown/hidden a lot of time in a
-                * short period of time, i.e. a "stuttering". In other words
-                * lots of leave/enter events are received when moving the mouse
-                * upwards on the screen when the mouse is already at the top.
-                * The expected leave event has a positive event->y value being
-                * >= to the height of the headerbar (approximately
-                * 40 <= y <= 50). So clearly when we receive a leave event with
-                * event->y <= 0, it means that the mouse has left the eventbox
-                * on the wrong side.
-                * The -1.0 <= event->y is there (instead of just <= 0.0) in the
-                * case that there is another screen *above*, even if this
-                * heuristic/workaround is not perfect in that case. But that
-                * case is quite rare, so it's probably a good enough solution.
-                *
-                * Note that apparently the "stuttering" occurs only on an Xorg
-                * session, not on Wayland (tested with GNOME).
-                *
-                * If you see a better solution...
-                */
-               return GDK_EVENT_PROPAGATE;
+       window->priv->in_fullscreen_eventbox = FALSE;
+
+       if (!hamburger_menu_state && !fullscreen_open_button_state)
+       {
+               gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), FALSE);
        }
 
-       window->priv->in_fullscreen_eventbox = FALSE;
-       update_fullscreen_revealer_state (window);
+       return G_SOURCE_REMOVE;
+}
+
+/* this idle is needed because the toggled signal from gear button is received
+ * after the leave event from the event box ( which is automatically triggered when user
+ * bring up the gear menu */
+static gboolean
+on_fullscreen_controls_leave_notify_event (GtkWidget        *widget,
+                                           GdkEventCrossing *event,
+                                           GeditWindow      *window)
+{
+       g_idle_add (real_fullscreen_controls_leave_notify_event, window);
 
        return GDK_EVENT_PROPAGATE;
 }
 
 static void
-setup_fullscreen_eventbox (GeditWindow *window)
+fullscreen_controls_setup (GeditWindow *window)
 {
-       gtk_widget_set_size_request (window->priv->fullscreen_eventbox, -1, 1);
-       gtk_widget_hide (window->priv->fullscreen_eventbox);
+       GeditWindowPrivate *priv = window->priv;
 
-       g_signal_connect (window->priv->fullscreen_eventbox,
+       g_signal_connect (priv->fullscreen_eventbox,
                          "enter-notify-event",
-                         G_CALLBACK (on_fullscreen_eventbox_enter_notify_event),
+                         G_CALLBACK (on_fullscreen_controls_enter_notify_event),
                          window);
 
-       g_signal_connect (window->priv->fullscreen_eventbox,
+       g_signal_connect (priv->fullscreen_eventbox,
                          "leave-notify-event",
-                         G_CALLBACK (on_fullscreen_eventbox_leave_notify_event),
+                         G_CALLBACK (on_fullscreen_controls_leave_notify_event),
+                         window);
+
+       gtk_widget_set_size_request (GTK_WIDGET (window->priv->fullscreen_eventbox), -1, 1);
+       gtk_widget_hide (window->priv->fullscreen_eventbox);
+
+       priv->fullscreen_open_document_popover = gtk_popover_new (priv->fullscreen_open_button);
+       gtk_menu_button_set_popover (GTK_MENU_BUTTON (priv->fullscreen_open_button),
+                                    priv->fullscreen_open_document_popover);
+
+       window->priv->fullscreen_open_document_selector = gedit_open_document_selector_new (window);
+
+       gtk_container_add (GTK_CONTAINER (priv->fullscreen_open_document_popover),
+                          GTK_WIDGET (priv->fullscreen_open_document_selector));
+
+       gtk_widget_show_all (GTK_WIDGET (priv->fullscreen_open_document_selector));
+
+       g_signal_connect (window->priv->fullscreen_open_document_selector,
+                         "file-activated",
+                         G_CALLBACK (on_recent_chooser_item_activated),
                          window);
 }
 
@@ -1885,7 +1947,7 @@ on_tab_added (GeditMultiNotebook *multi,
                          G_CALLBACK (bracket_matched_cb),
                          window);
        g_signal_connect (doc,
-                         "tepl-cursor-moved",
+                         "cursor-moved",
                          G_CALLBACK (update_cursor_position_statusbar),
                          window);
        g_signal_connect (doc,
@@ -2144,10 +2206,23 @@ on_notebook_removed (GeditMultiNotebook *mnb,
 }
 
 static void
-on_fullscreen_toggle_button_toggled (GtkToggleButton *fullscreen_toggle_button,
-                                    GeditWindow     *window)
+on_fullscreen_gear_button_toggled (GtkToggleButton *fullscreen_gear_button,
+                                   GeditWindow     *window)
 {
-       update_fullscreen_revealer_state (window);
+       gboolean button_active = gtk_toggle_button_get_active (fullscreen_gear_button);
+
+       gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls),
+                                      button_active || window->priv->in_fullscreen_eventbox);
+}
+
+static void
+on_fullscreen_file_menu_button_toggled (GtkMenuButton *fullscreen_open_button,
+                                        GeditWindow   *window)
+{
+       gboolean button_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fullscreen_open_button));
+
+       gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls),
+                                      button_active || window->priv->in_fullscreen_eventbox);
 }
 
 static void
@@ -2537,6 +2612,18 @@ window_unrealized (GtkWidget *window,
                                              window);
 }
 
+static void
+check_window_is_active (GeditWindow *window,
+                       GParamSpec *property,
+                       gpointer useless)
+{
+       if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN)
+       {
+               gtk_widget_set_visible (window->priv->fullscreen_eventbox,
+                                       gtk_window_is_active (GTK_WINDOW (window)));
+       }
+}
+
 static void
 extension_added (PeasExtensionSet *extensions,
                 PeasPluginInfo   *info,
@@ -2608,76 +2695,6 @@ sync_fullscreen_actions (GeditWindow *window,
        g_object_unref (action);
 }
 
-static void
-init_amtk_application_window (GeditWindow *gedit_window)
-{
-       AmtkApplicationWindow *amtk_window;
-
-       amtk_window = amtk_application_window_get_from_gtk_application_window (GTK_APPLICATION_WINDOW 
(gedit_window));
-       amtk_application_window_set_statusbar (amtk_window, GTK_STATUSBAR (gedit_window->priv->statusbar));
-}
-
-static GtkWidget *
-create_open_buttons (GeditWindow    *window,
-                    GtkMenuButton **open_recent_button)
-{
-       GtkWidget *hbox;
-       GtkStyleContext *style_context;
-       GtkWidget *open_dialog_button;
-       GtkWidget *my_open_recent_button;
-       AmtkApplicationWindow *amtk_window;
-       GtkWidget *recent_menu;
-
-       /* It currently needs to be a GtkBox, not a GtkGrid, because GtkGrid and
-        * GTK_STYLE_CLASS_LINKED doesn't work as expected in a RTL locale.
-        * Probably a GtkGrid bug.
-        */
-       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-       style_context = gtk_widget_get_style_context (hbox);
-       gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_LINKED);
-
-       open_dialog_button = gtk_button_new_with_mnemonic (_("_Open"));
-       gtk_widget_set_tooltip_text (open_dialog_button, _("Open a file"));
-       gtk_actionable_set_action_name (GTK_ACTIONABLE (open_dialog_button), "win.open");
-
-       my_open_recent_button = gtk_menu_button_new ();
-       gtk_widget_set_tooltip_text (my_open_recent_button, _("Open a recently used file"));
-
-       amtk_window = amtk_application_window_get_from_gtk_application_window (GTK_APPLICATION_WINDOW 
(window));
-       recent_menu = amtk_application_window_create_open_recent_menu (amtk_window);
-       gtk_menu_button_set_popup (GTK_MENU_BUTTON (my_open_recent_button), recent_menu);
-
-       gtk_container_add (GTK_CONTAINER (hbox), open_dialog_button);
-       gtk_container_add (GTK_CONTAINER (hbox), my_open_recent_button);
-       gtk_widget_show_all (hbox);
-
-       if (open_recent_button != NULL)
-       {
-               *open_recent_button = GTK_MENU_BUTTON (my_open_recent_button);
-       }
-
-       return hbox;
-}
-
-static void
-init_open_buttons (GeditWindow *window)
-{
-       gtk_container_add_with_properties (GTK_CONTAINER (window->priv->headerbar),
-                                          create_open_buttons (window, NULL),
-                                          "position", 0, /* The first on the left. */
-                                          NULL);
-
-       gtk_container_add_with_properties (GTK_CONTAINER (window->priv->fullscreen_headerbar),
-                                          create_open_buttons (window, 
&(window->priv->fullscreen_open_recent_button)),
-                                          "position", 0, /* The first on the left. */
-                                          NULL);
-
-       g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_open_recent_button),
-                         "toggled",
-                         G_CALLBACK (on_fullscreen_toggle_button_toggled),
-                         window);
-}
-
 static void
 gedit_window_init (GeditWindow *window)
 {
@@ -2692,6 +2709,7 @@ gedit_window_init (GeditWindow *window)
        window->priv->state = GEDIT_WINDOW_STATE_NORMAL;
        window->priv->inhibition_cookie = 0;
        window->priv->dispose_has_run = FALSE;
+       window->priv->fullscreen_controls = NULL;
        window->priv->direct_save_uri = NULL;
        window->priv->closed_docs_stack = NULL;
        window->priv->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
@@ -2705,8 +2723,6 @@ gedit_window_init (GeditWindow *window)
        window->priv->message_bus = gedit_message_bus_new ();
 
        gtk_widget_init_template (GTK_WIDGET (window));
-       init_amtk_application_window (window);
-       init_open_buttons (window);
 
        g_action_map_add_action_entries (G_ACTION_MAP (window),
                                         win_entries,
@@ -2716,9 +2732,32 @@ gedit_window_init (GeditWindow *window)
        window->priv->window_group = gtk_window_group_new ();
        gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window));
 
-       setup_fullscreen_eventbox (window);
+       /* Setup file popover and file dialog */
+       window->priv->open_document_popover = gtk_popover_new (window->priv->open_button);
+       gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->open_button),
+                                    window->priv->open_document_popover);
+
+       window->priv->open_document_selector = gedit_open_document_selector_new (window);
+
+       gtk_container_add (GTK_CONTAINER (window->priv->open_document_popover),
+                          GTK_WIDGET (window->priv->open_document_selector));
+
+       gtk_widget_show_all (GTK_WIDGET (window->priv->open_document_selector));
+
+       g_signal_connect (window->priv->open_document_selector,
+                         "file-activated",
+                         G_CALLBACK (on_recent_chooser_item_activated),
+                         window);
+
+       fullscreen_controls_setup (window);
        sync_fullscreen_actions (window, FALSE);
 
+       g_object_bind_property (gedit_open_document_selector_get_search_entry 
(window->priv->open_document_selector),
+                               "text",
+                               gedit_open_document_selector_get_search_entry 
(window->priv->fullscreen_open_document_selector),
+                               "text",
+                               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
        hamburger_menu = _gedit_app_get_hamburger_menu (GEDIT_APP (g_application_get_default ()));
        if (hamburger_menu)
        {
@@ -2733,9 +2772,14 @@ gedit_window_init (GeditWindow *window)
                gtk_widget_set_no_show_all (GTK_WIDGET (window->priv->fullscreen_gear_button), TRUE);
        }
 
+       g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_open_button),
+                         "toggled",
+                         G_CALLBACK (on_fullscreen_file_menu_button_toggled),
+                         window);
+
        g_signal_connect (GTK_TOGGLE_BUTTON (window->priv->fullscreen_gear_button),
                          "toggled",
-                         G_CALLBACK (on_fullscreen_toggle_button_toggled),
+                         G_CALLBACK (on_fullscreen_gear_button_toggled),
                          window);
 
        /* Setup status bar */
@@ -2849,6 +2893,12 @@ gedit_window_init (GeditWindow *window)
                          G_CALLBACK (window_unrealized),
                          NULL);
 
+       /* Check if the window is active for fullscreen */
+       g_signal_connect (window,
+                         "notify::is-active",
+                         G_CALLBACK (check_window_is_active),
+                         NULL);
+
        gedit_debug_message (DEBUG_WINDOW, "Update plugins ui");
 
        window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (gedit_plugins_engine_get_default ()),
diff --git a/gedit/gedit.c b/gedit/gedit.c
index fcffdaca6..ee3769537 100644
--- a/gedit/gedit.c
+++ b/gedit/gedit.c
@@ -28,13 +28,12 @@
 #  include "gedit-app-win32.h"
 #endif
 
+#include <glib.h>
 #include <locale.h>
 #include <libintl.h>
-#include <tepl/tepl.h>
 
 #include "gedit-dirs.h"
 #include "gedit-debug.h"
-#include "gedit-factory.h"
 #include "gedit-settings.h"
 
 #ifdef G_OS_WIN32
@@ -117,7 +116,6 @@ int
 main (int argc, char *argv[])
 {
        GType type;
-       GeditFactory *factory;
        GeditApp *app;
        gint status;
 
@@ -140,9 +138,6 @@ main (int argc, char *argv[])
        gedit_dirs_init ();
 
        setup_i18n ();
-       tepl_init ();
-       factory = gedit_factory_new ();
-       tepl_abstract_factory_set_singleton (TEPL_ABSTRACT_FACTORY (factory));
 
        app = g_object_new (type,
                            "application-id", "org.gnome.gedit",
@@ -167,7 +162,6 @@ main (int argc, char *argv[])
                                     G_OBJECT (app)->ref_count);
        }
 
-       tepl_finalize ();
        gedit_dirs_shutdown ();
 
 #ifdef G_OS_WIN32
diff --git a/gedit/meson.build b/gedit/meson.build
index 9fc81468e..844b6bac8 100644
--- a/gedit/meson.build
+++ b/gedit/meson.build
@@ -8,6 +8,7 @@ libgedit_public_headers = [
   'gedit-menu-extension.h',
   'gedit-message-bus.h',
   'gedit-message.h',
+  'gedit-progress-info-bar.h',
   'gedit-statusbar.h',
   'gedit-tab.h',
   'gedit-utils.h',
@@ -27,11 +28,13 @@ libgedit_public_sources = [
   'gedit-menu-extension.c',
   'gedit-message-bus.c',
   'gedit-message.c',
+  'gedit-progress-info-bar.c',
   'gedit-statusbar.c',
   'gedit-tab.c',
   'gedit-utils.c',
   'gedit-view-activatable.c',
   'gedit-view.c',
+  'gedit-view-centering.c',
   'gedit-window-activatable.c',
   'gedit-window.c',
 ]
@@ -45,30 +48,37 @@ libgedit_private_headers = [
   'gedit-documents-panel.h',
   'gedit-encoding-items.h',
   'gedit-encodings-dialog.h',
-  'gedit-factory.h',
   'gedit-file-chooser-dialog-gtk.h',
   'gedit-file-chooser-dialog.h',
   'gedit-file-chooser.h',
   'gedit-file-chooser-open-dialog.h',
   'gedit-file-chooser-open.h',
   'gedit-file-chooser-open-native.h',
+  'gedit-highlight-mode-dialog.h',
+  'gedit-highlight-mode-selector.h',
   'gedit-history-entry.h',
   'gedit-io-error-info-bar.h',
   'gedit-menu-stack-switcher.h',
+  'gedit-metadata-manager.h',
   'gedit-multi-notebook.h',
   'gedit-notebook.h',
   'gedit-notebook-popup-menu.h',
   'gedit-notebook-stack-switcher.h',
+  'gedit-open-document-selector.h',
+  'gedit-open-document-selector-helper.h',
+  'gedit-open-document-selector-store.h',
+  'gedit-pango.h',
   'gedit-plugins-engine.h',
   'gedit-preferences-dialog.h',
   'gedit-print-job.h',
   'gedit-print-preview.h',
   'gedit-recent.h',
-  'gedit-recent-osx.h',
   'gedit-replace-dialog.h',
   'gedit-settings.h',
   'gedit-status-menu-button.h',
   'gedit-tab-label.h',
+  'gedit-tab-private.h',
+  'gedit-view-centering.h',
   'gedit-view-frame.h',
   'gedit-window-private.h',
 ]
@@ -85,20 +95,26 @@ libgedit_private_sources = [
   'gedit-documents-panel.c',
   'gedit-encoding-items.c',
   'gedit-encodings-dialog.c',
-  'gedit-factory.c',
   'gedit-file-chooser.c',
   'gedit-file-chooser-dialog.c',
   'gedit-file-chooser-dialog-gtk.c',
   'gedit-file-chooser-open.c',
   'gedit-file-chooser-open-dialog.c',
   'gedit-file-chooser-open-native.c',
+  'gedit-highlight-mode-dialog.c',
+  'gedit-highlight-mode-selector.c',
   'gedit-history-entry.c',
   'gedit-io-error-info-bar.c',
   'gedit-menu-stack-switcher.c',
+  'gedit-metadata-manager.c',
   'gedit-multi-notebook.c',
   'gedit-notebook.c',
   'gedit-notebook-popup-menu.c',
   'gedit-notebook-stack-switcher.c',
+  'gedit-open-document-selector.c',
+  'gedit-open-document-selector-helper.c',
+  'gedit-open-document-selector-store.c',
+  'gedit-pango.c',
   'gedit-plugins-engine.c',
   'gedit-preferences-dialog.c',
   'gedit-print-job.c',
@@ -117,6 +133,7 @@ libgedit_link_args = []
 libgedit_deps = [
   deps_basic_list,
   libgd_dep,
+  libxml_dep,
 ]
 
 if host_machine.system() == 'darwin'
diff --git a/gedit/resources/css/gedit-style.css b/gedit/resources/css/gedit-style.css
index eb43a8233..7036567c4 100644
--- a/gedit/resources/css/gedit-style.css
+++ b/gedit/resources/css/gedit-style.css
@@ -14,6 +14,18 @@
     padding: 12px;
 }
 
+.gedit-map-frame:dir(ltr) border {
+    border-width: 0 0 0 1px;
+}
+
+.gedit-map-frame:dir(rtl) border {
+    border-width: 0 1px 0 0;
+}
+
+.open-document-selector-treeview {
+    padding: 3px 6px 3px 6px;
+}
+
 statusbar frame {
     border: none;
     padding-left: 6px;
diff --git a/gedit/resources/css/gedit.adwaita.css b/gedit/resources/css/gedit.adwaita.css
index 784e72aa2..8377c62a9 100644
--- a/gedit/resources/css/gedit.adwaita.css
+++ b/gedit/resources/css/gedit.adwaita.css
@@ -1,3 +1,28 @@
+.open-document-selector-treeview:hover {
+    background-color: alpha(@theme_fg_color, 0.05);
+}
+
+.open-document-selector-treeview:selected:hover {
+    background-color: @theme_selected_bg_color;
+}
+
+/* Only normal state is handle */
+.open-document-selector-name-label {
+    color: @theme_fg_color;
+}
+
+/* Only normal state is handle */
+.open-document-selector-path-label {
+    color: @theme_unfocused_fg_color;
+    font-size: smaller;
+}
+
+/* Only normal state is handle */
+.open-document-selector-match {
+    color: shade (@theme_fg_color, 0.6);
+    background-color: alpha(@warning_color, 0.4);
+}
+
 .gedit-document-panel {
     background-color: @sidebar_bg;
 }
diff --git a/gedit/resources/gedit.gresource.xml.in b/gedit/resources/gedit.gresource.xml.in
index a5905110e..b0a70c185 100644
--- a/gedit/resources/gedit.gresource.xml.in
+++ b/gedit/resources/gedit.gresource.xml.in
@@ -8,10 +8,14 @@
     <file preprocess="xml-stripblanks">ui/gedit-replace-dialog.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-print-preview.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-print-preferences.ui</file>
+    <file preprocess="xml-stripblanks">ui/gedit-progress-info-bar.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-status-menu-button.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-tab-label.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-view-frame.ui</file>
+    <file preprocess="xml-stripblanks">ui/gedit-highlight-mode-dialog.ui</file>
+    <file preprocess="xml-stripblanks">ui/gedit-highlight-mode-selector.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-window.ui</file>
+    <file preprocess="xml-stripblanks">ui/gedit-open-document-selector.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-shortcuts.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-statusbar.ui</file>
     <file>css/gedit-style.css</file>
diff --git a/gedit/resources/ui/gedit-highlight-mode-dialog.ui 
b/gedit/resources/ui/gedit-highlight-mode-dialog.ui
new file mode 100644
index 000000000..31b8690bd
--- /dev/null
+++ b/gedit/resources/ui/gedit-highlight-mode-dialog.ui
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="GeditHighlightModeDialog" parent="GtkDialog">
+    <property name="width_request">300</property>
+    <property name="height_request">400</property>
+    <property name="can_focus">False</property>
+    <property name="has_focus">False</property>
+    <property name="is_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Highlight Mode</property>
+    <property name="type_hint">dialog</property>
+    <property name="modal">True</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="has_focus">False</property>
+        <property name="is_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="has_focus">False</property>
+            <property name="is_focus">False</property>
+            <property name="layout_style">end</property>
+            <property name="border_width">5</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkButton" id="cancel_button">
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="has_focus">False</property>
+                <property name="is_focus">False</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="ok_button">
+                <property name="label" translatable="yes">_Select</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="has_focus">False</property>
+                <property name="is_focus">False</property>
+                <property name="receives_default">True</property>
+                <property name="can_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GeditHighlightModeSelector" id="selector">
+            <property name="visible">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">cancel_button</action-widget>
+      <action-widget response="-5">ok_button</action-widget>
+    </action-widgets>
+  </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-highlight-mode-selector.ui 
b/gedit/resources/ui/gedit-highlight-mode-selector.ui
new file mode 100644
index 000000000..1aa5c950e
--- /dev/null
+++ b/gedit/resources/ui/gedit-highlight-mode-selector.ui
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <object class="GtkListStore" id="liststore">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name lang -->
+      <column type="GtkSourceLanguage"/>
+    </columns>
+  </object>
+  <object class="GtkTreeModelFilter" id="treemodelfilter">
+    <property name="child_model">liststore</property>
+  </object>
+  <template class="GeditHighlightModeSelector" parent="GtkGrid">
+    <property name="width_request">300</property>
+    <property name="height_request">400</property>
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="has_focus">False</property>
+    <property name="is_focus">False</property>
+    <property name="row_spacing">3</property>
+    <property name="border_width">6</property>
+    <child>
+      <object class="GtkSearchEntry" id="entry">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="has_focus">True</property>
+        <property name="is_focus">False</property>
+        <property name="activates_default">True</property>
+        <property name="placeholder_text" translatable="yes">Search highlight mode…</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolledwindow1">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="has_focus">False</property>
+        <property name="is_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkTreeView" id="treeview">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="has_focus">False</property>
+            <property name="is_focus">False</property>
+            <property name="model">treemodelfilter</property>
+            <property name="headers_visible">False</property>
+            <property name="headers_clickable">False</property>
+            <property name="enable_search">False</property>
+            <child internal-child="selection">
+              <object class="GtkTreeSelection" id="treeview_selection"/>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn" id="treeviewcolumn">
+                <child>
+                  <object class="GtkCellRendererText" id="cellrenderertext"/>
+                  <attributes>
+                    <attribute name="text">0</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+  </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-open-document-selector.ui 
b/gedit/resources/ui/gedit-open-document-selector.ui
new file mode 100644
index 000000000..9393ac46c
--- /dev/null
+++ b/gedit/resources/ui/gedit-open-document-selector.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.10"/>
+  <template class="GeditOpenDocumentSelector" parent="GtkBox">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">9</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkSearchEntry" id="search_entry">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="primary_icon_name">edit-find-symbolic</property>
+        <property name="primary_icon_activatable">False</property>
+        <property name="primary_icon_sensitive">False</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkFrame" id="placeholder_box">
+        <property name="visible">False</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkBox" id="placeholder_inner_box">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <child>
+              <object class="GtkImage" id="placeholder_image">
+                <property name="visible">True</property>
+                <property name="icon_name">edit-find-symbolic</property>
+                <property name="pixel_size">64</property>
+                <property name="can_focus">False</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="placeholder_label">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">No results</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolled_window">
+        <property name="visible">True</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="hscrollbar_policy">never</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkTreeView" id="treeview">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="headers_visible">False</property>
+            <property name="fixed_height_mode">True</property>
+            <property name="enable_grid_lines">horizontal</property>
+            <property name="enable_search">False</property>
+            <property name="activate_on_single_click">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkButton" id="open_button">
+        <property name="label" translatable="yes">Other _Documents…</property>
+        <property name="use-underline">True</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="tooltip_text" translatable="yes">Open another file</property>
+        <property name="margin-top">6</property>
+        <property name="action_name">win.open</property>
+        <style>
+          <class name="text-button"/>
+        </style>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">3</property>
+      </packing>
+    </child>
+  </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-preferences-dialog.ui b/gedit/resources/ui/gedit-preferences-dialog.ui
index f1eeed45c..1ce0755da 100644
--- a/gedit/resources/ui/gedit-preferences-dialog.ui
+++ b/gedit/resources/ui/gedit-preferences-dialog.ui
@@ -105,6 +105,21 @@
                     <property name="width">2</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="GtkCheckButton" id="display_overview_map_checkbutton">
+                    <property name="label" translatable="yes">Display _overview map</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">3</property>
+                    <property name="width">2</property>
+                  </packing>
+                </child>
                 <child>
                   <object class="GtkCheckButton" id="display_grid_checkbutton">
                     <property name="label" translatable="yes">Display _grid pattern</property>
@@ -116,7 +131,7 @@
                   </object>
                   <packing>
                     <property name="left_attach">0</property>
-                    <property name="top_attach">3</property>
+                    <property name="top_attach">4</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
@@ -630,8 +645,19 @@
                     <property name="hexpand">True</property>
                     <property name="vexpand">True</property>
                     <child>
-                      <object class="TeplStyleSchemeChooserWidget" id="schemes_list">
+                      <object class="GtkScrolledWindow" id="schemes_scrolled_window">
                         <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="vexpand">True</property>
+                        <property name="shadow_type">etched-in</property>
+                        <property name="min_content_height">200</property>
+                        <child>
+                          <object class="GtkSourceStyleSchemeChooserWidget" id="schemes_list">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                          </object>
+                        </child>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
diff --git a/gedit/resources/ui/gedit-progress-info-bar.ui b/gedit/resources/ui/gedit-progress-info-bar.ui
new file mode 100644
index 000000000..3f733e4b6
--- /dev/null
+++ b/gedit/resources/ui/gedit-progress-info-bar.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.6 -->
+  <template class="GeditProgressInfoBar" parent="GtkInfoBar">
+    <property name="app_paintable">True</property>
+    <property name="can_focus">False</property>
+    <property name="message_type">other</property>
+    <child internal-child="content_area">
+      <object class="GtkBox" id="infobar-content_area1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">4</property>
+            <child>
+              <object class="GtkImage" id="image">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon-size">2</property>
+                <property name="icon_name">image-missing</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">4</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label">label</property>
+                <property name="use_markup">True</property>
+                <property name="ellipsize">end</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkProgressBar" id="progress">
+            <property name="height_request">15</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child internal-child="action_area">
+      <object class="GtkButtonBox" id="infobar-action_area1">
+        <property name="can_focus">False</property>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </template>
+</interface>
diff --git a/gedit/resources/ui/gedit-view-frame.ui b/gedit/resources/ui/gedit-view-frame.ui
index ebf70b013..b61d82c3a 100644
--- a/gedit/resources/ui/gedit-view-frame.ui
+++ b/gedit/resources/ui/gedit-view-frame.ui
@@ -7,15 +7,33 @@
     <property name="has_focus">False</property>
     <property name="is_focus">False</property>
     <child>
-      <object class="GtkScrolledWindow" id="scrolled_window">
+      <object class="GtkGrid" id="grid">
         <property name="visible">True</property>
-        <property name="hexpand">True</property>
-        <property name="vexpand">True</property>
-        <property name="overlay_scrolling">False</property>
         <child>
-          <object class="GeditView" id="view">
+          <object class="GeditViewCentering" id="view_centering">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <child>
+              <object class="GeditView" id="view">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkFrame" id="map_frame">
+            <property name="visible">True</property>
+            <style>
+              <class name="gedit-map-frame"/>
+            </style>
+            <child>
+              <object class="GtkSourceMap" id="map">
+                <property name="visible">True</property>
+                <property name="view">view</property>
+              </object>
+            </child>
           </object>
         </child>
       </object>
diff --git a/gedit/resources/ui/gedit-window.ui b/gedit/resources/ui/gedit-window.ui
index 0d131ad69..b6283dcf4 100644
--- a/gedit/resources/ui/gedit-window.ui
+++ b/gedit/resources/ui/gedit-window.ui
@@ -27,6 +27,50 @@
           <object class="GtkHeaderBar" id="headerbar">
             <property name="visible">True</property>
             <property name="show_close_button">True</property>
+            <child>
+              <object class="GtkMenuButton" id="open_button">
+                <property name="visible">True</property>
+                <property name="tooltip_text" translatable="yes">Open a file</property>
+                <property name="valign">center</property>
+                <property name="use_popover">True</property>
+                <style>
+                  <class name="text-button"/>
+                  <class name="image-button"/>
+                </style>
+                <child>
+                  <object class="GtkBox" id="open_button_box">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="has_focus">False</property>
+                    <property name="is_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="open_button_name">
+                        <property name="label" translatable="yes">_Open</property>
+                        <property name="use-underline">True</property>
+                        <property name="visible">True</property>
+                        <property name="valign">baseline</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImage" id="open_button_arrow">
+                        <property name="visible">True</property>
+                        <property name="valign">baseline</property>
+                        <property name="icon_name">pan-down-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="open_button_a11y">
+                    <property name="accessible-name" translatable="yes">Open</property>
+                    <property name="accessible-description" translatable="yes">Open a file</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="pack_type">start</property>
+              </packing>
+            </child>
             <child>
               <object class="GtkButton" id="new_button">
                 <property name="visible">True</property>
@@ -310,7 +354,7 @@
             <property name="can_focus">False</property>
             <property name="valign">start</property>
             <child>
-              <object class="GtkRevealer" id="fullscreen_revealer">
+              <object class="GtkRevealer" id="fullscreen_controls">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="reveal_child">False</property>
@@ -318,6 +362,47 @@
                 <child>
                   <object class="GtkHeaderBar" id="fullscreen_headerbar">
                     <property name="visible">True</property>
+                    <child>
+                      <object class="GtkMenuButton" id="fullscreen_open_button">
+                        <property name="visible">True</property>
+                        <property name="tooltip_text" translatable="yes">Open a file dialog</property>
+                        <property name="valign">center</property>
+                        <property name="use_popover">True</property>
+                        <style>
+                          <class name="text-button"/>
+                          <class name="image-button"/>
+                        </style>
+                        <child>
+                          <object class="GtkBox" id="fullscreen_open_button_box">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="has_focus">False</property>
+                            <property name="is_focus">False</property>
+                            <child>
+                              <object class="GtkLabel" id="fullscreen_open_button_name">
+                                <property name="label" translatable="yes">Open</property>
+                                <property name="visible">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkImage" id="fullscreen_open_button_arrow">
+                                <property name="visible">True</property>
+                                <property name="icon_name">pan-down-symbolic</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child internal-child="accessible">
+                          <object class="AtkObject" id="fullscreen_open_button_a11y">
+                            <property name="accessible-name" translatable="yes">Open</property>
+                            <property name="accessible-description" translatable="yes">Open a file</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="pack_type">start</property>
+                      </packing>
+                    </child>
                     <child>
                       <object class="GtkButton" id="fullscreen_new_button">
                         <property name="visible">True</property>
diff --git a/help/C/gedit-tab-groups.page b/help/C/gedit-tab-groups.page
index a25fcb6e0..d7ed84e8b 100644
--- a/help/C/gedit-tab-groups.page
+++ b/help/C/gedit-tab-groups.page
@@ -24,8 +24,8 @@
   <p>If you are working with multiple tabs in <app>gedit</app> you can group
   them, making it easier to keep your opened files organized. Adding a new tab
   group will divide the <app>gedit</app> window in two panes, open a new
-  “Untitled File” in the new pane, and make it active. You can open files into
-  that tab group and move tabs from one tab group to another.</p>
+  “Untitled Document” in the new pane, and make it active. You can open files
+  into that tab group and move tabs from one tab group to another.</p>
 
 <section id="open-new-tab-group">
   <title>Open a new tab group in the gedit window</title>
diff --git a/meson.build b/meson.build
index be77a885f..ef77bc8a8 100644
--- a/meson.build
+++ b/meson.build
@@ -40,13 +40,25 @@ libgd_subproject = subproject(
 libgd_dep = libgd_subproject.get_variable('libgd_dep')
 
 # Dependencies
-gio_dep = dependency('gio-2.0', version: '>= 2.64')
+glib_req = '>= 2.64'
+gtk_req = '>= 2.22'
+gtksourceview_req =  '>= 4.0'
+libpeas_req = '>= 1.14.1'
+libxml_req = '>= 2.5.0'
+gspell_req = '>= 1.0'
+pygobject_req = '>= 3.0.0'
+
+gio_dep = dependency('gio-2.0', version: glib_req)
+libxml_dep = dependency('libxml-2.0', version: libxml_req)
+gspell_dep = dependency('gspell-1', version: gspell_req)
+
+python3 = python.find_installation('python3')
 
 libgedit_public_deps = [
   gio_dep,
-  dependency('gtk+-3.0', version: '>= 3.22'),
-  dependency('tepl-6', version: '>= 5.99.0'),
-  dependency('libpeas-gtk-1.0'),
+  dependency('gtk+-3.0', version: gtk_req),
+  dependency('gtksourceview-4', version: gtksourceview_req),
+  dependency('libpeas-gtk-1.0', version: libpeas_req),
 ]
 
 deps_basic_list = [
@@ -54,9 +66,6 @@ deps_basic_list = [
   dependency('gobject-introspection-1.0'),
 ]
 
-gspell_dep = dependency('gspell-1', version: '>= 1.0')
-python3 = python.find_installation('python3')
-
 # Configurations
 config_h = configuration_data()
 config_h.set_quoted('PACKAGE_STRING', 'gedit-@0@'.format(api_version))
@@ -65,6 +74,17 @@ config_h.set_quoted('LIBDIR', join_paths(get_option('prefix'), get_option('libdi
 config_h.set_quoted('DATADIR', join_paths(get_option('prefix'), get_option('datadir')))
 config_h.set_quoted('VERSION', meson.project_version())
 
+enable_gvfs_metadata = get_option('enable-gvfs-metadata')
+if enable_gvfs_metadata == 'yes' or (enable_gvfs_metadata == 'auto' and host_machine.system() == 'linux')
+  enable_gvfs_metadata = true
+else
+  enable_gvfs_metadata = false
+endif
+
+if enable_gvfs_metadata
+  config_h.set('ENABLE_GVFS_METADATA', 1)
+endif
+
 configure_file(
   output: 'config.h',
   configuration: config_h
diff --git a/meson_options.txt b/meson_options.txt
index 4e842d1ea..33d03cb14 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -21,4 +21,11 @@ option(
   description: 'Build user documentation'
 )
 
+option(
+  'enable-gvfs-metadata',
+  type: 'combo',
+  choices: ['yes', 'no', 'auto'], value: 'auto',
+  description: 'Enable using gvfs to store metadata'
+)
+
 option('plugin_externaltools', type: 'boolean', value: true)
diff --git a/plugins/snippets/snippets/document.py b/plugins/snippets/snippets/document.py
index 003237d17..23df28091 100644
--- a/plugins/snippets/snippets/document.py
+++ b/plugins/snippets/snippets/document.py
@@ -162,13 +162,13 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
         buf = self.view.get_buffer()
 
         self.connect_signal(buf, 'changed', self.on_buffer_changed)
-        self.connect_signal(buf, 'tepl-cursor-moved', self.on_buffer_cursor_moved)
+        self.connect_signal(buf, 'cursor-moved', self.on_buffer_cursor_moved)
         self.connect_signal_after(buf, 'insert-text', self.on_buffer_insert_text)
 
     def last_snippet_removed(self):
         buf = self.view.get_buffer()
         self.disconnect_signal(buf, 'changed')
-        self.disconnect_signal(buf, 'tepl-cursor-moved')
+        self.disconnect_signal(buf, 'cursor-moved')
         self.disconnect_signal(buf, 'insert-text')
 
     def current_placeholder(self):
@@ -559,7 +559,7 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
             self.goto_placeholder(current, None)
 
         if len(self.active_snippets) > 0:
-            self.block_signal(buf, 'tepl-cursor-moved')
+            self.block_signal(buf, 'cursor-moved')
 
         buf.begin_user_action()
 
@@ -569,7 +569,7 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
         # Insert the snippet
         if len(self.active_snippets) == 0:
             self.first_snippet_inserted()
-            self.block_signal(buf, 'tepl-cursor-moved')
+            self.block_signal(buf, 'cursor-moved')
 
         sn = s.insert_into(self, start)
         self.active_snippets.append(sn)
@@ -585,7 +585,7 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
         else:
             self.goto_placeholder(self.active_placeholder, sn.placeholders[keys[0]])
 
-        self.unblock_signal(buf, 'tepl-cursor-moved')
+        self.unblock_signal(buf, 'cursor-moved')
 
         if sn in self.active_snippets:
             # Check if we can get end_iter in view without moving the
diff --git a/plugins/spell/gedit-spell-plugin.c b/plugins/spell/gedit-spell-plugin.c
index 611677826..47d449433 100644
--- a/plugins/spell/gedit-spell-plugin.c
+++ b/plugins/spell/gedit-spell-plugin.c
@@ -30,8 +30,13 @@
 
 #include "gedit-spell-app-activatable.h"
 
-#define GEDIT_METADATA_ATTRIBUTE_SPELL_LANGUAGE "gedit-spell-language"
-#define GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED  "gedit-spell-enabled"
+#ifdef G_OS_WIN32
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_LANGUAGE "spell-language"
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED  "spell-enabled"
+#else
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_LANGUAGE "metadata::gedit-spell-language"
+#define GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED  "metadata::gedit-spell-enabled"
+#endif
 
 #define SPELL_ENABLED_STR "1"
 #define SPELL_BASE_SETTINGS    "org.gnome.gedit.plugins.spell"
diff --git a/po/POTFILES.in b/po/POTFILES.in
index be8af499a..25ff2db1a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -16,19 +16,22 @@ gedit/gedit-documents-panel.c
 gedit/gedit-encodings-combo-box.c
 gedit/gedit-encoding-items.c
 gedit/gedit-encodings-dialog.c
-gedit/gedit-factory.c
 gedit/gedit-file-chooser.c
 gedit/gedit-file-chooser-dialog-gtk.c
 gedit/gedit-file-chooser-open.c
 gedit/gedit-file-chooser-open-dialog.c
 gedit/gedit-file-chooser-open-native.c
+gedit/gedit-highlight-mode-dialog.c
+gedit/gedit-highlight-mode-selector.c
 gedit/gedit-io-error-info-bar.c
 gedit/gedit-notebook.c
 gedit/gedit-notebook-popup-menu.c
+gedit/gedit-open-document-selector.c
 gedit/gedit-plugins-engine.c
 gedit/gedit-preferences-dialog.c
 gedit/gedit-print-job.c
 gedit/gedit-print-preview.c
+gedit/gedit-progress-info-bar.c
 gedit/gedit-replace-dialog.c
 gedit/gedit-statusbar.c
 gedit/gedit-tab.c
@@ -41,6 +44,9 @@ gedit/resources/gtk/menus-common.ui
 gedit/resources/gtk/menus.ui
 gedit/resources/gtk/menus-traditional.ui
 gedit/resources/ui/gedit-encodings-dialog.ui
+gedit/resources/ui/gedit-highlight-mode-dialog.ui
+gedit/resources/ui/gedit-highlight-mode-selector.ui
+gedit/resources/ui/gedit-open-document-selector.ui
 gedit/resources/ui/gedit-preferences-dialog.ui
 gedit/resources/ui/gedit-print-preferences.ui
 gedit/resources/ui/gedit-print-preview.ui


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