Blob Blame History Raw
From b190bdb716fc8bb0cd515ee10fb3c51debede5fa Mon Sep 17 00:00:00 2001
From: Zander Brown <zbrown@gnome.org>
Date: Tue, 13 Apr 2021 04:53:21 +0000
Subject: [PATCH] deteplification: the mega commit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This commit is a reverse patch of a rebased version of gedit with
commits related to tepl/amtk removed

Sébastien Wilmet has stopped development of these libraries, relevant
commits:

https://gitlab.gnome.org/GNOME/amtk/-/commit/34a1171298808e5d9bd50540ee194b8be35bce9d
https://gitlab.gnome.org/GNOME/tepl/-/commit/457b5c37ebcb2ebb23cae10cd47f1342db45a98e

As a result usage is being dropped in favour simplifing gedit
dependencies, because there are not enough developers, and too many bugs.
Do you prefer a rock-solid text editor? Or a text editor with some shiny
and non-essential dependencies that complicate the build, at the expense
of more bugs?

Tracked at: https://gitlab.gnome.org/Infrastructure/Infrastructure/-/issues/564

Commits Dropped:
cfeb7cb6c build: add Tepl dependency, second try
872fb4809 Utils: use str truncate functions from Tepl
9a121d523 Utils: deprecate str_end_truncate()
e0e602799 No longer use gedit_utils_str_end_truncate()
657ce9f7a Utils: deprecate str_middle_truncate()
6eefa74c2 No longer use gedit_utils_str_middle_truncate()
169c1594e main: call tepl_init() and tepl_finalize()
ec31f0c22 snap: Fixed build failures by added tepl part
76cf5562d Document: remove metadata implementation
75cdb6a77 Document: second pass to remove metadata implementation
d6b158ca6 App: remove the GeditMetadataManager
6eccd6672 Remove GeditMetadataManager
03929157e build: remove enable-gvfs-metadata option
1dad3bce2 build: remove libxml dependency
8c0825424 metadata: adapt key names for TeplFileMetadata
c2904aa80 Document: metadata: create an internal TeplFile
9c8ede1e2 App: setup Tepl metadata manager
91bc04efc App: remove leftover comment
b39dd0201 Document: use TeplFileMetadata to re-implement set/get_metadata()
494677bfc Utils: use tepl_utils_replace_home_dir_with_tilde()
aaaa28a87 docs: gtk-doc fixxref: fix the path for gtk and add path for tepl
8710e89d8 Remove GeditViewCentering
5e0909c19 ViewFrame: disable overlay scrolling for the GtkScrolledWindow
7c7296b0e Remove overview map: remove from preferences dialog
26899e0ba Remove overview map
27f54a9ae replace-open-button: remove OpenDocumentSelector
504ced5a9 replace-open-button: Window: remove open document popover
3a8c5bbc2 replace-open-button: remove open button UI
abab6529f replace-open-button: re-create a simple Open button
1ee984a41 replace-open-button: re-create simple Open Recent menu button (UI)
f1a58a70b replace-open-button: set Open Recent menu with Amtk
020e0b340 replace-open-button: re-handle the fullscreen mode
4dfd2104e Window: remove dead code (#defines)
0caf371b1 Window: make the code a little clearer wrt fullscreen mode
584aeb202 Window: rename fullscreen_controls -> fullscreen_revealer
75705bf1d Window: some code cleanup wrt fullscreen mode
cf0d62617 Window: simplify setting the state of the fullscreen revealer
8706e5624 Window: fullscreen mode: remove idle function
6361b281c Window: fullscreen mode: remove no longer needed code
8d3e6faf2 Window: fullscreen mode: fix headerbar shown/hidden "stuttering"
a437e5245 Window: fullscreen mode: add comment about the "stuttering" fix
d064c5f88 Window: remove useless #include
15833e5c7 build: list of deps: simplify
007caff57 build: list of deps: simplify version requirements
72dc3a477 build: avoid the use of a variable
4a49c8562 flatpak: update Amtk to 5.0.2
9ab7b0f0a utils: remove GBOOLEAN_TO_POINTER() and GPOINTER_TO_BOOLEAN()
55c5f1423 Utils: deprecate gedit_warning()
cbdd3a85d PreferencesDialog: use tepl_utils_show_warning_dialog()
7a442c766 Utils: deprecate decode_uri(), use the tepl one
bf3d57003 Use tepl_utils_decode_uri()
2e45bb03f io-error-info-bar: remove useless #include's
092411115 io-error-info-bar: use TeplInfoBar for the file_already_open_warning
8ccb4566f io-error-info-bar: file_already_open_warning moved to Tepl
8bfe0559a io-error-info-bar: use TeplInfoBar for no_backup_saving_error
ca582d2c7 io-error-info-bar: fix fixme in no_backup_saving_error
fa1758081 io-error-info-bar: no_backup_saving_error: show also error->message
321eccdd7 io-error-info-bar: no_back_saving_error moved to Tepl
7bb880114 io-error-info-bar: tepl function renamed to have a shorter name
d1a14a063 io-error-info-bar: externally_modified: use TeplInfoBar
bf60cc1af io-error-info-bar: invalid_character: TeplInfoBar + other improvements
44cff9798 io-error-info-bar: externally_modified: remove unneeded code
873ed25f1 io-error-info-bar: externally_modified: further simplify the code
a8a4724fc io-error-info-bar: externally_modified: moved to Tepl
ec8d8c717 io-error-info-bar: invalid_character: moved to Tepl
2aae17c31 flatpak: switch Tepl to Meson
9caaddeda Window: fix RTL bug for Open buttons in the headerbar
82d8c507d View: subclass TeplView
e23569c59 View: deprecate lots of functions, use the TeplView ones
291eb9c8e commands-edit: use TeplView functions
00f8c5e63 Use tepl_view_scroll_to_cursor()
5fdeaee22 Document: deprecate goto_line() and goto_line_offset()
d87bf25ba commands-file: use tepl_view_goto_line*()
fd5500d90 Tab: use tepl_view_goto_line_offset()
3c8a1dcb8 ViewFrame: use tepl_view_goto_line*()
079f9699e pkg-config file: add Tepl as public dep
cf6281d04 docs: document that gedit is in the process of using more Tepl features
9ac62a6fd build: require Tepl 5
3f84484d8 App: port to new Tepl metadata API
9b9fa6c77 Document: port to new Tepl metadata API
491280c04 docs: roadmap: link to new Tepl roadmap
49db2a666 PreferencesDialog: use TeplStyleSchemeChooserWidget to fix several bugs
94c3b70cb PreferencesDialog: improvements to color scheme management
53cfa1715 PreferencesDialog: fix some bugs when (un)installing color schemes
da5b9af9f snap: the tepl build is meson only now
012a07cb7 snap: use the correct option to specify parameters
325aa857c Factory: class skeleton
7b8579770 Factory: implement ::create_metadata_manager_file vfunc
d5a43cece Factory: create it in main() and set it as the TeplAbstractFactory
392545195 App: use tepl_application_handle_metadata()
8b2fa9092 Keep default buttons orientation for TeplInfoBars
efe48bbe8 flatpak: remove uchardet, Tepl no longer depends on it
5e588d978 PreferencesDialog: improve code to install extra style scheme
eada68d97 PreferencesDialog: use GtkFileChooserNative, not GeditFileChooserDialog
55fc5973c FileChooserDialog: remove hide() (now dead code)
4f5a5681b FileChooserDialog: remove add_pattern_filter() (now dead code)
105ca1ded File choosers: remove GeditFileChooserFlags
ff1e9c27c Update Romanian translation
b4a52f479 Merge branch 'master' of gitlab.gnome.org:GNOME/gedit
21d94f23b Remove all the deprecated API
4b5838b1e docs: update path to Amtk docs for the gtk-doc fixxref_args
a4cf3ac57 Use tepl_pango_font_description_to_css()
205bfc855 Window: port to TeplLanguageChooserWidget
ffedbc882 commands-view: port to TeplLanguageChooserDialog
1dc325294 Remove GeditHighlightModeSelector and GeditHighlightModeDialog
e487680b2 Use Tepl 6 (currently 5.99)
ee465ef0c Tab: port to TeplProgressInfoBar
bc992e11e Remove GeditProgressInfoBar, replaced by TeplProgressInfoBar
fa9d6aeaa docs: document the GeditProgressInfoBar removal
bb4ba5543 docs: document that all deprecated APIs have been removed
325351805 GeditDocument: subclass TeplBuffer
8b01acace GeditDocument: remove the ::cursor-moved signal
b938c50f8 Use the TeplBuffer::tepl-cursor-moved signal
6b6a6e595 GeditDocument: bind GtkSourceFile and TeplFile :location properties
f73828fe1 GeditDocument: remove unused instance variable
01d8a1577 flatpak: build amtk from git master, not from an archive
6e78a57c9 GeditDocument: use tepl_file_get_short_name()
49749c38a GeditDocument: remove untitled_number handling
844f6185a Tab: use TeplFile:short-name property notification
49c0c814a GeditDocument: remove the :shortname property
a4670d7ce help: "Untitled Document" -> "Untitled File"
4d4d5d48c Use tepl_buffer_is_untouched()
b0f67d391 GeditDocument: remove is_untouched()
85b007052 GeditDocument: use the TeplFile location in is_untitled()
4df850fb6 View: use TeplSignalGroup
ef0d0ca9b View: minor code changes
284e6c05c View: make set_font() private
6b1e782d9 View: code refactorings for set_font()
ce790b510 View: use tepl_utils_override_font()
79b3e3011 GeditSettings: remove no longer needed code
da4b3e61a GeditSettings: minor code change: removed unused function param
13033affa GeditSettings: rework fonts changes handling, add ::fonts-changed signal
878ceb988 GeditSettings: minor code change, improve get_system_font()
1e89921a3 GeditSettings: add get_selected_font()
9ef4cf7ed View: simplify the code to update the font
3a3de93bd debug: remove DEBUG_METADATA (dead code)
43925dac7 recent: use the TeplFile
2f7c4a691 recent: move some functions to gedit-recent-osx
87b1f50d4 recent-osx: add TODO comment

Brought to you by GitLens, which honesntly has been very useful
unpicking all this and sticking it back together again
---
 NEWS                                          |   12 +
 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                 |   50 +
 docs/reference/gedit-docs.xml                 |    1 +
 docs/reference/gedit-sections.txt             |   36 +
 docs/reference/meson.build                    |    6 +-
 docs/roadmap-done.md                          |   56 -
 docs/roadmap.md                               |   19 +-
 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 +
 .../ui/gedit-highlight-mode-dialog.ui         |   87 ++
 .../ui/gedit-highlight-mode-selector.ui       |   83 ++
 .../ui/gedit-open-document-selector.ui        |  115 ++
 .../resources/ui/gedit-preferences-dialog.ui  |   30 +-
 gedit/resources/ui/gedit-progress-info-bar.ui |   88 ++
 gedit/resources/ui/gedit-view-frame.ui        |   27 +-
 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 +-
 86 files changed, 8160 insertions(+), 1283 deletions(-)
 delete mode 100644 docs/roadmap-done.md
 delete mode 100644 gedit/gedit-factory.c
 delete mode 100644 gedit/gedit-factory.h
 create mode 100644 gedit/gedit-highlight-mode-dialog.c
 create mode 100644 gedit/gedit-highlight-mode-dialog.h
 create mode 100644 gedit/gedit-highlight-mode-selector.c
 create mode 100644 gedit/gedit-highlight-mode-selector.h
 create mode 100644 gedit/gedit-metadata-manager.c
 create mode 100644 gedit/gedit-metadata-manager.h
 create mode 100644 gedit/gedit-open-document-selector-helper.c
 create mode 100644 gedit/gedit-open-document-selector-helper.h
 create mode 100644 gedit/gedit-open-document-selector-store.c
 create mode 100644 gedit/gedit-open-document-selector-store.h
 create mode 100644 gedit/gedit-open-document-selector.c
 create mode 100644 gedit/gedit-open-document-selector.h
 create mode 100644 gedit/gedit-pango.c
 create mode 100644 gedit/gedit-pango.h
 create mode 100644 gedit/gedit-progress-info-bar.c
 create mode 100644 gedit/gedit-progress-info-bar.h
 delete mode 100644 gedit/gedit-recent-osx.c
 delete mode 100644 gedit/gedit-recent-osx.h
 create mode 100644 gedit/gedit-view-centering.c
 create mode 100644 gedit/gedit-view-centering.h
 create mode 100644 gedit/resources/ui/gedit-highlight-mode-dialog.ui
 create mode 100644 gedit/resources/ui/gedit-highlight-mode-selector.ui
 create mode 100644 gedit/resources/ui/gedit-open-document-selector.ui
 create mode 100644 gedit/resources/ui/gedit-progress-info-bar.ui

diff --git a/NEWS b/NEWS
index e7f2c81f3..476a367a7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+News in [unreleased]
+----------------------------
+* Deteplification:
+   - The tepl maintainer has "frozen" the project until further notice
+   - Moving things to tepl introduced some breakage, such as translation of the
+     default filename
+   - gedit didn't use much of the API anyway
+   - Used even less of amtk
+   - Revert all usage of amtk and tepl
+   - Unfortunatly a couple bug fixes may have been lost
+   - Plugin API is essentially reverted to 3.36
+
 News in 40.1, 2021-04-17
 ------------------------
 * Use document folder when opening new files
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
@@ -32,56 +32,51 @@ cleanup:
   - "/share/aclocal"
   - "/man"
   - "/share/man"
   - "/share/gtk-doc"
   - "/share/vala"
   - "/share/gir-1.0"
   - "*.la"
   - "*.a"
 
 modules:
   - name: libpeas
     buildsystem: meson
     config-opts:
       - "-Dlua51=false"
       - "-Dvapi=true"
       - "-Ddemos=false"
       - "-Dglade_catalog=false"
     sources:
       - type: archive
         url: https://download.gnome.org/sources/libpeas/1.28/libpeas-1.28.0.tar.xz
         sha256: 42d91993b46ed50f16add6d9577ecc22beb8e2dffa7101e2232c2b63733b8b15
 
   - name: gspell
     cleanup:
       - "/bin"
     sources:
       - type: archive
         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
     sources:
       - type: git
         url: https://gitlab.gnome.org/GNOME/gedit.git
         # To build a local branch, comment out 'url' and uncomment:
         # path: ../../
         # branch: wip/misc
 
   - name: gedit-plugins
     buildsystem: meson
     sources:
       - type: git
         url: https://gitlab.gnome.org/GNOME/gedit-plugins.git
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
@@ -14,121 +14,98 @@ layout:
     symlink: $SNAP/usr/share/gedit
 
 slots:
   # for GtkApplication registration
   gedit:
     interface: dbus
     bus: session
     name: org.gnome.gedit
 
 apps:
   gedit:
     command: usr/bin/gedit
     extensions: [gnome-3-28]
     plugs:
       - avahi-observe
       - cups-control
       - gsettings
       - home
       - network
       - mount-observe
       - removable-media
     common-id: org.gnome.gedit.desktop
     environment:
       GSETTINGS_SCHEMA_DIR: $SNAP/share/glib-2.0/schemas
       LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/lib/$SNAPCRAFT_ARCH_TRIPLET/gedit:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/gnome-platform/usr/lib/$SNAPCRAFT_ARCH_TRIPLET
       GI_TYPELIB_PATH: $SNAP/usr/lib/girepository-1.0:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/gedit/girepository-1.0:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/girepository-1.0:$SNAP/gnome-platform/usr/lib/girepository-1.0:$SNAP/gnome-platform/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/girepository-1.0
       PYTHONPATH: $SNAP/usr/lib/python3/dist-packages:$SNAP/gnome-platform/usr/lib/python3/dist-packages
       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
     plugin: meson
     meson-parameters:
       - --prefix=/usr
       - -Dc_args="-Wno-error=undef"
     organize:
       snap/gedit/current/usr: usr
     build-packages:
       - autoconf-archive
       - gettext
       - gobject-introspection
       - gtk-doc-tools
       - libfribidi-dev
       - libgirepository1.0-dev
       - libglib2.0-dev
       - libgtk-3-dev
       - libpeas-dev
       - libxml2-dev
       - libxml2-utils
       - valac
     # meson gir overrides don't work well
     override-build: |
        snapcraftctl build
        cp $SNAPCRAFT_PART_INSTALL/usr/share/gir-1.0/GtkSource* /usr/share/gir-1.0
        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]
     plugin: meson
     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: |
        sed -i.bak -e 's|Icon=org.gnome.gedit$|Icon=${SNAP}/meta/gui/org.gnome.gedit.svg|g' data/org.gnome.gedit.desktop.in
        sed -i.bak -e "s|symlink_media: true|symlink_media: false|g" help/meson.build
        snapcraftctl build
        mkdir -p $SNAPCRAFT_PART_INSTALL/meta/gui/
        cp data/icons/org.gnome.gedit.svg $SNAPCRAFT_PART_INSTALL/meta/gui/
        cp ../install/usr/share/applications/org.gnome.gedit.desktop $SNAPCRAFT_PART_INSTALL/meta/gui/
     build-packages:
       - desktop-file-utils
       - gettext
       - gsettings-desktop-schemas-dev
       - gtk-doc-tools
       - itstool
       - libsoup2.4-dev
       - libgspell-1-dev
       - libxml2-dev
       - libglib2.0-dev
       - libgtk-3-dev
       - libpeas-dev
       - libx11-dev
       - python3
       - python-gi-dev
       - gobject-introspection
       - libgirepository1.0-dev
       - valac
     stage-packages:
       - libfribidi0
 
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
@@ -99,60 +99,65 @@
     <key name="auto-indent" type="b">
       <default>true</default>
       <summary>Automatic indent</summary>
       <description>Whether gedit should enable automatic indentation.</description>
     </key>
     <key name="display-line-numbers" type="b">
       <default>true</default>
       <summary>Display Line Numbers</summary>
       <description>Whether gedit should display line numbers in the editing area.</description>
     </key>
     <key name="highlight-current-line" type="b">
       <default>true</default>
       <summary>Highlight Current Line</summary>
       <description>Whether gedit should highlight the current line.</description>
     </key>
     <key name="bracket-matching" type="b">
       <default>true</default>
       <summary>Highlight Matching Brackets</summary>
       <description>Whether gedit should highlight matching brackets.</description>
     </key>
     <key name="display-right-margin" type="b">
       <default>false</default>
       <summary>Display Right Margin</summary>
       <description>Whether gedit should display the right margin in the editing area.</description>
     </key>
     <key name="right-margin-position" type="u">
       <default>80</default>
       <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>
       <description>Whether the document will get a background pattern painted.</description>
     </key>
     <key name="smart-home-end" enum="org.gnome.gedit.SmartHomeEnd">
       <aliases>
         <alias value='DISABLED' target='disabled'/>
         <alias value='BEFORE' target='before'/>
         <alias value='AFTER' target='after'/>
         <alias value='ALWAYS' target='always'/>
       </aliases>
       <default>'after'</default>
       <summary>Smart Home End</summary>
       <description>Specifies how the cursor moves when the HOME and END keys are pressed. Use “disabled” to always move at the start/end of the line, “after” to move to the start/end of the line the first time the keys are pressed and to the start/end of the text ignoring whitespaces the second time the keys are pressed, “before” to move to the start/end of the text before moving to the start/end of the line and “always” to always move to the start/end of the text instead of the start/end of the line.</description>
     </key>
     <key name="restore-cursor-position" type="b">
       <default>true</default>
       <summary>Restore Previous Cursor Position</summary>
       <description>Whether gedit should restore the previous cursor position when a file is loaded.</description>
     </key>
     <key name="syntax-highlighting" type="b">
       <default>true</default>
       <summary>Enable Syntax Highlighting</summary>
       <description>Whether gedit should enable syntax highlighting.</description>
     </key>
     <key name="search-highlighting" type="b">
       <default>true</default>
       <summary>Enable Search Highlighting</summary>
       <description>Whether gedit should highlight all the occurrences of the searched text.</description>
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
@@ -4,65 +4,63 @@ gedit development - getting started
 The following explanations can be improved over time, if you see something
 missing, a feedback is welcome.
 
 Programming languages and paradigms
 -----------------------------------
 
 gedit is mostly written in C, with some plugins in Python or
 [Vala](https://wiki.gnome.org/Projects/Vala/). The build system is in
 [Meson](https://mesonbuild.com/).
 
 The code is object-oriented and event-driven. In C, it's thanks to the use of
 the GObject library (see next section). If you open some `*.c` or `*.h` files,
 you may think “what is this horror?!” but – don't panic – it's just some
 C/GObject boilerplate code, and that boilerplate can be generated by a tool. So
 once you've learned GObject, you will no longer be afraid ;-)
 
 Libraries used
 --------------
 
 As every GNOME application, gedit uses the GLib, GObject and GTK libraries. To
 modify the gedit source code, you should be familiar with those libraries. See
 the [GTK website](https://www.gtk.org/) and the document
 [The GLib/GTK Development Platform – A Getting Started Guide](https://people.gnome.org/~swilmet/glib-gtk-book/).
 
 The main widget used by gedit is GtkTextView, a general-purpose multiline text
 editor. To learn that widget API, read the excellent
 [GtkTextView tutorial](http://www.bravegnu.org/gtktext/) (a bit old but still
 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.
 
 Plugins may have other dependencies, for example the spell-checking plugin uses
 [gspell](https://wiki.gnome.org/Projects/gspell).
 
 gedit architecture
 ------------------
 
 The [gedit Git repository](https://gitlab.gnome.org/GNOME/gedit) contains the
 _gedit core_ plus the default plugins. There is also the
 [gedit-plugins Git repository](https://gitlab.gnome.org/GNOME/gedit-plugins)
 for additional official plugins. The gedit core source code is in the `gedit/`
 directory. The plugins are in … `plugins/`!
 
 gedit core provides:
 - A basic text editor.
 - The integration of libpeas, with an API for plugins.
 
 There is a class diagram of gedit core in the file
 [class-diagram.dia](class-diagram.dia) (but it may be outdated, see the Git log
 for that file).
 
 Build/Installation
 ------------------
 
 See the file [build.md](build.md).
 
 First contribution
diff --git a/docs/reference/api-breaks.xml b/docs/reference/api-breaks.xml
index f631761a6..f03c35975 100644
--- a/docs/reference/api-breaks.xml
+++ b/docs/reference/api-breaks.xml
@@ -1,53 +1,103 @@
 <?xml version="1.0"?>
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
    "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
 [
  <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
 ]>
 
 <part id="api-breaks">
   <title>API Breaks</title>
 
   <para>
     gedit is a quite old piece of software (created in 1998, at the beginnings
     of the GNOME project), and as every software, the code evolves during its
     lifetime. So there are sometimes API breaks for gedit plugins, there are no
     API stability guarantees.
   </para>
 
   <para>
     When it is possible, instead of directly removing an API, that API is first
     marked as deprecated, and then removed for the next API break. See the
     <link linkend="api-index-deprecated">index of deprecated symbols</link>.
   </para>
 
+  <refsect1>
+    <title>40 -> 41</title>
+    <itemizedlist>
+      <listitem>
+        <para>
+          The <code>GeditProgressInfoBar</code> class has been restored
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link linkend="GeditDocument">GeditDocument</link> is no longer a subclass
+          of <link linkend="TeplBuffer">TeplBuffer</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          The <code>GeditDocument::cursor-moved</code> signal has been restored.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          The <code>GeditDocument:shortname</code> property has been restored.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          The <code>gedit_document_is_untouched()</code> function has been
+          restored.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          The <code>gedit_view_set_font()</code> function has been restored.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <code>DEBUG_METADATA</code> has been restored.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          The <code>GBOOLEAN_TO_POINTER()</code> and
+          <code>GPOINTER_TO_BOOLEAN()</code> macros have been restored to
+          <code>gedit-utils.h</code>.
+        </para>
+      </listitem>
+    </itemizedlist>
+  </refsect1>
+
   <refsect1>
     <title>3.38 -> 40</title>
     <itemizedlist>
       <listitem>
         <para>
           All previously deprecated APIs have been removed.
         </para>
       </listitem>
       <listitem>
         <para>
           The <code>GeditProgressInfoBar</code> class has been removed, you can
           use <link linkend="TeplProgressInfoBar">TeplProgressInfoBar</link>
           instead.
         </para>
       </listitem>
       <listitem>
         <para>
           <link linkend="GeditDocument">GeditDocument</link> is now a subclass
           of <link linkend="TeplBuffer">TeplBuffer</link>.
         </para>
       </listitem>
       <listitem>
         <para>
           The <code>GeditDocument::cursor-moved</code> signal has been removed.
           You can use the <link linkend="TeplBuffer">TeplBuffer</link> API
           instead.
         </para>
       </listitem>
       <listitem>
         <para>
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
@@ -1,48 +1,49 @@
 <?xml version="1.0"?>
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
                "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
 <book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
   <bookinfo>
     <title>gedit Reference Manual</title>
   </bookinfo>
 
   <part id="api-reference">
     <title>API Reference</title>
     <xi:include href="xml/gedit-app.xml"/>
     <xi:include href="xml/gedit-app-activatable.xml"/>
     <xi:include href="xml/gedit-commands.xml"/>
     <xi:include href="xml/gedit-document.xml"/>
     <xi:include href="xml/gedit-encodings-combo-box.xml"/>
     <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"/>
     <xi:include href="xml/gedit-view-activatable.xml"/>
     <xi:include href="xml/gedit-window.xml"/>
     <xi:include href="xml/gedit-window-activatable.xml"/>
     <xi:include href="xml/gedit-debug.xml"/>
     <xi:include href="xml/gedit-utils.xml"/>
   </part>
 
   <xi:include href="api-breaks.xml"/>
 
   <part id="annexes">
     <title>Annexes</title>
 
     <chapter>
       <title>Object Hierarchy</title>
        <xi:include href="xml/tree_index.sgml"/>
     </chapter>
 
     <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
 
     <index>
       <title>Index of all symbols</title>
       <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
     </index>
     <index role="deprecated">
       <title>Index of deprecated symbols</title>
       <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
     </index>
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
@@ -27,61 +27,64 @@ gedit_app_activatable_activate
 gedit_app_activatable_deactivate
 gedit_app_activatable_extend_menu
 <SUBSECTION Standard>
 GEDIT_TYPE_APP_ACTIVATABLE
 GEDIT_APP_ACTIVATABLE
 GEDIT_APP_ACTIVATABLE_IFACE
 GEDIT_IS_APP_ACTIVATABLE
 GEDIT_APP_ACTIVATABLE_GET_IFACE
 gedit_app_activatable_get_type
 </SECTION>
 
 <SECTION>
 <FILE>gedit-commands</FILE>
 <TITLE>GeditCommands</TITLE>
 gedit_commands_load_location
 gedit_commands_load_locations
 gedit_commands_save_document
 gedit_commands_save_document_async
 gedit_commands_save_document_finish
 gedit_commands_save_all_documents
 </SECTION>
 
 <SECTION>
 <FILE>gedit-document</FILE>
 <TITLE>GeditDocument</TITLE>
 GeditDocument
 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
 gedit_document_set_metadata
 gedit_document_set_search_context
 gedit_document_get_search_context
 <SUBSECTION Standard>
 GEDIT_DOCUMENT
 GEDIT_IS_DOCUMENT
 GEDIT_TYPE_DOCUMENT
 gedit_document_get_type
 GEDIT_DOCUMENT_CLASS
 GEDIT_IS_DOCUMENT_CLASS
 GEDIT_DOCUMENT_GET_CLASS
 </SECTION>
 
 <SECTION>
 <FILE>gedit-encodings-combo-box</FILE>
 <TITLE>GeditEncodingsComboBox</TITLE>
 GeditEncodingsComboBox
 gedit_encodings_combo_box_new
 gedit_encodings_combo_box_get_selected_encoding
 gedit_encodings_combo_box_set_selected_encoding
 <SUBSECTION Standard>
 GEDIT_ENCODINGS_COMBO_BOX
 GEDIT_IS_ENCODINGS_COMBO_BOX
 GEDIT_TYPE_ENCODINGS_COMBO_BOX
 gedit_encodings_combo_box_get_type
 GEDIT_ENCODINGS_COMBO_BOX_CLASS
 GEDIT_IS_ENCODINGS_COMBO_BOX_CLASS
@@ -121,111 +124,138 @@ GEDIT_TYPE_MESSAGE_BUS
 gedit_message_bus_get_type
 GEDIT_MESSAGE_BUS_CLASS
 GEDIT_IS_MESSAGE_BUS_CLASS
 GEDIT_MESSAGE_BUS_GET_CLASS
 GeditMessageBusPrivate
 </SECTION>
 
 <SECTION>
 <FILE>gedit-message</FILE>
 <TITLE>GeditMessage</TITLE>
 GeditMessage
 gedit_message_get_object_path
 gedit_message_get_method
 gedit_message_type_has
 gedit_message_type_check
 gedit_message_has
 gedit_message_is_valid_object_path
 gedit_message_type_identifier
 <SUBSECTION Standard>
 GEDIT_MESSAGE
 GEDIT_MESSAGE_CONST
 GEDIT_IS_MESSAGE
 GEDIT_TYPE_MESSAGE
 gedit_message_get_type
 GEDIT_MESSAGE_CLASS
 GEDIT_IS_MESSAGE_CLASS
 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>
 GeditStatusbar
 gedit_statusbar_new
 gedit_statusbar_set_window_state
 gedit_statusbar_set_overwrite
 gedit_statusbar_clear_overwrite
 gedit_statusbar_flash_message
 <SUBSECTION Standard>
 GEDIT_STATUSBAR
 GEDIT_IS_STATUSBAR
 GEDIT_TYPE_STATUSBAR
 gedit_statusbar_get_type
 GEDIT_STATUSBAR_CLASS
 GEDIT_IS_STATUSBAR_CLASS
 GEDIT_STATUSBAR_GET_CLASS
 </SECTION>
 
 <SECTION>
 <FILE>gedit-tab</FILE>
 <TITLE>GeditTab</TITLE>
 GeditTab
 GeditTabState
 gedit_tab_get_view
 gedit_tab_get_document
 gedit_tab_get_from_document
 gedit_tab_get_state
 gedit_tab_get_auto_save_enabled
 gedit_tab_set_auto_save_enabled
 gedit_tab_get_auto_save_interval
 gedit_tab_set_auto_save_interval
 gedit_tab_set_info_bar
 <SUBSECTION Standard>
 GEDIT_TAB
 GEDIT_IS_TAB
 GEDIT_TYPE_TAB
 gedit_tab_get_type
 GEDIT_TAB_CLASS
 GEDIT_IS_TAB_CLASS
 GEDIT_TAB_GET_CLASS
 GEDIT_TYPE_TAB_STATE
 gedit_tab_state_get_type
 </SECTION>
 
 <SECTION>
 <FILE>gedit-view</FILE>
 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
 GEDIT_TYPE_VIEW
 gedit_view_get_type
 GEDIT_VIEW_CLASS
 GEDIT_IS_VIEW_CLASS
 GEDIT_VIEW_GET_CLASS
 </SECTION>
 
 <SECTION>
 <FILE>gedit-view-activatable</FILE>
 <TITLE>GeditViewActivatable</TITLE>
 GeditViewActivatable
 gedit_view_activatable_activate
 gedit_view_activatable_deactivate
 <SUBSECTION Standard>
 GEDIT_TYPE_VIEW_ACTIVATABLE
 GEDIT_VIEW_ACTIVATABLE
 GEDIT_VIEW_ACTIVATABLE_IFACE
 GEDIT_IS_VIEW_ACTIVATABLE
 GEDIT_VIEW_ACTIVATABLE_GET_IFACE
 gedit_view_activatable_get_type
 </SECTION>
 
 <SECTION>
 <FILE>gedit-window</FILE>
 <TITLE>GeditWindow</TITLE>
 GeditWindow
 GeditWindowState
@@ -264,70 +294,76 @@ gedit_window_state_get_type
 
 <SECTION>
 <FILE>gedit-window-activatable</FILE>
 <TITLE>GeditWindowActivatable</TITLE>
 GeditWindowActivatable
 gedit_window_activatable_activate
 gedit_window_activatable_deactivate
 gedit_window_activatable_update_state
 <SUBSECTION Standard>
 GEDIT_TYPE_WINDOW_ACTIVATABLE
 GEDIT_WINDOW_ACTIVATABLE
 GEDIT_WINDOW_ACTIVATABLE_IFACE
 GEDIT_IS_WINDOW_ACTIVATABLE
 GEDIT_WINDOW_ACTIVATABLE_GET_IFACE
 gedit_window_activatable_get_type
 </SECTION>
 
 <SECTION>
 <FILE>gedit-debug</FILE>
 GeditDebugSection
 DEBUG_VIEW
 DEBUG_PREFS
 DEBUG_WINDOW
 DEBUG_PANEL
 DEBUG_PLUGINS
 DEBUG_TAB
 DEBUG_DOCUMENT
 DEBUG_COMMANDS
 DEBUG_APP
 DEBUG_UTILS
+DEBUG_METADATA
 gedit_debug_init
 gedit_debug
 gedit_debug_message
 gedit_debug_plugin_message
 <SUBSECTION Standard>
 GEDIT_TYPE_DEBUG_SECTION
 gedit_debug_section_get_type
 </SECTION>
 
 <SECTION>
 <FILE>gedit-menu-extension</FILE>
 GeditMenuExtension
 gedit_menu_extension_new
 gedit_menu_extension_append_menu_item
 gedit_menu_extension_prepend_menu_item
 gedit_menu_extension_remove_items
 <SUBSECTION Standard>
 GEDIT_IS_MENU_EXTENSION
 GEDIT_IS_MENU_EXTENSION_CLASS
 GEDIT_MENU_EXTENSION
 GEDIT_MENU_EXTENSION_CLASS
 GEDIT_MENU_EXTENSION_CONST
 GEDIT_MENU_EXTENSION_GET_CLASS
 GEDIT_TYPE_MENU_EXTENSION
 GeditMenuExtensionClass
 gedit_menu_extension_get_type
 </SECTION>
 
 <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
 gedit_utils_location_get_dirname_for_display
 gedit_utils_set_direct_save_filename
 gedit_utils_newline_type_to_string
 </SECTION>
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
@@ -1,42 +1,38 @@
 html_dir = get_option('prefix') / gnome.gtkdoc_html_dir('gedit')
 
 glib_docpath = dependency('glib-2.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/glib'
 gobject_docpath = dependency('gobject-2.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/gobject'
 gio_docpath = dependency('gio-2.0').get_pkgconfig_variable('prefix') / 'share/gtk-doc/html/gio'
 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(
   'gedit',
   main_xml: 'gedit-docs.xml',
   src_dir: include_directories('../../gedit/'),
   dependencies: gedit_doc_dep,
   scan_args: ['--rebuild-types'],
   fixxref_args: [
     '--html-dir=@0@'.format(html_dir),
     '--extra-dir=@0@'.format(glib_docpath),
     '--extra-dir=@0@'.format(gobject_docpath),
     '--extra-dir=@0@'.format(gio_docpath),
     '--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: [
     'api-breaks.xml'
   ],
   ignore_headers: libgedit_private_headers,
   install: true,
 )
diff --git a/docs/roadmap-done.md b/docs/roadmap-done.md
deleted file mode 100644
index 7f210e49b..000000000
--- a/docs/roadmap-done.md
+++ /dev/null
@@ -1,56 +0,0 @@
-gedit roadmap - done tasks
-==========================
-
-Tepl-ification of the gedit core
---------------------------------
-
-- gedit 3.36:
-	- Start to use the Tepl library.
-	- Use some Tepl utility functions.
-	- Use TeplFileMetadata, remove GeditMetadataManager.
-- gedit 3.38:
-	- Move some utility functions to the Tepl library.
-	- Refactor and move some I/O error infobars to Tepl.
-	- GeditView now inherits from TeplView.
-	- Port to the new Tepl metadata API.
-	- Use TeplStyleSchemeChooserWidget in the preferences dialog.
-	- Create GeditFactory class, subclass of TeplAbstractFactory.
-- gedit 40:
-	- Use `tepl_pango_font_description_to_css()`.
-	- Use TeplLanguageChooser's, for choosing a language for the syntax
-	  highlighting. Remove GeditHighlightModeSelector and
-	  GeditHighlightModeDialog.
-	- Use TeplProgressInfoBar. Remove GeditProgressInfoBar.
-	- GeditDocument now inherits from TeplBuffer, start to use the
-	  TeplBuffer and TeplFile APIs.
-
-Links:
-- https://wiki.gnome.org/Projects/Tepl
-
-Tepl-ification of the gedit plugins
------------------------------------
-
-- gedit 40:
-	- Draw Spaces plugin: new implementation based on TeplSpaceDrawerPrefs.
-
-Other done tasks in gedit plugins
----------------------------------
-
-- gedit 40:
-	- Smart Spaces plugin: new implementation based on a GtkSourceView
-	  feature.
-
-New version of gedit on Windows
--------------------------------
-
-[gedit is now available on the Microsoft Store](https://www.microsoft.com/store/apps/9PL1J21XF0PT).
-It was done during the GNOME 3.38 development cycle. The integration with
-Windows is not perfect, but it works. It is planned to improve gedit for
-Windows over time.
-
-Documentation for contributors
-------------------------------
-
-Write a guide to get started with gedit development.
-
-Done during the GNOME 3.34 development cycle.
diff --git a/docs/roadmap.md b/docs/roadmap.md
index 44a2f00b7..ec9445712 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -1,57 +1,40 @@
 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](https://wiki.gnome.org/Projects/GtkSourceView/RoadMap).
 
 See the [NEWS file](../NEWS) for a detailed history.
 
-See also the
-[Tepl roadmap](https://gitlab.gnome.org/GNOME/tepl/blob/master/docs/roadmap.md).
-
-Continue to make the gedit source code more re-usable
------------------------------------------------------
-
-Status: **in progress** (this is an ongoing effort)
-
-Next steps:
-- Use more features from the Tepl library, and develop Tepl alongside gedit.
-  The goal is to reduce the amount of code in gedit, by having re-usable code
-  in Tepl instead.
-
-Links:
-- https://wiki.gnome.org/Apps/Gedit/ReusableCode
-- https://wiki.gnome.org/Projects/Tepl
-
 Improve gedit on Windows
 ------------------------
 
 Status: **in progress**
 
 [gedit is now available on the Microsoft Store](https://www.microsoft.com/store/apps/9PL1J21XF0PT).
 The integration with Windows is not perfect, but it works. It is planned to
 improve gedit for Windows over time.
 
 Replace search and replace dialog window by an horizontal bar below the text
 ----------------------------------------------------------------------------
 
 Status: **todo**
 
 To not hide the text.
 
 Be able to quit the application with all documents saved, and restored on next start
 ------------------------------------------------------------------------------------
 
 Status: **todo**
 
 Even for unsaved and untitled files, be able to quit gedit, restart it later and
 come back to the state before with all tabs restored.
 
 Improve the workflow for printing to paper
 ------------------------------------------
 
 Status: **todo**
 
 Implement it like in Firefox, show first a preview of the file to print.
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
@@ -1,23 +1,24 @@
 App cheader_filename="gedit/gedit-app.h"
 AppActivatable cheader_filename="gedit/gedit-app-activatable.h"
 DebugSection cheader_filename="gedit/gedit-debug.h"
 Document cheader_filename="gedit/gedit-document.h"
 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"
 View cheader_filename="gedit/gedit-view.h"
 ViewActivatable cheader_filename="gedit/gedit-view-activatable.h"
 Window cheader_filename="gedit/gedit-window.h"
 WindowActivatable cheader_filename="gedit/gedit-window-activatable.h"
 WindowState cheader_filename="gedit/gedit-window.h"
 
 commands_* cheader_filename="gedit/gedit-commands.h"
 debug* cheader_filename="gedit/gedit-debug.h"
 utils_* cheader_filename="gedit/gedit-utils.h"
 
 MessageBusForeach cheader_filename="gedit/gedit-message-bus.h"
 MessageCallback cheader_filename="gedit/gedit-message-bus.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
@@ -4,61 +4,61 @@
  *
  * Copyright (C) 2010 - Jesse van den Kieboom
  *
  * gedit is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
  * gedit is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with gedit; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 
 #include "gedit-app-osx.h"
 
 #include <gdk/gdkquartz.h>
 #include <string.h>
 #include <glib/gi18n.h>
 
 #include "gedit-app-private.h"
 #include "gedit-dirs.h"
 #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);
 NSEvent *gdk_quartz_event_get_nsevent(GdkEvent *event);
 
 static GeditWindow *
 ensure_window (GeditAppOSX *app,
                gboolean     with_empty_document)
 {
 	GList *windows;
 	GeditWindow *ret = NULL;
 
 	windows = gtk_application_get_windows (GTK_APPLICATION (app));
 
 	while (windows)
 	{
 		GtkWindow *window;
 		GdkWindow *win;
 		NSWindow *nswin;
 
 		window = windows->data;
 		windows = g_list_next (windows);
 
 		if (!gtk_widget_get_realized (GTK_WIDGET (window)))
 		{
 			continue;
 		}
 
 		if (!GEDIT_IS_WINDOW (window))
 		{
@@ -259,61 +259,61 @@ gedit_app_osx_set_window_title_impl (GeditApp    *app,
 	}
 
 	native = gdk_quartz_window_get_nswindow (wnd);
 	document = gedit_window_get_active_document (window);
 
 	if (document)
 	{
 		bool ismodified;
 
 		if (gedit_document_is_untitled (document))
 		{
 			[native setRepresentedURL:nil];
 		}
 		else
 		{
 			GtkSourceFile *file;
 			GFile *location;
 			gchar *uri;
 
 			file = gedit_document_get_file (document);
 			location = gtk_source_file_get_location (file);
 
 			uri = g_file_get_uri (location);
 
 			NSURL *nsurl = [NSURL URLWithString:[NSString stringWithUTF8String:uri]];
 
 			[native setRepresentedURL:nsurl];
 			g_free (uri);
 		}
 
-		ismodified = !tepl_buffer_is_untouched (TEPL_BUFFER (document));
+		ismodified = !gedit_document_is_untouched (document);
 		[native setDocumentEdited:ismodified];
 	}
 	else
 	{
 		[native setRepresentedURL:nil];
 		[native setDocumentEdited:false];
 	}
 
 	GEDIT_APP_CLASS (gedit_app_osx_parent_class)->set_window_title (app, window, title);
 }
 
 typedef struct
 {
 	GeditAppOSX   *app;
 	GtkRecentInfo *info;
 } RecentFileInfo;
 
 static void
 recent_file_info_free (gpointer  data,
                        GClosure *closure)
 {
 	RecentFileInfo *info = data;
 
 	g_object_unref (info->app);
 	gtk_recent_info_unref (info->info);
 
 	g_slice_free (RecentFileInfo, data);
 }
 
 static void
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
@@ -1,52 +1,55 @@
 /*
  * gedit-app-private.h
  * This file is part of gedit
  *
  * Copyright (C) 2015 - Sébastien Wilmet <swilmet@gnome.org>
  *
  * 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_APP_PRIVATE_H
 #define GEDIT_APP_PRIVATE_H
 
 #include "gedit-app.h"
+#include "gedit-metadata-manager.h"
 #include "gedit-menu-extension.h"
 
 G_BEGIN_DECLS
 
 /* global print config */
 GtkPageSetup		*_gedit_app_get_default_page_setup	(GeditApp         *app);
 void			 _gedit_app_set_default_page_setup	(GeditApp         *app,
 								 GtkPageSetup     *page_setup);
 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);
 
 GMenuModel		*_gedit_app_get_tab_width_menu		(GeditApp  *app);
 
 GMenuModel		*_gedit_app_get_line_col_menu		(GeditApp  *app);
 
 GeditMenuExtension	*_gedit_app_extend_menu			(GeditApp    *app,
 								 const gchar *extension_point);
 
 G_END_DECLS
 
 #endif /* GEDIT_APP_PRIVATE_H */
 
 /* ex:set ts=8 noet: */
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
@@ -1,83 +1,92 @@
 /*
  * gedit-app.c
  * This file is part of gedit
  *
  * Copyright (C) 2005-2006 - 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 "config.h"
 
 #include "gedit-app.h"
 #include "gedit-app-private.h"
 
 #include <string.h>
 #include <unistd.h>
 #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"
 #include "gedit-debug.h"
 #include "gedit-utils.h"
 #include "gedit-enum-types.h"
 #include "gedit-dirs.h"
 #include "gedit-settings.h"
 #include "gedit-app-activatable.h"
 #include "gedit-plugins-engine.h"
 #include "gedit-commands.h"
 #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"
 
 typedef struct
 {
 	GeditPluginsEngine *engine;
 
+#ifndef ENABLE_GVFS_METADATA
+	GeditMetadataManager *metadata_manager;
+#endif
+
 	GtkCssProvider     *theme_provider;
 
 	GtkPageSetup      *page_setup;
 	GtkPrintSettings  *print_settings;
 
 	GSettings         *ui_settings;
 	GSettings         *window_settings;
 
 	GMenuModel        *hamburger_menu;
 	GMenuModel        *notebook_menu;
 	GMenuModel        *tab_width_menu;
 	GMenuModel        *line_col_menu;
 
 	PeasExtensionSet  *extensions;
 
 	/* command line parsing */
 	gboolean new_window;
 	gboolean new_document;
 	const GtkSourceEncoding *encoding;
 	GInputStream *stdin_stream;
 	GSList *file_list;
 	gint line_position;
 	gint column_position;
 	GApplicationCommandLine *command_line;
 } GeditAppPrivate;
 
 static const GOptionEntry options[] =
 {
 	/* Version */
 	{
@@ -118,60 +127,64 @@ static const GOptionEntry options[] =
 		"wait", 'w', 0, G_OPTION_ARG_NONE, NULL,
 		N_("Open files and block process until files are closed"),
 		NULL
 	},
 
 	/* New instance */
 	{
 		"standalone", 's', 0, G_OPTION_ARG_NONE, NULL,
 		N_("Run gedit in standalone mode"),
 		NULL
 	},
 
 	/* collects file arguments */
 	{
 		G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, NULL, NULL,
 		N_("[FILE…] [+LINE[:COLUMN]]")
 	},
 
 	{NULL}
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GeditApp, gedit_app, GTK_TYPE_APPLICATION)
 
 static void
 gedit_app_dispose (GObject *object)
 {
 	GeditAppPrivate *priv;
 
 	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);
 
 	g_clear_object (&priv->page_setup);
 	g_clear_object (&priv->print_settings);
 
 	/* Note that unreffing the extensions will automatically remove
 	 * all extensions which in turn will deactivate the extension
 	 */
 	g_clear_object (&priv->extensions);
 
 	g_clear_object (&priv->engine);
 
 	if (priv->theme_provider != NULL)
 	{
 		gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
 		                                              GTK_STYLE_PROVIDER (priv->theme_provider));
 		g_clear_object (&priv->theme_provider);
 	}
 
 	g_clear_object (&priv->hamburger_menu);
 	g_clear_object (&priv->notebook_menu);
 	g_clear_object (&priv->tab_width_menu);
 	g_clear_object (&priv->line_col_menu);
 
 	G_OBJECT_CLASS (gedit_app_parent_class)->dispose (object);
 }
 
 static gchar *
 gedit_app_help_link_id_impl (GeditApp    *app,
@@ -616,71 +629,82 @@ add_accelerator (GtkApplication *app,
                  const gchar    *action_name,
                  const gchar    *accel)
 {
 	const gchar *vaccels[] = {
 		accel,
 		NULL
 	};
 
 	gtk_application_set_accels_for_action (app, action_name, vaccels);
 }
 
 static gboolean
 show_menubar (void)
 {
 	GtkSettings *settings = gtk_settings_get_default ();
 	gboolean result;
 
 	g_object_get (settings,
 	              "gtk-shell-shows-menubar", &result,
 	              NULL);
 
 	return result;
 }
 
 static void
 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));
 
 	G_APPLICATION_CLASS (gedit_app_parent_class)->startup (application);
 
 	/* Setup debugging */
 	gedit_debug_init ();
 	gedit_debug_message (DEBUG_APP, "Startup");
 
 	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");
 	priv->window_settings = g_settings_new ("org.gnome.gedit.state.window");
 
 	g_action_map_add_action_entries (G_ACTION_MAP (application),
 	                                 app_entries,
 	                                 G_N_ELEMENTS (app_entries),
 	                                 application);
 
 	/* menus */
 	if (!show_menubar ())
 	{
 		gtk_application_set_menubar (GTK_APPLICATION (application), NULL);
 		priv->hamburger_menu = get_menu_model (GEDIT_APP (application),
 		                                       "hamburger-menu");
 	}
 
 	priv->notebook_menu = get_menu_model (GEDIT_APP (application), "notebook-menu");
 	priv->tab_width_menu = get_menu_model (GEDIT_APP (application), "tab-width-menu");
 	priv->line_col_menu = get_menu_model (GEDIT_APP (application), "line-col-menu");
 
 	/* Accelerators */
 	add_accelerator (GTK_APPLICATION (application), "app.new-window", "<Primary>N");
 	add_accelerator (GTK_APPLICATION (application), "app.quit", "<Primary>Q");
 	add_accelerator (GTK_APPLICATION (application), "app.help", "F1");
 	add_accelerator (GTK_APPLICATION (application), "app.shortcuts", "<Primary>question");
 
 	add_accelerator (GTK_APPLICATION (application), "win.hamburger-menu", "F10");
 	add_accelerator (GTK_APPLICATION (application), "win.open", "<Primary>O");
@@ -1087,60 +1111,64 @@ save_print_settings (GeditApp *app)
 		gchar *filename;
 		GError *error = NULL;
 
 		filename = get_print_settings_file ();
 
 		gtk_print_settings_to_file (priv->print_settings,
 					    filename,
 					    &error);
 		if (error)
 		{
 			g_warning ("%s", error->message);
 			g_error_free (error);
 		}
 
 		g_free (filename);
 	}
 }
 
 static void
 gedit_app_shutdown (GApplication *app)
 {
 	gedit_debug_message (DEBUG_APP, "Quitting\n");
 
 	/* Last window is gone... save some settings and exit */
 	ensure_user_config_dir ();
 
 	save_accels ();
 	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);
 }
 
 static gboolean
 window_delete_event (GeditWindow *window,
                      GdkEvent    *event,
                      GeditApp    *app)
 {
 	GeditWindowState ws;
 
 	ws = gedit_window_get_state (window);
 
 	if (ws &
 	    (GEDIT_WINDOW_STATE_SAVING | GEDIT_WINDOW_STATE_PRINTING))
 	{
 		return TRUE;
 	}
 
 	_gedit_cmd_file_quit (NULL, NULL, window);
 
 	/* Do not destroy the window */
 	return TRUE;
 }
 
 static GeditWindow *
 gedit_app_create_window_impl (GeditApp *app)
 {
 	GeditWindow *window;
 
 	window = g_object_new (GEDIT_TYPE_WINDOW, "application", app, NULL);
@@ -1226,69 +1254,64 @@ load_print_settings (GeditApp *app)
 
 	priv->print_settings = gtk_print_settings_new_from_file (filename, &error);
 	if (error != NULL)
 	{
 		/* - Ignore file not found error.
 		 * - Ignore empty file error, i.e. group not found. This happens
 		 *   when we click on cancel in the print dialog, when using the
 		 *   printing for the first time in gedit.
 		 */
 		if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
 		    !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
 		{
 			g_warning ("Load print settings error: %s", error->message);
 		}
 
 		g_error_free (error);
 	}
 
 	g_free (filename);
 
 	/* fall back to default settings */
 	if (priv->print_settings == NULL)
 	{
 		priv->print_settings = gtk_print_settings_new ();
 	}
 }
 
 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);
 }
 
 /**
  * gedit_app_create_window:
  * @app: the #GeditApp
  * @screen: (allow-none):
  *
  * Create a new #GeditWindow part of @app.
  *
  * Return value: (transfer none): the new #GeditWindow
  */
 GeditWindow *
 gedit_app_create_window (GeditApp  *app,
 			 GdkScreen *screen)
 {
 	GeditAppPrivate *priv;
 	GeditWindow *window;
 	GdkWindowState state;
 	gint w, h;
 
 	gedit_debug (DEBUG_APP);
 
 	priv = gedit_app_get_instance_private (app);
 
 	window = GEDIT_APP_GET_CLASS (app)->create_window (app);
 
 	if (screen != NULL)
 	{
 		gtk_window_set_screen (GTK_WINDOW (window), screen);
 	}
@@ -1544,60 +1567,79 @@ _gedit_app_get_default_print_settings (GeditApp *app)
 
 	priv = gedit_app_get_instance_private (app);
 
 	if (priv->print_settings == NULL)
 	{
 		load_print_settings (app);
 	}
 
 	return gtk_print_settings_copy (priv->print_settings);
 }
 
 void
 _gedit_app_set_default_print_settings (GeditApp         *app,
 				       GtkPrintSettings *settings)
 {
 	GeditAppPrivate *priv;
 
 	g_return_if_fail (GEDIT_IS_APP (app));
 	g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
 
 	priv = gedit_app_get_instance_private (app);
 
 	if (priv->print_settings != NULL)
 	{
 		g_object_unref (priv->print_settings);
 	}
 
 	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)
 {
 	GeditAppPrivate *priv;
 
 	g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
 
 	priv = gedit_app_get_instance_private (app);
 
 	return priv->hamburger_menu;
 }
 
 GMenuModel *
 _gedit_app_get_notebook_menu (GeditApp *app)
 {
 	GeditAppPrivate *priv;
 
 	g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
 
 	priv = gedit_app_get_instance_private (app);
 
 	return priv->notebook_menu;
 }
 
 GMenuModel *
 _gedit_app_get_tab_width_menu (GeditApp *app)
 {
 	GeditAppPrivate *priv;
 
 	g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
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
@@ -17,180 +17,180 @@
  * 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 "config.h"
 
 #include "gedit-commands.h"
 #include "gedit-commands-private.h"
 
 #include <gtk/gtk.h>
 
 #include "gedit-window.h"
 #include "gedit-debug.h"
 #include "gedit-view.h"
 #include "gedit-preferences-dialog.h"
 
 void
 _gedit_cmd_edit_undo (GSimpleAction *action,
                       GVariant      *parameter,
                       gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 	GtkSourceBuffer *active_document;
 
 	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));
 }
 
 void
 _gedit_cmd_edit_redo (GSimpleAction *action,
                       GVariant      *parameter,
                       gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 	GtkSourceBuffer *active_document;
 
 	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));
 }
 
 void
 _gedit_cmd_edit_cut (GSimpleAction *action,
                      GVariant      *parameter,
                      gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 
 	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));
 }
 
 void
 _gedit_cmd_edit_copy (GSimpleAction *action,
                       GVariant      *parameter,
                       gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 
 	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));
 }
 
 void
 _gedit_cmd_edit_paste (GSimpleAction *action,
                        GVariant      *parameter,
                        gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 
 	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));
 }
 
 void
 _gedit_cmd_edit_delete (GSimpleAction *action,
                         GVariant      *parameter,
                         gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 
 	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));
 }
 
 void
 _gedit_cmd_edit_select_all (GSimpleAction *action,
                             GVariant      *parameter,
                             gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 
 	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));
 }
 
 void
 _gedit_cmd_edit_preferences (GSimpleAction *action,
                              GVariant      *parameter,
                              gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	gedit_show_preferences_dialog (window);
 }
 
 void
 _gedit_cmd_edit_overwrite_mode (GSimpleAction *action,
                                 GVariant      *state,
                                 gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GeditView *active_view;
 	gboolean overwrite;
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	active_view = gedit_window_get_active_view (window);
 	g_return_if_fail (active_view);
 
diff --git a/gedit/gedit-commands-file.c b/gedit/gedit-commands-file.c
index fb64f880d..d1d440a3e 100644
--- a/gedit/gedit-commands-file.c
+++ b/gedit/gedit-commands-file.c
@@ -1,80 +1,75 @@
 /*
  * gedit-commands-file.c
  * This file is part of gedit
  *
  * 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 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
  * 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 "config.h"
 
 #include "gedit-commands.h"
 #include "gedit-commands-private.h"
 
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 
 #include "gedit-app.h"
 #include "gedit-debug.h"
 #include "gedit-document.h"
 #include "gedit-document-private.h"
 #include "gedit-tab.h"
 #include "gedit-tab-private.h"
 #include "gedit-window.h"
 #include "gedit-window-private.h"
 #include "gedit-notebook.h"
 #include "gedit-statusbar.h"
 #include "gedit-utils.h"
 #include "gedit-file-chooser-dialog.h"
 #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"
 #define GEDIT_IS_QUITTING_ALL "gedit-is-quitting-all"
 
 void
 _gedit_cmd_file_new (GSimpleAction *action,
                      GVariant      *parameter,
                      gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	gedit_window_create_tab (window, TRUE);
 }
 
 static GeditTab *
 get_tab_from_file (GList *docs,
 		   GFile *file)
 {
 	GList *l;
 
 	for (l = docs; l != NULL; l = l->next)
 	{
 		GeditDocument *doc;
 		GtkSourceFile *source_file;
 		GFile *location;
 
 		doc = l->data;
@@ -123,105 +118,107 @@ load_file_list (GeditWindow             *window,
 	gboolean jump_to = TRUE; /* Whether to jump to the new tab */
 	const GSList *l;
 	gint num_loaded_files = 0;
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	win_docs = gedit_window_get_documents (window);
 
 	/* Remove the files corresponding to documents already opened in
 	 * "window" and remove duplicates from the "files" list.
 	 */
 	for (l = files; l != NULL; l = l->next)
 	{
 		GFile *file = l->data;
 
 		if (is_duplicated_file (files_to_load, file))
 		{
 			continue;
 		}
 
 		tab = get_tab_from_file (win_docs, file);
 
 		if (tab == NULL)
 		{
 			files_to_load = g_slist_prepend (files_to_load, file);
 		}
 		else
 		{
 			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));
 				}
 			}
 
 			++num_loaded_files;
 			loaded_files = g_slist_prepend (loaded_files,
 			                                gedit_tab_get_document (tab));
 		}
 	}
 
 	g_list_free (win_docs);
 
 	if (files_to_load == NULL)
 	{
 		return g_slist_reverse (loaded_files);
 	}
 
 	files_to_load = g_slist_reverse (files_to_load);
 	l = files_to_load;
 
 	tab = gedit_window_get_active_tab (window);
 	if (tab != NULL)
 	{
 		GeditDocument *doc;
 
 		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,
 					 l->data,
 					 encoding,
 					 line_pos,
 					 column_pos,
 					 create);
 
 			/* make sure the view has focus */
 			gtk_widget_grab_focus (GTK_WIDGET (gedit_tab_get_view (tab)));
 
 			l = g_slist_next (l);
 			jump_to = FALSE;
 
 			++num_loaded_files;
 			loaded_files = g_slist_prepend (loaded_files,
 			                                gedit_tab_get_document (tab));
 		}
 	}
 
 	while (l != NULL)
 	{
 		g_return_val_if_fail (l->data != NULL, NULL);
 
 		tab = gedit_window_create_tab_from_location (window,
 							     l->data,
 							     encoding,
 							     line_pos,
 							     column_pos,
@@ -446,113 +443,113 @@ _gedit_cmd_file_reopen_closed_tab (GSimpleAction *action,
 	GFile *file;
 
 	file = _gedit_window_pop_last_closed_doc (window);
 	if (file != NULL)
 	{
 		gedit_commands_load_location (window, file, NULL, 0, 0);
 	}
 }
 
 /* File saving */
 
 /* FIXME: modify this dialog to be similar to the one provided by gtk+ for
  * already existing files - Paolo (Oct. 11, 2005) */
 static gboolean
 replace_read_only_file (GtkWindow *parent,
 			GFile     *file)
 {
 	GtkWidget *dialog;
 	gint ret;
 	gchar *parse_name;
 	gchar *name_for_display;
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	parse_name = g_file_get_parse_name (file);
 
 	/* Truncate the name so it doesn't get insanely wide. Note that even
 	 * 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,
 					 GTK_DIALOG_DESTROY_WITH_PARENT,
 					 GTK_MESSAGE_QUESTION,
 					 GTK_BUTTONS_NONE,
 					 _("The file “%s” is read-only."),
 				         name_for_display);
 	g_free (name_for_display);
 
 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 						  _("Do you want to try to replace it "
 						    "with the one you are saving?"));
 
 	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
 			        _("_Cancel"), GTK_RESPONSE_CANCEL,
 				_("_Replace"), GTK_RESPONSE_YES,
 				NULL);
 
 	gtk_dialog_set_default_response	(GTK_DIALOG (dialog),
 					 GTK_RESPONSE_CANCEL);
 
 	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
 
 	ret = gtk_dialog_run (GTK_DIALOG (dialog));
 
 	gtk_widget_destroy (dialog);
 
 	return ret == GTK_RESPONSE_YES;
 }
 
 static gboolean
 change_compression (GtkWindow *parent,
                     GFile     *file,
                     gboolean   compressed)
 {
 	GtkWidget *dialog;
 	gint ret;
 	gchar *parse_name;
 	gchar *name_for_display;
 	const gchar *primary_message;
 	const gchar *button_label;
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	parse_name = g_file_get_parse_name (file);
 
 	/* Truncate the name so it doesn't get insanely wide. Note that even
 	 * 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)
 	{
 		primary_message = _("Save the file using compression?");
 	}
 	else
 	{
 		primary_message = _("Save the file as plain text?");
 	}
 
 	dialog = gtk_message_dialog_new (parent,
 					 GTK_DIALOG_DESTROY_WITH_PARENT,
 					 GTK_MESSAGE_QUESTION,
 					 GTK_BUTTONS_NONE,
 					 "%s",
 					 primary_message);
 
 	if (compressed)
 	{
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 							  _("The file “%s” was previously saved as plain "
 							    "text and will now be saved using compression."),
 							  name_for_display);
 
 		button_label = _("_Save Using Compression");
 	}
 	else
 	{
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
@@ -760,60 +757,61 @@ confirm_overwrite_callback (GeditFileChooserDialog *dialog,
 
 /* Call save_as_tab_finish() in @callback. */
 static void
 save_as_tab_async (GeditTab            *tab,
 		   GeditWindow         *window,
 		   GCancellable        *cancellable,
 		   GAsyncReadyCallback  callback,
 		   gpointer             user_data)
 {
 	GTask *task;
 	GeditFileChooserDialog *save_dialog;
 	GtkWindowGroup *window_group;
 	GtkWindow *dialog_window;
 	GeditDocument *doc;
 	GtkSourceFile *file;
 	GFile *location;
 	const GtkSourceEncoding *encoding;
 	GtkSourceNewlineType newline_type;
 
 	g_return_if_fail (GEDIT_IS_TAB (tab));
 	g_return_if_fail (GEDIT_IS_WINDOW (window));
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	task = g_task_new (tab, cancellable, callback, user_data);
 	g_task_set_task_data (task, g_object_ref (window), g_object_unref);
 
 	/* 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"));
 
 	gedit_file_chooser_dialog_set_do_overwrite_confirmation (save_dialog, TRUE);
 
 	g_signal_connect (save_dialog,
 			  "confirm-overwrite",
 			  G_CALLBACK (confirm_overwrite_callback),
 			  NULL);
 
 	window_group = gedit_window_get_group (window);
 
 	dialog_window = gedit_file_chooser_dialog_get_window (save_dialog);
 
 	if (dialog_window != NULL)
 	{
 		gtk_window_group_add_window (window_group, dialog_window);
 	}
 
 	/* Save As dialog is modal to its main window */
 	gedit_file_chooser_dialog_set_modal (save_dialog, TRUE);
 
 	/* Set the suggested file name */
 	doc = gedit_tab_get_document (tab);
 	file = gedit_document_get_file (doc);
 	location = gtk_source_file_get_location (file);
 
 	if (location != NULL)
 	{
 		gedit_file_chooser_dialog_set_file (save_dialog, location);
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
@@ -2,61 +2,60 @@
  * gedit-commands-search.c
  * This file is part of gedit
  *
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002-2006 Paolo Maggi
  * Copyright (C) 2013 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
  * 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 "config.h"
 
 #include "gedit-commands.h"
 #include "gedit-commands-private.h"
 
 #include <string.h>
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
-#include <tepl/tepl.h>
 
 #include "gedit-debug.h"
 #include "gedit-statusbar.h"
 #include "gedit-tab.h"
 #include "gedit-tab-private.h"
 #include "gedit-view-frame.h"
 #include "gedit-window.h"
 #include "gedit-window-private.h"
 #include "gedit-utils.h"
 #include "gedit-replace-dialog.h"
 
 #define GEDIT_REPLACE_DIALOG_KEY	"gedit-replace-dialog-key"
 #define GEDIT_LAST_SEARCH_DATA_KEY	"gedit-last-search-data-key"
 
 typedef struct _LastSearchData LastSearchData;
 struct _LastSearchData
 {
 	gint x;
 	gint y;
 };
 
 static void
 last_search_data_free (LastSearchData *data)
 {
 	g_slice_free (LastSearchData, data);
 }
 
 static void
 last_search_data_restore_position (GeditReplaceDialog *dlg)
 {
@@ -105,117 +104,117 @@ text_found (GeditWindow *window,
 					       window->priv->generic_message_cid,
 					       ngettext("Found and replaced %d occurrence",
 					     	        "Found and replaced %d occurrences",
 					     	        occurrences),
 					       occurrences);
 	}
 	else if (occurrences == 1)
 	{
 		gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
 					       window->priv->generic_message_cid,
 					       _("Found and replaced one occurrence"));
 	}
 	else
 	{
 		gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
 					       window->priv->generic_message_cid,
 					       " ");
 	}
 }
 
 #define MAX_MSG_LENGTH 40
 
 static void
 text_not_found (GeditWindow        *window,
 		GeditReplaceDialog *replace_dialog)
 {
 	const gchar *search_text;
 	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,
 				       /* Translators: %s is replaced by the text
 				          entered by the user in the search box */
 				       _("“%s” not found"), truncated_text);
 
 	g_free (truncated_text);
 }
 
 static void
 finish_search_from_dialog (GeditWindow *window,
 			   gboolean     found)
 {
 	GeditReplaceDialog *replace_dialog;
 
 	replace_dialog = g_object_get_data (G_OBJECT (window), GEDIT_REPLACE_DIALOG_KEY);
 
 	g_return_if_fail (replace_dialog != NULL);
 
 	if (found)
 	{
 		text_found (window, 0);
 	}
 	else
 	{
 		text_not_found (window, replace_dialog);
 	}
 }
 
 static gboolean
 forward_search_finished (GtkSourceSearchContext *search_context,
 			 GAsyncResult           *result,
 			 GeditView              *view)
 {
 	gboolean found;
 	GtkSourceBuffer *buffer;
 	GtkTextIter match_start;
 	GtkTextIter match_end;
 
 	found = gtk_source_search_context_forward_finish (search_context,
 							  result,
 							  &match_start,
 							  &match_end,
 							  NULL,
 							  NULL);
 
 	buffer = gtk_source_search_context_get_buffer (search_context);
 
 	if (found)
 	{
 		gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer),
 					      &match_start,
 					      &match_end);
 
-		tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+		gedit_view_scroll_to_cursor (view);
 	}
 	else
 	{
 		GtkTextIter end_selection;
 
 		gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (buffer),
 						      NULL,
 						      &end_selection);
 
 		gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer),
 					      &end_selection,
 					      &end_selection);
 	}
 
 	return found;
 }
 
 static void
 forward_search_from_dialog_finished (GtkSourceSearchContext *search_context,
 				     GAsyncResult           *result,
 				     GeditWindow            *window)
 {
 	GeditView *view = gedit_window_get_active_view (window);
 	gboolean found;
 
 	if (view == NULL)
 	{
 		return;
 	}
 
@@ -267,61 +266,61 @@ run_forward_search (GeditWindow *window,
 							 (GAsyncReadyCallback)forward_search_finished,
 							 view);
 	}
 }
 
 static gboolean
 backward_search_finished (GtkSourceSearchContext *search_context,
 			  GAsyncResult           *result,
 			  GeditView              *view)
 {
 	gboolean found;
 	GtkTextIter match_start;
 	GtkTextIter match_end;
 	GtkSourceBuffer *buffer;
 
 	found = gtk_source_search_context_backward_finish (search_context,
 							   result,
 							   &match_start,
 							   &match_end,
 							   NULL,
 							   NULL);
 
 	buffer = gtk_source_search_context_get_buffer (search_context);
 
 	if (found)
 	{
 		gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer),
 					      &match_start,
 					      &match_end);
 
