diff --git a/.gitignore b/.gitignore index 4276918..ce6b5fb 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,4 @@ gedit-2.31.6.tar.bz2 /gedit-3.38.1.tar.xz /gedit-40.0.tar.xz /gedit-40.1.tar.xz +/gedit-41.alpha.tar.xz diff --git a/0001-deteplification-the-mega-commit.patch b/0001-deteplification-the-mega-commit.patch deleted file mode 100644 index bbb2adc..0000000 --- a/0001-deteplification-the-mega-commit.patch +++ /dev/null @@ -1,20206 +0,0 @@ -From b190bdb716fc8bb0cd515ee10fb3c51debede5fa Mon Sep 17 00:00:00 2001 -From: Zander Brown -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 @@ - - true - Automatic indent - Whether gedit should enable automatic indentation. - - - true - Display Line Numbers - Whether gedit should display line numbers in the editing area. - - - true - Highlight Current Line - Whether gedit should highlight the current line. - - - true - Highlight Matching Brackets - Whether gedit should highlight matching brackets. - - - false - Display Right Margin - Whether gedit should display the right margin in the editing area. - - - 80 - Right Margin Position - Specifies the position of the right margin. - -+ -+ false -+ Display Overview Map -+ Whether gedit should display the overview map for the document. -+ - - 'none' - Document background pattern type - Whether the document will get a background pattern painted. - - - - - - - - - 'after' - Smart Home End - 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. - - - true - Restore Previous Cursor Position - Whether gedit should restore the previous cursor position when a file is loaded. - - - true - Enable Syntax Highlighting - Whether gedit should enable syntax highlighting. - - - true - Enable Search Highlighting - Whether gedit should highlight all the occurrences of the searched text. -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 @@ - - - ]> - - - API Breaks - - - 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. - - - - 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 - index of deprecated symbols. - - -+ -+ 40 -> 41 -+ -+ -+ -+ The GeditProgressInfoBar class has been restored -+ -+ -+ -+ -+ GeditDocument is no longer a subclass -+ of TeplBuffer. -+ -+ -+ -+ -+ The GeditDocument::cursor-moved signal has been restored. -+ -+ -+ -+ -+ The GeditDocument:shortname property has been restored. -+ -+ -+ -+ -+ The gedit_document_is_untouched() function has been -+ restored. -+ -+ -+ -+ -+ The gedit_view_set_font() function has been restored. -+ -+ -+ -+ -+ DEBUG_METADATA has been restored. -+ -+ -+ -+ -+ The GBOOLEAN_TO_POINTER() and -+ GPOINTER_TO_BOOLEAN() macros have been restored to -+ gedit-utils.h. -+ -+ -+ -+ -+ - - 3.38 -> 40 - - - - All previously deprecated APIs have been removed. - - - - - The GeditProgressInfoBar class has been removed, you can - use TeplProgressInfoBar - instead. - - - - - GeditDocument is now a subclass - of TeplBuffer. - - - - - The GeditDocument::cursor-moved signal has been removed. - You can use the TeplBuffer API - instead. - - - - -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 @@ - - - - - gedit Reference Manual - - - - API Reference - - - - - - - - -+ - - - - - - - - - - - - - - Annexes - - - Object Hierarchy - - - - - - - Index of all symbols - - - - Index of deprecated symbols - - -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 - - 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 - - -
- gedit-commands - GeditCommands - 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 -
- -
- gedit-document - GeditDocument - 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 - - GEDIT_DOCUMENT - GEDIT_IS_DOCUMENT - GEDIT_TYPE_DOCUMENT - gedit_document_get_type - GEDIT_DOCUMENT_CLASS - GEDIT_IS_DOCUMENT_CLASS - GEDIT_DOCUMENT_GET_CLASS -
- -
- gedit-encodings-combo-box - GeditEncodingsComboBox - GeditEncodingsComboBox - gedit_encodings_combo_box_new - gedit_encodings_combo_box_get_selected_encoding - gedit_encodings_combo_box_set_selected_encoding - - 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 -
- -
- gedit-message - GeditMessage - 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 - - 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 -
- -+
-+gedit-progress-info-bar -+GeditProgressInfoBar -+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 -+ -+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 -+
-+ -
- gedit-statusbar - GeditStatusbar - GeditStatusbar - gedit_statusbar_new - gedit_statusbar_set_window_state - gedit_statusbar_set_overwrite - gedit_statusbar_clear_overwrite - gedit_statusbar_flash_message - - GEDIT_STATUSBAR - GEDIT_IS_STATUSBAR - GEDIT_TYPE_STATUSBAR - gedit_statusbar_get_type - GEDIT_STATUSBAR_CLASS - GEDIT_IS_STATUSBAR_CLASS - GEDIT_STATUSBAR_GET_CLASS -
- -
- gedit-tab - GeditTab - 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 - - 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 -
- -
- gedit-view - GeditViewPrivate - GeditView - 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 - - GEDIT_VIEW - GEDIT_IS_VIEW - GEDIT_TYPE_VIEW - gedit_view_get_type - GEDIT_VIEW_CLASS - GEDIT_IS_VIEW_CLASS - GEDIT_VIEW_GET_CLASS -
- -
- gedit-view-activatable - GeditViewActivatable - GeditViewActivatable - gedit_view_activatable_activate - gedit_view_activatable_deactivate - - 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 -
- -
- gedit-window - GeditWindow - GeditWindow - GeditWindowState -@@ -264,70 +294,76 @@ gedit_window_state_get_type - -
- gedit-window-activatable - GeditWindowActivatable - GeditWindowActivatable - gedit_window_activatable_activate - gedit_window_activatable_deactivate - gedit_window_activatable_update_state - - 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 -
- -
- gedit-debug - 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 - - GEDIT_TYPE_DEBUG_SECTION - gedit_debug_section_get_type -
- -
- gedit-menu-extension - GeditMenuExtension - gedit_menu_extension_new - gedit_menu_extension_append_menu_item - gedit_menu_extension_prepend_menu_item - gedit_menu_extension_remove_items - - 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 -
- -
- gedit-utils -+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 -
-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 - #include - #include - - #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 - - 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 - * - * 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 . - */ - - #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 . - */ - - #include "config.h" - - #include "gedit-app.h" - #include "gedit-app-private.h" - - #include - #include - #include - - #include -+#include - #include --#include -+#include - - #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", "N"); - add_accelerator (GTK_APPLICATION (application), "app.quit", "Q"); - add_accelerator (GTK_APPLICATION (application), "app.help", "F1"); - add_accelerator (GTK_APPLICATION (application), "app.shortcuts", "question"); - - add_accelerator (GTK_APPLICATION (application), "win.hamburger-menu", "F10"); - add_accelerator (GTK_APPLICATION (application), "win.open", "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 . - */ - - #include "config.h" - - #include "gedit-commands.h" - #include "gedit-commands-private.h" - - #include - - #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 . - */ - - #include "config.h" - - #include "gedit-commands.h" - #include "gedit-commands-private.h" - - #include --#include - - #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 . - */ - - #include "config.h" - - #include "gedit-commands.h" - #include "gedit-commands-private.h" - - #include - #include - #include --#include - - #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 . - */ - - #include "config.h" -+ - #include "gedit-commands.h" - #include "gedit-commands-private.h" --#include -+ -+#include -+ - #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 - - /** - * 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 GEDIT_DEBUG_PLUGINS - * environment variable enables all debugging output for the %GEDIT_DEBUG_PLUGINS - * section. Setting the special environment variable GEDIT_DEBUG - * 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 . - */ - - #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 . - */ - - #include "config.h" -+ - #include "gedit-document.h" - #include "gedit-document-private.h" -+ - #include - #include -+ -+#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: - * - * - * 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. - * - */ - 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. -+ * -+ * -+ * 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. -+ * -+ */ -+ 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 . - */ - - #ifndef GEDIT_DOCUMENT_H - #define GEDIT_DOCUMENT_H - --#include -+#include - - 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 - * - * 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 . - */ - - #include "config.h" - - #include "gedit-documents-panel.h" - - #include --#include - - #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 ("%s", 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 -- * -- * 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 . -- */ -- --#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 -- * -- * 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 . -- */ -- --#ifndef GEDIT_FACTORY_H --#define GEDIT_FACTORY_H -- --#include -- --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 . - */ - - #ifndef GEDIT_FILE_CHOOSER_DIALOG_GTK_H - #define GEDIT_FILE_CHOOSER_DIALOG_GTK_H - - #include - #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 . -+ */ -+ -+#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 . -+ */ -+ -+ -+#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 . -+ */ -+ -+#include "gedit-highlight-mode-selector.h" -+#include -+ -+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 . -+ */ -+ -+#ifndef GEDIT_HIGHLIGHT_MODE_SELECTOR_H -+#define GEDIT_HIGHLIGHT_MODE_SELECTOR_H -+ -+#include -+ -+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 . - */ - - /* - * Verbose error reporting for file I/O operations (load, save, revert, create) - */ - - #include "gedit-io-error-info-bar.h" -+ -+#include -+#include - #include --#include -+#include -+ - #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 ("%s", 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 ("%s", -+ 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 ("%s", 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 ("%s", - 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 ("%s", 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 ("%s", -+ 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 ("%s", 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 ("%s", -+ 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 . - */ - - #ifndef GEDIT_IO_ERROR_INFO_BAR_H - #define GEDIT_IO_ERROR_INFO_BAR_H - - #include - - 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 . -+ */ -+ -+#include "gedit-metadata-manager.h" -+#include -+#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 . -+ */ -+ -+#ifndef GEDIT_METADATA_MANAGER_H -+#define GEDIT_METADATA_MANAGER_H -+ -+#include -+ -+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 . -+ */ -+ -+#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 . -+ */ -+ -+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H -+#define GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H -+ -+#include "gedit-open-document-selector.h" -+ -+#include -+ -+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 . -+ */ -+ -+/* 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 -+ -+#include -+#include -+ -+#include -+#include -+ -+#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 . -+ */ -+ -+#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 -+#include -+ -+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 . -+ */ -+ -+#include "gedit-open-document-selector.h" -+#include "gedit-open-document-selector-store.h" -+#include "gedit-open-document-selector-helper.h" -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#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, ""); -+ } -+ 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 ("", -+ 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 . -+ */ -+ -+#ifndef GEDIT_OPEN_DOCUMENT_SELECTOR_H -+#define GEDIT_OPEN_DOCUMENT_SELECTOR_H -+ -+#include -+#include "gedit-window.h" -+ -+#include -+ -+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 -+ * -+ * 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 . -+ */ -+ -+#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 . -+ */ -+ -+#ifndef GEDIT_PANGO_H -+#define GEDIT_PANGO_H -+ -+#include -+ -+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 . - */ - - #include "config.h" - - #include "gedit-preferences-dialog.h" - -+#include -+#include -+#include -+ - #include - #include --#include -+#include - #include - -+#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 . - */ - - #include "gedit-print-job.h" - - #include --#include -+#include - - #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 . -+ */ -+ -+#include "gedit-progress-info-bar.h" -+#include -+ -+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 . -+ */ -+ -+#ifndef GEDIT_PROGRESS_INFO_BAR_H -+#define GEDIT_PROGRESS_INFO_BAR_H -+ -+#include -+ -+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 . -- */ -- --#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 . -- */ -- --#ifndef GEDIT_RECENT_OSX_H --#define GEDIT_RECENT_OSX_H -- --#include -- --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 . - */ - - #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 . - */ - - #ifndef GEDIT_RECENT_H - #define GEDIT_RECENT_H - - #include - #include - - 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 - #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 - - 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 . - */ - - #include "gedit-tab.h" - #include "gedit-tab-private.h" - - #include - #include --#include - - #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 ("%s", name); - - if (data->tab->state == GEDIT_TAB_STATE_REVERTING) - { - if (dirname != NULL) - { - dirname_markup = g_markup_printf_escaped ("%s", 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 ("%s", 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 ("%s", from); - - if (to != NULL) - { - to_markup = g_markup_printf_escaped ("%s", 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 ("%s", 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 . - */ - - #include "gedit-utils.h" - #include - #include --#include - #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 ' 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 ' */ -@@ -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 . - */ - - #ifndef GEDIT_UTILS_H - #define GEDIT_UTILS_H - - #include - - 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 -+ -+#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", ¤t_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 -+ -+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 - #include - #include - #include - -+#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 . - */ - - #ifndef GEDIT_VIEW_FRAME_H - #define GEDIT_VIEW_FRAME_H - - #include - #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 . - */ - - #include "gedit-view.h" - #include - #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 . - */ - - #ifndef GEDIT_VIEW_H - #define GEDIT_VIEW_H - -+#include -+ - #include --#include -+#include - - 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 . - */ - - #ifndef GEDIT_WINDOW_PRIVATE_H - #define GEDIT_WINDOW_PRIVATE_H - - #include - - #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 . - */ - - #include "config.h" - - #include "gedit-window.h" - - #include - #include - #include - - #include - #include --#include - - #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 . - */ - - #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 - #include - #include --#include - - #include "gedit-dirs.h" - #include "gedit-debug.h" --#include "gedit-factory.h" - #include "gedit-settings.h" - - #ifdef G_OS_WIN32 - #include - 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 @@ - - - - gtk/menus.ui - gtk/menus-common.ui - ui/gedit-encodings-dialog.ui - ui/gedit-preferences-dialog.ui - ui/gedit-replace-dialog.ui - ui/gedit-print-preview.ui - ui/gedit-print-preferences.ui -+ ui/gedit-progress-info-bar.ui - ui/gedit-status-menu-button.ui - ui/gedit-tab-label.ui - ui/gedit-view-frame.ui -+ ui/gedit-highlight-mode-dialog.ui -+ ui/gedit-highlight-mode-selector.ui - ui/gedit-window.ui -+ ui/gedit-open-document-selector.ui - ui/gedit-shortcuts.ui - ui/gedit-statusbar.ui - css/gedit-style.css - css/gedit.adwaita.css - css/gedit.highcontrast.css - - @OS_DEPENDENT_RESOURCE_FILES@ - - -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 @@ -+ -+ -+ -+ -+ -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 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ liststore -+ -+ -+ -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 @@ -+ -+ -+ -+ -+ -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 @@ - 1 - True - True - - - 0 - 0 - - - - - 1 - 1 - - - - - Display _statusbar - True - True - False - True - True - - - 0 - 2 - 2 - - -+ -+ -+ Display _overview map -+ True -+ True -+ False -+ True -+ True -+ -+ -+ 0 -+ 3 -+ 2 -+ -+ - - - Display _grid pattern - True - True - False - True - True - - - 0 -- 3 -+ 4 - 2 - - - - - 0 - 0 - - - - - True - False - 6 - - - True - False - 0 - Text Wrapping - - - - - - 0 - 0 - - - -@@ -603,62 +618,73 @@ - - - - True - False - True - True - 6 - - - True - False - 0 - Color Scheme - - - - - - 0 - 0 - - - - - True - False - True - True - -- -+ - True -+ True -+ True -+ True -+ etched-in -+ 200 -+ -+ -+ True -+ True -+ -+ - - - 0 - 0 - - - - - True - False - icons - 1 - - - True - False - True - Install scheme - Install scheme - Install Scheme - True - list-add-symbolic - - - False - True - - - - -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 @@ -+ -+ -+ -+ -+ -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 @@ - - - -