-		tepl_view_scroll_to_cursor (TEPL_VIEW (view));
+		gedit_view_scroll_to_cursor (view);
 	}
 	else
 	{
 		GtkTextIter start_selection;
 
 		gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (buffer),
 						      &start_selection,
 						      NULL);
 
 		gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer),
 					      &start_selection,
 					      &start_selection);
 	}
 
 	return found;
 }
 
 static void
 backward_search_from_dialog_finished (GtkSourceSearchContext *search_context,
 				      GAsyncResult           *result,
 				      GeditWindow            *window)
 {
 	GeditView *view = gedit_window_get_active_view (window);
 	gboolean found;
 
 	if (view == NULL)
 	{
 		return;
 	}
 
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
@@ -1,58 +1,63 @@
 /*
  * gedit-view-commands.c
  * This file is part of gedit
  *
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002-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 "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,
                               GVariant      *state,
                               gpointer       user_data)
 {
 	GeditView *active_view;
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	active_view = gedit_window_get_active_view (window);
 
 	if (active_view)
 	{
 		gtk_widget_grab_focus (GTK_WIDGET (active_view));
 	}
 }
 
 void
 _gedit_cmd_view_toggle_side_panel (GSimpleAction *action,
                                    GVariant      *state,
                                    gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 	GtkWidget *panel;
 	gboolean visible;
 
 	gedit_debug (DEBUG_COMMANDS);
 
@@ -94,88 +99,75 @@ _gedit_cmd_view_toggle_bottom_panel (GSimpleAction *action,
 }
 
 void
 _gedit_cmd_view_toggle_fullscreen_mode (GSimpleAction *action,
                                         GVariant      *state,
                                         gpointer       user_data)
 {
 	GeditWindow *window = GEDIT_WINDOW (user_data);
 
 	gedit_debug (DEBUG_COMMANDS);
 
 	if (g_variant_get_boolean (state))
 	{
 		_gedit_window_fullscreen (window);
 	}
 	else
 	{
 		_gedit_window_unfullscreen (window);
 	}
 }
 
 void
 _gedit_cmd_view_leave_fullscreen_mode (GSimpleAction *action,
                                        GVariant      *parameter,
                                        gpointer       user_data)
 {
 	_gedit_window_unfullscreen (GEDIT_WINDOW (user_data));
 }
 
 static void
-language_activated_cb (TeplLanguageChooserDialog *dialog,
-		       GtkSourceLanguage         *language,
-		       GeditWindow               *window)
+language_selected_cb (GeditHighlightModeSelector *selector,
+		      GtkSourceLanguage          *language,
+		      GeditWindow                *window)
 {
 	GeditDocument *active_document;
 
 	active_document = gedit_window_get_active_document (window);
 	if (active_document != NULL)
 	{
 		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
 _gedit_cmd_view_highlight_mode (GSimpleAction *action,
                                 GVariant      *parameter,
                                 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)
 	{
 		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));
 }
 
 /* ex:set ts=8 noet: */
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
@@ -73,60 +73,64 @@ gedit_debug_init (void)
 		enabled_sections |= GEDIT_DEBUG_WINDOW;
 	}
 	if (g_getenv ("GEDIT_DEBUG_PANEL") != NULL)
 	{
 		enabled_sections |= GEDIT_DEBUG_PANEL;
 	}
 	if (g_getenv ("GEDIT_DEBUG_PLUGINS") != NULL)
 	{
 		enabled_sections |= GEDIT_DEBUG_PLUGINS;
 	}
 	if (g_getenv ("GEDIT_DEBUG_TAB") != NULL)
 	{
 		enabled_sections |= GEDIT_DEBUG_TAB;
 	}
 	if (g_getenv ("GEDIT_DEBUG_DOCUMENT") != NULL)
 	{
 		enabled_sections |= GEDIT_DEBUG_DOCUMENT;
 	}
 	if (g_getenv ("GEDIT_DEBUG_COMMANDS") != NULL)
 	{
 		enabled_sections |= GEDIT_DEBUG_COMMANDS;
 	}
 	if (g_getenv ("GEDIT_DEBUG_APP") != NULL)
 	{
 		enabled_sections |= GEDIT_DEBUG_APP;
 	}
 	if (g_getenv ("GEDIT_DEBUG_UTILS") != NULL)
 	{
 		enabled_sections |= GEDIT_DEBUG_UTILS;
 	}
+	if (g_getenv ("GEDIT_DEBUG_METADATA") != NULL)
+	{
+		enabled_sections |= GEDIT_DEBUG_METADATA;
+	}
 
 out:
 
 #ifdef ENABLE_PROFILING
 	if (enabled_sections != GEDIT_NO_DEBUG)
 	{
 		timer = g_timer_new ();
 	}
 #endif
 }
 
 /**
  * gedit_debug:
  * @section: debug section.
  * @file: file name.
  * @line: line number.
  * @function: name of the function that is calling gedit_debug().
  *
  * If @section is enabled, then logs the trace information @file, @line, and
  * @function.
  */
 void
 gedit_debug (GeditDebugSection  section,
 	     const gchar       *file,
 	     gint               line,
 	     const gchar       *function)
 {
 	gedit_debug_message (section, file, line, function, "%s", "");
 }
 
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
@@ -21,63 +21,65 @@
  */
 
 #ifndef GEDIT_DEBUG_H
 #define GEDIT_DEBUG_H
 
 #include <glib.h>
 
 /**
  * GeditDebugSection:
  *
  * Enumeration of debug sections.
  *
  * Debugging output for a section is enabled by setting an environment variable
  * of the same name. For example, setting the <code>GEDIT_DEBUG_PLUGINS</code>
  * environment variable enables all debugging output for the %GEDIT_DEBUG_PLUGINS
  * section. Setting the special environment variable <code>GEDIT_DEBUG</code>
  * enables output for all sections.
  */
 typedef enum {
 	GEDIT_NO_DEBUG       = 0,
 	GEDIT_DEBUG_VIEW     = 1 << 0,
 	GEDIT_DEBUG_PREFS    = 1 << 1,
 	GEDIT_DEBUG_WINDOW   = 1 << 2,
 	GEDIT_DEBUG_PANEL    = 1 << 3,
 	GEDIT_DEBUG_PLUGINS  = 1 << 4,
 	GEDIT_DEBUG_TAB      = 1 << 5,
 	GEDIT_DEBUG_DOCUMENT = 1 << 6,
 	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
 #define	DEBUG_PREFS	GEDIT_DEBUG_PREFS,   __FILE__, __LINE__, G_STRFUNC
 #define	DEBUG_WINDOW	GEDIT_DEBUG_WINDOW,  __FILE__, __LINE__, G_STRFUNC
 #define	DEBUG_PANEL	GEDIT_DEBUG_PANEL,   __FILE__, __LINE__, G_STRFUNC
 #define	DEBUG_PLUGINS	GEDIT_DEBUG_PLUGINS, __FILE__, __LINE__, G_STRFUNC
 #define	DEBUG_TAB	GEDIT_DEBUG_TAB,     __FILE__, __LINE__, G_STRFUNC
 #define	DEBUG_DOCUMENT	GEDIT_DEBUG_DOCUMENT,__FILE__, __LINE__, G_STRFUNC
 #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);
 
 void gedit_debug (GeditDebugSection  section,
 		  const gchar       *file,
 		  gint               line,
 		  const gchar       *function);
 
 void gedit_debug_message (GeditDebugSection  section,
 			  const gchar       *file,
 			  gint               line,
 			  const gchar       *function,
 			  const gchar       *format, ...) G_GNUC_PRINTF(5, 6);
 
 void gedit_debug_plugin_message (const gchar       *file,
 				 gint               line,
 				 const gchar       *function,
 				 const gchar       *message);
 
 #endif /* GEDIT_DEBUG_H */
 /* ex:set ts=8 noet: */
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
@@ -1,57 +1,63 @@
 /*
  * gedit-document.h
  * This file is part of gedit
  *
  * 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
  *
  * 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_DOCUMENT_PRIVATE_H
 #define GEDIT_DOCUMENT_PRIVATE_H
 
 #include "gedit-document.h"
 
 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);
 
 G_GNUC_INTERNAL
 gboolean	_gedit_document_needs_saving				(GeditDocument *doc);
 
 G_GNUC_INTERNAL
 gboolean	_gedit_document_get_empty_search			(GeditDocument *doc);
 
 G_GNUC_INTERNAL
 void		_gedit_document_set_create				(GeditDocument *doc,
 									 gboolean       create);
 
 G_GNUC_INTERNAL
 gboolean	_gedit_document_get_create				(GeditDocument *doc);
 
 G_GNUC_INTERNAL
 gchar *		_gedit_document_get_uri_for_display			(GeditDocument *doc);
 
 G_END_DECLS
 
 #endif /* GEDIT_DOCUMENT_PRIVATE_H */
 /* ex:set ts=8 noet: */
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
@@ -1,156 +1,177 @@
 /*
  * gedit-document.c
  * This file is part of gedit
  *
  * 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
  * 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 "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_"
 
 static void	gedit_document_loaded_real	(GeditDocument *doc);
 
 static void	gedit_document_saved_real	(GeditDocument *doc);
 
 static void	set_content_type		(GeditDocument *doc,
 						 const gchar   *content_type);
 
 typedef struct
 {
 	GtkSourceFile *file;
 
-	TeplMetadata *metadata;
+	GSettings   *editor_settings;
+
+	gint 	     untitled_number;
+
+	GFileInfo   *metadata_info;
 
 	gchar	    *content_type;
 
 	GDateTime   *time_of_last_save_or_load;
 
 	/* The search context for the incremental search, or the search and
 	 * replace. They are mutually exclusive.
 	 */
 	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
 	 * actions.
 	 */
 	guint empty_search : 1;
 
 	/* Create file if location points to a non existing file (for example
 	 * when opened from the command line).
 	 */
 	guint create : 1;
 } GeditDocumentPrivate;
 
 enum
 {
 	PROP_0,
+	PROP_SHORTNAME,
 	PROP_CONTENT_TYPE,
 	PROP_MIME_TYPE,
 	PROP_EMPTY_SEARCH,
+	PROP_USE_GVFS_METADATA,
 	LAST_PROP
 };
 
 static GParamSpec *properties[LAST_PROP];
 
 enum
 {
+	CURSOR_MOVED,
 	LOAD,
 	LOADED,
 	SAVE,
 	SAVED,
 	LAST_SIGNAL
 };
 
 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
 update_time_of_last_save_or_load (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
 
 	if (priv->time_of_last_save_or_load != NULL)
 	{
 		g_date_time_unref (priv->time_of_last_save_or_load);
 	}
 
 	priv->time_of_last_save_or_load = g_date_time_new_now_utc ();
 }
 
 static const gchar *
 get_language_string (GeditDocument *doc)
 {
 	GtkSourceLanguage *lang = gedit_document_get_language (doc);
 
 	return lang != NULL ? gtk_source_language_get_id (lang) : NO_LANGUAGE_NAME;
 }
 
 static void
 save_metadata (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv;
 	const gchar *language = NULL;
 	GtkTextIter iter;
 	gchar *position;
@@ -168,215 +189,361 @@ save_metadata (GeditDocument *doc)
 	position = g_strdup_printf ("%d", gtk_text_iter_get_offset (&iter));
 
 	if (language == NULL)
 	{
 		gedit_document_set_metadata (doc,
 					     GEDIT_METADATA_ATTRIBUTE_POSITION, position,
 					     NULL);
 	}
 	else
 	{
 		gedit_document_set_metadata (doc,
 					     GEDIT_METADATA_ATTRIBUTE_POSITION, position,
 					     GEDIT_METADATA_ATTRIBUTE_LANGUAGE, language,
 					     NULL);
 	}
 
 	g_free (position);
 }
 
 static void
 gedit_document_dispose (GObject *object)
 {
 	GeditDocument *doc = GEDIT_DOCUMENT (object);
 	GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
 
 	gedit_debug (DEBUG_DOCUMENT);
 
 	/* 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);
 }
 
 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)
 	{
 		g_date_time_unref (priv->time_of_last_save_or_load);
 	}
 
 	G_OBJECT_CLASS (gedit_document_parent_class)->finalize (object);
 }
 
 static void
 gedit_document_get_property (GObject    *object,
 			     guint       prop_id,
 			     GValue     *value,
 			     GParamSpec *pspec)
 {
 	GeditDocument *doc = GEDIT_DOCUMENT (object);
 	GeditDocumentPrivate *priv;
 
 	priv = gedit_document_get_instance_private (doc);
 
 	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;
 
 		case PROP_MIME_TYPE:
 			g_value_take_string (value, gedit_document_get_mime_type (doc));
 			break;
 
 		case PROP_EMPTY_SEARCH:
 			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;
 	}
 }
 
 static void
 gedit_document_set_property (GObject      *object,
 			     guint         prop_id,
 			     const GValue *value,
 			     GParamSpec   *pspec)
 {
 	GeditDocument *doc = GEDIT_DOCUMENT (object);
+	GeditDocumentPrivate *priv = gedit_document_get_instance_private (doc);
 
 	switch (prop_id)
 	{
 		case PROP_CONTENT_TYPE:
 			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",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
 
 	G_OBJECT_CLASS (gedit_document_parent_class)->constructed (object);
 }
 
 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;
 	object_class->get_property = gedit_document_get_property;
 	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:
 	 *
 	 * The document's content type.
 	 */
 	properties[PROP_CONTENT_TYPE] =
 		g_param_spec_string ("content-type",
 		                     "Content Type",
 		                     "The document's Content Type",
 		                     NULL,
 		                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * GeditDocument:mime-type:
 	 *
 	 * The document's MIME type.
 	 */
 	properties[PROP_MIME_TYPE] =
 		g_param_spec_string ("mime-type",
 		                     "MIME Type",
 		                     "The document's MIME Type",
 		                     "text/plain",
 		                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * GeditDocument:empty-search:
 	 *
 	 * <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_EMPTY_SEARCH] =
 		g_param_spec_boolean ("empty-search",
 		                      "Empty search",
 		                      "Whether the search is empty",
 		                      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.
 	 *
 	 * The "load" signal is emitted at the beginning of a file loading.
 	 *
 	 * Before gedit 3.14 this signal contained parameters to configure the
 	 * file loading (the location, encoding, etc). Plugins should not need
 	 * those parameters.
 	 */
 	document_signals[LOAD] =
 		g_signal_new ("load",
 			      G_OBJECT_CLASS_TYPE (object_class),
 			      G_SIGNAL_RUN_LAST,
 			      G_STRUCT_OFFSET (GeditDocumentClass, load),
 			      NULL, NULL, NULL,
 			      G_TYPE_NONE, 0);
 
 	/**
 	 * GeditDocument::loaded:
 	 * @document: the #GeditDocument.
 	 *
 	 * The "loaded" signal is emitted at the end of a successful file
 	 * loading.
 	 *
 	 * Before gedit 3.14 this signal contained a #GError parameter, and the
 	 * signal was also emitted if an error occurred. Plugins should not need
 	 * the error parameter.
 	 */
 	document_signals[LOADED] =
@@ -605,128 +772,188 @@ static void
 on_content_type_changed (GeditDocument *doc,
 			 GParamSpec    *pspec,
 			 gpointer       useless)
 {
 	GeditDocumentPrivate *priv;
 
 	priv = gedit_document_get_instance_private (doc);
 
 	if (!priv->language_set_by_user)
 	{
 		GtkSourceLanguage *language = guess_language (doc);
 
 		gedit_debug_message (DEBUG_DOCUMENT, "Language: %s",
 				     language != NULL ? gtk_source_language_get_name (language) : "None");
 
 		set_language (doc, language, FALSE);
 	}
 }
 
 static gchar *
 get_default_content_type (void)
 {
 	return g_content_type_from_mime_type ("text/plain");
 }
 
 static void
 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;
 
 	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",
 				 G_CALLBACK (on_location_changed),
 				 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);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_SYNTAX_HIGHLIGHTING,
 			 doc, "highlight-syntax",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_BRACKET_MATCHING,
 	                 doc, "highlight-matching-brackets",
 	                 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
 
 	g_signal_connect_object (editor_settings,
 				 "changed::" GEDIT_SETTINGS_SCHEME,
 				 G_CALLBACK (editor_settings_scheme_changed_cb),
 				 doc,
 				 0);
 
 	update_style_scheme (doc);
 
 	g_signal_connect (doc,
 			  "notify::content-type",
 			  G_CALLBACK (on_content_type_changed),
 			  NULL);
 }
 
 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 *
 get_content_type_from_content (GeditDocument *doc)
 {
 	gchar *content_type;
 	gchar *data;
 	GtkTextBuffer *buffer;
 	GtkTextIter start;
 	GtkTextIter end;
 
 	buffer = GTK_TEXT_BUFFER (doc);
 
 	gtk_text_buffer_get_start_iter (buffer, &start);
 	end = start;
 	gtk_text_iter_forward_chars (&end, 255);
 
 	data = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
 
 	content_type = g_content_type_guess (NULL,
 	                                     (const guchar *)data,
 	                                     strlen (data),
 	                                     NULL);
 
 	g_free (data);
 
 	return content_type;
 }
 
 static void
@@ -787,93 +1014,107 @@ set_content_type (GeditDocument *doc,
 	if (content_type == NULL)
 	{
 		GFile *location;
 		gchar *guessed_type = NULL;
 
 		/* If content type is null, we guess from the filename */
 		location = gtk_source_file_get_location (priv->file);
 		if (location != NULL)
 		{
 			gchar *basename;
 
 			basename = g_file_get_basename (location);
 			guessed_type = g_content_type_guess (basename, NULL, 0, NULL);
 
 			g_free (basename);
 		}
 
 		set_content_type_no_guess (doc, guessed_type);
 		g_free (guessed_type);
 	}
 	else
 	{
 		set_content_type_no_guess (doc, content_type);
 	}
 }
 
 /* Note: this never returns %NULL. */
 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
 	{
 		return g_file_get_parse_name (location);
 	}
 }
 
 /**
  * gedit_document_get_short_name_for_display:
  * @doc: a #GeditDocument.
  *
  * Note: this never returns %NULL.
  **/
 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 *
 gedit_document_get_content_type (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv;
 
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
 
 	priv = gedit_document_get_instance_private (doc);
 
 	return g_strdup (priv->content_type);
 }
 
 /**
  * gedit_document_get_mime_type:
  * @doc: a #GeditDocument.
  *
  * Note: this never returns %NULL.
  **/
 gchar *
 gedit_document_get_mime_type (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv;
 
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), g_strdup ("text/plain"));
 
 	priv = gedit_document_get_instance_private (doc);
 
 	if (priv->content_type != NULL &&
@@ -1005,225 +1246,398 @@ saved_query_info_cb (GFile         *location,
 	priv->create = FALSE;
 
 	save_encoding_metadata (doc);
 
 	/* Async operation finished. */
 	g_object_unref (doc);
 }
 
 static void
 gedit_document_saved_real (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv;
 	GFile *location;
 
 	priv = gedit_document_get_instance_private (doc);
 
 	location = gtk_source_file_get_location (priv->file);
 
 	/* Keep the doc alive during the async operation. */
 	g_object_ref (doc);
 
 	g_file_query_info_async (location,
 				 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
 				 G_FILE_QUERY_INFO_NONE,
 				 G_PRIORITY_DEFAULT,
 				 NULL,
 				 (GAsyncReadyCallback) saved_query_info_cb,
 				 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;
 }
 
 /*
  * Deletion and external modification is only checked for local files.
  */
 gboolean
 _gedit_document_needs_saving (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv;
 	gboolean externally_modified = FALSE;
 	gboolean deleted = FALSE;
 
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
 
 	priv = gedit_document_get_instance_private (doc);
 
 	if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
 	{
 		return TRUE;
 	}
 
 	if (gtk_source_file_is_local (priv->file))
 	{
 		gtk_source_file_check_file_on_disk (priv->file);
 		externally_modified = gtk_source_file_is_externally_modified (priv->file);
 		deleted = gtk_source_file_is_deleted (priv->file);
 	}
 
 	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:
  * @lang: (allow-none):
  **/
 void
 gedit_document_set_language (GeditDocument     *doc,
 			     GtkSourceLanguage *lang)
 {
 	g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
 
 	set_language (doc, lang, TRUE);
 }
 
 /**
  * gedit_document_get_language:
  * @doc:
  *
  * Return value: (transfer none):
  */
 GtkSourceLanguage *
 gedit_document_get_language (GeditDocument *doc)
 {
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
 
 	return gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (doc));
 }
 
 glong
 _gedit_document_get_seconds_since_last_save_or_load (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv;
 	GDateTime *now;
 	GTimeSpan n_microseconds;
 
 	gedit_debug (DEBUG_DOCUMENT);
 
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), -1);
 
 	priv = gedit_document_get_instance_private (doc);
 
 	if (priv->time_of_last_save_or_load == NULL)
 	{
 		return -1;
 	}
 
 	now = g_date_time_new_now_utc ();
 	if (now == NULL)
 	{
 		return -1;
 	}
 
 	n_microseconds = g_date_time_difference (now, priv->time_of_last_save_or_load);
 	g_date_time_unref (now);
 
 	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
  * @key: name of the key
  *
  * Gets the metadata assigned to @key.
  *
  * Returns: the value assigned to @key. Free with g_free().
  */
 gchar *
 gedit_document_get_metadata (GeditDocument *doc,
 			     const gchar   *key)
 {
 	GeditDocumentPrivate *priv;
 
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
 	g_return_val_if_fail (key != NULL, NULL);
 
 	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);
 }
 
 /**
  * gedit_document_set_metadata:
  * @doc: a #GeditDocument
  * @first_key: name of the first key to set
  * @...: (allow-none): value for the first key, followed optionally by more key/value pairs,
  * followed by %NULL.
  *
  * Sets metadata on a document.
  */
 void
 gedit_document_set_metadata (GeditDocument *doc,
 			     const gchar   *first_key,
 			     ...)
 {
 	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
 update_empty_search (GeditDocument *doc)
 {
 	GeditDocumentPrivate *priv;
 	gboolean new_value;
 
 	priv = gedit_document_get_instance_private (doc);
 
 	if (priv->search_context == NULL)
 	{
 		new_value = TRUE;
 	}
 	else
 	{
 		GtkSourceSearchSettings *search_settings;
 
 		search_settings = gtk_source_search_context_get_settings (priv->search_context);
 
 		new_value = gtk_source_search_settings_get_search_text (search_settings) == NULL;
 	}
 
 	if (priv->empty_search != new_value)
 	{
 		priv->empty_search = new_value;
 		g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_EMPTY_SEARCH]);
 	}
 }
 
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
@@ -1,83 +1,93 @@
 /*
  * gedit-document.h
  * This file is part of gedit
  *
  * 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
  * 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_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);
 
 	void (* loaded)			(GeditDocument *document);
 
 	void (* save)			(GeditDocument *document);
 
 	void (* saved)  		(GeditDocument *document);
 };
 
 GeditDocument   *gedit_document_new				(void);
 
 GtkSourceFile	*gedit_document_get_file			(GeditDocument       *doc);
 
 gchar		*gedit_document_get_short_name_for_display	(GeditDocument       *doc);
 
 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
 		*gedit_document_get_language			(GeditDocument       *doc);
 
 gchar		*gedit_document_get_metadata			(GeditDocument       *doc,
 								 const gchar         *key);
 
 void		 gedit_document_set_metadata			(GeditDocument       *doc,
 								 const gchar         *first_key,
 								 ...);
 
 void		 gedit_document_set_search_context		(GeditDocument          *doc,
 								 GtkSourceSearchContext *search_context);
 
 GtkSourceSearchContext *
 		 gedit_document_get_search_context		(GeditDocument       *doc);
 
 G_END_DECLS
 
 #endif /* GEDIT_DOCUMENT_H */
 /* ex:set ts=8 noet: */
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
@@ -1,56 +1,55 @@
 /*
  * gedit-documents-panel.c
  * This file is part of gedit
  *
  * Copyright (C) 2014 - Sébastien Lafargue <slafargue@gnome.org>
  *
  * 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 "config.h"
 
 #include "gedit-documents-panel.h"
 
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 
 #include "gedit-debug.h"
 #include "gedit-document.h"
 #include "gedit-multi-notebook.h"
 #include "gedit-notebook.h"
 #include "gedit-notebook-popup-menu.h"
 #include "gedit-tab.h"
 #include "gedit-tab-private.h"
 #include "gedit-utils.h"
 #include "gedit-commands-private.h"
 
 typedef struct _GeditDocumentsGenericRow GeditDocumentsGenericRow;
 typedef struct _GeditDocumentsGenericRow GeditDocumentsGroupRow;
 typedef struct _GeditDocumentsGenericRow GeditDocumentsDocumentRow;
 
 struct _GeditDocumentsGenericRow
 {
 	GtkListBoxRow        parent_instance;
 
 	GeditDocumentsPanel *panel;
 	GtkWidget           *ref;
 
 	GtkWidget           *box;
 	GtkWidget           *label;
 	GtkWidget           *close_button;
 
 	/* Not used in GeditDocumentsGroupRow */
 	GtkWidget           *image;
 	GtkWidget           *status_label;
 };
@@ -420,61 +419,61 @@ group_row_update_names (GeditDocumentsPanel *panel,
 		{
 			group_row_set_notebook_name (row);
 		}
 	}
 
 	g_list_free (children);
 }
 
 static void
 group_row_refresh_visibility (GeditDocumentsPanel *panel)
 {
 	gboolean notebook_is_unique;
 	GtkWidget *first_group_row;
 
 	notebook_is_unique = gedit_multi_notebook_get_n_notebooks (panel->mnb) <= 1;
 	first_group_row = GTK_WIDGET (get_first_notebook_found (panel));
 
 	gtk_widget_set_no_show_all (first_group_row, notebook_is_unique);
 	gtk_widget_set_visible (first_group_row, !notebook_is_unique);
 }
 
 static gchar *
 doc_get_name (GeditDocument *doc)
 {
 	gchar *name;
 	gchar *docname;
 
 	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);
 
 	return docname;
 }
 
 static void
 document_row_sync_tab_name_and_icon (GeditTab   *tab,
                                      GParamSpec *pspec,
                                      GtkWidget  *row)
 {
 	GeditDocumentsDocumentRow *document_row = GEDIT_DOCUMENTS_DOCUMENT_ROW (row);
 	GeditDocument *doc;
 	GtkSourceFile *file;
 	gchar *name;
 	GdkPixbuf *pixbuf;
 
 	doc = gedit_tab_get_document (tab);
 	name = doc_get_name (doc);
 
 	if (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
 	{
 		gtk_label_set_text (GTK_LABEL (document_row->label), name);
 	}
 	else
 	{
 		gchar *markup;
 
 		markup = g_markup_printf_escaped ("<b>%s</b>", name);
 		gtk_label_set_markup (GTK_LABEL (document_row->label), markup);
diff --git a/gedit/gedit-factory.c b/gedit/gedit-factory.c
deleted file mode 100644
index 409b3beb2..000000000
--- a/gedit/gedit-factory.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This file is part of gedit
- *
- * Copyright (C) 2020 Sébastien Wilmet <swilmet@gnome.org>
- *
- * 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-factory.h"
-#include "gedit-dirs.h"
-
-G_DEFINE_TYPE (GeditFactory, gedit_factory, TEPL_TYPE_ABSTRACT_FACTORY)
-
-static GFile *
-gedit_factory_create_metadata_manager_file (TeplAbstractFactory *factory)
-{
-	return g_file_new_build_filename (gedit_dirs_get_user_data_dir (),
-					  "gedit-metadata.xml",
-					  NULL);
-}
-
-static void
-gedit_factory_class_init (GeditFactoryClass *klass)
-{
-	TeplAbstractFactoryClass *factory_class = TEPL_ABSTRACT_FACTORY_CLASS (klass);
-
-	factory_class->create_metadata_manager_file = gedit_factory_create_metadata_manager_file;
-}
-
-static void
-gedit_factory_init (GeditFactory *factory)
-{
-}
-
-GeditFactory *
-gedit_factory_new (void)
-{
-	return g_object_new (GEDIT_TYPE_FACTORY, NULL);
-}
diff --git a/gedit/gedit-factory.h b/gedit/gedit-factory.h
deleted file mode 100644
index 05e19f715..000000000
--- a/gedit/gedit-factory.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * This file is part of gedit
- *
- * Copyright (C) 2020 Sébastien Wilmet <swilmet@gnome.org>
- *
- * 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_FACTORY_H
-#define GEDIT_FACTORY_H
-
-#include <tepl/tepl.h>
-
-G_BEGIN_DECLS
-
-#define GEDIT_TYPE_FACTORY             (gedit_factory_get_type ())
-#define GEDIT_FACTORY(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FACTORY, GeditFactory))
-#define GEDIT_FACTORY_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FACTORY, GeditFactoryClass))
-#define GEDIT_IS_FACTORY(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FACTORY))
-#define GEDIT_IS_FACTORY_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FACTORY))
-#define GEDIT_FACTORY_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FACTORY, GeditFactoryClass))
-
-typedef struct _GeditFactory         GeditFactory;
-typedef struct _GeditFactoryClass    GeditFactoryClass;
-
-struct _GeditFactory
-{
-	TeplAbstractFactory parent;
-};
-
-struct _GeditFactoryClass
-{
-	TeplAbstractFactoryClass parent_class;
-};
-
-GType		gedit_factory_get_type	(void);
-
-GeditFactory *	gedit_factory_new	(void);
-
-G_END_DECLS
-
-#endif /* GEDIT_FACTORY_H */
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
@@ -165,131 +165,160 @@ chooser_set_current_name (GeditFileChooserDialog *dialog,
 	gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), name);
 }
 
 static void
 chooser_set_file (GeditFileChooserDialog *dialog,
                   GFile                  *file)
 {
 	gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), file, NULL);
 }
 
 static GFile *
 chooser_get_file (GeditFileChooserDialog *dialog)
 {
 	return gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
 }
 
 static void
 chooser_set_do_overwrite_confirmation (GeditFileChooserDialog *dialog,
                                        gboolean                overwrite_confirmation)
 {
 	gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), overwrite_confirmation);
 }
 
 static void
 chooser_show (GeditFileChooserDialog *dialog)
 {
 	gtk_window_present (GTK_WINDOW (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)
 {
 	gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 static void
 chooser_set_modal (GeditFileChooserDialog *dialog,
                    gboolean is_modal)
 {
 	gtk_window_set_modal (GTK_WINDOW (dialog), is_modal);
 }
 
 static GtkWindow *
 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)
 {
 	GeditFileChooserDialogInterface *iface = g_iface;
 
 	iface->set_encoding = chooser_set_encoding;
 	iface->get_encoding = chooser_get_encoding;
 
 	iface->set_newline_type = chooser_set_newline_type;
 	iface->get_newline_type = chooser_get_newline_type;
 
 	iface->set_current_folder = chooser_set_current_folder;
 	iface->set_current_name = chooser_set_current_name;
 	iface->set_file = chooser_set_file;
 	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
 gedit_file_chooser_dialog_gtk_dispose (GObject *object)
 {
 	GeditFileChooserDialogGtk *dialog = GEDIT_FILE_CHOOSER_DIALOG_GTK (object);
 
 	g_clear_object (&dialog->gedit_file_chooser);
 
 	G_OBJECT_CLASS (gedit_file_chooser_dialog_gtk_parent_class)->dispose (object);
 }
 
 static void
 gedit_file_chooser_dialog_gtk_class_init (GeditFileChooserDialogGtkClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
 	object_class->dispose = gedit_file_chooser_dialog_gtk_dispose;
 }
 
 static void
-create_option_menu (GeditFileChooserDialogGtk *dialog)
+create_option_menu (GeditFileChooserDialogGtk *dialog,
+                    GeditFileChooserFlags      flags)
 {
 	GtkWidget *label;
 	GtkWidget *menu;
 	gboolean save_mode;
 
 	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);
 
 	gtk_box_pack_start (GTK_BOX (dialog->extra_widget),
 	                    label,
 	                    FALSE,
 	                    TRUE,
 	                    0);
 
 	gtk_box_pack_start (GTK_BOX (dialog->extra_widget),
 	                    menu,
 	                    TRUE,
 	                    TRUE,
 	                    0);
 
 	gtk_widget_show (label);
 	gtk_widget_show (menu);
 
 	dialog->option_menu = menu;
 }
 
 static void
 update_newline_visibility (GeditFileChooserDialogGtk *dialog)
 {
 	gboolean visible = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE;
 
 	gtk_widget_set_visible (dialog->newline_label, visible);
 	gtk_widget_set_visible (dialog->newline_combo, visible);
 }
@@ -347,119 +376,138 @@ create_newline_combo (GeditFileChooserDialogGtk *dialog)
 	                      GTK_SOURCE_NEWLINE_TYPE_CR);
 
 	newline_combo_append (GTK_COMBO_BOX (combo),
 	                      store,
 	                      &iter,
 	                      gedit_utils_newline_type_to_string (GTK_SOURCE_NEWLINE_TYPE_CR_LF),
 	                      GTK_SOURCE_NEWLINE_TYPE_CR_LF);
 
 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
 
 	gtk_box_pack_start (GTK_BOX (dialog->extra_widget),
 	                    label,
 	                    FALSE,
 	                    TRUE,
 	                    0);
 
 	gtk_box_pack_start (GTK_BOX (dialog->extra_widget),
 	                    combo,
 	                    TRUE,
 	                    TRUE,
 	                    0);
 
 	dialog->newline_combo = combo;
 	dialog->newline_label = label;
 	dialog->newline_store = store;
 
 	update_newline_visibility (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);
 }
 
 static void
 action_changed (GeditFileChooserDialogGtk *dialog,
 		GParamSpec                *pspec,
 		gpointer                   data)
 {
 	GtkFileChooserAction action;
 
 	action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog));
 
 	switch (action)
 	{
 		case GTK_FILE_CHOOSER_ACTION_OPEN:
 			g_object_set (dialog->option_menu,
 			              "save_mode", FALSE,
 			              NULL);
 			gtk_widget_show (dialog->option_menu);
 			break;
 		case GTK_FILE_CHOOSER_ACTION_SAVE:
 			g_object_set (dialog->option_menu,
 			              "save_mode", TRUE,
 			              NULL);
 			gtk_widget_show (dialog->option_menu);
 			break;
 		default:
 			gtk_widget_hide (dialog->option_menu);
 	}
 
 	update_newline_visibility (dialog);
 }
 
 static void
 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",
 			  G_CALLBACK (action_changed),
 			  NULL);
 
 	/* FIXME: attention, there is a ref cycle here. This will be fixed when
 	 * GeditFileChooserSave will be created (and this class removed).
 	 */
 	result->gedit_file_chooser = _gedit_file_chooser_new ();
 	_gedit_file_chooser_set_gtk_file_chooser (result->gedit_file_chooser,
 						  GTK_FILE_CHOOSER (result));
 
 	if (parent != NULL)
 	{
 		gtk_window_set_transient_for (GTK_WINDOW (result), parent);
 		gtk_window_set_destroy_with_parent (GTK_WINDOW (result), TRUE);
 	}
 
 	gtk_dialog_add_button (GTK_DIALOG (result), cancel_label, GTK_RESPONSE_CANCEL);
 	gtk_dialog_add_button (GTK_DIALOG (result), accept_label, GTK_RESPONSE_ACCEPT);
 	gtk_dialog_set_default_response (GTK_DIALOG (result), GTK_RESPONSE_ACCEPT);
 
 	return GEDIT_FILE_CHOOSER_DIALOG (result);
 }
 
 /* ex:set ts=8 noet: */
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
@@ -6,40 +6,41 @@
  * Copyright (C) 2014 - Jesse van den Kieboom
  *
  * 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_FILE_CHOOSER_DIALOG_GTK_H
 #define GEDIT_FILE_CHOOSER_DIALOG_GTK_H
 
 #include <gtk/gtk.h>
 #include "gedit-file-chooser-dialog.h"
 
 G_BEGIN_DECLS
 
 #define GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK (gedit_file_chooser_dialog_gtk_get_type ())
 
 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
 
 #endif /* GEDIT_FILE_CHOOSER_DIALOG_GTK_H */
 
 /* ex:set ts=8 noet: */
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
@@ -35,67 +35,69 @@ confirm_overwrite_accumulator (GSignalInvocationHint *ihint,
 
 	conf = g_value_get_enum (handler_return);
 	g_value_set_enum (return_accu, conf);
 	continue_emission = (conf == GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM);
 
 	return continue_emission;
 }
 
 static void
 gedit_file_chooser_dialog_default_init (GeditFileChooserDialogInterface *iface)
 {
 	g_signal_new ("response",
 	              G_TYPE_FROM_INTERFACE (iface),
 	              G_SIGNAL_RUN_LAST,
 	              0,
 	              NULL, NULL, NULL,
 	              G_TYPE_NONE,
 	              1,
 	              G_TYPE_INT);
 
 	g_signal_new ("confirm-overwrite",
 	              G_TYPE_FROM_INTERFACE (iface),
 	              G_SIGNAL_RUN_LAST,
 	              0,
 	              confirm_overwrite_accumulator, NULL, NULL,
 	              GTK_TYPE_FILE_CHOOSER_CONFIRMATION,
 	              0);
 }
 
 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);
 }
 
 void
 gedit_file_chooser_dialog_set_encoding (GeditFileChooserDialog  *dialog,
                                         const GtkSourceEncoding *encoding)
 {
 	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->set_encoding != NULL);
 
 	iface->set_encoding (dialog, encoding);
 }
 
 const GtkSourceEncoding *
 gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog)
 {
 	GeditFileChooserDialogInterface *iface;
 
 	g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
 	iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
 	g_return_val_if_fail (iface->get_encoding != NULL, NULL);
 
 	return iface->get_encoding (dialog);
 }
@@ -184,75 +186,105 @@ gedit_file_chooser_dialog_get_file (GeditFileChooserDialog *dialog)
 	return iface->get_file (dialog);
 }
 
 void
 gedit_file_chooser_dialog_set_do_overwrite_confirmation (GeditFileChooserDialog *dialog,
                                                          gboolean                overwrite_confirmation)
 {
 	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->set_do_overwrite_confirmation != NULL);
 
 	iface->set_do_overwrite_confirmation (dialog, overwrite_confirmation);
 }
 
 void
 gedit_file_chooser_dialog_show (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->show != NULL);
 
 	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)
 {
 	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->destroy != NULL);
 
 	iface->destroy (dialog);
 }
 
 void
 gedit_file_chooser_dialog_set_modal (GeditFileChooserDialog *dialog,
                                      gboolean                is_modal)
 {
 	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->set_modal != NULL);
 
 	iface->set_modal (dialog, is_modal);
 }
 
 GtkWindow *
 gedit_file_chooser_dialog_get_window (GeditFileChooserDialog *dialog)
 {
 	GeditFileChooserDialogInterface *iface;
 
 	g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
 	iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
 
 	if (iface->get_window)
 	{
 		return iface->get_window (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
@@ -37,87 +37,104 @@ struct _GeditFileChooserDialogInterface
 
 	/* Virtual public methods */
 	void	(*set_encoding)		(GeditFileChooserDialog  *dialog,
 					 const GtkSourceEncoding *encoding);
 
 	const GtkSourceEncoding *
 		(*get_encoding)		(GeditFileChooserDialog *dialog);
 
 	void	(*set_newline_type)	(GeditFileChooserDialog  *dialog,
 					 GtkSourceNewlineType     newline_type);
 
 	GtkSourceNewlineType
 		(*get_newline_type)	(GeditFileChooserDialog *dialog);
 
 	void	(*set_current_folder)	(GeditFileChooserDialog *dialog,
 					 GFile                  *folder);
 
 	void	(*set_current_name)	(GeditFileChooserDialog *dialog,
 					 const gchar            *name);
 
 	void	(*set_file)		(GeditFileChooserDialog *dialog,
 					 GFile                  *file);
 
 	GFile *	(*get_file)		(GeditFileChooserDialog *dialog);
 
 	void	(*set_do_overwrite_confirmation)
 					(GeditFileChooserDialog *dialog,
 					 gboolean                overwrite_confirmation);
 
 	void	(*show)			(GeditFileChooserDialog *dialog);
+	void	(*hide)			(GeditFileChooserDialog *dialog);
 
 	void    (*destroy)		(GeditFileChooserDialog *dialog);
 
 	void	(*set_modal)		(GeditFileChooserDialog *dialog,
 					 gboolean                is_modal);
 
 	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);
 
 void		 gedit_file_chooser_dialog_destroy		(GeditFileChooserDialog   *dialog);
 
 void		 gedit_file_chooser_dialog_set_encoding		(GeditFileChooserDialog   *dialog,
 								 const GtkSourceEncoding  *encoding);
 
 const GtkSourceEncoding *
 		 gedit_file_chooser_dialog_get_encoding		(GeditFileChooserDialog   *dialog);
 
 void		 gedit_file_chooser_dialog_set_newline_type	(GeditFileChooserDialog   *dialog,
 								 GtkSourceNewlineType      newline_type);
 
 GtkSourceNewlineType
 		 gedit_file_chooser_dialog_get_newline_type	(GeditFileChooserDialog   *dialog);
 
 void		 gedit_file_chooser_dialog_set_current_folder	(GeditFileChooserDialog   *dialog,
 								 GFile                    *folder);
 
 void		 gedit_file_chooser_dialog_set_current_name	(GeditFileChooserDialog   *dialog,
 								 const gchar              *name);
 
 void		 gedit_file_chooser_dialog_set_file		(GeditFileChooserDialog   *dialog,
 								 GFile                    *file);
 
 GFile		*gedit_file_chooser_dialog_get_file		(GeditFileChooserDialog   *dialog);
 
 void		 gedit_file_chooser_dialog_set_do_overwrite_confirmation (
 								 GeditFileChooserDialog   *dialog,
 								 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 */
 
 /* ex:set ts=8 noet: */
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 1edbe313a..1539e3b7b 100644
--- a/gedit/gedit-io-error-info-bar.c
+++ b/gedit/gedit-io-error-info-bar.c
@@ -1,58 +1,65 @@
 /*
  * gedit-io-error-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/>.
  */
 
 /*
  * Verbose error reporting for file I/O operations (load, save, revert, create)
  */
 
 #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
 
 static gboolean
 is_recoverable_error (const GError *error)
 {
 	gboolean is_recoverable = FALSE;
 
 	if (error->domain == G_IO_ERROR)
 	{
 		switch (error->code)
 		{
 			case G_IO_ERROR_PERMISSION_DENIED:
 			case G_IO_ERROR_NOT_FOUND:
 			case G_IO_ERROR_HOST_NOT_FOUND:
 			case G_IO_ERROR_TIMED_OUT:
 			case G_IO_ERROR_NOT_MOUNTABLE_FILE:
 			case G_IO_ERROR_NOT_MOUNTED:
 			case G_IO_ERROR_BUSY:
 				is_recoverable = TRUE;
 				break;
 			default:
 				break;
 		}
 	}
 
 	return is_recoverable;
 }
 
 static gboolean
@@ -193,61 +200,61 @@ parse_gio_error (gint          code,
 
 		case G_IO_ERROR_IS_DIRECTORY:
 			*error_message = g_strdup_printf (_("“%s” is a directory."),
 							 uri_for_display);
 			*message_details = g_strdup (_("Please check that you typed the "
 						      "location correctly and try again."));
 			break;
 
 		case G_IO_ERROR_INVALID_FILENAME:
 			*error_message = g_strdup_printf (_("“%s” is not a valid location."),
 							 uri_for_display);
 			*message_details = g_strdup (_("Please check that you typed the "
 						      "location correctly and try again."));
 			break;
 
 		case G_IO_ERROR_HOST_NOT_FOUND:
 			/* This case can be hit for user-typed strings like "foo" due to
 			 * the code that guesses web addresses when there's no initial "/".
 			 * But this case is also hit for legitimate web addresses when
 			 * the proxy is set up wrong.
 			 */
 			{
 				gchar *hn = NULL;
 				gchar *uri = NULL;
 
 				if (location)
 				{
 					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)
 					{
 						gchar *host_markup;
 						gchar *host_name;
 
 						host_name = g_utf8_make_valid (hn, -1);
 						g_free (hn);
 
 						host_markup = g_markup_escape_text (host_name, -1);
 						g_free (host_name);
 
 						*message_details = g_strdup_printf (
 							/* Translators: %s is a host name */
 							_("Host “%s” could not be found. "
 							"Please check that your proxy settings "
 							"are correct and try again."),
 							host_markup);
 
 						g_free (host_markup);
 					}
 				}
 
 				g_free (uri);
 
 				if (!*message_details)
 				{
 					/* use the same string as INVALID_HOST */
 					*message_details = g_strdup_printf (
 						_("Hostname was invalid. "
@@ -296,62 +303,62 @@ parse_error (const GError *error,
 	{
 		g_warning ("Hit unhandled case %d (%s) in %s.",
 			   error->code, error->message, G_STRFUNC);
 		*message_details = g_strdup_printf (_("Unexpected error: %s"),
 						    error->message);
 	}
 }
 
 GtkWidget *
 gedit_unrecoverable_reverting_error_info_bar_new (GFile        *location,
 						  const GError *error)
 {
 	gchar *error_message = NULL;
 	gchar *message_details = NULL;
 	gchar *full_formatted_uri;
 	gchar *uri_for_display;
 	gchar *temp_uri_for_display;
 	GtkWidget *info_bar;
 
 	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 == GTK_SOURCE_FILE_LOADER_ERROR ||
 			      error->domain == G_IO_ERROR, 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 = 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);
 	g_free (temp_uri_for_display);
 
 	if (is_gio_error (error, G_IO_ERROR_NOT_FOUND))
 	{
 		message_details = g_strdup (_("Cannot find the requested file. "
 					      "Perhaps it has recently been deleted."));
 	}
 	else
 	{
 		parse_error (error, &error_message, &message_details, location, uri_for_display);
 	}
 
 	if (error_message == NULL)
 	{
 		error_message = g_strdup_printf (_("Could not revert the file “%s”."),
 						 uri_for_display);
 	}
 
 	info_bar = create_io_loading_error_info_bar (error_message,
 						     message_details,
 						     FALSE);
 
 	g_free (uri_for_display);
 	g_free (error_message);
 	g_free (message_details);
 
 	return info_bar;
@@ -472,62 +479,62 @@ gedit_io_loading_error_info_bar_new (GFile                   *location,
 				     const GtkSourceEncoding *encoding,
 				     const GError            *error)
 {
 	gchar *error_message = NULL;
 	gchar *message_details = NULL;
 	gchar *full_formatted_uri;
 	gchar *uri_for_display;
 	gchar *temp_uri_for_display;
 	GtkWidget *info_bar;
 	gboolean edit_anyway = FALSE;
 	gboolean convert_error = FALSE;
 
 	g_return_val_if_fail (error != NULL, NULL);
 	g_return_val_if_fail (error->domain == GTK_SOURCE_FILE_LOADER_ERROR ||
 			      error->domain == G_IO_ERROR ||
 			      error->domain == G_CONVERT_ERROR, NULL);
 
 	if (location != NULL)
 	{
 		full_formatted_uri = g_file_get_parse_name (location);
 	}
 	else
 	{
 		full_formatted_uri = g_strdup ("stdin");
 	}
 
 	/* 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 = 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);
 	g_free (temp_uri_for_display);
 
 	if (is_gio_error (error, G_IO_ERROR_TOO_MANY_LINKS))
 	{
 		message_details = g_strdup (_("The number of followed links is limited and the actual file could not be found within this limit."));
 	}
 	else if (is_gio_error (error, G_IO_ERROR_PERMISSION_DENIED))
 	{
 		message_details = g_strdup (_("You do not have the permissions necessary to open the file."));
 	}
 	else if ((is_gio_error (error, G_IO_ERROR_INVALID_DATA) && encoding == NULL) ||
 		 (error->domain == GTK_SOURCE_FILE_LOADER_ERROR &&
 		  error->code == GTK_SOURCE_FILE_LOADER_ERROR_ENCODING_AUTO_DETECTION_FAILED))
 	{
 		message_details = g_strconcat (_("Unable to detect the character encoding."), "\n",
 					       _("Please check that you are not trying to open a binary file."), "\n",
 					       _("Select a character encoding from the menu and try again."), NULL);
 		convert_error = TRUE;
 	}
 	else if (error->domain == GTK_SOURCE_FILE_LOADER_ERROR &&
 		 error->code == GTK_SOURCE_FILE_LOADER_ERROR_CONVERSION_FALLBACK)
 	{
 		error_message = g_strdup_printf (_("There was a problem opening the file “%s”."),
 						 uri_for_display);
 		message_details = g_strconcat (_("The file you opened has some invalid characters. "
 					       "If you continue editing this file you could corrupt this "
 					       "document."), "\n",
@@ -578,219 +585,405 @@ gedit_io_loading_error_info_bar_new (GFile                   *location,
 	g_free (message_details);
 
 	return info_bar;
 }
 
 GtkWidget *
 gedit_conversion_error_while_saving_info_bar_new (GFile                   *location,
 						  const GtkSourceEncoding *encoding,
 						  const GError            *error)
 {
 	gchar *error_message = NULL;
 	gchar *message_details = NULL;
 	gchar *full_formatted_uri;
 	gchar *encoding_name;
 	gchar *uri_for_display;
 	gchar *temp_uri_for_display;
 	GtkWidget *info_bar;
 
 	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_CONVERT_ERROR ||
 	                      error->domain == G_IO_ERROR, NULL);
 	g_return_val_if_fail (encoding != NULL, 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 = 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);
 	g_free (temp_uri_for_display);
 
 	encoding_name = gtk_source_encoding_to_string (encoding);
 
 	error_message = g_strdup_printf (_("Could not save the file “%s” using the “%s” character encoding."),
 					 uri_for_display,
 					 encoding_name);
 	message_details = g_strconcat (_("The document contains one or more characters that cannot be encoded "
 					 "using the specified character encoding."), "\n",
 				       _("Select a different character encoding from the menu and try again."), NULL);
 
 	info_bar = create_conversion_error_info_bar (error_message,
 						     message_details,
 						     FALSE);
 
 	g_free (uri_for_display);
 	g_free (encoding_name);
 	g_free (error_message);
 	g_free (message_details);
 
 	return info_bar;
 }
 
 const GtkSourceEncoding *
 gedit_conversion_error_info_bar_get_encoding (GtkWidget *info_bar)
 {
 	gpointer menu;
 
 	g_return_val_if_fail (GTK_IS_INFO_BAR (info_bar), NULL);
 
 	menu = g_object_get_data (G_OBJECT (info_bar),
 				  "gedit-info-bar-encoding-menu");
 	if (menu != NULL)
 	{
 		return gedit_encodings_combo_box_get_selected_encoding (GEDIT_ENCODINGS_COMBO_BOX (menu));
 	}
 
 	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)
 {
 	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);
 	g_return_val_if_fail (error != NULL, NULL);
 	g_return_val_if_fail (error->domain == GTK_SOURCE_FILE_SAVER_ERROR, NULL);
 	g_return_val_if_fail (error->code == GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED, 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 = 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);
 	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);
 
 	/* FIXME: review this message, it's not clear since for the user the "modification"
 	 * could be interpreted as the changes he made in the document. beside "reading" is
 	 * not accurate (since last load/save)
 	 */
 	primary_text = g_strdup_printf (_("The file “%s” has been modified since reading it."),
 					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 save it, all the external changes could be lost. Save 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_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)
 {
 	gchar *error_message = NULL;
 	gchar *message_details = NULL;
 	gchar *full_formatted_uri;
 	gchar *scheme_string;
 	gchar *scheme_markup;
 	gchar *uri_for_display;
 	gchar *temp_uri_for_display;
 	GtkWidget *info_bar;
 
 	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 == GTK_SOURCE_FILE_SAVER_ERROR ||
 			      error->domain == G_IO_ERROR, 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 = 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);
 	g_free (temp_uri_for_display);
 
 	if (is_gio_error (error, G_IO_ERROR_NOT_SUPPORTED))
 	{
 		scheme_string = g_file_get_uri_scheme (location);
 
 		if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL))
 		{
 			scheme_markup = g_markup_escape_text (scheme_string, -1);
 
 			/* Translators: %s is a URI scheme (like for example http:, ftp:, etc.) */
 			message_details = g_strdup_printf (_("Cannot handle “%s:” locations in write mode. "
 							     "Please check that you typed the "
 							     "location correctly and try again."),
 							   scheme_markup);
 			g_free (scheme_markup);
 		}
 		else
 		{
 			message_details = g_strdup (_("Cannot handle this location in write mode. "
 						      "Please check that you typed the "
 						      "location correctly and try again."));
 		}
 
 		g_free (scheme_string);
 	}
 	else if (is_gio_error (error, G_IO_ERROR_INVALID_FILENAME))
@@ -840,31 +1033,176 @@ gedit_unrecoverable_saving_error_info_bar_new (GFile        *location,
 					      "a smaller file or saving it to a disk that does not "
 					      "have this limitation."));
 	}
 #endif
 	else
 	{
 		parse_error (error,
 			     &error_message,
 			     &message_details,
 			     location,
 			     uri_for_display);
 	}
 
 	if (error_message == NULL)
 	{
 		error_message = g_strdup_printf (_("Could not save the file “%s”."),
 						 uri_for_display);
 	}
 
 	info_bar = create_io_loading_error_info_bar (error_message,
 						     message_details,
 						     FALSE);
 
 	g_free (uri_for_display);
 	g_free (error_message);
 	g_free (message_details);
 
 	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
@@ -12,41 +12,51 @@
  * 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_IO_ERROR_INFO_BAR_H
 #define GEDIT_IO_ERROR_INFO_BAR_H
 
 #include <gtksourceview/gtksource.h>
 
 G_BEGIN_DECLS
 
 GtkWidget	*gedit_io_loading_error_info_bar_new			(GFile                   *location,
 									 const GtkSourceEncoding *encoding,
 									 const GError            *error);
 
 GtkWidget	*gedit_unrecoverable_reverting_error_info_bar_new	(GFile               *location,
 									 const GError        *error);
 
 GtkWidget	*gedit_conversion_error_while_saving_info_bar_new	(GFile                   *location,
 									 const GtkSourceEncoding *encoding,
 									 const GError            *error);
 
 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  */
 
 /* ex:set ts=8 noet: */
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
@@ -1,137 +1,148 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * gedit-preferences-dialog.c
  * This file is part of gedit
  *
  * Copyright (C) 2001-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 "config.h"
 
 #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
  * want two dialogs showing an inconsistent state of the
  * preferences.
  * When gedit_show_preferences_dialog is called and there
  * is already a prefs dialog dialog open, it is reparented
  * and shown.
  */
 
 static GtkWidget *preferences_dialog = NULL;
 
 #define GEDIT_SCHEME_ROW_ID_KEY "gedit-scheme-row-id"
 
 #define GEDIT_TYPE_PREFERENCES_DIALOG (gedit_preferences_dialog_get_type())
 
 G_DECLARE_FINAL_TYPE (GeditPreferencesDialog, gedit_preferences_dialog, GEDIT, PREFERENCES_DIALOG, GtkWindow)
 
 enum
 {
 	ID_COLUMN = 0,
 	NAME_COLUMN,
 	DESC_COLUMN,
 	NUM_COLUMNS
 };
 
 enum
 {
 	CLOSE,
 	LAST_SIGNAL
 };
 
 static guint signals[LAST_SIGNAL];
 
 struct _GeditPreferencesDialog
 {
 	GtkWindow	parent_instance;
 
 	GSettings	*editor;
 	GSettings	*uisettings; /* unfortunately our settings are split for historical reasons */
 
 	GtkWidget	*notebook;
 
 	/* Font */
 	GtkWidget	*default_font_checkbutton;
 	GtkWidget	*font_button;
 	GtkWidget	*font_grid;
 
 	/* Style Scheme */
 	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;
 	GtkWidget	*insert_spaces_checkbutton;
 
 	/* Auto indentation */
 	GtkWidget	*auto_indent_checkbutton;
 
 	/* Text Wrapping */
 	GtkWidget	*wrap_text_checkbutton;
 	GtkWidget	*split_checkbutton;
 
 	/* File Saving */
 	GtkWidget	*backup_copy_checkbutton;
 	GtkWidget	*auto_save_checkbutton;
 	GtkWidget	*auto_save_spinbutton;
 
 	GtkWidget	*display_line_numbers_checkbutton;
 	GtkWidget	*display_statusbar_checkbutton;
+	GtkWidget	*display_overview_map_checkbutton;
 	GtkWidget	*display_grid_checkbutton;
 
 	/* Right margin */
 	GtkWidget	*right_margin_checkbutton;
 	GtkWidget       *right_margin_position_grid;
 	GtkWidget	*right_margin_position_spinbutton;
 
 	/* Highlighting */
 	GtkWidget	*highlight_current_line_checkbutton;
 	GtkWidget	*bracket_matching_checkbutton;
 
 	/* Plugin manager */
 	GtkWidget	*plugin_manager;
 };
 
 G_DEFINE_TYPE (GeditPreferencesDialog, gedit_preferences_dialog, GTK_TYPE_WINDOW)
 
 static void
 gedit_preferences_dialog_dispose (GObject *object)
 {
 	GeditPreferencesDialog *dlg = GEDIT_PREFERENCES_DIALOG (object);
 
 	g_clear_object (&dlg->editor);
 	g_clear_object (&dlg->uisettings);
 
 	G_OBJECT_CLASS (gedit_preferences_dialog_parent_class)->dispose (object);
 }
 
 static void
 gedit_preferences_dialog_close (GeditPreferencesDialog *dialog)
@@ -143,77 +154,79 @@ static void
 gedit_preferences_dialog_class_init (GeditPreferencesDialogClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 	GtkBindingSet *binding_set;
 
 	/* Otherwise libpeas-gtk might not be linked */
 	g_type_ensure (PEAS_GTK_TYPE_PLUGIN_MANAGER);
 
 	object_class->dispose = gedit_preferences_dialog_dispose;
 
 	signals[CLOSE] =
 		g_signal_new_class_handler ("close",
 		                            G_TYPE_FROM_CLASS (klass),
 		                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 		                            G_CALLBACK (gedit_preferences_dialog_close),
 		                            NULL, NULL, NULL,
 		                            G_TYPE_NONE,
 		                            0);
 
 	binding_set = gtk_binding_set_by_class (klass);
 	gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
 
 	/* Bind class to template */
 	gtk_widget_class_set_template_from_resource (widget_class,
 	                                             "/org/gnome/gedit/ui/gedit-preferences-dialog.ui");
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, notebook);
 	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);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, highlight_current_line_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, bracket_matching_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, wrap_text_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, split_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, tabs_width_spinbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, insert_spaces_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, auto_indent_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, backup_copy_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, auto_save_checkbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, auto_save_spinbutton);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, default_font_checkbutton);
 	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);
 	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, plugin_manager);
 }
 
 static void
 setup_editor_page (GeditPreferencesDialog *dlg)
 {
 	gedit_debug (DEBUG_PREFS);
 
 	/* Connect signal */
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_TABS_SIZE,
 			 dlg->tabs_width_spinbutton,
 			 "value",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_INSERT_SPACES,
 			 dlg->insert_spaces_checkbutton,
 			 "active",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_AUTO_INDENT,
 			 dlg->auto_indent_checkbutton,
 			 "active",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_CREATE_BACKUP_COPY,
 			 dlg->backup_copy_checkbutton,
@@ -359,488 +372,554 @@ setup_view_page (GeditPreferencesDialog *dlg)
 			gtk_toggle_button_set_inconsistent (
 				GTK_TOGGLE_BUTTON (dlg->split_checkbutton), TRUE);
 	}
 
 	gtk_toggle_button_set_active (
 		GTK_TOGGLE_BUTTON (dlg->right_margin_checkbutton),
 		display_right_margin);
 	gtk_toggle_button_set_active (
 		GTK_TOGGLE_BUTTON (dlg->display_grid_checkbutton),
 		background_pattern == GTK_SOURCE_BACKGROUND_PATTERN_TYPE_GRID);
 
 	/* Set widgets sensitivity */
 	gtk_widget_set_sensitive (dlg->split_checkbutton,
 				  (wrap_mode != GTK_WRAP_NONE));
 
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_DISPLAY_LINE_NUMBERS,
 			 dlg->display_line_numbers_checkbutton,
 			 "active",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_HIGHLIGHT_CURRENT_LINE,
 			 dlg->highlight_current_line_checkbutton,
 			 "active",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->uisettings,
 	                 GEDIT_SETTINGS_STATUSBAR_VISIBLE,
 	                 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,
 	                 "active",
 	                 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 	                 GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN,
 	                 dlg->right_margin_position_grid,
 	                 "sensitive",
 	                 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_RIGHT_MARGIN_POSITION,
 			 dlg->right_margin_position_spinbutton,
 			 "value",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_AUTO_SAVE_INTERVAL,
 			 dlg->auto_save_spinbutton,
 			 "value",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_signal_connect (dlg->wrap_text_checkbutton,
 			  "toggled",
 			  G_CALLBACK (wrap_mode_checkbutton_toggled),
 			  dlg);
 	g_signal_connect (dlg->split_checkbutton,
 			  "toggled",
 			  G_CALLBACK (wrap_mode_checkbutton_toggled),
 			  dlg);
 	g_signal_connect (dlg->display_grid_checkbutton,
 			  "toggled",
 			  G_CALLBACK (grid_checkbutton_toggled),
 			  dlg);
 }
 
 static void
 setup_font_colors_page_font_section (GeditPreferencesDialog *dlg)
 {
 	GeditSettings *settings;
 	gchar *system_font = NULL;
 	gchar *label;
 
 	gedit_debug (DEBUG_PREFS);
 
 	gtk_widget_set_tooltip_text (dlg->font_button,
 			 _("Click on this button to select the font to be used by the editor"));
 
 	/* 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);
 	gtk_button_set_label (GTK_BUTTON (dlg->default_font_checkbutton),
 			      label);
 	g_free (system_font);
 	g_free (label);
 
 	/* Bind settings */
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_USE_DEFAULT_FONT,
 			 dlg->default_font_checkbutton,
 			 "active",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_USE_DEFAULT_FONT,
 			 dlg->font_grid,
 			 "sensitive",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_INVERT_BOOLEAN);
 	g_settings_bind (dlg->editor,
 			 GEDIT_SETTINGS_EDITOR_FONT,
 			 dlg->font_button,
 			 "font-name",
 			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
 }
 
 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)
 {
 	GtkSourceStyleSchemeManager *manager;
 	const gchar *filename;
 
 	g_return_val_if_fail (GTK_SOURCE_IS_STYLE_SCHEME (scheme), FALSE);
 
 	manager = gtk_source_style_scheme_manager_get_default ();
 
 	filename = gtk_source_style_scheme_get_filename (scheme);
 	if (filename == NULL)
 		return FALSE;
 
 	if (g_unlink (filename) == -1)
 		return FALSE;
 
 	/* Reload the available style schemes */
 	gtk_source_style_scheme_manager_force_rescan (manager);
 
 	return TRUE;
 }
 
 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
 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));
 	}
 }
 
 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);
 
 	/* 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",
 			  G_CALLBACK (install_scheme_clicked),
 			  dlg);
 	g_signal_connect (dlg->uninstall_scheme_button,
 			  "clicked",
 			  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
 setup_font_colors_page (GeditPreferencesDialog *dlg)
 {
 	setup_font_colors_page_font_section (dlg);
 	setup_font_colors_page_style_scheme_section (dlg);
 }
 
 static void
 setup_plugins_page (GeditPreferencesDialog *dlg)
 {
 	gtk_widget_show_all (dlg->plugin_manager);
 }
 
 static void
 gedit_preferences_dialog_init (GeditPreferencesDialog *dlg)
 {
 	gedit_debug (DEBUG_PREFS);
 
 	dlg->editor = g_settings_new ("org.gnome.gedit.preferences.editor");
 	dlg->uisettings = g_settings_new ("org.gnome.gedit.preferences.ui");
 
 	gtk_widget_init_template (GTK_WIDGET (dlg));
 
 	setup_editor_page (dlg);
 	setup_view_page (dlg);
 	setup_font_colors_page (dlg);
 	setup_plugins_page (dlg);
 }
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
@@ -1,56 +1,56 @@
 /*
  * gedit-print-job.c
  * This file is part of gedit
  *
  * Copyright (C) 2000-2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002-2008 Paolo Maggi
  * Copyright (C) 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
  * 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-print-job.h"
 
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
+#include <gtksourceview/gtksource.h>
 
 #include "gedit-debug.h"
 #include "gedit-document-private.h"
 #include "gedit-print-preview.h"
 #include "gedit-utils.h"
 #include "gedit-dirs.h"
 #include "gedit-settings.h"
 
 struct _GeditPrintJob
 {
 	GObject parent_instance;
 
 	GSettings *gsettings;
 
 	GeditView *view;
 
 	GtkPrintOperation *operation;
 	GtkSourcePrintCompositor *compositor;
 
 	GtkWidget *preview;
 
 	gchar *status_string;
 	gdouble progress;
 
 	/* Widgets part of the custom print preferences widget.
 	 * These pointers are valid just when the dialog is displayed.
 	 */
 	GtkToggleButton *syntax_checkbutton;
 	GtkToggleButton *page_header_checkbutton;
 	GtkToggleButton *line_numbers_checkbutton;
@@ -508,61 +508,61 @@ create_compositor (GeditPrintJob *job)
 			      "tab-width", tab_width,
 			      "highlight-syntax", syntax_hl,
 			      "wrap-mode", wrap_mode,
 			      "print-line-numbers", print_line_numbers,
 			      "print-header", print_header,
 			      "print-footer", FALSE,
 			      "body-font-name", print_font_body,
 			      "line-numbers-font-name", print_font_numbers,
 			      "header-font-name", print_font_header,
 			      NULL));
 
 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_LEFT);
 	gtk_source_print_compositor_set_left_margin (job->compositor, margin, GTK_UNIT_MM);
 
 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_TOP);
 	gtk_source_print_compositor_set_top_margin (job->compositor, margin, GTK_UNIT_MM);
 
 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_RIGHT);
 	gtk_source_print_compositor_set_right_margin (job->compositor, margin, GTK_UNIT_MM);
 
 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_BOTTOM);
 	gtk_source_print_compositor_set_bottom_margin (job->compositor, margin, GTK_UNIT_MM);
 
 	if (print_header)
 	{
 		gchar *doc_name;
 		gchar *name_to_display;
 		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);
 
 		gtk_source_print_compositor_set_header_format (job->compositor,
 							       TRUE,
 							       left,
 							       NULL,
 							       /* Translators: %N is the current page number, %Q is the total
 							        * number of pages (ex. Page 2 of 10)
 							        */
 							       _("Page %N of %Q"));
 
 		g_free (doc_name);
 		g_free (name_to_display);
 		g_free (left);
 	}
 
 	g_free (print_font_body);
 	g_free (print_font_header);
 	g_free (print_font_numbers);
 }
 
 static void
 begin_print_cb (GtkPrintOperation *operation,
 	        GtkPrintContext   *context,
 	        GeditPrintJob     *job)
 {
 	create_compositor (job);
 
 	job->progress = 0.0;
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-osx.c b/gedit/gedit-recent-osx.c
deleted file mode 100644
index 6f8c8cd6e..000000000
--- a/gedit/gedit-recent-osx.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * This file is part of gedit
- *
- * Copyright (C) 2005 - Paolo Maggi
- * Copyright (C) 2014 - Paolo Borelli
- * Copyright (C) 2014 - Jesse van den Kieboom
- *
- * 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-recent-osx.h"
-
-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-osx.h b/gedit/gedit-recent-osx.h
deleted file mode 100644
index df77ca724..000000000
--- a/gedit/gedit-recent-osx.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This file is part of gedit
- *
- * Copyright (C) 2005 - Paolo Maggi
- * Copyright (C) 2014 - Paolo Borelli
- * Copyright (C) 2014 - Jesse van den Kieboom
- *
- * 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
- * MERCHANWINDOWILITY 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_RECENT_OSX_H
-#define GEDIT_RECENT_OSX_H
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-/* TODO: this code can be simplified, the struct can be made private, the dead
- * code can be removed, etc.
- */
-
-typedef struct
-{
-	GtkRecentManager *manager;
-	GtkRecentFilter *filter;
-
-	gint limit;
-	gchar *substring_filter;
-
-	guint show_private : 1;
-	guint show_not_found : 1;
-	guint local_only : 1;
-} GeditRecentConfiguration;
-
-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_OSX_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
@@ -1,92 +1,317 @@
 /*
  * This file is part of gedit
  *
  * Copyright (C) 2005 - Paolo Maggi
  * Copyright (C) 2014 - Paolo Borelli
  * Copyright (C) 2014 - Jesse van den Kieboom
  *
  * 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-recent.h"
 
 void
 gedit_recent_add_document (GeditDocument *document)
 {
-	TeplFile *file;
+	GtkSourceFile *file;
 	GFile *location;
 	GtkRecentManager *recent_manager;
 	GtkRecentData recent_data;
 	gchar *uri;
 	static gchar *groups[2];
 
 	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)
 	{
 		return;
 	}
 
 	recent_manager = gtk_recent_manager_get_default ();
 
 	groups[0] = (gchar *) g_get_application_name ();
 	groups[1] = NULL;
 
 	recent_data.display_name = NULL;
 	recent_data.description = NULL;
 	recent_data.mime_type = gedit_document_get_mime_type (document);
 	recent_data.app_name = (gchar *) g_get_application_name ();
 	recent_data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
 	recent_data.groups = groups;
 	recent_data.is_private = FALSE;
 
 	uri = g_file_get_uri (location);
 
 	if (!gtk_recent_manager_add_full (recent_manager, uri, &recent_data))
 	{
 		g_warning ("Failed to add uri '%s' to the recent manager.", uri);
 	}
 
 	g_free (uri);
 	g_free (recent_data.app_exec);
 	g_free (recent_data.mime_type);
 }
 
 void
 gedit_recent_remove_if_local (GFile *location)
 {
 	g_return_if_fail (G_IS_FILE (location));
 
 	/* If a file is local chances are that if load/save fails the file has
 	 * beed removed and the failure is permanent so we remove it from the
 	 * list of recent files. For remote files the failure may be just
 	 * transitory and we keep the file in the list.
 	 */
 	if (g_file_has_uri_scheme (location, "file"))
 	{
 		GtkRecentManager *recent_manager;
 		gchar *uri;
 
 		recent_manager = gtk_recent_manager_get_default ();
 
 		uri = g_file_get_uri (location);
 		gtk_recent_manager_remove_item (recent_manager, uri, NULL);
 		g_free (uri);
 	}
 }
 
+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
@@ -1,38 +1,55 @@
 /*
  * This file is part of gedit
  *
  * Copyright (C) 2005 - Paolo Maggi
  * Copyright (C) 2014 - Paolo Borelli
  * Copyright (C) 2014 - Jesse van den Kieboom
  *
  * 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
  * MERCHANWINDOWILITY 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_RECENT_H
 #define GEDIT_RECENT_H
 
 #include <gtk/gtk.h>
 #include <gedit/gedit-document.h>
 
 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
@@ -10,144 +10,184 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
  * gedit is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with gedit; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 
 #include "gedit-settings.h"
 #include <gtksourceview/gtksource.h>
 #include "gedit-app.h"
 
 #define GEDIT_SETTINGS_SYSTEM_FONT "monospace-font-name"
 
 struct _GeditSettings
 {
 	GObject parent_instance;
 
 	GSettings *settings_interface;
 	GSettings *settings_editor;
 	GSettings *settings_ui;
 	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)
 
 static void
 gedit_settings_dispose (GObject *object)
 {
 	GeditSettings *self = GEDIT_SETTINGS (object);
 
 	g_clear_object (&self->settings_interface);
 	g_clear_object (&self->settings_editor);
 	g_clear_object (&self->settings_ui);
 	g_clear_object (&self->settings_file_chooser_state);
 
 	G_OBJECT_CLASS (gedit_settings_parent_class)->dispose (object);
 }
 
 static void
 gedit_settings_finalize (GObject *object)
 {
 	GeditSettings *self = GEDIT_SETTINGS (object);
 
 	if (singleton == self)
 	{
 		singleton = NULL;
 	}
 
 	G_OBJECT_CLASS (gedit_settings_parent_class)->finalize (object);
 }
 
 static void
 gedit_settings_class_init (GeditSettingsClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (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);
 	}
 }
 
 static void
 on_auto_save_changed (GSettings     *settings,
 		      const gchar   *key,
 		      GeditSettings *self)
 {
 	gboolean auto_save;
 	GList *docs;
 	GList *l;
 
 	auto_save = g_settings_get_boolean (settings, key);
 
 	docs = gedit_app_get_documents (GEDIT_APP (g_application_get_default ()));
 
 	for (l = docs; l != NULL; l = l->next)
 	{
 		GeditTab *tab = gedit_tab_get_from_document (GEDIT_DOCUMENT (l->data));
 		gedit_tab_set_auto_save_enabled (tab, auto_save);
 	}
 
 	g_list_free (docs);
 }
 
 static void
 on_auto_save_interval_changed (GSettings     *settings,
 			       const gchar   *key,
 			       GeditSettings *self)
 {
@@ -180,163 +220,146 @@ on_syntax_highlighting_changed (GSettings     *settings,
 
 	enable = g_settings_get_boolean (settings, key);
 
 	docs = gedit_app_get_documents (GEDIT_APP (g_application_get_default ()));
 
 	for (l = docs; l != NULL; l = l->next)
 	{
 		GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (l->data);
 		gtk_source_buffer_set_highlight_syntax (buffer, enable);
 	}
 
 	g_list_free (docs);
 
 	/* update the sensitivity of the Higlight Mode menu item */
 	windows = gedit_app_get_main_windows (GEDIT_APP (g_application_get_default ()));
 
 	for (l = windows; l != NULL; l = l->next)
 	{
 		GAction *action;
 
 		action = g_action_map_lookup_action (G_ACTION_MAP (l->data), "highlight-mode");
 		g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enable);
 	}
 
 	g_list_free (windows);
 }
 
 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 *
 _gedit_settings_get_singleton (void)
 {
 	if (singleton == NULL)
 	{
 		singleton = g_object_new (GEDIT_TYPE_SETTINGS, NULL);
 	}
 
 	return singleton;
 }
 
 void
 gedit_settings_unref_singleton (void)
 {
 	if (singleton != NULL)
 	{
 		g_object_unref (singleton);
 	}
 
 	/* singleton is not set to NULL here, it is set to NULL in
 	 * gedit_settings_finalize() (i.e. when we are sure that the ref count
 	 * reaches 0).
 	 */
 }
 
 GSettings *
 _gedit_settings_peek_editor_settings (GeditSettings *self)
 {
 	g_return_val_if_fail (GEDIT_IS_SETTINGS (self), NULL);
 
 	return self->settings_editor;
 }
 
 GSettings *
 _gedit_settings_peek_file_chooser_state_settings (GeditSettings *self)
 {
 	g_return_val_if_fail (GEDIT_IS_SETTINGS (self), NULL);
 
 	return self->settings_file_chooser_state;
 }
 
 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
 strv_is_empty (gchar **strv)
 {
 	if (strv == NULL || strv[0] == NULL)
 	{
 		return TRUE;
 	}
 
 	/* Contains one empty string. */
 	if (strv[1] == NULL && strv[0][0] == '\0')
 	{
 		return TRUE;
 	}
 
 	return FALSE;
 }
 
 static GSList *
 encoding_strv_to_list (const gchar * const *encoding_strv)
 {
 	GSList *list = NULL;
 	gchar **p;
 
 	for (p = (gchar **)encoding_strv; p != NULL && *p != NULL; p++)
 	{
 		const gchar *charset = *p;
 		const GtkSourceEncoding *encoding;
 
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
@@ -16,90 +16,87 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with gedit; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 
 #ifndef GEDIT_SETTINGS_H
 #define GEDIT_SETTINGS_H
 
 #include <gio/gio.h>
 
 G_BEGIN_DECLS
 
 #define GEDIT_TYPE_SETTINGS (gedit_settings_get_type ())
 
 G_DECLARE_FINAL_TYPE (GeditSettings, gedit_settings, GEDIT, SETTINGS, GObject)
 
 G_GNUC_INTERNAL
 GeditSettings *	_gedit_settings_get_singleton				(void);
 
 void		gedit_settings_unref_singleton				(void);
 
 G_GNUC_INTERNAL
 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);
 
 /* key constants */
 #define GEDIT_SETTINGS_USE_DEFAULT_FONT			"use-default-font"
 #define GEDIT_SETTINGS_EDITOR_FONT			"editor-font"
 #define GEDIT_SETTINGS_SCHEME				"scheme"
 #define GEDIT_SETTINGS_CREATE_BACKUP_COPY		"create-backup-copy"
 #define GEDIT_SETTINGS_AUTO_SAVE			"auto-save"
 #define GEDIT_SETTINGS_AUTO_SAVE_INTERVAL		"auto-save-interval"
 #define GEDIT_SETTINGS_MAX_UNDO_ACTIONS			"max-undo-actions"
 #define GEDIT_SETTINGS_WRAP_MODE			"wrap-mode"
 #define GEDIT_SETTINGS_WRAP_LAST_SPLIT_MODE		"wrap-last-split-mode"
 #define GEDIT_SETTINGS_TABS_SIZE			"tabs-size"
 #define GEDIT_SETTINGS_INSERT_SPACES			"insert-spaces"
 #define GEDIT_SETTINGS_AUTO_INDENT			"auto-indent"
 #define GEDIT_SETTINGS_DISPLAY_LINE_NUMBERS		"display-line-numbers"
 #define GEDIT_SETTINGS_HIGHLIGHT_CURRENT_LINE		"highlight-current-line"
 #define GEDIT_SETTINGS_BRACKET_MATCHING			"bracket-matching"
 #define GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN		"display-right-margin"
 #define GEDIT_SETTINGS_RIGHT_MARGIN_POSITION		"right-margin-position"
 #define GEDIT_SETTINGS_SMART_HOME_END			"smart-home-end"
 #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"
 #define GEDIT_SETTINGS_BOTTOM_PANEL_VISIBLE		"bottom-panel-visible"
 #define GEDIT_SETTINGS_PRINT_SYNTAX_HIGHLIGHTING	"print-syntax-highlighting"
 #define GEDIT_SETTINGS_PRINT_HEADER			"print-header"
 #define GEDIT_SETTINGS_PRINT_WRAP_MODE			"print-wrap-mode"
 #define GEDIT_SETTINGS_PRINT_LINE_NUMBERS		"print-line-numbers"
 #define GEDIT_SETTINGS_PRINT_FONT_BODY_PANGO		"print-font-body-pango"
 #define GEDIT_SETTINGS_PRINT_FONT_HEADER_PANGO		"print-font-header-pango"
 #define GEDIT_SETTINGS_PRINT_FONT_NUMBERS_PANGO		"print-font-numbers-pango"
 #define GEDIT_SETTINGS_PRINT_MARGIN_LEFT		"margin-left"
 #define GEDIT_SETTINGS_PRINT_MARGIN_TOP			"margin-top"
 #define GEDIT_SETTINGS_PRINT_MARGIN_RIGHT		"margin-right"
 #define GEDIT_SETTINGS_PRINT_MARGIN_BOTTOM		"margin-bottom"
 #define GEDIT_SETTINGS_CANDIDATE_ENCODINGS		"candidate-encodings"
 #define GEDIT_SETTINGS_ACTIVE_PLUGINS			"active-plugins"
 #define GEDIT_SETTINGS_ENSURE_TRAILING_NEWLINE		"ensure-trailing-newline"
 
 /* window state keys */
 #define GEDIT_SETTINGS_WINDOW_STATE			"state"
 #define GEDIT_SETTINGS_WINDOW_SIZE			"size"
 #define GEDIT_SETTINGS_SHOW_TABS_MODE			"show-tabs-mode"
 #define GEDIT_SETTINGS_SIDE_PANEL_SIZE			"side-panel-size"
 #define GEDIT_SETTINGS_SIDE_PANEL_ACTIVE_PAGE		"side-panel-active-page"
 #define GEDIT_SETTINGS_BOTTOM_PANEL_SIZE		"bottom-panel-size"
 #define GEDIT_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE		"bottom-panel-active-page"
 
 /* file chooser state keys */
 #define GEDIT_SETTINGS_ACTIVE_FILE_FILTER		"filter-id"
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index af72864e2..6bb38b160 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -1,65 +1,65 @@
 /*
  * gedit-tab.c
  * This file is part of gedit
  *
  * Copyright (C) 2005 - Paolo Maggi
  * 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
  * 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-tab.h"
 #include "gedit-tab-private.h"
 
 #include <stdlib.h>
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 
 #include "gedit-app.h"
 #include "gedit-app-private.h"
 #include "gedit-recent.h"
 #include "gedit-utils.h"
 #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"
 #include "gedit-enum-types.h"
 #include "gedit-settings.h"
 #include "gedit-view-frame.h"
 
 #define GEDIT_TAB_KEY "GEDIT_TAB_KEY"
 
 struct _GeditTab
 {
 	GtkBox parent_instance;
 
 	GeditTabState state;
 
 	GSettings *editor_settings;
 
 	GeditViewFrame *frame;
 
 	GtkWidget *info_bar;
 	GtkWidget *info_bar_hidden;
 
 	GeditPrintJob *print_job;
 	GtkWidget *print_preview;
 
 	GtkSourceFileSaverFlags save_flags;
 
 	guint idle_scroll;
 
 	gint auto_save_interval;
@@ -547,63 +547,63 @@ gedit_tab_set_state (GeditTab      *tab,
 	if (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
 	{
 		gtk_widget_hide (GTK_WIDGET (tab->frame));
 	}
 	else if (state != GEDIT_TAB_STATE_LOADING_ERROR)
 	{
 		gtk_widget_show (GTK_WIDGET (tab->frame));
 	}
 
 	set_cursor_according_to_state (GTK_TEXT_VIEW (gedit_tab_get_view (tab)),
 				       state);
 
 	update_auto_save_timeout (tab);
 
 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_STATE]);
 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_CAN_CLOSE]);
 }
 
 static void
 document_location_notify_handler (GtkSourceFile *file,
 				  GParamSpec    *pspec,
 				  GeditTab      *tab)
 {
 	gedit_debug (DEBUG_TAB);
 
 	/* Notify the change in the location */
 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
 }
 
 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);
 
 	/* Notify the change in the shortname */
 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
 }
 
 static void
 document_modified_changed (GtkTextBuffer *document,
 			   GeditTab      *tab)
 {
 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
 	g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_CAN_CLOSE]);
 }
 
 static void
 set_info_bar (GeditTab        *tab,
               GtkWidget       *info_bar,
               GtkResponseType  default_response)
 {
 	gedit_debug (DEBUG_TAB);
 
 	if (tab->info_bar == info_bar)
 	{
 		return;
 	}
 
 	if (info_bar == NULL)
 	{
 		/* Don't destroy the old info_bar right away,
@@ -699,369 +699,369 @@ io_loading_error_info_bar_response (GtkWidget *info_bar,
 			g_task_return_boolean (loading_task, FALSE);
 			g_object_unref (loading_task);
 			break;
 	}
 }
 
 static void
 file_already_open_warning_info_bar_response (GtkWidget *info_bar,
 					     gint       response_id,
 					     GeditTab  *tab)
 {
 	GeditView *view = gedit_tab_get_view (tab);
 
 	if (response_id == GTK_RESPONSE_YES)
 	{
 		set_editable (tab, TRUE);
 	}
 
 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
 	gtk_widget_grab_focus (GTK_WIDGET (view));
 }
 
 static void
 load_cancelled (GtkWidget *bar,
 		gint       response_id,
 		GTask     *loading_task)
 {
 	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);
 }
 
 static void
 unrecoverable_reverting_error_info_bar_response (GtkWidget *info_bar,
 						 gint       response_id,
 						 GTask     *loading_task)
 {
 	LoaderData *data = g_task_get_task_data (loading_task);
 	GeditView *view;
 
 	gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_NORMAL);
 
 	set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
 
 	view = gedit_tab_get_view (data->tab);
 	gtk_widget_grab_focus (GTK_WIDGET (view));
 
 	g_task_return_boolean (loading_task, FALSE);
 	g_object_unref (loading_task);
 }
 
 #define MAX_MSG_LENGTH 100
 
 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;
 	gchar *msg = NULL;
 	gchar *name_markup;
 	gchar *dirname_markup;
 	gint len;
 
 	if (data->tab->info_bar != NULL)
 	{
 		return;
 	}
 
 	gedit_debug (DEBUG_TAB);
 
 	doc = gedit_tab_get_document (data->tab);
 
 	name = gedit_document_get_short_name_for_display (doc);
 	len = g_utf8_strlen (name, -1);
 
 	/* if the name is awfully long, truncate it and be done with it,
 	 * otherwise also show the directory (ellipsized if needed)
 	 */
 	if (len > MAX_MSG_LENGTH)
 	{
 		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;
 	}
 	else
 	{
 		GtkSourceFile *file = gedit_document_get_file (doc);
 		GFile *location = gtk_source_file_get_location (file);
 
 		if (location != NULL)
 		{
 			gchar *str = gedit_utils_location_get_dirname_for_display (location);
 
 			/* use the remaining space for the dir, but use a min of 20 chars
 			 * so that we do not end up with a dirname like "(a...b)".
 			 * This means that in the worst case when the filename is long 99
 			 * 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);
 		}
 	}
 
 	name_markup = g_markup_printf_escaped ("<b>%s</b>", name);
 
 	if (data->tab->state == GEDIT_TAB_STATE_REVERTING)
 	{
 		if (dirname != NULL)
 		{
 			dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
 
 			/* Translators: the first %s is a file name (e.g. test.txt) the second one
 			   is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
 			msg = g_strdup_printf (_("Reverting %s from %s"),
 					       name_markup,
 					       dirname_markup);
 			g_free (dirname_markup);
 		}
 		else
 		{
 			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
 	{
 		if (dirname != NULL)
 		{
 			dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
 
 			/* Translators: the first %s is a file name (e.g. test.txt) the second one
 			   is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
 			msg = g_strdup_printf (_("Loading %s from %s"),
 					       name_markup,
 					       dirname_markup);
 			g_free (dirname_markup);
 		}
 		else
 		{
 			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,
 				 "response",
 				 G_CALLBACK (load_cancelled),
 				 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);
 	g_free (name_markup);
 	g_free (dirname);
 }
 
 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;
 	gchar *to = NULL;
 	gchar *from_markup;
 	gchar *to_markup;
 	gchar *msg = NULL;
 	gint len;
 
 	if (tab->info_bar != NULL)
 	{
 		return;
 	}
 
 	gedit_debug (DEBUG_TAB);
 
 	doc = gedit_tab_get_document (tab);
 
 	short_name = gedit_document_get_short_name_for_display (doc);
 
 	len = g_utf8_strlen (short_name, -1);
 
 	/* if the name is awfully long, truncate it and be done with it,
 	 * otherwise also show the directory (ellipsized if needed)
 	 */
 	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
 	{
 		gchar *str;
 		SaverData *data;
 		GFile *location;
 
 		data = g_task_get_task_data (saving_task);
 		location = gtk_source_file_saver_get_location (data->saver);
 
 		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;
 	}
 
 	from_markup = g_markup_printf_escaped ("<b>%s</b>", from);
 
 	if (to != NULL)
 	{
 		to_markup = g_markup_printf_escaped ("<b>%s</b>", to);
 
 		/* Translators: the first %s is a file name (e.g. test.txt) the second one
 		   is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
 		msg = g_strdup_printf (_("Saving %s to %s"), from_markup, to_markup);
 		g_free (to_markup);
 	}
 	else
 	{
 		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);
 	g_free (from);
 	g_free (from_markup);
 }
 
 static void
 info_bar_set_progress (GeditTab *tab,
 		       goffset   size,
 		       goffset   total_size)
 {
-	TeplProgressInfoBar *progress_info_bar;
+	GeditProgressInfoBar *progress_info_bar;
 
 	if (tab->info_bar == NULL)
 	{
 		return;
 	}
 
 	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);
 	}
 }
 
 /* Returns whether progress info should be shown. */
 static gboolean
 should_show_progress_info (GTimer  **timer,
 			   goffset   size,
 			   goffset   total_size)
 {
 	gdouble elapsed_time;
 	gdouble total_time;
 	gdouble remaining_time;
 
 	g_assert (timer != NULL);
 
 	if (*timer == NULL)
 	{
 		return TRUE;
 	}
 
 	elapsed_time = g_timer_elapsed (*timer, NULL);
 
 	/* Wait a little, because at the very beginning it's maybe not very
 	 * accurate (it takes initially more time for the first bytes, the
 	 * following chunks should arrive more quickly, as a rough guess).
 	 */
 	if (elapsed_time < 0.5)
 	{
 		return FALSE;
 	}
 
 	/* elapsed_time / total_time = size / total_size */
 	total_time = (elapsed_time * total_size) / size;
 
 	remaining_time = total_time - elapsed_time;
 
 	/* Approximately more than 3 seconds remaining. */
 	if (remaining_time > 3.0)
 	{
 		/* Once the progress info bar is shown, it must remain
 		 * shown until the end, so we don't need the timer
 		 * anymore.
 		 */
 		g_timer_destroy (*timer);
 		*timer = NULL;
 
 		return TRUE;
 	}
 
 	return FALSE;
 }
 
 static gboolean
 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;
 }
 
 static void
 unrecoverable_saving_error_info_bar_response (GtkWidget *info_bar,
 					      gint       response_id,
 					      GTask     *saving_task)
 {
 	GeditTab *tab = g_task_get_source_object (saving_task);
 	GeditView *view;
 
 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
 
 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
 	view = gedit_tab_get_view (tab);
 	gtk_widget_grab_focus (GTK_WIDGET (view));
 
 	g_task_return_boolean (saving_task, FALSE);
 	g_object_unref (saving_task);
 }
 
 /* Sets the save flags after an info bar response. */
 static void
 response_set_save_flags (GTask                   *saving_task,
 			 GtkSourceFileSaverFlags  save_flags)
 {
 	GeditTab *tab = g_task_get_source_object (saving_task);
@@ -1091,63 +1091,63 @@ response_set_save_flags (GTask                   *saving_task,
 static void
 invalid_character_info_bar_response (GtkWidget *info_bar,
 				     gint       response_id,
 				     GTask     *saving_task)
 {
 	if (response_id == GTK_RESPONSE_YES)
 	{
 		GeditTab *tab = g_task_get_source_object (saving_task);
 		SaverData *data = g_task_get_task_data (saving_task);
 		GtkSourceFileSaverFlags save_flags;
 
 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
 		/* Don't bug the user again with this... */
 		tab->save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
 
 		save_flags = gtk_source_file_saver_get_flags (data->saver);
 		save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
 		response_set_save_flags (saving_task, save_flags);
 
 		/* Force saving */
 		launch_saver (saving_task);
 	}
 	else
 	{
 		unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
 	}
 }
 
 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)
 	{
 		GeditTab *tab = g_task_get_source_object (saving_task);
 		SaverData *data = g_task_get_task_data (saving_task);
 		GtkSourceFileSaverFlags save_flags;
 
 		set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
 		data->force_no_backup = TRUE;
 		save_flags = gtk_source_file_saver_get_flags (data->saver);
 		response_set_save_flags (saving_task, save_flags);
 
 		/* Force saving */
 		launch_saver (saving_task);
 	}
 	else
 	{
 		unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
 	}
 }
 
 static void
 externally_modified_error_info_bar_response (GtkWidget *info_bar,
 					     gint       response_id,
 					     GTask     *saving_task)
 {
 	if (response_id == GTK_RESPONSE_YES)
 	{
 		GeditTab *tab = g_task_get_source_object (saving_task);
@@ -1199,77 +1199,77 @@ recoverable_saving_error_info_bar_response (GtkWidget *info_bar,
 
 static void
 externally_modified_notification_info_bar_response (GtkWidget *info_bar,
 						    gint       response_id,
 						    GeditTab  *tab)
 {
 	GeditView *view;
 
 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
 	view = gedit_tab_get_view (tab);
 
 	if (response_id == GTK_RESPONSE_OK)
 	{
 		_gedit_tab_revert (tab);
 	}
 	else
 	{
 		tab->ask_if_externally_modified = FALSE;
 
 		/* go back to normal state */
 		gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
 	}
 
 	gtk_widget_grab_focus (GTK_WIDGET (view));
 }
 
 static void
 display_externally_modified_notification (GeditTab *tab)
 {
-	TeplInfoBar *info_bar;
+	GtkWidget *info_bar;
 	GeditDocument *doc;
 	GtkSourceFile *file;
 	GFile *location;
 	gboolean document_modified;
 
 	doc = gedit_tab_get_document (tab);
 	file = gedit_document_get_file (doc);
 
 	/* we're here because the file we're editing changed on disk */
 	location = gtk_source_file_get_location (file);
 	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",
 			  G_CALLBACK (externally_modified_notification_info_bar_response),
 			  tab);
 }
 
 static gboolean
 view_focused_in (GtkWidget     *widget,
                  GdkEventFocus *event,
                  GeditTab      *tab)
 {
 	GeditDocument *doc;
 	GtkSourceFile *file;
 
 	g_return_val_if_fail (GEDIT_IS_TAB (tab), GDK_EVENT_PROPAGATE);
 
 	/* we try to detect file changes only in the normal state */
 	if (tab->state != GEDIT_TAB_STATE_NORMAL)
 	{
 		return GDK_EVENT_PROPAGATE;
 	}
 
 	/* we already asked, don't bug the user again */
 	if (!tab->ask_if_externally_modified)
 	{
 		return GDK_EVENT_PROPAGATE;
 	}
 
 	doc = gedit_tab_get_document (tab);
@@ -1280,104 +1280,101 @@ view_focused_in (GtkWidget     *widget,
 	{
 		gtk_source_file_check_file_on_disk (file);
 
 		if (gtk_source_file_is_externally_modified (file))
 		{
 			gedit_tab_set_state (tab, GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
 
 			display_externally_modified_notification (tab);
 		}
 	}
 
 	return GDK_EVENT_PROPAGATE;
 }
 
 static void
 on_drop_uris (GeditView  *view,
 	      gchar     **uri_list,
 	      GeditTab   *tab)
 {
 	g_signal_emit (G_OBJECT (tab), signals[DROP_URIS], 0, uri_list);
 }
 
 static void
 gedit_tab_init (GeditTab *tab)
 {
 	gboolean auto_save;
 	gint auto_save_interval;
 	GeditDocument *doc;
 	GeditView *view;
 	GtkSourceFile *file;
-	TeplFile *tepl_file;
 
 	tab->state = GEDIT_TAB_STATE_NORMAL;
 
 	tab->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
 
 	tab->editable = TRUE;
 
 	tab->ask_if_externally_modified = TRUE;
 
 	gtk_orientable_set_orientation (GTK_ORIENTABLE (tab),
 	                                GTK_ORIENTATION_VERTICAL);
 
 	/* Manage auto save data */
 	auto_save = g_settings_get_boolean (tab->editor_settings,
 					    GEDIT_SETTINGS_AUTO_SAVE);
 	g_settings_get (tab->editor_settings, GEDIT_SETTINGS_AUTO_SAVE_INTERVAL,
 			"u", &auto_save_interval);
 	tab->auto_save = auto_save != FALSE;
 	tab->auto_save_interval = auto_save_interval;
 
 	/* Create the frame */
 	tab->frame = gedit_view_frame_new ();
 	gtk_widget_show (GTK_WIDGET (tab->frame));
 
 	gtk_box_pack_end (GTK_BOX (tab), GTK_WIDGET (tab->frame), TRUE, TRUE, 0);
 
 	doc = gedit_tab_get_document (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",
 				 G_CALLBACK (document_location_notify_handler),
 				 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",
 			  G_CALLBACK (document_modified_changed),
 			  tab);
 
 	view = gedit_tab_get_view (tab);
 
 	g_signal_connect_after (view,
 				"focus-in-event",
 				G_CALLBACK (view_focused_in),
 				tab);
 
 	g_signal_connect_after (view,
 				"realize",
 				G_CALLBACK (view_realized),
 				tab);
 
 	g_signal_connect (view,
 			  "drop-uris",
 			  G_CALLBACK (on_drop_uris),
 			  tab);
 }
 
 GeditTab *
 _gedit_tab_new (void)
 {
 	return g_object_new (GEDIT_TYPE_TAB, NULL);
 }
 
@@ -1407,94 +1404,94 @@ gedit_tab_get_view (GeditTab *tab)
  */
 GeditDocument *
 gedit_tab_get_document (GeditTab *tab)
 {
 	GeditView *view;
 
 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
 
 	view = gedit_view_frame_get_view (tab->frame);
 
 	return GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
 }
 
 #define MAX_DOC_NAME_LENGTH 40
 
 gchar *
 _gedit_tab_get_name (GeditTab *tab)
 {
 	GeditDocument *doc;
 	gchar *name;
 	gchar *docname;
 	gchar *tab_name;
 
 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
 
 	doc = gedit_tab_get_document (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)))
 	{
 		tab_name = g_strdup_printf ("*%s", docname);
 	}
 	else
 	{
 		tab_name = g_strdup (docname);
 	}
 
 	g_free (docname);
 	g_free (name);
 
 	return tab_name;
 }
 
 gchar *
 _gedit_tab_get_tooltip (GeditTab *tab)
 {
 	GeditDocument *doc;
 	gchar *tip;
 	gchar *uri;
 	gchar *ruri;
 	gchar *ruri_markup;
 
 	g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
 
 	doc = gedit_tab_get_document (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);
 
 	switch (tab->state)
 	{
 		gchar *content_type;
 		gchar *mime_type;
 		gchar *content_description;
 		gchar *content_full_description;
 		gchar *encoding;
 		GtkSourceFile *file;
 		const GtkSourceEncoding *enc;
 
 		case GEDIT_TAB_STATE_LOADING_ERROR:
 			tip = g_strdup_printf (_("Error opening file %s"),
 					       ruri_markup);
 			break;
 
 		case GEDIT_TAB_STATE_REVERTING_ERROR:
 			tip = g_strdup_printf (_("Error reverting file %s"),
 					       ruri_markup);
 			break;
 
 		case GEDIT_TAB_STATE_SAVING_ERROR:
 			tip =  g_strdup_printf (_("Error saving file %s"),
 						ruri_markup);
 			break;
 		default:
 			content_type = gedit_document_get_content_type (doc);
@@ -1606,65 +1603,63 @@ gedit_tab_get_from_document (GeditDocument *doc)
 	return g_object_get_data (G_OBJECT (doc), GEDIT_TAB_KEY);
 }
 
 static void
 loader_progress_cb (goffset  size,
 		    goffset  total_size,
 		    GTask   *loading_task)
 {
 	LoaderData *data = g_task_get_task_data (loading_task);
 
 	g_return_if_fail (data->tab->state == GEDIT_TAB_STATE_LOADING ||
 			  data->tab->state == GEDIT_TAB_STATE_REVERTING);
 
 	if (should_show_progress_info (&data->timer, size, total_size))
 	{
 		show_loading_info_bar (loading_task);
 		info_bar_set_progress (data->tab, size, total_size);
 	}
 }
 
 static void
 goto_line (GTask *loading_task)
 {
 	LoaderData *data = g_task_get_task_data (loading_task);
 	GeditDocument *doc = gedit_tab_get_document (data->tab);
 	GtkTextIter iter;
 
 	/* 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;
 	}
 
 	/* If enabled, move to the position stored in the metadata. */
 	if (g_settings_get_boolean (data->tab->editor_settings, GEDIT_SETTINGS_RESTORE_CURSOR_POSITION))
 	{
 		gchar *pos;
 		gint offset;
 
 		pos = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_POSITION);
 
 		offset = pos != NULL ? atoi (pos) : 0;
 		g_free (pos);
 
 		gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc),
 						    &iter,
 						    MAX (0, offset));
 
 		/* make sure it's a valid position, if the file
 		 * changed we may have ended up in the middle of
 		 * a utf8 character cluster */
 		if (!gtk_text_iter_is_cursor_position (&iter))
 		{
 			gtk_text_iter_set_line_offset (&iter, 0);
 		}
 	}
 
 	/* Otherwise to the top. */
 	else
 	{
@@ -1726,72 +1721,72 @@ successful_load (GTask *loading_task)
 
 	if (data->user_requested_encoding)
 	{
 		const GtkSourceEncoding *encoding = gtk_source_file_loader_get_encoding (data->loader);
 		const gchar *charset = gtk_source_encoding_get_charset (encoding);
 
 		gedit_document_set_metadata (doc,
 					     GEDIT_METADATA_ATTRIBUTE_ENCODING, charset,
 					     NULL);
 	}
 
 	goto_line (loading_task);
 
 	/* Scroll to the cursor when the document is loaded, we need to do it in
 	 * an idle as after the document is loaded the textview is still
 	 * redrawing and relocating its internals.
 	 */
 	if (data->tab->idle_scroll == 0)
 	{
 		data->tab->idle_scroll = g_idle_add ((GSourceFunc)scroll_to_cursor, data->tab);
 	}
 
 	location = gtk_source_file_loader_get_location (data->loader);
 
 	/* If the document is readonly we don't care how many times the file
 	 * is opened.
 	 */
 	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
 	 * buffer as modified.
 	 */
 	if (location == NULL)
 	{
 		gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), TRUE);
 	}
 
 	data->tab->ask_if_externally_modified = TRUE;
 
 	g_signal_emit_by_name (doc, "loaded");
 }
 
 static void
 load_cb (GtkSourceFileLoader *loader,
 	 GAsyncResult        *result,
 	 GTask               *loading_task)
 {
 	LoaderData *data = g_task_get_task_data (loading_task);
 	GeditDocument *doc;
 	GFile *location = gtk_source_file_loader_get_location (loader);
 	gboolean create_named_new_doc;
 	GError *error = NULL;
 
 	g_clear_pointer (&data->timer, g_timer_destroy);
 
 	gtk_source_file_loader_load_finish (loader, result, &error);
 
@@ -2283,75 +2278,75 @@ save_cb (GtkSourceFileSaver *saver,
 	if (data->timer != NULL)
 	{
 		g_timer_destroy (data->timer);
 		data->timer = NULL;
 	}
 
 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
 	if (error != NULL)
 	{
 		GtkWidget *info_bar;
 
 		gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING_ERROR);
 
 		if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
 		    error->code == GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED)
 		{
 			/* This error is recoverable */
 			info_bar = gedit_externally_modified_saving_error_info_bar_new (location, error);
 			g_return_if_fail (info_bar != NULL);
 
 			g_signal_connect (info_bar,
 					  "response",
 					  G_CALLBACK (externally_modified_error_info_bar_response),
 					  saving_task);
 		}
 		else if (error->domain == G_IO_ERROR &&
 			 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 &&
 			 error->code == GTK_SOURCE_FILE_SAVER_ERROR_INVALID_CHARS)
 		{
 			/* 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,
 			                  "response",
 			                  G_CALLBACK (invalid_character_info_bar_response),
 			                  saving_task);
 		}
 		else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR ||
 			 (error->domain == G_IO_ERROR &&
 			  error->code != G_IO_ERROR_INVALID_DATA &&
 			  error->code != G_IO_ERROR_PARTIAL_INPUT))
 		{
 			/* These errors are _NOT_ recoverable */
 			gedit_recent_remove_if_local (location);
 
 			info_bar = gedit_unrecoverable_saving_error_info_bar_new (location, error);
 			g_return_if_fail (info_bar != NULL);
 
 			g_signal_connect (info_bar,
 					  "response",
 					  G_CALLBACK (unrecoverable_saving_error_info_bar_response),
 					  saving_task);
 		}
 		else
 		{
 			const GtkSourceEncoding *encoding;
 
 			/* This error is recoverable */
 			g_return_if_fail (error->domain == G_CONVERT_ERROR ||
 			                  error->domain == G_IO_ERROR);
@@ -2679,69 +2674,69 @@ get_print_settings (GeditTab *tab)
 				  GEDIT_PRINT_SETTINGS_KEY);
 
 	if (data == NULL)
 	{
 		settings = _gedit_app_get_default_print_settings (GEDIT_APP (g_application_get_default ()));
 	}
 	else
 	{
 		settings = gtk_print_settings_copy (GTK_PRINT_SETTINGS (data));
 	}
 
 	/* Be sure the OUTPUT_URI is unset, because otherwise the
 	 * OUTPUT_BASENAME is not taken into account.
 	 */
 	gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, NULL);
 
 	name = gedit_document_get_short_name_for_display (doc);
 	gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_BASENAME, name);
 
 	g_free (name);
 
 	return settings;
 }
 
 /* FIXME: show the info bar only if the operation will be "long" */
 static void
 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
 store_print_settings (GeditTab      *tab,
 		      GeditPrintJob *job)
 {
 	GeditDocument *doc;
 	GtkPrintSettings *settings;
 	GtkPageSetup *page_setup;
 
 	doc = gedit_tab_get_document (tab);
 
 	settings = gedit_print_job_get_print_settings (job);
 
 	/* clear n-copies settings since we do not want to
 	 * persist that one */
 	gtk_print_settings_unset (settings,
 				  GTK_PRINT_SETTINGS_N_COPIES);
 
 	/* remember settings for this document */
 	g_object_set_data_full (G_OBJECT (doc),
 				GEDIT_PRINT_SETTINGS_KEY,
 				g_object_ref (settings),
 				(GDestroyNotify)g_object_unref);
 
 	/* make them the default */
 	_gedit_app_set_default_print_settings (GEDIT_APP (g_application_get_default ()),
 					       settings);
 
 	page_setup = gedit_print_job_get_page_setup (job);
@@ -2797,73 +2792,75 @@ show_preview_cb (GeditPrintJob     *job,
 	/* destroy the info bar */
 	set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
 	tab->print_preview = GTK_WIDGET (preview);
 	g_object_ref_sink (tab->print_preview);
 
 	gtk_box_pack_end (GTK_BOX (tab), tab->print_preview, TRUE, TRUE, 0);
 
 	gtk_widget_show (tab->print_preview);
 	gtk_widget_grab_focus (tab->print_preview);
 
 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
 }
 
 static void
 print_cancelled (GtkWidget *bar,
 		 gint       response_id,
 		 GeditTab  *tab)
 {
 	gedit_debug (DEBUG_TAB);
 
 	if (tab->print_job != NULL)
 	{
 		gedit_print_job_cancel (tab->print_job);
 	}
 }
 
 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
 _gedit_tab_print (GeditTab *tab)
 {
 	GeditView *view;
 	GtkPageSetup *setup;
 	GtkPrintSettings *settings;
 	GtkPrintOperationResult res;
 	GError *error = NULL;
 
 	g_return_if_fail (GEDIT_IS_TAB (tab));
 
 	/* FIXME: currently we can have just one printoperation going on at a
 	 * given time, so before starting the print we close the preview.
 	 * Would be nice to handle it properly though.
 	 */
 	if (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
 	{
 		close_printing (tab);
 	}
 
 	g_return_if_fail (tab->print_job == NULL);
 	g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
 
 	view = gedit_tab_get_view (tab);
 
 	tab->print_job = gedit_print_job_new (view);
 
 	add_printing_info_bar (tab);
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
@@ -1,56 +1,55 @@
 /*
  * gedit-utils.c
  * This file is part of gedit
  *
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2002 Chema Celorio, Paolo Maggi
  * Copyright (C) 2003-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-utils.h"
 #include <string.h>
 #include <glib/gi18n.h>
-#include <tepl/tepl.h>
 #include "gedit-debug.h"
 
 gboolean
 gedit_utils_menu_position_under_tree_view (GtkTreeView  *tree_view,
 					   GdkRectangle *rect)
 {
 	GtkTreeSelection *selection;
 	GtkTreeModel *model;
 	gint count_rows;
 	GList *rows;
 	gint widget_x, widget_y;
 
 	model = gtk_tree_view_get_model (tree_view);
 	g_return_val_if_fail (model != NULL, FALSE);
 
 	selection = gtk_tree_view_get_selection (tree_view);
 	g_return_val_if_fail (selection != NULL, FALSE);
 
 	count_rows = gtk_tree_selection_count_selected_rows (selection);
 	if (count_rows != 1)
 		return FALSE;
 
 	rows = gtk_tree_selection_get_selected_rows (selection, &model);
 	gtk_tree_view_get_cell_area (tree_view, (GtkTreePath *)(rows->data),
 				     gtk_tree_view_get_column (tree_view, 0),
 				     rect);
 
 	gtk_tree_view_convert_bin_window_to_widget_coords (tree_view, rect->x, rect->y, &widget_x, &widget_y);
 	rect->x = widget_x;
 	rect->y = widget_y;
@@ -60,160 +59,321 @@ gedit_utils_menu_position_under_tree_view (GtkTreeView  *tree_view,
 }
 
 /**
  * gedit_utils_set_atk_name_description:
  * @widget: The Gtk widget for which name/description to be set
  * @name: Atk name string
  * @description: Atk description string
  *
  * This function sets up name and description
  * for a specified gtk widget.
  */
 void
 gedit_utils_set_atk_name_description (GtkWidget   *widget,
 				      const gchar *name,
 				      const gchar *description)
 {
 	AtkObject *aobj;
 
 	aobj = gtk_widget_get_accessible (widget);
 
 	if (!(GTK_IS_ACCESSIBLE (aobj)))
 		return;
 
 	if (name)
 		atk_object_set_name (aobj, name);
 
 	if (description)
 		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)
 {
 	gchar *res;
 	gchar *str;
 
 	g_return_val_if_fail (uri != NULL, NULL);
 
 	/* CHECK: does it work with uri chaining? - Paolo */
 	str = g_path_get_dirname (uri);
 	g_return_val_if_fail (str != NULL, g_strdup ("."));
 
 	if ((strlen (str) == 1) && (*str == '.'))
 	{
 		g_free (str);
 
 		return NULL;
 	}
 
-	res = tepl_utils_replace_home_dir_with_tilde (str);
+	res = gedit_utils_replace_home_dir_with_tilde (str);
 
 	g_free (str);
 
 	return res;
 }
 
 /**
  * gedit_utils_location_get_dirname_for_display:
  * @location: the location
  *
  * Returns a string suitable to be displayed in the UI indicating
  * the name of the directory where the file is located.
  * For remote files it may also contain the hostname etc.
  * For local files it tries to replace the home dir with ~.
  *
  * Returns: (transfer full): a string to display the dirname
  */
 gchar *
 gedit_utils_location_get_dirname_for_display (GFile *location)
 {
 	gchar *uri;
 	gchar *res;
 	GMount *mount;
 
 	g_return_val_if_fail (location != NULL, NULL);
 
 	/* we use the parse name, that is either the local path
 	 * or an uri but which is utf8 safe */
 	uri = g_file_get_parse_name (location);
 
 	/* FIXME: this is sync... is it a problem? */
 	mount = g_file_find_enclosing_mount (location, NULL, NULL);
 	if (mount != NULL)
 	{
 		gchar *mount_name;
 		gchar *path = NULL;
 		gchar *dirname;
 
 		mount_name = g_mount_get_name (mount);
 		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)
 		{
 			dirname = uri_get_dirname (uri);
 		}
 		else
 		{
 			dirname = uri_get_dirname (path);
 		}
 
 		if (dirname == NULL || strcmp (dirname, ".") == 0)
 		{
 			res = mount_name;
 		}
 		else
 		{
 			res = g_strdup_printf ("%s %s", mount_name, dirname);
 			g_free (mount_name);
 		}
 
 		g_free (path);
 		g_free (dirname);
 	}
 	else
 	{
 		/* fallback for local files or uris without mounts */
 		res = uri_get_dirname (uri);
 	}
 
 	g_free (uri);
 
 	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)
 {
 	return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
 }
 
 static gboolean
 has_valid_scheme (const gchar *uri)
 {
 	const gchar *p;
 
 	p = uri;
 
 	if (!is_valid_scheme_character (*p))
 	{
 		return FALSE;
 	}
 
 	do
 	{
 		p++;
 	} while (is_valid_scheme_character (*p));
 
 	return *p == ':';
 }
 
 gboolean
 gedit_utils_is_valid_location (GFile *location)
 {
 	const guchar *p;
@@ -326,61 +486,61 @@ gedit_utils_basename_for_display (GFile *location)
 
 	/* First, try to query the display name, but only on local files */
 	if (g_file_has_uri_scheme (location, "file"))
 	{
 		GFileInfo *info;
 
 		info = g_file_query_info (location,
 					  G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
 					  G_FILE_QUERY_INFO_NONE,
 					  NULL,
 					  NULL);
 
 		if (info)
 		{
 			/* Simply get the display name to use as the basename */
 			name = g_strdup (g_file_info_get_display_name (info));
 			g_object_unref (info);
 		}
 		else
 		{
 			/* This is a local file, and therefore we will use
 			 * g_filename_display_basename on the local path */
 			gchar *local_path;
 
 			local_path = g_file_get_path (location);
 			name = g_filename_display_basename (local_path);
 			g_free (local_path);
 		}
 	}
 	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,
 		   use the _parse_name and take basename of that */
 		gchar *parse_name;
 		gchar *base;
 
 		parse_name = g_file_get_parse_name (location);
 		base = g_filename_display_basename (parse_name);
 		name = g_uri_unescape_string (base, NULL);
 
 		g_free (base);
 		g_free (parse_name);
 	}
 	else
 	{
 		/* display '/ on <host>' using the decoded host */
 		gchar *hn_utf8;
 
 		if  (hn != NULL)
 		{
 			hn_utf8 = g_utf8_make_valid (hn, -1);
 		}
 		else
 		{
 			/* we should never get here */
 			hn_utf8 = g_strdup ("?");
 		}
 
 		/* Translators: '/ on <remote-share>' */
@@ -411,60 +571,219 @@ gedit_utils_drop_get_uris (GtkSelectionData *selection_data)
 	gchar **uris;
 	gint i;
 	gint p = 0;
 	gchar **uri_list;
 
 	uris = g_uri_list_extract_uris ((gchar *) gtk_selection_data_get_data (selection_data));
 	uri_list = g_new0(gchar *, g_strv_length (uris) + 1);
 
 	for (i = 0; uris[i] != NULL; i++)
 	{
 		gchar *uri;
 
 		uri = make_canonical_uri_from_shell_arg (uris[i]);
 
 		/* Silently ignore malformed URI/filename */
 		if (uri != NULL)
 			uri_list[p++] = uri;
 	}
 
 	if (*uri_list == NULL)
 	{
 		g_free(uri_list);
 		g_strfreev (uris);
 		return NULL;
 	}
 
 	g_strfreev (uris);
 	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)
 {
 	if (content_type == NULL)
 	{
 		return GTK_SOURCE_COMPRESSION_TYPE_NONE;
 	}
 
 	if (g_content_type_is_a (content_type, "application/x-gzip"))
 	{
 		return GTK_SOURCE_COMPRESSION_TYPE_GZIP;
 	}
 
 	return GTK_SOURCE_COMPRESSION_TYPE_NONE;
 }
 
 /* Copied from nautilus */
 static gchar *
 get_direct_save_filename (GdkDragContext *context)
 {
 	guchar *prop_text;
 	gint prop_len;
 
 	if (!gdk_property_get (gdk_drag_context_get_source_window  (context), gdk_atom_intern ("XdndDirectSave0", FALSE),
 			       gdk_atom_intern ("text/plain", FALSE), 0, 1024, FALSE, NULL, NULL,
 			       &prop_len, &prop_text) && prop_text != NULL) {
 		return NULL;
 	}
 
 	/* Zero-terminate the string */
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
@@ -1,56 +1,75 @@
 /*
  * gedit-utils.h
  * This file is part of gedit
  *
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002 - 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_UTILS_H
 #define GEDIT_UTILS_H
 
 #include <gtksourceview/gtksource.h>
 
 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);
 
 gchar                     *gedit_utils_set_direct_save_filename               (GdkDragContext       *context);
 
 GtkSourceCompressionType   gedit_utils_get_compression_type_from_content_type (const gchar          *content_type);
 
 const gchar               *gedit_utils_newline_type_to_string                 (GtkSourceNewlineType  newline_type);
 
 G_END_DECLS
 
 #endif /* GEDIT_UTILS_H */
 
 /* ex:set ts=8 noet: */
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
@@ -1,86 +1,91 @@
 /*
  * gedit-view-frame.c
  * 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
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
  * gedit is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with gedit; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 
 #include "gedit-view-frame.h"
 
 #include <gtksourceview/gtksource.h>
 #include <gdk/gdkkeysyms.h>
 #include <glib/gi18n.h>
 #include <stdlib.h>
 
+#include "gedit-view-centering.h"
 #include "gedit-debug.h"
 #include "gedit-utils.h"
 #include "gedit-settings.h"
 #include "libgd/gd.h"
 
 #define FLUSH_TIMEOUT_DURATION 30 /* in seconds */
 
 #define SEARCH_POPUP_MARGIN 12
 
 typedef enum
 {
 	GOTO_LINE,
 	SEARCH
 } SearchMode;
 
 typedef enum
 {
 	SEARCH_STATE_NORMAL,
 	SEARCH_STATE_NOT_FOUND
 } SearchState;
 
 struct _GeditViewFrame
 {
 	GtkOverlay parent_instance;
 
+	GSettings *editor_settings;
+
 	GeditView *view;
+	GeditViewCentering *view_centering;
+	GtkFrame *map_frame;
 
 	SearchMode search_mode;
 
 	/* Where the search has started. When the user presses escape in the
 	 * search entry (to cancel the search), we return to the start_mark.
 	 */
 	GtkTextMark *start_mark;
 
 	GtkRevealer *revealer;
 	GdTaggedEntry *search_entry;
 	GdTaggedEntryTag *entry_tag;
 	GtkWidget *go_up_button;
 	GtkWidget *go_down_button;
 
 	guint flush_timeout_id;
 	guint idle_update_entry_tag_id;
 	guint remove_entry_tag_timeout_id;
 	gulong view_scroll_event_id;
 	gulong search_entry_focus_out_id;
 	gulong search_entry_changed_id;
 
 	GtkSourceSearchSettings *search_settings;
 
 	/* Used to restore the search state if an incremental search is
 	 * cancelled.
 	 */
 	GtkSourceSearchSettings *old_search_settings;
 
 	/* The original search texts. In search_settings and
 	 * old_search_settings, the search text is unescaped. Since the escape
@@ -132,115 +137,116 @@ gedit_view_frame_dispose (GObject *object)
 	if (frame->start_mark != NULL && buffer != NULL)
 	{
 		gtk_text_buffer_delete_mark (buffer, frame->start_mark);
 		frame->start_mark = NULL;
 	}
 
 	if (frame->flush_timeout_id != 0)
 	{
 		g_source_remove (frame->flush_timeout_id);
 		frame->flush_timeout_id = 0;
 	}
 
 	if (frame->idle_update_entry_tag_id != 0)
 	{
 		g_source_remove (frame->idle_update_entry_tag_id);
 		frame->idle_update_entry_tag_id = 0;
 	}
 
 	if (frame->remove_entry_tag_timeout_id != 0)
 	{
 		g_source_remove (frame->remove_entry_tag_timeout_id);
 		frame->remove_entry_tag_timeout_id = 0;
 	}
 
 	if (buffer != NULL)
 	{
 		GtkSourceFile *file = gedit_document_get_file (GEDIT_DOCUMENT (buffer));
 		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);
 
 	G_OBJECT_CLASS (gedit_view_frame_parent_class)->dispose (object);
 }
 
 static void
 gedit_view_frame_finalize (GObject *object)
 {
 	GeditViewFrame *frame = GEDIT_VIEW_FRAME (object);
 
 	g_free (frame->search_text);
 	g_free (frame->old_search_text);
 
 	G_OBJECT_CLASS (gedit_view_frame_parent_class)->finalize (object);
 }
 
 static void
 hide_search_widget (GeditViewFrame *frame,
                     gboolean        cancel)
 {
 	GtkTextBuffer *buffer;
 
 	if (!gtk_revealer_get_reveal_child (frame->revealer))
 	{
 		return;
 	}
 
 	if (frame->view_scroll_event_id != 0)
 	{
 		g_signal_handler_disconnect (frame->view,
 		                             frame->view_scroll_event_id);
 		frame->view_scroll_event_id = 0;
 	}
 
 	if (frame->flush_timeout_id != 0)
 	{
 		g_source_remove (frame->flush_timeout_id);
 		frame->flush_timeout_id = 0;
 	}
 
 	gtk_revealer_set_reveal_child (frame->revealer, FALSE);
 
 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (frame->view));
 
 	if (cancel && frame->start_mark != NULL)
 	{
 		GtkTextIter iter;
 
 		gtk_text_buffer_get_iter_at_mark (buffer, &iter,
 		                                  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)
 	{
 		gtk_text_buffer_delete_mark (buffer, frame->start_mark);
 		frame->start_mark = NULL;
 	}
 }
 
 static gboolean
 search_entry_flush_timeout (GeditViewFrame *frame)
 {
 	frame->flush_timeout_id = 0;
 	hide_search_widget (frame, FALSE);
 
 	return G_SOURCE_REMOVE;
 }
 
 static void
 renew_flush_timeout (GeditViewFrame *frame)
 {
 	if (frame->flush_timeout_id != 0)
 	{
 		g_source_remove (frame->flush_timeout_id);
 	}
 
 	frame->flush_timeout_id =
 		g_timeout_add_seconds (FLUSH_TIMEOUT_DURATION,
 				       (GSourceFunc)search_entry_flush_timeout,
 				       frame);
@@ -270,61 +276,61 @@ get_search_context (GeditViewFrame *frame)
 
 	return NULL;
 }
 
 static void
 set_search_state (GeditViewFrame *frame,
 		  SearchState     state)
 {
 	GtkStyleContext *context;
 
 	context = gtk_widget_get_style_context (GTK_WIDGET (frame->search_entry));
 
 	if (state == SEARCH_STATE_NOT_FOUND)
 	{
 		gtk_style_context_add_class (context, GTK_STYLE_CLASS_ERROR);
 	}
 	else
 	{
 		gtk_style_context_remove_class (context, GTK_STYLE_CLASS_ERROR);
 	}
 }
 
 static void
 finish_search (GeditViewFrame    *frame,
 	       gboolean           found)
 {
 	const gchar *entry_text = gtk_entry_get_text (GTK_ENTRY (frame->search_entry));
 
 	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);
 	}
 	else
 	{
 		set_search_state (frame, SEARCH_STATE_NOT_FOUND);
 	}
 }
 
 static void
 start_search_finished (GtkSourceSearchContext *search_context,
 		       GAsyncResult           *result,
 		       GeditViewFrame         *frame)
 {
 	GtkTextIter match_start;
 	GtkTextIter match_end;
 	gboolean found;
 	GtkSourceBuffer *buffer;
 
 	found = gtk_source_search_context_forward_finish (search_context,
 							  result,
 							  &match_start,
 							  &match_end,
 							  NULL,
 							  NULL);
 
 	buffer = gtk_source_search_context_get_buffer (search_context);
 
 	if (found)
 	{
@@ -1034,117 +1040,121 @@ customize_for_search_mode (GeditViewFrame *frame)
 		gtk_widget_set_tooltip_text (GTK_WIDGET (frame->search_entry),
 		                             _("Line you want to move the cursor to"));
 
 		gtk_widget_hide (frame->go_up_button);
 		gtk_widget_hide (frame->go_down_button);
 	}
 
 	gtk_entry_set_icon_from_gicon (GTK_ENTRY (frame->search_entry),
 	                               GTK_ENTRY_ICON_PRIMARY,
 	                               icon);
 
 	gtk_widget_set_size_request (GTK_WIDGET (frame->search_entry),
 				     width_request,
 				     -1);
 
 	g_object_unref (icon);
 }
 
 static void
 update_goto_line (GeditViewFrame *frame)
 {
 	const gchar *entry_text;
 	gboolean moved;
 	gboolean moved_offset;
 	gint line;
 	gint offset_line = 0;
 	gint line_offset = 0;
 	gchar **split_text = NULL;
 	const gchar *text;
 	GtkTextIter iter;
+	GeditDocument *doc;
 
 	entry_text = gtk_entry_get_text (GTK_ENTRY (frame->search_entry));
 
 	if (entry_text[0] == '\0')
 	{
 		return;
 	}
 
 	get_iter_at_start_mark (frame, &iter);
 
 	split_text = g_strsplit (entry_text, ":", -1);
 
 	if (g_strv_length (split_text) > 1)
 	{
 		text = split_text[0];
 	}
 	else
 	{
 		text = entry_text;
 	}
 
 	if (text[0] == '-')
 	{
 		gint cur_line = gtk_text_iter_get_line (&iter);
 
 		if (text[1] != '\0')
 		{
 			offset_line = MAX (atoi (text + 1), 0);
 		}
 
 		line = MAX (cur_line - offset_line, 0);
 	}
 	else if (entry_text[0] == '+')
 	{
 		gint cur_line = gtk_text_iter_get_line (&iter);
 
 		if (text[1] != '\0')
 		{
 			offset_line = MAX (atoi (text + 1), 0);
 		}
 
 		line = cur_line + offset_line;
 	}
 	else
 	{
 		line = MAX (atoi (text) - 1, 0);
 	}
 
 	if (split_text[1] != NULL)
 	{
 		line_offset = atoi (split_text[1]);
 	}
 
 	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)
 	{
 		set_search_state (frame, SEARCH_STATE_NOT_FOUND);
 	}
 	else
 	{
 		set_search_state (frame, SEARCH_STATE_NORMAL);
 	}
 }
 
 static void
 search_entry_changed_cb (GtkEntry       *entry,
 			 GeditViewFrame *frame)
 {
 	renew_flush_timeout (frame);
 
 	if (frame->search_mode == SEARCH)
 	{
 		update_search_text (frame);
 		start_search (frame);
 	}
 	else
 	{
 		update_goto_line (frame);
 	}
 }
 
 static gboolean
 search_entry_focus_out_event (GtkWidget      *widget,
@@ -1401,86 +1411,95 @@ start_interactive_search_real (GeditViewFrame *frame,
 
 	gtk_widget_grab_focus (GTK_WIDGET (frame->search_entry));
 
 	customize_for_search_mode (frame);
 	init_search_entry (frame);
 
 	/* Manage the scroll also for the view */
 	frame->view_scroll_event_id =
 		g_signal_connect (frame->view, "scroll-event",
 			          G_CALLBACK (search_widget_scroll_event),
 			          frame);
 
 	renew_flush_timeout (frame);
 
 	install_update_entry_tag_idle (frame);
 }
 
 static void
 gedit_view_frame_class_init (GeditViewFrameClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
 	object_class->dispose = gedit_view_frame_dispose;
 	object_class->finalize = gedit_view_frame_finalize;
 
 	/* Bind class to template */
 	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);
 	gtk_widget_class_bind_template_child (widget_class, GeditViewFrame, go_down_button);
 }
 
 static GMountOperation *
 view_frame_mount_operation_factory (GtkSourceFile *file,
 				    gpointer       user_data)
 {
 	GtkWidget *view_frame = user_data;
 	GtkWidget *window = gtk_widget_get_toplevel (view_frame);
 
 	return gtk_mount_operation_new (GTK_WINDOW (window));
 }
 
 static void
 gedit_view_frame_init (GeditViewFrame *frame)
 {
 	GeditDocument *doc;
 	GtkSourceFile *file;
 
 	gedit_debug (DEBUG_WINDOW);
 
 	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);
 
 	gtk_source_file_set_mount_operation_factory (file,
 						     view_frame_mount_operation_factory,
 						     frame,
 						     NULL);
 
 	frame->entry_tag = gd_tagged_entry_tag_new ("");
 
 	gd_tagged_entry_tag_set_style (frame->entry_tag,
 				       "gedit-search-entry-occurrences-tag");
 
 	gd_tagged_entry_tag_set_has_close_button (frame->entry_tag, FALSE);
 
 	gtk_widget_set_margin_end (GTK_WIDGET (frame->revealer),
 				   SEARCH_POPUP_MARGIN);
 
 	g_signal_connect (doc,
 			  "mark-set",
 			  G_CALLBACK (mark_set_cb),
 			  frame);
 
 	g_signal_connect (frame->revealer,
 			  "key-press-event",
 	                  G_CALLBACK (search_widget_key_press_event),
 	                  frame);
 
 	g_signal_connect (frame->revealer,
 			  "scroll-event",
@@ -1524,60 +1543,68 @@ gedit_view_frame_init (GeditViewFrame *frame)
 
 	frame->search_entry_changed_id =
 		g_signal_connect (frame->search_entry,
 		                  "changed",
 		                  G_CALLBACK (search_entry_changed_cb),
 		                  frame);
 
 	frame->search_entry_focus_out_id =
 		g_signal_connect (frame->search_entry,
 				  "focus-out-event",
 				  G_CALLBACK (search_entry_focus_out_event),
 				  frame);
 
 	g_signal_connect_swapped (frame->go_up_button,
 				  "clicked",
 				  G_CALLBACK (backward_search),
 				  frame);
 
 	g_signal_connect_swapped (frame->go_down_button,
 				  "clicked",
 				  G_CALLBACK (forward_search),
 				  frame);
 }
 
 GeditViewFrame *
 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)
 {
 	g_return_val_if_fail (GEDIT_IS_VIEW_FRAME (frame), NULL);
 
 	return frame->view;
 }
 
 void
 gedit_view_frame_popup_search (GeditViewFrame *frame)
 {
 	g_return_if_fail (GEDIT_IS_VIEW_FRAME (frame));
 
 	start_interactive_search_real (frame, SEARCH);
 }
 
 void
 gedit_view_frame_popup_goto_line (GeditViewFrame *frame)
 {
 	g_return_if_fail (GEDIT_IS_VIEW_FRAME (frame));
 
 	start_interactive_search_real (frame, GOTO_LINE);
 }
 
 void
 gedit_view_frame_clear_search (GeditViewFrame *frame)
 {
 	g_return_if_fail (GEDIT_IS_VIEW_FRAME (frame));
 
 	g_signal_handler_block (frame->search_entry,
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
@@ -1,45 +1,49 @@
 /*
  * gedit-view-frame.h
  * This file is part of gedit
  *
  * Copyright (C) 2010 - 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_VIEW_FRAME_H
 #define GEDIT_VIEW_FRAME_H
 
 #include <gtk/gtk.h>
 #include "gedit-document.h"
 #include "gedit-view.h"
+#include "gedit-view-centering.h"
 
 G_BEGIN_DECLS
 
 #define GEDIT_TYPE_VIEW_FRAME (gedit_view_frame_get_type ())
 G_DECLARE_FINAL_TYPE (GeditViewFrame, gedit_view_frame, GEDIT, VIEW_FRAME, GtkOverlay)
 
 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);
 
 void		 gedit_view_frame_popup_goto_line	(GeditViewFrame *frame);
 
 void		 gedit_view_frame_clear_search		(GeditViewFrame *frame);
 
 G_END_DECLS
 
 #endif /* GEDIT_VIEW_FRAME_H */
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
@@ -1,232 +1,259 @@
 /*
  * This file is part of gedit
  *
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2002 Chema Celorio, Paolo Maggi
  * Copyright (C) 2003-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-view.h"
 #include <libpeas/peas-extension-set.h>
 #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
 {
 	TARGET_URI_LIST = 100,
 	TARGET_XDNDDIRECTSAVE
 };
 
 enum
 {
 	SIGNAL_DROP_URIS,
 	N_SIGNALS
 };
 
 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)
 {
 	GeditDocument *doc;
 	GtkSourceFile *file;
 
 	doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
 	file = gedit_document_get_file (doc);
 
 	gtk_text_view_set_editable (GTK_TEXT_VIEW (view),
 				    !gtk_source_file_is_readonly (file));
 }
 
 static void
 file_read_only_notify_cb (GtkSourceFile *file,
 			  GParamSpec    *pspec,
 			  GeditView     *view)
 {
 	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);
 }
 
 static void
 buffer_notify_cb (GeditView  *view,
 		  GParamSpec *pspec,
 		  gpointer    user_data)
 {
 	buffer_changed (view);
 }
 
 static void
 gedit_view_init (GeditView *view)
 {
 	GtkTargetList *target_list;
-	GtkStyleContext *style_context;
+	GtkStyleContext *context;
 
 	gedit_debug (DEBUG_VIEW);
 
 	view->priv = gedit_view_get_instance_private (view);
 
 	/* Drag and drop support */
 	view->priv->direct_save_uri = NULL;
 	target_list = gtk_drag_dest_get_target_list (GTK_WIDGET (view));
 
 	if (target_list != NULL)
 	{
 		gtk_target_list_add (target_list,
 		                     gdk_atom_intern ("XdndDirectSave0", FALSE),
 		                     0,
 		                     TARGET_XDNDDIRECTSAVE);
 		gtk_target_list_add_uri_targets (target_list, TARGET_URI_LIST);
 	}
 
 	/* GeditViewActivatable */
 	view->priv->extensions =
 		peas_extension_set_new (PEAS_ENGINE (gedit_plugins_engine_get_default ()),
 		                        GEDIT_TYPE_VIEW_ACTIVATABLE,
 		                        "view", view,
 		                        NULL);
 
 	/* Act on buffer changes */
 	buffer_changed (view);
 	g_signal_connect (view,
 			  "notify::buffer",
 			  G_CALLBACK (buffer_notify_cb),
 			  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
 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
 	 * reinstate a buffer which we don't want.
 	 * There is no problem calling g_signal_handlers_disconnect_by_func()
 	 * several times (if dispose() is called several times).
 	 */
 	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
 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",
 	                 G_SETTINGS_BIND_GET);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_AUTO_INDENT,
 	                 view, "auto-indent",
 	                 G_SETTINGS_BIND_GET);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_TABS_SIZE,
 	                 view, "tab-width",
 	                 G_SETTINGS_BIND_GET);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_INSERT_SPACES,
 	                 view, "insert-spaces-instead-of-tabs",
 	                 G_SETTINGS_BIND_GET);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN,
 	                 view, "show-right-margin",
 	                 G_SETTINGS_BIND_GET);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_BACKGROUND_PATTERN,
 	                 view, "background-pattern",
 	                 G_SETTINGS_BIND_GET);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_RIGHT_MARGIN_POSITION,
 	                 view, "right-margin-position",
 	                 G_SETTINGS_BIND_GET);
 
 	g_settings_bind (editor_settings, GEDIT_SETTINGS_HIGHLIGHT_CURRENT_LINE,
@@ -693,31 +720,244 @@ gedit_view_class_init (GeditViewClass *klass)
 	                              GDK_CONTROL_MASK,
 	                              "change-case", 1,
 	                              G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_LOWER);
 
 	gtk_binding_entry_add_signal (binding_set,
 	                              GDK_KEY_asciitilde,
 	                              GDK_CONTROL_MASK,
 	                              "change-case", 1,
 	                              G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_TOGGLE);
 }
 
 /**
  * gedit_view_new:
  * @doc: a #GeditDocument
  *
  * Creates a new #GeditView object displaying the @doc document.
  * @doc cannot be %NULL.
  *
  * Returns: a new #GeditView.
  */
 GtkWidget *
 gedit_view_new (GeditDocument *doc)
 {
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
 
 	return g_object_new (GEDIT_TYPE_VIEW,
 			     "buffer", 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
@@ -1,67 +1,85 @@
 /*
  * This file is part of gedit
  *
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002-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_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
 
 #define GEDIT_TYPE_VIEW            (gedit_view_get_type ())
 #define GEDIT_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_VIEW, GeditView))
 #define GEDIT_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_VIEW, GeditViewClass))
 #define GEDIT_IS_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_VIEW))
 #define GEDIT_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_VIEW))
 #define GEDIT_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_VIEW, GeditViewClass))
 
 typedef struct _GeditView		GeditView;
 typedef struct _GeditViewClass		GeditViewClass;
 typedef struct _GeditViewPrivate	GeditViewPrivate;
 
 struct _GeditView
 {
-	TeplView view;
+	GtkSourceView view;
 
 	/*< private >*/
 	GeditViewPrivate *priv;
 };
 
 struct _GeditViewClass
 {
-	TeplViewClass parent_class;
+	GtkSourceViewClass parent_class;
 
 	void	(*drop_uris)	(GeditView  *view,
 				 gchar     **uri_list);
 
 	gpointer padding;
 };
 
 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 */
 
 /* ex:set ts=8 noet: */
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
@@ -1,112 +1,119 @@
 /*
  * gedit-window-private.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
  * MERCHANWINDOWILITY 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_WINDOW_PRIVATE_H
 #define GEDIT_WINDOW_PRIVATE_H
 
 #include <libpeas/peas-extension-set.h>
 
 #include "gedit/gedit-window.h"
 #include "gedit-message-bus.h"
 #include "gedit-settings.h"
 #include "gedit-multi-notebook.h"
+#include "gedit-open-document-selector.h"
 
 G_BEGIN_DECLS
 
 /* WindowPrivate is in a separate .h so that we can access it from gedit-commands */
 
 struct _GeditWindowPrivate
 {
 	GSettings      *editor_settings;
 	GSettings      *ui_settings;
 	GSettings      *window_settings;
 
 	GeditMultiNotebook *multi_notebook;
 
 	GtkWidget      *side_panel;
 	GtkWidget      *side_stack_switcher;
 	GtkWidget      *side_panel_inline_stack_switcher;
 	GtkWidget      *bottom_panel_box;
 	GtkWidget      *bottom_panel;
 
 	GtkWidget      *hpaned;
 	GtkWidget      *vpaned;
 
 	GeditMessageBus *message_bus;
 	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;
 	GtkWidget      *line_col_button;
 	GtkWidget      *tab_width_button;
 	GtkWidget      *language_button;
 	GtkWidget      *language_button_label;
 	GtkWidget      *language_popover;
 	guint           generic_message_cid;
 	guint           tip_message_cid;
 	guint 	        bracket_match_message_cid;
 	guint 	        tab_width_id;
 	guint 	        language_changed_id;
 	guint           wrap_mode_changed_id;
 
 	/* Headerbars */
 	GtkWidget      *titlebar_paned;
 	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;
 
 	gint            num_tabs_with_error;
 
 	gint            width;
 	gint            height;
 	GdkWindowState  window_state;
 
 	gint            side_panel_size;
 	gint            bottom_panel_size;
 
 	GeditWindowState state;
 
 	guint           inhibition_cookie;
 
 	gint            bottom_panel_item_removed_handler_id;
 
 	GtkWindowGroup *window_group;
 
 	gchar          *file_chooser_folder_uri;
 
 	gchar          *direct_save_uri;
 
 	GSList         *closed_docs_stack;
 
 	guint           removing_tabs : 1;
 	guint           dispose_has_run : 1;
 
 	guint           in_fullscreen_eventbox : 1;
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
@@ -1,86 +1,92 @@
 /*
  * gedit-window.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 "config.h"
 
 #include "gedit-window.h"
 
 #include <time.h>
 #include <sys/types.h>
 #include <string.h>
 
 #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"
 #include "gedit-statusbar.h"
 #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"
 #include "gedit-debug.h"
 #include "gedit-document.h"
 #include "gedit-document-private.h"
 #include "gedit-documents-panel.h"
 #include "gedit-plugins-engine.h"
 #include "gedit-window-activatable.h"
 #include "gedit-enum-types.h"
 #include "gedit-dirs.h"
 #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
 {
 	PROP_0,
 	PROP_STATE,
 	LAST_PROP
 };
 
 static GParamSpec *properties[LAST_PROP];
 
 enum
 {
 	TAB_ADDED,
 	TAB_REMOVED,
 	TABS_REORDERED,
 	ACTIVE_TAB_CHANGED,
 	ACTIVE_TAB_STATE_CHANGED,
 	LAST_SIGNAL
 };
 
 static guint signals[LAST_SIGNAL];
 
 enum
 {
 	TARGET_URI_LIST = 100,
 	TARGET_XDNDDIRECTSAVE
 };
 
 static const GtkTargetEntry drop_types [] = {
 	{ "XdndDirectSave0", 0, TARGET_XDNDDIRECTSAVE }, /* XDS Protocol Type */
@@ -131,63 +137,63 @@ save_panels_state (GeditWindow *window)
 	{
 		g_settings_set_string (window->priv->window_settings,
 				       GEDIT_SETTINGS_SIDE_PANEL_ACTIVE_PAGE,
 				       panel_page);
 	}
 
 	if (window->priv->bottom_panel_size > 0)
 	{
 		g_settings_set_int (window->priv->window_settings,
 				    GEDIT_SETTINGS_BOTTOM_PANEL_SIZE,
 				    window->priv->bottom_panel_size);
 	}
 
 	panel_page = gtk_stack_get_visible_child_name (GTK_STACK (window->priv->bottom_panel));
 	if (panel_page != NULL)
 	{
 		g_settings_set_string (window->priv->window_settings,
 				       GEDIT_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE,
 				       panel_page);
 	}
 
 	g_settings_apply (window->priv->window_settings);
 }
 
 static void
 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);
 	}
 }
 
 static void
 gedit_window_dispose (GObject *object)
 {
 	GeditWindow *window;
 
 	gedit_debug (DEBUG_WINDOW);
 
 	window = GEDIT_WINDOW (object);
 
 	/* Stop tracking removal of panels otherwise we always
 	 * end up with thinking we had no panel active, since they
 	 * should all be removed below */
 	if (window->priv->bottom_panel_item_removed_handler_id != 0)
 	{
 		g_signal_handler_disconnect (window->priv->bottom_panel,
 					     window->priv->bottom_panel_item_removed_handler_id);
 		window->priv->bottom_panel_item_removed_handler_id = 0;
 	}
 
 	/* First of all, force collection so that plugins
 	 * really drop some of the references.
 	 */
 	peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
 
@@ -204,142 +210,160 @@ gedit_window_dispose (GObject *object)
 
 		peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
 
 		window->priv->dispose_has_run = TRUE;
 	}
 
 	g_clear_object (&window->priv->message_bus);
 	g_clear_object (&window->priv->window_group);
 
 	/* We must free the settings after saving the panels */
 	g_clear_object (&window->priv->editor_settings);
 	g_clear_object (&window->priv->ui_settings);
 	g_clear_object (&window->priv->window_settings);
 
 	/* Now that there have broken some reference loops,
 	 * force collection again.
 	 */
 	peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
 
 	g_clear_object (&window->priv->side_stack_switcher);
 
 	/* GTK+/GIO unref the action map in an idle. For the last GeditWindow,
 	 * the application quits before the idle, so the action map is not
 	 * unreffed, and some objects are not finalized on application shutdown
 	 * (GeditView for example).
 	 * So this is just for making the debugging of object references a bit
 	 * nicer.
 	 */
 	remove_actions (window);
 
-	window->priv->fullscreen_open_recent_button = NULL;
-
 	G_OBJECT_CLASS (gedit_window_parent_class)->dispose (object);
 }
 
 static void
 gedit_window_finalize (GObject *object)
 {
 	GeditWindow *window = GEDIT_WINDOW (object);
 
 	g_free (window->priv->file_chooser_folder_uri);
 	g_slist_free_full (window->priv->closed_docs_stack, (GDestroyNotify)g_object_unref);
 
 	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)
 {
 	GAction *fullscreen_action;
 
 	_gedit_multi_notebook_set_show_tabs (window->priv->multi_notebook, !is_fullscreen);
 
 	if (is_fullscreen)
 	{
 		gtk_widget_hide (window->priv->statusbar);
 	}
 	else
 	{
 		if (g_settings_get_boolean (window->priv->ui_settings, "statusbar-visible"))
 		{
 			gtk_widget_show (window->priv->statusbar);
 		}
 	}
 
+	gedit_multi_notebook_foreach_tab (window->priv->multi_notebook,
+					  (GtkCallback)update_view_centering,
+					  GBOOLEAN_TO_POINTER (is_fullscreen));
+
 #ifndef OS_OSX
 	if (is_fullscreen)
 	{
 		gtk_widget_show_all (window->priv->fullscreen_eventbox);
 	}
 	else
 	{
 		gtk_widget_hide (window->priv->fullscreen_eventbox);
 	}
 #endif
 
 	fullscreen_action = g_action_map_lookup_action (G_ACTION_MAP (window),
 	                                                "fullscreen");
 
 	g_simple_action_set_state (G_SIMPLE_ACTION (fullscreen_action),
 	                           g_variant_new_boolean (is_fullscreen));
 }
 
 static gboolean
 gedit_window_window_state_event (GtkWidget           *widget,
 				 GdkEventWindowState *event)
 {
 	GeditWindow *window = GEDIT_WINDOW (widget);
 
 	window->priv->window_state = event->new_window_state;
 
 	g_settings_set_int (window->priv->window_settings, GEDIT_SETTINGS_WINDOW_STATE,
 			    window->priv->window_state);
 
 	if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) != 0)
 	{
 		update_fullscreen (window, (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0);
 	}
 
 	return GTK_WIDGET_CLASS (gedit_window_parent_class)->window_state_event (widget, event);
 }
 
 static gboolean
 gedit_window_configure_event (GtkWidget         *widget,
 			      GdkEventConfigure *event)
 {
 	GeditWindow *window = GEDIT_WINDOW (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);
 	}
 
 	return GTK_WIDGET_CLASS (gedit_window_parent_class)->configure_event (widget, event);
 }
 
 /*
  * GtkWindow catches keybindings for the menu items _before_ passing them to
  * the focused widget. This is unfortunate and means that pressing ctrl+V
  * in an entry on a panel ends up pasting text in the TextView.
  * Here we override GtkWindow's handler to do the same things that it
  * does, but in the opposite order and then we chain up to the grand
  * parent handler, skipping gtk_window_key_press_event.
  */
 static gboolean
 gedit_window_key_press_event (GtkWidget   *widget,
 			      GdkEventKey *event)
 {
 	static gpointer grand_parent_class = NULL;
 
 	GtkWindow *window = GTK_WINDOW (widget);
 	gboolean handled = FALSE;
 
 	if (grand_parent_class == NULL)
 	{
 		grand_parent_class = g_type_class_peek_parent (gedit_window_parent_class);
 	}
 
 	/* handle focus widget key events */
@@ -427,76 +451,78 @@ gedit_window_class_init (GeditWindowClass *klass)
 			      G_SIGNAL_RUN_FIRST,
 			      G_STRUCT_OFFSET (GeditWindowClass, tabs_reordered),
 			      NULL, NULL, NULL,
 			      G_TYPE_NONE,
 			      0);
 	signals[ACTIVE_TAB_CHANGED] =
 		g_signal_new ("active-tab-changed",
 			      G_OBJECT_CLASS_TYPE (object_class),
 			      G_SIGNAL_RUN_FIRST,
 			      G_STRUCT_OFFSET (GeditWindowClass, active_tab_changed),
 			      NULL, NULL, NULL,
 			      G_TYPE_NONE,
 			      1,
 			      GEDIT_TYPE_TAB);
 	signals[ACTIVE_TAB_STATE_CHANGED] =
 		g_signal_new ("active-tab-state-changed",
 			      G_OBJECT_CLASS_TYPE (object_class),
 			      G_SIGNAL_RUN_FIRST,
 			      G_STRUCT_OFFSET (GeditWindowClass, active_tab_state_changed),
 			      NULL, NULL, NULL,
 			      G_TYPE_NONE,
 			      0);
 
 	/* Bind class to template */
 	gtk_widget_class_set_template_from_resource (widget_class,
 	                                             "/org/gnome/gedit/ui/gedit-window.ui");
 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, titlebar_paned);
 	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);
 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_panel_inline_stack_switcher);
 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, vpaned);
 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, multi_notebook);
 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, bottom_panel_box);
 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, bottom_panel);
 	gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, statusbar);
 	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);
 }
 
 static void
 received_clipboard_contents (GtkClipboard     *clipboard,
 			     GtkSelectionData *selection_data,
 			     GeditWindow      *window)
 {
 	GeditTab *tab;
 	gboolean enabled;
 	GAction *action;
 
 	/* getting clipboard contents is async, so we need to
 	 * get the current tab and its state */
 
 	tab = gedit_window_get_active_tab (window);
 
 	if (tab != NULL)
 	{
 		GeditTabState state;
 		gboolean state_normal;
 
 		state = gedit_tab_get_state (tab);
 		state_normal = (state == GEDIT_TAB_STATE_NORMAL);
 
 		enabled = state_normal &&
 		          gtk_selection_data_targets_include_text (selection_data);
 	}
 	else
 	{
@@ -738,138 +764,178 @@ update_actions_sensitivity (GeditWindow *window)
 
 	/* We disable File->Quit/SaveAll/CloseAll while printing to avoid to have two
 	   operations (save and print/print preview) that uses the message area at
 	   the same time (may be we can remove this limitation in the future) */
 	/* We disable File->Quit/CloseAll if state is saving since saving cannot be
 	   cancelled (may be we can remove this limitation in the future) */
 	action = g_action_map_lookup_action (G_ACTION_MAP (g_application_get_default ()),
 	                                     "quit");
 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
 	                             !(window->priv->state & GEDIT_WINDOW_STATE_SAVING) &&
 	                             !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING));
 
 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "save-all");
 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
 	                             !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING) &&
 	                             num_tabs > 0);
 
 	action = g_action_map_lookup_action (G_ACTION_MAP (window), "close-all");
 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
 	                             num_tabs > 0 &&
 	                             !(window->priv->state & GEDIT_WINDOW_STATE_SAVING) &&
 	                             !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING) &&
 	                             num_tabs > 0);
 
 	peas_extension_set_foreach (window->priv->extensions,
 	                            (PeasExtensionSetForeachFunc) extension_update_state,
 	                            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;
 
 	active_document = gedit_window_get_active_document (window);
 	if (active_document != NULL)
 	{
 		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;
 
 	active_document = gedit_window_get_active_document (window);
 	if (active_document != NULL)
 	{
 		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);
 
 	window->priv->generic_message_cid = gtk_statusbar_get_context_id
 		(GTK_STATUSBAR (window->priv->statusbar), "generic_message");
 	window->priv->tip_message_cid = gtk_statusbar_get_context_id
 		(GTK_STATUSBAR (window->priv->statusbar), "tip_message");
 	window->priv->bracket_match_message_cid = gtk_statusbar_get_context_id
 		(GTK_STATUSBAR (window->priv->statusbar), "bracket_match_message");
 
 	g_settings_bind (window->priv->ui_settings,
 	                 "statusbar-visible",
 	                 window->priv->statusbar,
 	                 "visible",
 	                 G_SETTINGS_BIND_GET);
 
 	/* Line Col button */
 	gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (window->priv->line_col_button),
 	                                _gedit_app_get_line_col_menu (GEDIT_APP (g_application_get_default ())));
 
 	/* Tab Width button */
 	gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (window->priv->tab_width_button),
 	                                _gedit_app_get_tab_width_menu (GEDIT_APP (g_application_get_default ())));
 
 	/* Language button */
 	window->priv->language_popover = gtk_popover_new (window->priv->language_button);
 	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 *
 clone_window (GeditWindow *origin)
 {
 	GeditWindow *window;
 	GdkScreen *screen;
 	GeditApp  *app;
 	const gchar *panel_page;
 
 	gedit_debug (DEBUG_WINDOW);
 
 	app = GEDIT_APP (g_application_get_default ());
 
 	screen = gtk_window_get_screen (GTK_WINDOW (origin));
 	window = gedit_app_create_window (app, screen);
 
 	gtk_window_set_default_size (GTK_WINDOW (window),
 				     origin->priv->width,
 				     origin->priv->height);
 
 	if ((origin->priv->window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
 		gtk_window_maximize (GTK_WINDOW (window));
 	else
 		gtk_window_unmaximize (GTK_WINDOW (window));
 
 	if ((origin->priv->window_state & GDK_WINDOW_STATE_STICKY) != 0)
 		gtk_window_stick (GTK_WINDOW (window));
 	else
 		gtk_window_unstick (GTK_WINDOW (window));
@@ -1017,81 +1083,81 @@ set_title (GeditWindow *window)
 		gedit_app_set_window_title (GEDIT_APP (g_application_get_default ()),
 		                            window,
 		                            "gedit");
 		gtk_header_bar_set_title (GTK_HEADER_BAR (window->priv->headerbar),
 		                          "gedit");
 		gtk_header_bar_set_subtitle (GTK_HEADER_BAR (window->priv->headerbar),
 		                             NULL);
 		gtk_header_bar_set_title (GTK_HEADER_BAR (window->priv->fullscreen_headerbar),
 		                          "gedit");
 		gtk_header_bar_set_subtitle (GTK_HEADER_BAR (window->priv->fullscreen_headerbar),
 		                             NULL);
 		return;
 	}
 
 	doc = gedit_tab_get_document (tab);
 	g_return_if_fail (doc != NULL);
 
 	file = gedit_document_get_file (doc);
 
 	name = gedit_document_get_short_name_for_display (doc);
 
 	len = g_utf8_strlen (name, -1);
 
 	/* if the name is awfully long, truncate it and be done with it,
 	 * otherwise also show the directory (ellipsized if needed)
 	 */
 	if (len > MAX_TITLE_LENGTH)
 	{
 		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;
 	}
 	else
 	{
 		GFile *location = gtk_source_file_get_location (file);
 
 		if (location != NULL)
 		{
 			gchar *str = gedit_utils_location_get_dirname_for_display (location);
 
 			/* use the remaining space for the dir, but use a min of 20 chars
 			 * so that we do not end up with a dirname like "(a...b)".
 			 * This means that in the worst case when the filename is long 99
 			 * 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);
 		}
 	}
 
 	if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
 	{
 		gchar *tmp_name;
 
 		tmp_name = g_strdup_printf ("*%s", name);
 		g_free (name);
 
 		name = tmp_name;
 	}
 
 	if (gtk_source_file_is_readonly (file))
 	{
 		title = g_strdup_printf ("%s [%s]",
 		                         name, _("Read-Only"));
 
 		if (dirname != NULL)
 		{
 			main_title = g_strdup_printf ("%s [%s] (%s) - gedit",
 			                              name,
 			                              _("Read-Only"),
 			                              dirname);
 			subtitle = dirname;
 		}
 		else
 		{
 			main_title = g_strdup_printf ("%s [%s] - gedit",
@@ -1663,142 +1729,138 @@ drag_drop_cb (GtkWidget      *widget,
 
 		found = gtk_target_list_find (target_list, target, &info);
 		g_assert (found);
 
 		if (info == TARGET_XDNDDIRECTSAVE)
 		{
 			gchar *uri;
 			uri = gedit_utils_set_direct_save_filename (context);
 
 			if (uri != NULL)
 			{
 				g_free (window->priv->direct_save_uri);
 				window->priv->direct_save_uri = uri;
 			}
 		}
 
 		gtk_drag_get_data (GTK_WIDGET (widget), context,
 				   target, time);
 	}
 }
 
 /* Handle drops on the GeditView */
 static void
 drop_uris_cb (GtkWidget    *widget,
 	      gchar       **uri_list,
 	      GeditWindow  *window)
 {
 	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);
 }
 
 static void
 empty_search_notify_cb (GeditDocument *doc,
 			GParamSpec    *pspec,
 			GeditWindow   *window)
 {
 	if (doc == gedit_window_get_active_document (window))
 	{
 		update_actions_sensitivity (window);
 	}
 }
 
 static void
 can_undo (GeditDocument *doc,
 	  GParamSpec    *pspec,
 	  GeditWindow   *window)
 {
 	if (doc == gedit_window_get_active_document (window))
 	{
 		update_actions_sensitivity (window);
 	}
 }
 
 static void
 can_redo (GeditDocument *doc,
 	  GParamSpec    *pspec,
 	  GeditWindow   *window)
 {
@@ -1858,61 +1920,61 @@ on_tab_added (GeditMultiNotebook *multi,
 	update_actions_sensitivity (window);
 
 	view = gedit_tab_get_view (tab);
 	doc = gedit_tab_get_document (tab);
 	file = gedit_document_get_file (doc);
 
 	/* IMPORTANT: remember to disconnect the signal in notebook_tab_removed
 	 * if a new signal is connected here */
 
 	g_signal_connect (tab,
 			 "notify::name",
 			  G_CALLBACK (sync_name),
 			  window);
 	g_signal_connect (tab,
 			 "notify::state",
 			  G_CALLBACK (sync_state),
 			  window);
 	g_signal_connect (tab,
 			  "notify::can-close",
 			  G_CALLBACK (sync_can_close),
 			  window);
 	g_signal_connect (tab,
 			  "drop_uris",
 			  G_CALLBACK (drop_uris_cb),
 			  window);
 	g_signal_connect (doc,
 			  "bracket-matched",
 			  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,
 			  "notify::empty-search",
 			  G_CALLBACK (empty_search_notify_cb),
 			  window);
 	g_signal_connect (doc,
 			  "notify::can-undo",
 			  G_CALLBACK (can_undo),
 			  window);
 	g_signal_connect (doc,
 			  "notify::can-redo",
 			  G_CALLBACK (can_redo),
 			  window);
 	g_signal_connect (doc,
 			  "notify::has-selection",
 			  G_CALLBACK (selection_changed),
 			  window);
 	g_signal_connect (view,
 			  "notify::overwrite",
 			  G_CALLBACK (overwrite_mode_changed),
 			  window);
 	g_signal_connect (view,
 			  "notify::editable",
 			  G_CALLBACK (editable_changed),
 			  window);
 	g_signal_connect (file,
 			  "notify::read-only",
 			  G_CALLBACK (readonly_changed),
 			  window);
@@ -2117,64 +2179,77 @@ on_show_popup_menu (GeditMultiNotebook *multi,
 	}
 
 	menu = gedit_notebook_popup_menu_new (window, tab);
 
 	g_signal_connect (menu,
 			  "selection-done",
 			  G_CALLBACK (gtk_widget_destroy),
 			  NULL);
 
 	gtk_widget_show (menu);
 	gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
 }
 
 static void
 on_notebook_changed (GeditMultiNotebook *mnb,
 		     GParamSpec         *pspec,
 		     GeditWindow        *window)
 {
 	update_actions_sensitivity (window);
 }
 
 static void
 on_notebook_removed (GeditMultiNotebook *mnb,
 		     GeditNotebook      *notebook,
 		     GeditWindow        *window)
 {
 	update_actions_sensitivity (window);
 }
 
 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
 side_panel_size_allocate (GtkWidget     *widget,
 			  GtkAllocation *allocation,
 			  GeditWindow   *window)
 {
 	window->priv->side_panel_size = allocation->width;
 }
 
 static void
 bottom_panel_size_allocate (GtkWidget     *widget,
 			    GtkAllocation *allocation,
 			    GeditWindow   *window)
 {
 	window->priv->bottom_panel_size = allocation->height;
 }
 
 static void
 hpaned_restore_position (GtkWidget   *widget,
 			 GeditWindow *window)
 {
 	gint pos;
 
 	gedit_debug_message (DEBUG_WINDOW,
 			     "Restoring hpaned position: side panel size %d",
 			     window->priv->side_panel_size);
 
 	pos = MAX (100, window->priv->side_panel_size);
 	gtk_paned_set_position (GTK_PANED (window->priv->hpaned), pos);
@@ -2510,60 +2585,72 @@ clipboard_owner_change (GtkClipboard        *clipboard,
 
 static void
 window_realized (GtkWidget *window,
 		 gpointer  *data)
 {
 	GtkClipboard *clipboard;
 
 	clipboard = gtk_widget_get_clipboard (window,
 					      GDK_SELECTION_CLIPBOARD);
 
 	g_signal_connect (clipboard,
 			  "owner_change",
 			  G_CALLBACK (clipboard_owner_change),
 			  window);
 }
 
 static void
 window_unrealized (GtkWidget *window,
 		   gpointer  *data)
 {
 	GtkClipboard *clipboard;
 
 	clipboard = gtk_widget_get_clipboard (window,
 					      GDK_SELECTION_CLIPBOARD);
 
 	g_signal_handlers_disconnect_by_func (clipboard,
 					      G_CALLBACK (clipboard_owner_change),
 					      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,
 		 PeasExtension    *exten,
 		 GeditWindow      *window)
 {
 	gedit_window_activatable_activate (GEDIT_WINDOW_ACTIVATABLE (exten));
 }
 
 static void
 extension_removed (PeasExtensionSet *extensions,
 		   PeasPluginInfo   *info,
 		   PeasExtension    *exten,
 		   GeditWindow      *window)
 {
 	gedit_window_activatable_deactivate (GEDIT_WINDOW_ACTIVATABLE (exten));
 }
 
 static GActionEntry win_entries[] = {
 	{ "new-tab", _gedit_cmd_file_new },
 	{ "open", _gedit_cmd_file_open },
 	{ "revert", _gedit_cmd_file_revert },
 	{ "reopen-closed-tab", _gedit_cmd_file_reopen_closed_tab },
 	{ "save", _gedit_cmd_file_save },
 	{ "save-as", _gedit_cmd_file_save_as },
 	{ "save-all", _gedit_cmd_file_save_all },
 	{ "close", _gedit_cmd_file_close },
 	{ "close-all", _gedit_cmd_file_close_all },
 	{ "print", _gedit_cmd_file_print },
 	{ "focus-active-view", NULL, NULL, "false", _gedit_cmd_view_focus_active },
@@ -2581,188 +2668,145 @@ static GActionEntry win_entries[] = {
 	{ "previous-tab-group", _gedit_cmd_documents_previous_tab_group },
 	{ "next-tab-group", _gedit_cmd_documents_next_tab_group },
 	{ "previous-document", _gedit_cmd_documents_previous_document },
 	{ "next-document", _gedit_cmd_documents_next_document },
 	{ "move-to-new-window", _gedit_cmd_documents_move_to_new_window },
 	{ "undo", _gedit_cmd_edit_undo },
 	{ "redo", _gedit_cmd_edit_redo },
 	{ "cut", _gedit_cmd_edit_cut },
 	{ "copy", _gedit_cmd_edit_copy },
 	{ "paste", _gedit_cmd_edit_paste },
 	{ "delete", _gedit_cmd_edit_delete },
 	{ "select-all", _gedit_cmd_edit_select_all },
 	{ "highlight-mode", _gedit_cmd_view_highlight_mode },
 	{ "overwrite-mode", NULL, NULL, "false", _gedit_cmd_edit_overwrite_mode }
 };
 
 static void
 sync_fullscreen_actions (GeditWindow *window,
 			 gboolean     fullscreen)
 {
 	GtkMenuButton *button;
 	GPropertyAction *action;
 
 	button = fullscreen ? window->priv->fullscreen_gear_button : window->priv->gear_button;
 	g_action_map_remove_action (G_ACTION_MAP (window), "hamburger-menu");
 	action = g_property_action_new ("hamburger-menu", button, "active");
 	g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
 	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)
 {
 	GtkTargetList *tl;
 	GMenuModel *hamburger_menu;
 
 	gedit_debug (DEBUG_WINDOW);
 
 	window->priv = gedit_window_get_instance_private (window);
 
 	window->priv->removing_tabs = FALSE;
 	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");
 	window->priv->ui_settings = g_settings_new ("org.gnome.gedit.preferences.ui");
 
 	/* window settings are applied only once the window is closed. We do not
 	   want to keep writing to disk when the window is dragged around */
 	window->priv->window_settings = g_settings_new ("org.gnome.gedit.state.window");
 	g_settings_delay (window->priv->window_settings);
 
 	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,
 	                                 G_N_ELEMENTS (win_entries),
 	                                 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)
 	{
 		gtk_menu_button_set_menu_model (window->priv->gear_button, hamburger_menu);
 		gtk_menu_button_set_menu_model (window->priv->fullscreen_gear_button, hamburger_menu);
 	}
 	else
 	{
 		gtk_widget_hide (GTK_WIDGET (window->priv->gear_button));
 		gtk_widget_hide (GTK_WIDGET (window->priv->fullscreen_gear_button));
 		gtk_widget_set_no_show_all (GTK_WIDGET (window->priv->gear_button), TRUE);
 		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 */
 	setup_statusbar (window);
 
 	/* Setup main area */
 	g_signal_connect (window->priv->multi_notebook,
 			  "notebook-removed",
 			  G_CALLBACK (on_notebook_removed),
 			  window);
 	g_signal_connect (window->priv->multi_notebook,
 			  "notify::active-notebook",
 			  G_CALLBACK (on_notebook_changed),
 			  window);
 
 	g_signal_connect (window->priv->multi_notebook,
 			  "tab-added",
 			  G_CALLBACK (on_tab_added),
 			  window);
 
 	g_signal_connect (window->priv->multi_notebook,
 			  "tab-removed",
 			  G_CALLBACK (on_tab_removed),
 			  window);
 
 	g_signal_connect (window->priv->multi_notebook,
 			  "switch-tab",
 			  G_CALLBACK (tab_switched),
 			  window);
 
@@ -2822,60 +2866,66 @@ gedit_window_init (GeditWindow *window)
 	{
 		tl = gtk_target_list_new (drop_types, G_N_ELEMENTS (drop_types));
 		gtk_drag_dest_set_target_list (GTK_WIDGET (window), tl);
 		gtk_target_list_unref (tl);
 	}
 
 	gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
 
 	/* connect instead of override, so that we can
 	 * share the cb code with the view */
 	g_signal_connect (window,
 			  "drag_data_received",
 	                  G_CALLBACK (drag_data_received_cb),
 	                  NULL);
 	g_signal_connect (window,
 			  "drag_drop",
 	                  G_CALLBACK (drag_drop_cb),
 	                  NULL);
 
 	/* we can get the clipboard only after the widget
 	 * is realized */
 	g_signal_connect (window,
 			  "realize",
 			  G_CALLBACK (window_realized),
 			  NULL);
 	g_signal_connect (window,
 			  "unrealize",
 			  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 ()),
 							   GEDIT_TYPE_WINDOW_ACTIVATABLE,
 							   "window", window,
 							   NULL);
 	g_signal_connect (window->priv->extensions,
 			  "extension-added",
 			  G_CALLBACK (extension_added),
 			  window);
 	g_signal_connect (window->priv->extensions,
 			  "extension-removed",
 			  G_CALLBACK (extension_removed),
 			  window);
 	peas_extension_set_foreach (window->priv->extensions,
 	                            (PeasExtensionSetForeachFunc) extension_added,
 	                            window);
 
 	/* set visibility of panels.
 	 * This needs to be done after plugins activatation */
 	init_panels_visibility (window);
 
 	update_actions_sensitivity (window);
 
 	gedit_debug_message (DEBUG_WINDOW, "END");
 }
 
 /**
  * gedit_window_get_active_view:
  * @window: a #GeditWindow
diff --git a/gedit/gedit.c b/gedit/gedit.c
index fcffdaca6..ee3769537 100644
--- a/gedit/gedit.c
+++ b/gedit/gedit.c
@@ -1,67 +1,66 @@
 /*
  * gedit.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 "config.h"
 
 #include "gedit-app.h"
 
 #if defined OS_OSX
 #  include "gedit-app-osx.h"
 #elif defined G_OS_WIN32
 #  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
 #include <gmodule.h>
 static GModule *libgedit_dll = NULL;
 
 /* This code must live in gedit.exe, not in libgedit.dll, since the whole
  * point is to find and load libgedit.dll.
  */
 static gboolean
 gedit_w32_load_private_dll (void)
 {
 	gchar *dllpath;
 	gchar *prefix;
 
 	prefix = g_win32_get_package_installation_directory_of_module (NULL);
 
 	if (prefix != NULL)
 	{
 		/* Instead of g_module_open () it may be possible to do any of the
 		 * following:
 		 * A) Change PATH to "${dllpath}/lib/gedit;$PATH"
 		 * B) Call SetDllDirectory ("${dllpath}/lib/gedit")
 		 * C) Call AddDllDirectory ("${dllpath}/lib/gedit")
 		 * But since we only have one library, and its name is known, may as well
 		 * use gmodule.
 		 */
 		dllpath = g_build_filename (prefix, "lib", "gedit", "lib" PACKAGE_STRING ".dll", NULL);
 		g_free (prefix);
 
@@ -90,91 +89,86 @@ gedit_w32_load_private_dll (void)
 
 static void
 gedit_w32_unload_private_dll (void)
 {
 	if (libgedit_dll)
 	{
 		g_module_close (libgedit_dll);
 		libgedit_dll = NULL;
 	}
 }
 #endif /* G_OS_WIN32 */
 
 static void
 setup_i18n (void)
 {
 	const gchar *dir;
 
 	setlocale (LC_ALL, "");
 
 	dir = gedit_dirs_get_gedit_locale_dir ();
 	bindtextdomain (GETTEXT_PACKAGE, dir);
 
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 	textdomain (GETTEXT_PACKAGE);
 }
 
 int
 main (int argc, char *argv[])
 {
 	GType type;
-	GeditFactory *factory;
 	GeditApp *app;
 	gint status;
 
 #if defined OS_OSX
 	type = GEDIT_TYPE_APP_OSX;
 #elif defined G_OS_WIN32
 	if (!gedit_w32_load_private_dll ())
 	{
 		return 1;
 	}
 
 	type = GEDIT_TYPE_APP_WIN32;
 #else
 	type = GEDIT_TYPE_APP;
 #endif
 
 	/* NOTE: we should not make any calls to the gedit API before the
 	 * private library is loaded.
 	 */
 	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",
 	                    "flags", G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,
 	                    NULL);
 
 	status = g_application_run (G_APPLICATION (app), argc, argv);
 
 	gedit_settings_unref_singleton ();
 
 	/* Break reference cycles caused by the PeasExtensionSet
 	 * for GeditAppActivatable which holds a ref on the GeditApp
 	 */
 	g_object_run_dispose (G_OBJECT (app));
 
 	g_object_add_weak_pointer (G_OBJECT (app), (gpointer *) &app);
 	g_object_unref (app);
 
 	if (app != NULL)
 	{
 		gedit_debug_message (DEBUG_APP, "Leaking with %i refs",
 		                     G_OBJECT (app)->ref_count);
 	}
 
-	tepl_finalize ();
 	gedit_dirs_shutdown ();
 
 #ifdef G_OS_WIN32
 	gedit_w32_unload_private_dll ();
 #endif
 
 	return status;
 }
 
 /* ex:set ts=8 noet: */
diff --git a/gedit/meson.build b/gedit/meson.build
index 214c2b9a5..51472f12d 100644
--- a/gedit/meson.build
+++ b/gedit/meson.build
@@ -1,149 +1,166 @@
 libgedit_public_headers = [
   'gedit-app-activatable.h',
   'gedit-app.h',
   'gedit-commands.h',
   'gedit-debug.h',
   'gedit-document.h',
   'gedit-encodings-combo-box.h',
   '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',
   'gedit-view-activatable.h',
   'gedit-view.h',
   'gedit-window-activatable.h',
   'gedit-window.h',
 ]
 
 libgedit_public_sources = [
   'gedit-app-activatable.c',
   'gedit-app.c',
   'gedit-commands-file.c',
   'gedit-debug.c',
   'gedit-document.c',
   'gedit-encodings-combo-box.c',
   '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',
 ]
 
 libgedit_private_headers = [
   'gedit-app-osx.h',
   'gedit-app-win32.h',
   'gedit-close-confirmation-dialog.h',
   'gedit-dirs.h',
   'gedit-document-private.h',
   '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',
 ]
 
 libgedit_private_sources = [
   'gedit-close-confirmation-dialog.c',
   'gedit-commands-documents.c',
   'gedit-commands-edit.c',
   'gedit-commands-file-print.c',
   'gedit-commands-help.c',
   'gedit-commands-search.c',
   'gedit-commands-view.c',
   'gedit-dirs.c',
   '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',
   'gedit-print-preview.c',
   'gedit-recent.c',
   'gedit-replace-dialog.c',
   'gedit-settings.c',
   'gedit-status-menu-button.c',
   'gedit-tab-label.c',
   'gedit-view-frame.c',
 ]
 
 libgedit_c_args = []
 libgedit_link_args = []
 
 libgedit_deps = [
   deps_basic_list,
   libgd_dep,
+  libxml_dep,
 ]
 
 if host_machine.system() == 'darwin'
   libgedit_private_sources += [
     'gedit-app-osx.m',
     'gedit-recent-osx.c',
   ]
   libgedit_c_args += [
     '-DOS_OSX=1',
   ]
   libgedit_link_args += [
     '-Wl,-framework', '-Wl,Foundation',
     '-Wl,-framework', '-Wl,AppKit',
   ]
   libgedit_deps += [
     dependency('gtk-mac-integration-gtk3'),
   ]
 elif host_machine.system() == 'windows'
   libgedit_private_sources += [
     'gedit-app-win32.c',
   ]
 endif
 
 headers_install_dir = get_option('includedir') / 'gedit-@0@/gedit/'.format(api_version)
 install_headers(
   libgedit_public_headers,
   install_dir: headers_install_dir,
 )
 
 libgedit_public_enum_types = gnome.mkenums_simple(
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
@@ -1,31 +1,43 @@
 .gedit-side-panel-paned.pane-separator:dir(ltr),
 .gedit-side-panel-paned.pane-separator:hover:dir(ltr) {
     border-radius: 0;
     border-width: 0 1px 0 0;
 }
 
 .gedit-side-panel-paned.pane-separator:dir(rtl),
 .gedit-side-panel-paned.pane-separator:hover:dir(rtl) {
     border-radius: 0;
     border-width: 0 0 0 1px;
 }
 
 .gedit-menu-stack-switcher {
     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;
     padding-right: 6px;
 }
 
 statusbar button.flat {
     border-radius: 0;
     border-bottom: none;
 }
 
 GeditFileBrowserWidget .small-button {
   padding: 2px 4px;
 }
 
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,30 +1,55 @@
+.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;
 }
 
 .gedit-document-panel:backdrop {
     color: #b0b2b2;
 }
 
 .gedit-document-panel row:selected:backdrop {
     background-color: #8b8e8f;
 }
 
 .gedit-document-panel-group-row,
 .gedit-document-panel-group-row:hover {
     border-top: 1px solid alpha(currentColor, 0.3);
 }
 
 .gedit-document-panel-group-row:first-child,
 .gedit-document-panel-group-row:first-child:hover {
     border-top: 0px;
 }
 
 /* Try to look as the notebook tab close button */
 .gedit-document-panel row button.flat {
     padding: 0;
     margin-top: 8px;
     margin-bottom: 8px;
     min-width: 18px;
     min-height: 18px;
     color: alpha(currentColor,0.3);
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
@@ -1,23 +1,27 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/gedit">
     <file preprocess="xml-stripblanks">gtk/menus.ui</file>
     <file preprocess="xml-stripblanks">gtk/menus-common.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-encodings-dialog.ui</file>
     <file preprocess="xml-stripblanks">ui/gedit-preferences-dialog.ui</file>
     <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>
     <file>css/gedit.adwaita.css</file>
     <file>css/gedit.highcontrast.css</file>
 
     @OS_DEPENDENT_RESOURCE_FILES@
   </gresource>
 </gresources>
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
@@ -78,72 +78,87 @@
                         <property name="climb_rate">1</property>
                         <property name="snap_to_ticks">True</property>
                         <property name="numeric">True</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
                         <property name="top_attach">0</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
                     <property name="left_attach">1</property>
                     <property name="top_attach">1</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkCheckButton" id="display_statusbar_checkbutton">
                     <property name="label" translatable="yes">Display _statusbar</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">2</property>
                     <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>
                     <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="top_attach">4</property>
                     <property name="width">2</property>
                   </packing>
                 </child>
               </object>
               <packing>
                 <property name="left_attach">0</property>
                 <property name="top_attach">0</property>
               </packing>
             </child>
             <child>
               <object class="GtkGrid" id="grid2">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="row_spacing">6</property>
                 <child>
                   <object class="GtkLabel" id="label848">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="xalign">0</property>
                     <property name="label" translatable="yes">Text Wrapping</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
                   </object>
                   <packing>
                     <property name="left_attach">0</property>
                     <property name="top_attach">0</property>
                   </packing>
                 </child>
                 <child>
@@ -603,62 +618,73 @@
             </child>
             <child>
               <object class="GtkGrid" id="grid14">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
                 <property name="row_spacing">6</property>
                 <child>
                   <object class="GtkLabel" id="label798">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="xalign">0</property>
                     <property name="label" translatable="yes">Color Scheme</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
                   </object>
                   <packing>
                     <property name="left_attach">0</property>
                     <property name="top_attach">0</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkGrid" id="grid15">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <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>
                         <property name="top_attach">0</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkToolbar" id="schemes_toolbar">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="toolbar_style">icons</property>
                         <property name="icon_size">1</property>
                         <child>
                           <object class="GtkToolButton" id="install_scheme_button">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
                             <property name="has_tooltip">True</property>
                             <property name="tooltip_markup" translatable="yes">Install scheme</property>
                             <property name="tooltip_text" translatable="yes">Install scheme</property>
                             <property name="label" translatable="yes">Install Scheme</property>
                             <property name="use_underline">True</property>
                             <property name="icon_name">list-add-symbolic</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
                             <property name="homogeneous">True</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkToolButton" id="uninstall_scheme_button">
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 4c783c711..779802db3 100644
--- a/gedit/resources/ui/gedit-view-frame.ui
+++ b/gedit/resources/ui/gedit-view-frame.ui
@@ -1,47 +1,68 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.8 -->
   <template class="GeditViewFrame" parent="GtkOverlay">
     <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="GtkScrolledWindow" id="scrolled_window">
+      <object class="GtkGrid" id="grid">
         <property name="visible">True</property>
         <property name="hexpand">True</property>
         <property name="vexpand">True</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>
     </child>
     <child type="overlay">
       <object class="GtkRevealer" id="revealer">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="halign">end</property>
         <property name="valign">start</property>
         <child>
           <object class="GtkFrame" id="frame">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="shadow_type">none</property>
             <style>
               <class name="gedit-search-slider"/>
             </style>
             <child>
               <object class="GtkBox" id="hbox">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="orientation">horizontal</property>
                 <style>
                   <class name="linked"/>
                 </style>
                 <child>
                   <object class="GdTaggedEntry" id="search_entry">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
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
@@ -1,59 +1,103 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.10 -->
   <template class="GeditWindow" parent="GtkApplicationWindow">
     <property name="can_focus">False</property>
     <property name="has_focus">False</property>
     <property name="is_focus">False</property>
     <style>
       <class name="org-gnome-gedit"/>
     </style>
     <child type="titlebar">
       <object class="GtkPaned" id="titlebar_paned">
         <property name="visible">True</property>
         <property name="position" bind-source="hpaned" bind-property="position" bind-flags="bidirectional|sync-create"/>
         <child>
           <object class="GtkHeaderBar" id="side_headerbar">
             <property name="visible" bind-source="side_panel" bind-property="visible" bind-flags="sync-create"/>
             <property name="show_close_button">True</property>
             <property name="title" translatable="yes">Documents</property>
           </object>
           <packing>
             <property name="resize">False</property>
             <property name="shrink">False</property>
           </packing>
         </child>
         <child>
           <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>
                 <property name="can_focus">True</property>
                 <property name="can_default">True</property>
                 <property name="receives_default">False</property>
                 <property name="tooltip_text" translatable="yes">Create a new document</property>
                 <property name="action_name">win.new-tab</property>
                 <property name="image">new_tab_image</property>
                 <child internal-child="accessible">
                   <object class="AtkObject" id="new_button_a11y">
                     <property name="accessible-name" translatable="yes">New</property>
                     <property name="accessible-description" translatable="yes">Create a new document</property>
                   </object>
                 </child>
               </object>
             </child>
             <child>
               <object class="GtkMenuButton" id="gear_button">
                 <property name="visible">True</property>
                 <property name="use_popover">True</property>
                 <property name="image">menu_image</property>
               </object>
               <packing>
                 <property name="pack_type">end</property>
               </packing>
             </child>
             <child>
               <object class="GtkButton" id="save_button">
                 <property name="label" translatable="yes">_Save</property>
@@ -283,68 +327,109 @@
                           </packing>
                         </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">True</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
                     <property name="resize">True</property>
                     <property name="shrink">True</property>
                   </packing>
                 </child>
               </object>
               <packing>
                 <property name="expand">True</property>
                 <property name="fill">True</property>
                 <property name="position">1</property>
               </packing>
             </child>
           </object>
         </child>
         <child type="overlay">
           <object class="GtkEventBox" id="fullscreen_eventbox">
             <property name="visible">True</property>
             <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>
                 <property name="valign">start</property>
                 <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>
                         <property name="can_focus">True</property>
                         <property name="can_default">True</property>
                         <property name="receives_default">False</property>
                         <property name="tooltip_text" translatable="yes">Create a new document</property>
                         <property name="action_name">win.new-tab</property>
                         <property name="image">fullscreen_new_tab_image</property>
                         <child internal-child="accessible">
                           <object class="AtkObject" id="fullscreen_new_button_a11y">
                             <property name="accessible-name" translatable="yes">New</property>
                             <property name="accessible-description" translatable="yes">Create a new document</property>
                           </object>
                         </child>
                       </object>
                     </child>
                     <child>
                       <object class="GtkButton" id="leave_fullscreen_button">
                         <property name="visible">True</property>
                         <property name="tooltip_text" translatable="yes">Leave Fullscreen</property>
                         <property name="action_name">win.leave-fullscreen</property>
                         <property name="image">leave_fullscreen_image</property>
                         <child internal-child="accessible">
                           <object class="AtkObject" id="leave_fullscreen_button_a11y">
                             <property name="accessible-name" translatable="yes">Leave Fullscreen</property>
                             <property name="accessible-description" translatable="yes">Leave Fullscreen</property>
                           </object>
                         </child>
                       </object>
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
@@ -1,58 +1,58 @@
 <page xmlns="http://projectmallard.org/1.0/"
       xmlns:its="http://www.w3.org/2005/11/its"
       type="topic" style="task"
       id="gedit-tab-groups">
 
   <info>
     <link type="guide" xref="index#gedit-working-with-files" group="last"/>
     <link type="seealso" xref="gedit-tabs"/>
     <link type="seealso" xref="gedit-tabs-moving"/>
     <desc>Group similar tabs together.</desc>
     <revision pkgversion="3.8" date="2013-06-19" status="draft"/>
 
     <credit type="author copyright">
       <name>Radina Matic</name>
       <email its:translate="no">radina.matic@gmail.com</email>
       <years>2013</years>
     </credit>
 
     <include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
   </info>
 
   <title>Organize files in grouped tabs</title>
 
   <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>
 
   <p>To open a new tab group you can:</p>
 
   <list>
     <item>
       <p>Right click on a tab and select <gui>Move to New Tab Group</gui>.</p>
     </item>
     <item>
       <p>Use the <keyseq><key>Ctrl</key><key>Alt</key><key>N</key></keyseq>
       shortcut.</p>
     </item>
   </list>
 
   <p>This action will divide the <app>gedit</app> window in two panes, and the
   pane with the new tab group will be placed on the right of the active tab.
   You can move the handle right or left assigning more or less space of the
   <app>gedit</app> window between panes according to your needs.</p>
 
   <p>You can open as much tab groups in a <app>gedit</app> window as your screen
   allows, but you will have to move the handle in order to see them
   correctly.</p>
 
   <p>To close a tab group pane just close all the tabs that are opened inside
   it.</p>
 </section>
 
 <!--
diff --git a/meson.build b/meson.build
index be77a885f..ef77bc8a8 100644
--- a/meson.build
+++ b/meson.build
@@ -13,84 +13,104 @@ i18n = import('i18n')
 pkg_config = import('pkgconfig')
 python = import('python')
 
 api_version = '40.0'
 
 # Paths
 root_include_dir = include_directories('.')
 
 srcdir = meson.current_source_dir()
 
 pkglibdir = get_option('prefix') / get_option('libdir') / 'gedit'
 pkgdatadir = get_option('prefix') / get_option('datadir') / 'gedit'
 glibdir = get_option('prefix') / get_option('datadir') / 'glib-2.0'
 
 # Subprojects
 if not get_option('buildtype').contains('plain')
   run_command('git', '-C', meson.source_root(), 'submodule', 'update', '--init', '--recursive')
 endif
 
 libgd_subproject = subproject(
   'libgd',
   default_options: [
     'with-tagged-entry=true',
     'static=true',
   ]
 )
 
 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 = [
   libgedit_public_deps,
   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))
 config_h.set_quoted('GETTEXT_PACKAGE', meson.project_name())
 config_h.set_quoted('LIBDIR', join_paths(get_option('prefix'), get_option('libdir')))
 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
 )
 
 subdir('data')
 subdir('po')
 subdir('gedit')
 subdir('plugins')
 
 if get_option('gtk_doc')
   subdir('docs/reference')
 endif
 
 if get_option('user_documentation')
   subdir('help')
 endif
 
 meson.add_install_script(
   'build-aux/meson/post_install.py',
   get_option('prefix') / get_option('libdir'),
   get_option('prefix') / get_option('datadir')
 )
 
 summary('API version', api_version)
 summary('Prefix', get_option('prefix'))
 summary('API documentation', get_option('gtk_doc'))
 summary('User documentation', get_option('user_documentation'))
 summary('Require all tests', get_option('require_all_tests'))
diff --git a/meson_options.txt b/meson_options.txt
index 4e842d1ea..33d03cb14 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,24 +1,31 @@
 option(
   'gtk_doc',
   type: 'boolean', value: false,
   description: 'Build API reference for plugins (requires gtk-doc)'
 )
 
 # If this option is kept to false, then it's an automatic behavior: if the
 # third party program is found, then the test is defined.
 # Setting this option to true will stop the configure phase with a hard error
 # if a third party program is not found and is required to define a test.
 option(
   'require_all_tests',
   type: 'boolean', value: false,
   description: 'Require that all tests can be run, even those that depend on third party programs'
 )
 
 # This option exists for the developers, to speed up the install.
 option(
   'user_documentation',
   type: 'boolean', value: true,
   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
@@ -135,67 +135,67 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
         self.provider.language_id = self.language_id
 
         SharedData().update_state(self.view.get_toplevel())
 
     def accelerator_activate(self, keyval, mod):
         if not self.view or not self.view.get_editable():
             return False
 
         accelerator = Gtk.accelerator_name(keyval, mod)
         snippets = Library().from_accelerator(accelerator, \
                 self.language_id)
 
         if len(snippets) == 0:
             return False
         elif len(snippets) == 1:
             self.apply_snippet(snippets[0])
         else:
             # Do the fancy completion dialog
             provider = completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)
             provider.set_proposals(snippets)
 
             cm = self.view.get_completion()
             cm.show([provider], cm.create_context(None))
 
         return True
 
     def first_snippet_inserted(self):
         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):
         buf = self.view.get_buffer()
 
         piter = buf.get_iter_at_mark(buf.get_insert())
         found = []
 
         for placeholder in self.placeholders:
             begin = placeholder.begin_iter()
             end = placeholder.end_iter()
 
             if piter.compare(begin) >= 0 and piter.compare(end) <= 0:
                 found.append(placeholder)
 
         if self.active_placeholder in found:
             return self.active_placeholder
         elif len(found) > 0:
             return found[0]
         else:
             return None
 
     def advance_placeholder(self, direction):
         # Returns (CurrentPlaceholder, NextPlaceholder), depending on direction
         buf = self.view.get_buffer()
 
         piter = buf.get_iter_at_mark(buf.get_insert())
         found = current = next = None
         length = len(self.placeholders)
 
@@ -532,87 +532,87 @@ class Document(GObject.Object, Gedit.ViewActivatable, Signals):
 
             for k in environ['noenc']:
                 env['noenc'][k] = environ['noenc'][k]
 
         buf = self.view.get_buffer()
         s = Snippet(snippet, env)
 
         if not start:
             start = buf.get_iter_at_mark(buf.get_insert())
 
         if not end:
             end = buf.get_iter_at_mark(buf.get_selection_bound())
 
         if start.equal(end) and self.uses_current_word(s):
             # There is no tab trigger and no selection and the snippet uses
             # the current word. Set start and end to the word boundary so that
             # it will be removed
             start, end = helper.buffer_word_boundary(buf)
         elif start.equal(end) and self.uses_current_line(s):
             # There is no tab trigger and no selection and the snippet uses
             # the current line. Set start and end to the line boundary so that
             # it will be removed
             start, end = helper.buffer_line_boundary(buf)
 
         # You know, we could be in an end placeholder
         (current, next) = self.next_placeholder()
         if current and current.__class__ == PlaceholderEnd:
             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()
 
         # Remove the tag, selection or current word
         buf.delete(start, end)
 
         # 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)
 
         # Put cursor at first tab placeholder
         keys = [x for x in sn.placeholders.keys() if x > 0]
 
         if len(keys) == 0:
             if 0 in sn.placeholders:
                 self.goto_placeholder(self.active_placeholder, sn.placeholders[0])
             else:
                 buf.place_cursor(sn.begin_iter())
         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
             # current cursor position out of view
             cur = buf.get_iter_at_mark(buf.get_insert())
             last = sn.end_iter()
 
             curloc = self.view.get_iter_location(cur)
             lastloc = self.view.get_iter_location(last)
 
             if (lastloc.y + lastloc.height) - curloc.y <= \
                self.view.get_visible_rect().height:
                 self.view.scroll_mark_onscreen(sn.end_mark)
 
         buf.end_user_action()
         self.view.grab_focus()
 
         return True
 
     def get_tab_tag(self, buf, end = None):
         if not end:
             end = buf.get_iter_at_mark(buf.get_insert())
 
         start = end.copy()
         word = None
         first = True
 
         # Move start backward as long as there is a valid character
         while start.backward_char():
             c = start.get_char()
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
@@ -3,62 +3,67 @@
  *
  * Copyright (C) 2002-2005 Paolo Maggi
  * Copyright (C) 2015-2016 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
  * the Free Software Foundation; either version 2, 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-spell-plugin.h"
 
 #include <glib/gi18n.h>
 #include <gedit/gedit-debug.h>
 #include <gedit/gedit-app.h>
 #include <gedit/gedit-window.h>
 #include <gedit/gedit-window-activatable.h>
 #include <gspell/gspell.h>
 #include <libpeas-gtk/peas-gtk-configurable.h>
 
 #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"
 #define SETTINGS_KEY_HIGHLIGHT_MISSPELLED "highlight-misspelled"
 
 static void gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface);
 static void peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface);
 
 struct _GeditSpellPluginPrivate
 {
 	GeditWindow *window;
 	GSettings   *settings;
 };
 
 enum
 {
 	PROP_0,
 	PROP_WINDOW
 };
 
 typedef struct _SpellConfigureWidget SpellConfigureWidget;
 
 struct _SpellConfigureWidget
 {
 	GtkWidget *content;
 	GtkWidget *highlight_button;
 
 	GSettings *settings;
 };
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2383549f4..dc6b1f9d7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,73 +1,79 @@
 # List of source files containing translatable strings.
 # Please keep this file sorted alphabetically.
 data/org.gnome.gedit.appdata.xml.in
 data/org.gnome.gedit.desktop.in
 data/org.gnome.gedit.gschema.xml.in
 gedit/gedit-app.c
 gedit/gedit-app-osx.m
 gedit/gedit.c
 gedit/gedit-close-confirmation-dialog.c
 gedit/gedit-commands-file.c
 gedit/gedit-commands-help.c
 gedit/gedit-commands-search.c
 gedit/gedit-debug.c
 gedit/gedit-document.c
 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
 gedit/gedit-tab-label.c
 gedit/gedit-utils.c
 gedit/gedit-view.c
 gedit/gedit-view-frame.c
 gedit/gedit-window.c
 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
 gedit/resources/ui/gedit-replace-dialog.ui
 gedit/resources/ui/gedit-shortcuts.ui
 gedit/resources/ui/gedit-tab-label.ui
 gedit/resources/ui/gedit-window.ui
 plugins/docinfo/docinfo.plugin.desktop.in
 plugins/docinfo/gedit-docinfo-plugin.c
 plugins/docinfo/resources/ui/gedit-docinfo-plugin.ui
 plugins/externaltools/data/build.desktop.in
 plugins/externaltools/data/open-terminal-here.desktop.in
 plugins/externaltools/data/open-terminal-here-osx.desktop.in
 plugins/externaltools/data/remove-trailing-spaces.desktop.in
 plugins/externaltools/data/run-command.desktop.in
 plugins/externaltools/data/send-to-fpaste.desktop.in
 plugins/externaltools/externaltools.plugin.desktop.in
 plugins/externaltools/org.gnome.gedit.plugins.externaltools.gschema.xml
 plugins/externaltools/tools/appactivatable.py
 plugins/externaltools/tools/capture.py
 plugins/externaltools/tools/functions.py
 plugins/externaltools/tools/__init__.py
 plugins/externaltools/tools/manager.py
 plugins/externaltools/tools/outputpanel.py
 plugins/externaltools/tools/outputpanel.ui
 plugins/externaltools/tools/tools.ui
 plugins/externaltools/tools/windowactivatable.py
 plugins/filebrowser/filebrowser.plugin.desktop.in
 plugins/filebrowser/gedit-file-bookmarks-store.c
 plugins/filebrowser/gedit-file-browser-plugin.c
-- 
2.31.1