From 4cd7cf8c80164d79e95da375c7e153a8b01233b6 Mon Sep 17 00:00:00 2001 From: Paolo Borelli Date: Mon, 12 Dec 2005 17:28:04 +0000 Subject: [PATCH] The. Big. Merge. --- .cvsignore | 6 + ChangeLog | 1790 +------ ChangeLog-20051212 | 1754 +++++++ Makefile.am | 3 +- NEWS | 246 +- README | 20 +- autogen.sh | 6 +- bindings/.cvsignore | 2 + bindings/Makefile.am | 5 + bindings/python/.cvsignore | 4 + bindings/python/Makefile.am | 61 + bindings/python/gedit.defs | 808 +++ bindings/python/gedit.override | 199 + configure.ac | 330 ++ data/GNOME_Gedit.server.in.in | 41 - data/Makefile.am | 14 +- data/gedit.schemas.in | 41 +- gedit/{ChangeLog => ChangeLog-20051212} | 0 gedit/Makefile.am | 199 +- gedit/bacon-message-connection.c | 365 ++ gedit/bacon-message-connection.h | 44 + gedit/dialogs/Makefile.am | 47 +- .../dialogs/gedit-close-confirmation-dialog.c | 343 +- .../dialogs/gedit-close-confirmation-dialog.h | 15 +- gedit/dialogs/gedit-encodings-dialog.c | 445 +- gedit/dialogs/gedit-encodings-dialog.glade | 278 + gedit/dialogs/gedit-encodings-dialog.h | 59 +- gedit/dialogs/gedit-open-location-dialog.c | 251 + .../dialogs/gedit-open-location-dialog.glade | 208 + gedit/dialogs/gedit-open-location-dialog.h | 96 + gedit/dialogs/gedit-page-setup-dialog.c | 547 +- gedit/dialogs/gedit-page-setup-dialog.glade | 654 +++ gedit/dialogs/gedit-page-setup-dialog.h | 56 +- gedit/dialogs/gedit-preferences-dialog.c | 997 ++-- gedit/dialogs/gedit-preferences-dialog.glade | 2360 +++++++++ gedit/dialogs/gedit-preferences-dialog.h | 55 +- gedit/dialogs/gedit-search-dialog.c | 499 ++ gedit/dialogs/gedit-search-dialog.glade | 334 ++ gedit/dialogs/gedit-search-dialog.h | 122 + gedit/gedit-app.c | 376 ++ gedit/gedit-app.h | 105 + gedit/gedit-commands-documents.c | 63 + gedit/gedit-commands-edit.c | 174 + gedit/gedit-commands-file-print.c | 191 + gedit/gedit-commands-file.c | 1721 +++++++ gedit/gedit-commands-help.c | 103 + gedit/gedit-commands-search.c | 727 +++ gedit/gedit-commands-view.c | 93 + gedit/gedit-commands.h | 132 +- gedit/gedit-convert.c | 157 +- gedit/gedit-convert.h | 5 +- gedit/gedit-debug.c | 91 +- gedit/gedit-debug.h | 52 +- gedit/gedit-document-loader.c | 1045 ++++ gedit/gedit-document-loader.h | 119 + gedit/gedit-document-saver.c | 1299 +++++ gedit/gedit-document-saver.h | 117 + gedit/gedit-document.c | 3454 ++++--------- gedit/gedit-document.h | 327 +- gedit/gedit-documents-panel.c | 672 +++ gedit/gedit-documents-panel.h | 86 + gedit/gedit-encodings-option-menu.c | 183 +- gedit/gedit-encodings-option-menu.h | 8 +- gedit/gedit-encodings.c | 69 +- gedit/gedit-encodings.h | 20 +- gedit/gedit-file-chooser-dialog.c | 279 + gedit/gedit-file-chooser-dialog.h | 82 + gedit/gedit-help.c | 84 + gedit/gedit-help.h | 44 + gedit/gedit-io-error-message-area.c | 1302 +++++ gedit/gedit-io-error-message-area.h | 77 + gedit/gedit-languages-manager.c | 16 +- gedit/gedit-languages-manager.h | 17 +- gedit/gedit-marshal.list | 5 +- gedit/gedit-mdi-child.c | 50 +- gedit/gedit-mdi.c | 88 +- gedit/gedit-message-area.c | 538 ++ gedit/gedit-message-area.h | 130 + gedit/gedit-metadata-manager.c | 30 +- gedit/gedit-module.c | 220 + gedit/gedit-module.h | 65 + gedit/gedit-notebook.c | 1100 ++++ gedit/gedit-notebook.h | 143 + gedit/gedit-output-window.c | 5 +- gedit/gedit-panel.c | 703 +++ gedit/gedit-panel.h | 107 + gedit/gedit-plugin-manager.c | 579 +++ gedit/gedit-plugin-manager.h | 85 + gedit/gedit-plugin.c | 92 +- gedit/gedit-plugin.h | 173 +- gedit/gedit-plugins-engine.c | 726 +-- gedit/gedit-plugins-engine.h | 46 +- gedit/gedit-prefs-manager-app.c | 724 +-- gedit/gedit-prefs-manager-app.h | 21 +- gedit/gedit-prefs-manager.c | 148 +- gedit/gedit-prefs-manager.h | 33 + gedit/gedit-print-job-preview.c | 1252 +++++ gedit/gedit-print-job-preview.h | 81 + gedit/gedit-print.c | 564 +-- gedit/gedit-print.h | 60 +- gedit/gedit-progress-message-area.c | 242 + gedit/gedit-progress-message-area.h | 101 + gedit/gedit-python-module.c | 304 ++ gedit/gedit-python-module.h | 61 + gedit/gedit-python-plugin.c | 149 + gedit/gedit-python-plugin.h | 50 + gedit/gedit-recent.c | 17 +- gedit/gedit-recent.h | 46 +- gedit/gedit-session.c | 745 ++- gedit/gedit-session.h | 25 +- gedit/gedit-spinner.c | 828 +++ gedit/gedit-spinner.h | 96 + gedit/gedit-statusbar.c | 415 ++ gedit/gedit-statusbar.h | 99 + gedit/gedit-tab.c | 1979 ++++++++ gedit/gedit-tab.h | 149 + gedit/gedit-tooltips.c | 44 +- gedit/gedit-tooltips.h | 11 +- gedit/gedit-ui.h | 152 + gedit/gedit-ui.xml | 502 +- gedit/gedit-utils.c | 540 +- gedit/gedit-utils.h | 103 +- gedit/gedit-view.c | 1650 ++++-- gedit/gedit-view.h | 112 +- gedit/gedit-window-private.h | 93 + gedit/gedit-window.c | 3105 ++++++++++++ gedit/gedit-window.h | 180 + gedit/gedit.c | 547 ++ gedit/recent-files/Makefile.am | 4 +- gedit/recent-files/egg-recent-model.c | 112 +- gedit/recent-files/egg-recent-util.c | 5 + gedit/recent-files/egg-recent-view-gtk.c | 2 + .../recent-files/egg-recent-view-uimanager.c | 884 ++++ .../recent-files/egg-recent-view-uimanager.h | 63 + gedit/sexy-icon-entry.c | 921 ++++ gedit/sexy-icon-entry.h | 101 + gedit/update-from-bacon.sh | 25 + m4/.cvsignore | 1 + m4/python.m4 | 62 + plugins/{ChangeLog => ChangeLog-20051212} | 0 plugins/Makefile.am | 12 +- plugins/changecase/Makefile.am | 18 +- .../changecase.gedit-plugin.desktop.in | 8 +- plugins/changecase/gedit-changecase-plugin.c | 386 ++ plugins/changecase/gedit-changecase-plugin.h | 72 + plugins/docinfo/Makefile.am | 9 +- .../docinfo/docinfo.gedit-plugin.desktop.in | 8 +- plugins/docinfo/docinfo.glade2 | 403 +- plugins/docinfo/gedit-docinfo-plugin.c | 555 ++ plugins/docinfo/gedit-docinfo-plugin.h | 75 + plugins/indent/Makefile.am | 16 +- plugins/indent/gedit-indent-plugin.c | 323 ++ plugins/indent/gedit-indent-plugin.h | 75 + plugins/indent/indent.gedit-plugin.desktop.in | 8 +- plugins/pythonconsole/.cvsignore | 3 + plugins/pythonconsole/Makefile.am | 14 + .../pythonconsole.gedit-plugin.desktop.in | 9 + plugins/pythonconsole/pythonconsole.py | 327 ++ plugins/sample/Makefile.am | 13 +- plugins/sample/gedit-sample-plugin.c | 257 + plugins/sample/gedit-sample-plugin.h | 78 + plugins/sample/sample.gedit-plugin.desktop.in | 8 +- plugins/savecopy/savecopy.c | 11 +- plugins/shell_output/shell_output.c | 51 +- plugins/sort/Makefile.am | 9 +- plugins/sort/gedit-sort-plugin.c | 545 ++ plugins/sort/gedit-sort-plugin.h | 73 + plugins/sort/sort.gedit-plugin.desktop.in | 8 +- plugins/sort/sort.glade2 | 33 +- plugins/spell/Makefile.am | 7 +- plugins/spell/gedit-automatic-spell-checker.c | 23 +- plugins/spell/gedit-spell-language-dialog.c | 52 +- plugins/spell/gedit-spell-plugin.c | 979 ++++ plugins/spell/gedit-spell-plugin.h | 75 + plugins/spell/spell.gedit-plugin.desktop.in | 9 +- plugins/taglist/Makefile.am | 8 +- plugins/taglist/gedit-taglist-plugin-panel.c | 578 +++ plugins/taglist/gedit-taglist-plugin-panel.h | 88 + plugins/taglist/gedit-taglist-plugin-parser.c | 61 +- plugins/taglist/gedit-taglist-plugin-parser.h | 43 +- plugins/taglist/gedit-taglist-plugin.c | 256 +- plugins/taglist/gedit-taglist-plugin.h | 81 +- .../taglist/taglist.gedit-plugin.desktop.in | 8 +- plugins/time/Makefile.am | 21 +- plugins/time/gedit-time-plugin.c | 1248 +++++ plugins/time/gedit-time-plugin.h | 78 + plugins/time/time.gedit-plugin.desktop.in | 8 +- plugins/time/time.glade2 | 4 +- po/ChangeLog | 4492 ----------------- po/ChangeLog-20051212 | 4492 +++++++++++++++++ po/POTFILES.in | 87 +- tools/generate-plugin.py | 124 + tools/plugin_template/Makefile.am | 34 + tools/plugin_template/gedit-xyz-plugin.c | 108 + tools/plugin_template/gedit-xyz-plugin.h | 78 + .../xyz.gedit-plugin.desktop.in | 8 + 196 files changed, 51733 insertions(+), 13611 deletions(-) create mode 100644 ChangeLog-20051212 create mode 100644 bindings/.cvsignore create mode 100644 bindings/Makefile.am create mode 100644 bindings/python/.cvsignore create mode 100644 bindings/python/Makefile.am create mode 100644 bindings/python/gedit.defs create mode 100644 bindings/python/gedit.override create mode 100644 configure.ac delete mode 100644 data/GNOME_Gedit.server.in.in rename gedit/{ChangeLog => ChangeLog-20051212} (100%) create mode 100644 gedit/bacon-message-connection.c create mode 100644 gedit/bacon-message-connection.h create mode 100644 gedit/dialogs/gedit-encodings-dialog.glade create mode 100644 gedit/dialogs/gedit-open-location-dialog.c create mode 100644 gedit/dialogs/gedit-open-location-dialog.glade create mode 100644 gedit/dialogs/gedit-open-location-dialog.h create mode 100644 gedit/dialogs/gedit-page-setup-dialog.glade create mode 100644 gedit/dialogs/gedit-preferences-dialog.glade create mode 100644 gedit/dialogs/gedit-search-dialog.c create mode 100644 gedit/dialogs/gedit-search-dialog.glade create mode 100644 gedit/dialogs/gedit-search-dialog.h create mode 100644 gedit/gedit-app.c create mode 100644 gedit/gedit-app.h create mode 100644 gedit/gedit-commands-documents.c create mode 100644 gedit/gedit-commands-edit.c create mode 100644 gedit/gedit-commands-file-print.c create mode 100644 gedit/gedit-commands-file.c create mode 100644 gedit/gedit-commands-help.c create mode 100644 gedit/gedit-commands-search.c create mode 100644 gedit/gedit-commands-view.c create mode 100644 gedit/gedit-document-loader.c create mode 100644 gedit/gedit-document-loader.h create mode 100644 gedit/gedit-document-saver.c create mode 100644 gedit/gedit-document-saver.h create mode 100644 gedit/gedit-documents-panel.c create mode 100644 gedit/gedit-documents-panel.h create mode 100644 gedit/gedit-file-chooser-dialog.c create mode 100644 gedit/gedit-file-chooser-dialog.h create mode 100644 gedit/gedit-help.c create mode 100644 gedit/gedit-help.h create mode 100644 gedit/gedit-io-error-message-area.c create mode 100644 gedit/gedit-io-error-message-area.h create mode 100644 gedit/gedit-message-area.c create mode 100644 gedit/gedit-message-area.h create mode 100644 gedit/gedit-module.c create mode 100644 gedit/gedit-module.h create mode 100644 gedit/gedit-notebook.c create mode 100644 gedit/gedit-notebook.h create mode 100644 gedit/gedit-panel.c create mode 100644 gedit/gedit-panel.h create mode 100644 gedit/gedit-plugin-manager.c create mode 100644 gedit/gedit-plugin-manager.h create mode 100644 gedit/gedit-print-job-preview.c create mode 100644 gedit/gedit-print-job-preview.h create mode 100644 gedit/gedit-progress-message-area.c create mode 100644 gedit/gedit-progress-message-area.h create mode 100644 gedit/gedit-python-module.c create mode 100644 gedit/gedit-python-module.h create mode 100644 gedit/gedit-python-plugin.c create mode 100644 gedit/gedit-python-plugin.h create mode 100644 gedit/gedit-spinner.c create mode 100644 gedit/gedit-spinner.h create mode 100644 gedit/gedit-statusbar.c create mode 100644 gedit/gedit-statusbar.h create mode 100644 gedit/gedit-tab.c create mode 100644 gedit/gedit-tab.h create mode 100644 gedit/gedit-ui.h create mode 100644 gedit/gedit-window-private.h create mode 100644 gedit/gedit-window.c create mode 100644 gedit/gedit-window.h create mode 100644 gedit/gedit.c create mode 100644 gedit/recent-files/egg-recent-view-uimanager.c create mode 100644 gedit/recent-files/egg-recent-view-uimanager.h create mode 100644 gedit/sexy-icon-entry.c create mode 100644 gedit/sexy-icon-entry.h create mode 100644 gedit/update-from-bacon.sh create mode 100644 m4/.cvsignore create mode 100644 m4/python.m4 rename plugins/{ChangeLog => ChangeLog-20051212} (100%) create mode 100644 plugins/changecase/gedit-changecase-plugin.c create mode 100644 plugins/changecase/gedit-changecase-plugin.h create mode 100644 plugins/docinfo/gedit-docinfo-plugin.c create mode 100644 plugins/docinfo/gedit-docinfo-plugin.h create mode 100644 plugins/indent/gedit-indent-plugin.c create mode 100644 plugins/indent/gedit-indent-plugin.h create mode 100644 plugins/pythonconsole/.cvsignore create mode 100644 plugins/pythonconsole/Makefile.am create mode 100644 plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in create mode 100644 plugins/pythonconsole/pythonconsole.py create mode 100644 plugins/sample/gedit-sample-plugin.c create mode 100644 plugins/sample/gedit-sample-plugin.h create mode 100644 plugins/sort/gedit-sort-plugin.c create mode 100644 plugins/sort/gedit-sort-plugin.h create mode 100644 plugins/spell/gedit-spell-plugin.c create mode 100644 plugins/spell/gedit-spell-plugin.h create mode 100644 plugins/taglist/gedit-taglist-plugin-panel.c create mode 100644 plugins/taglist/gedit-taglist-plugin-panel.h create mode 100644 plugins/time/gedit-time-plugin.c create mode 100644 plugins/time/gedit-time-plugin.h create mode 100644 po/ChangeLog-20051212 create mode 100755 tools/generate-plugin.py create mode 100644 tools/plugin_template/Makefile.am create mode 100644 tools/plugin_template/gedit-xyz-plugin.c create mode 100644 tools/plugin_template/gedit-xyz-plugin.h create mode 100644 tools/plugin_template/xyz.gedit-plugin.desktop.in diff --git a/.cvsignore b/.cvsignore index e295c323..515b53a7 100644 --- a/.cvsignore +++ b/.cvsignore @@ -41,3 +41,9 @@ intltool-update omf.make xmldocs.make +compile +depcomp +intltool-extract.in +intltool-merge.in +intltool-update.in +py-compile diff --git a/ChangeLog b/ChangeLog index ca10e5d8..7738a541 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,1754 +1,36 @@ -==== gedit 2.12.1 ==== - -2005-10-03 Paolo Borelli - - * NEWS: - * README: - * configure.in 2.12.1 released. - -2005-09-11 Paolo Borelli - - * configure.in: readd ku. - -2005-09-11 Paolo Borelli - - * configure.in: temporarely remove the ku translation since - Erdal forgot to cvs add it. - -==== gedit 2.12.0 ==== - -2005-09-10 Erdal Ronahi - - * po/ku.po: Added Kurdish translation - -2005-09-05 Paolo Borelli - - * NEWS: - * README: - * configure.in 2.12.0 released. - -==== gedit 2.11.93 ==== - -2005-08-29 Paolo Borelli - - * NEWS: - * README: - * configure.in 2.11.93 released. - -==== gedit 2.11.92 ==== - -2005-08-23 Paolo Borelli - - * NEWS: - * README: - * configure.in 2.11.92 released. - -==== gedit 2.11.91 ==== - -2005-08-08 Paolo Borelli - - * NEWS: - * README: - * configure.in 2.11.91 released. - -2005-08-05 Paolo Maggi - - Fixed bug #101281: [ui-review] Undo preference dialog - - * data/gedit.schemas.in: deprecated key - /schemas/apps/gedit-2/preferences/editor/undo/undo_actions_limits and - added new key .../undo/max_undo_actions - -2005-08-04 Paolo Maggi - - Fixed bug #168965: Grammatical error in message - - * data/gedit.schemas.in: fixed message. - Patch by Guillaume Desmottes - -==== gedit 2.10.4 ==== - -2005-08-04 Paolo Maggi - - * NEWS: - * README: - * configure.in: 2.10.4 released - -==== gedit 2.10.3 ==== - -2005-06-08 Paolo Borelli - - * README: - * configure.in 2.10.3 released. - -2005-04-08 Sunil Mohan Adapa - - * configure.in: Added "te" to ALL_LINGUAS. - -==== gedit 2.10.2 ==== - -2005-04-04 Paolo Borelli - - * README: - * configure.in 2.10.2 released. - -2005-03-31 Steve Murphy - - * configure.in: Added "rw" to ALL_LINGUAS. - -==== gedit 2.10.1 ==== - -2005-03-25 Paolo Borelli - - * README: - * configure.in 2.10.1 released. - -2005-03-22 Adi Attar - - * configure.in: Added 'xh' to ALL_LINGUAS. - -==== gedit 2.10.0 ==== - -2005-03-08 Paolo Borelli - - * README: - * configure.in: 2.10.0 released. - -==== gedit 2.9.7 ==== - -2005-03-01 Paolo Maggi - - * README: - * NEWS: 2.9.7 released. - -2005-02-20 Paolo Maggi - - * data/gedit.1: updated - -2005-02-13 Paolo Maggi - - * data/gedit.schemas.in: fixed bug #167060 (gedit schema messages - need translator comments) - -==== gedit 2.9.6 ==== - -2005-02-07 Paolo Borelli - - * README: - * NEWS: 2.9.6 released. - -2005-02-04 Paolo Maggi - - * data/gedit.schemas.in: added savecopy to the list of default - plugins. - -==== gedit 2.9.5 ==== - -==== gedit 2.9.4 ==== - -2005-01-11 Paolo Maggi - - * configure.in: version 2.9.4 - - * README: updated - -2005-01-10 Paolo Maggi - - Based on a patch by Juerg Billeter - - * data/gedit.schemas.in: added editor/bracket_matching/bracket_matching - -2005-01-10 Paolo Maggi - - * configure.in: set GEDIT_MAJOR to 2.10 - -2005-01-08 Paolo Maggi - - * configure.in: requires GtkSourceView >= 1.1.90 - - * data/gedit.schemas.in: added editor/current_line/highlight_current_line - key - -2004-12-07 Paolo Maggi - - * configure.in: show message-of-doom, remove redundant check for - ngettext, since AM_GLIB_GNU_GETTEXT already checks for it (in both - libc and libintl). - -2004-12-05 Paolo Maggi - - * data/gedit.schemas.in: fixed bug #147664 (Please add translator - comments to gedit schema messages). - -2004-11-29 Paolo Borelli - - * README: - * NEWS: 2.9.2 released. - -2004-11-29 Paolo Borelli - - * data/gedit.desktop.in.in: use @VERSION@ for bug-buddy reports - * configure.in: modify for the above change and update for 2.9.2 - -2004-11-11 Paolo Borelli - - * configure.in: bump glib and gtk+ requirements. - -2004-11-09 Paolo Maggi - - * data/gedit.schemas.in: added new keys - /schemas/apps/gedit-2/preferences/print/fonts/print_font_body_pango, - /schemas/apps/gedit-2/preferences/print/fonts/print_font_header_pango and - /schemas/apps/gedit-2/preferences/print/fonts/print_font_numbers_pango. Patch - by Owen Taylor - -2004-11-01 Paolo Maggi - - * configure.in: removed version number from GETTEXT_PACKAGE (fixes - bug #149988: Is gedit potfile versioning needed?) - -2004-11-01 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.9.1 - -2004-10-31 Paolo Maggi - - * configure.in: set version to 2.9.0 - - * data/gedit.schemas.in: added - /schemas/apps/gedit-2/plugins/active-plugins key - -2004-10-15 Marco Pesenti Gritti - - reviewed by: Paolo Borelli - - * gedit/dialogs/gedit-encodings-dialog.c: (update_list), - (gedit_encodings_dialog_run): - - Fix trivial compile issue - -2004-10-13 Paolo Borelli - - * Makefile.am: - * configure.in: - * viewer/*.c: removed the nautilus view. - -2004-10-11 Paolo Borelli - - * Makefile.am: fix distcheck with latest gnome-common. - -2004-10-10 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.8.1 - -2004-09-14 Gora Mohanty - - * configure.in: Added 'or' to ALL_LINGUAS. - -2004-09-13 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.8.0 - -2004-08-30 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.7.92 - -2004-08-30 Paolo Borelli - - * HACKING: put patches in bugzilla - * AUTHORS: update email adresses - * MAINTAINERS: ditto - * Makefile.am: distribute MAINTAINERS - -2004-08-29 Akagic Amila - - * configure.in: Added 'bs' to ALL_LINGUAS. - -2004-08-24 Breda McColgan - - * help/C/gedit.xml: Updated for GNOME 2.8, technical review draft - * help/C/gedit-C.omf: Updated for GNOME 2.8 - * help/C/l10n.txt: Updated for GNOME 2.8 - -2004-08-16 Kjartan Maraas - - * configure.in: Added nb to ALL_LINGUAS. - -2004-08-16 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.7.91 - -2004-08-05 Paolo Borelli - - * configure.in: bump required intltool to 0.31 as - suggested by Owen Taylor in bug #149219 - -2004-08-01 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.7.90 - -2004-07-21 Ray Strode - * gedit/data/gedit.desktop.in: Add MimeType line to desktop file - new mime sytem. - -2004-07-19 Paolo Maggi - - * .cvsignore: added omf.make and xmldocs.make - -2004-07-19 Paolo Maggi - - * help/eu/.cvsignore: added - -2004-07-16 Paolo Borelli - - * data/gedit.1: document --encoding. - -2004-07-13 Paolo Borelli - - * data/gedit.1: small updates to man page. - -2004-07-05 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.7.1 - -2004-06-25 Paolo Borelli - - * merge gnome-2-6 branch fixes into HEAD. - -2004-06-25 Paolo Borelli - - * configure.in: - * README: - * NEWS: release 2.6.2 - -2004-05-29 Christian Rose - - * configure.in: Added "tk" to ALL_LINGUAS. - -2004-05-26 Mohammad DAMT - - * po/id.po: Added Indonesian translation done by Ahmad Riza H Nst - * configure.in: Added id to ALL_LINGUAS - -2004-05-05 Frederic Crozat - - * gedit/recent-files/egg-recent-item.c: (egg_recent_item_new), - (egg_recent_item_set_private), (egg_recent_item_get_private): - * gedit/recent-files/egg-recent-item.h: - * gedit/recent-files/egg-recent-util.c: (egg_recent_util_get_icon): - * gedit/recent-files/egg-recent-view.h: - Resync recent-files with latest libegg version, so it doesn't - complain when icon theme is not set. - -2002-05-08 Pablo Saratxaga - - * help/eu: Added Basque help files - -2004-04-09 Guntupalli Karunakar - - * configure.in: Added "gu" (Gujarati) to ALL_LINGUAS. - -2004-04-05 Paolo Maggi - - * data/gedit.schemas.in: fixed bug #138508 (default values - in gedit.schemas are not gettexized). Thanks to Takao Fujiwara - and Mark McLoughlin - -2004-04-05 Paolo Maggi - - * data/gedit.keys.in: bug #106911 fixed. The file contains - the right keys now. - -2004-04-05 Paolo Borelli - - * configure.in: add changecase plugin to the build. - -2004-04-03 Samúel Jón Gunnarsson - - is.po: Added "is" to ALL_LINGUAS - -2004-03-31 Christian Rose - - * configure.in: Added "af" to ALL_LINGUAS. - -2004-03-22 Paolo Borelli - - * configure.in: - * README: bump version to 2.6.0 - - * NEWS: updated - -2004-03-19 Gareth Owen - - * configure.in: Added en_GB to ALL_LINGUAS - -2004-03-18 Guntupalli Karunakar - - * configure.in: Added "mr" for Marathi to ALL_LINGUAS. - -2004-03-17 Glynn Foster - - * help/*: Add back localized documentation from Sun's translation - team for de, es, fr, it, ja, ko, sv, zh_CN, zh_HK and zh_TW. - -2004-03-16 Paolo Borelli - - * configure.in: - * README: bump version to 2.5.92 - - * NEWS: updated - -2004-03-14 Thomas Vander Stichele - - * configure.in: use ACLOCAL_AMFLAGS to make maintainer builds work - -2004-03-08 Paolo Maggi - - * configure.in: - * README: bump version to 2.5.91 - - * NEWS: updated - -2004-03-04 Guntupalli Karunakar - - * configure.in: Added "pa" for Punjabi in ALL_LINGUAS. - -2004-03-04 Glynn Foster - - * pixmaps/Makefile.am: Don't list pixmaps in SOURCES. Fixes #135824. - -2004-03-01 Breda McColgan - - * help/C/gedit.xml: Updated for GNOME 2.6, technical review draft - * help/C/gedit-C.omf: Updated for GNOME 2.6 - * help/C/l10n.txt: Updated for GNOME 2.6 - * help/C/figures/gedit_window.png: Updated for GNOME 2.6 - * help/C/figures/gedit_format_bold.png: Added for GNOME 2.6 - * help/C/figures/gedit_format_italic.png: Added for GNOME 2.6 - * help/C/figures/gedit_format_strikethrough.png: Added for GNOME 2.6 - * help/C/figures/gedit_format_underline.png: Added for GNOME 2.6 - -2004-02-25 Paolo Maggi - - * AUTHORS: added Paolo Borelli - -2004-02-24 Paolo Maggi - - [ gedit 2.5.90 released ] - -2004-02-24 Paolo Maggi - - * configure.in: requires gtksourceview 0.9, sets version - to 2.5.90 - - * README: bump version to 2.5.90 - - * NEWS: updated - -2004-02-23 Padraig O'Briain - - * gedit/dialogs/gedit-close-confirmation-dialog.c - (gedit_close_confirmation_dialog_init): Set role to ATK_ROLE_ALERT. - Fixes bug #135000. - -2004-02-21 Christian Rose - - * configure.in: Added "en_CA" to ALL_LINGUAS. - -2004-02-15 Tomasz Kłoczko - - * configure.in: Trivial cleanup: remove AC_SUBST(CFLAGS), - AC_SUBST(CPPFLAGS) and AC_SUBST(LDFLAGS). This variables are - substed by default. - -2004-02-12 Paolo Maggi - - * data/gedit.schemas.in: removed unused key - schemas/apps/gedit-2/preferences/editor/save/save_encoding - -2004-02-09 Alexander Winston - - * acinclude.m4: Quoted definitions of macros - AM_PATH_PROG_WITH_TEST, AM_LC_MESSAGES, AM_WITH_NLS, and - AM_GNU_GETTEXT. Fixes #133178. - -2004-02-06 Mark McLoughlin - - * configure.in: add a --enable-deprecations flag - to switch on the DISABLE_DEPRECATED cflags. Also - re-use the gnome-common --enable-compile-warnings - impl. which doesn't touch CFLAGS. - -2004-01-27 Christian Rose - - * configure.in: Added "mi" to ALL_LINGUAS. - -2004-01-15 Paolo Maggi - - [ gedit 2.5.3 released ] - -2004-01-15 Paolo Maggi - - * configure.in: requires intltool 0.29, sets version - to 2.5.3 - - * README: bump version to 2.5.3 - - * NEWS: updated - - * Makefile.am: Removed OrigTree.pm to EXTRA_DIST - -2004-01-06 Paolo Maggi - - * TODO: Updated - -2004-01-03 Paolo Maggi - - * configure.in: bump version to 2.5.2 - - * README: bump version to 2.5.2 - -2004-01-03 Robert Sedak - - * configure.in: Added "hr" in ALL_LINGUAS. - -2003-12-29 Paolo Maggi - - * Makefile.am: Added OrigTree.pm to EXTRA_DIST. - - * configure.in: requires intltool 0.28 - -2003-12-29 Paolo Maggi - - * data/gedit.1: removed an unknown macro in man page - (fixed bug #127693). - - * configure.in: check for the ngettext function - -2003-11-24 Paolo Maggi - - [ gedit 2.5.0 released ] - -2003-10-21 Paolo Maggi - - * data/Makefile.am: don't distribute generated files (fixes - bug #103846) - -2003-10-20 Paolo Maggi - - * configure.in: bump version to 2.5.0, set - GEDIT_MAJOR to 2.6 and GETTEXT_PACKAGE to gedit-2.6, - updated requirements - -2003-09-18 Paolo Maggi - - * TODO: Updated - - * configure.in: show message-of-doom - - * message-of-doom: updated - - * data/gedit.schemas.in: added the following keys: - display_right_margin, right_margin_position and - syntax_highlighting/enable - -2003-09-09 Paolo Maggi - - [ gedit 2.4.0 released ] - -2003-09-09 Paolo Maggi - - * configure.in: bump version to 2.4.0 - - * README: bump version to 2.4.0, updated requirements - -2003-09-06 Laurent Dhima - - * configure.in: Added "sq" to ALL_LINGUAS. - -2003-09-05 Irene Ryan - - * help/C/gedit.xml: updated the Help to reflect gedit 2.2.2 for GNOME - 2.4 release - * help/C/gedit-C.omf: updated the manual version/release information - * help/C/l10n.txt: updated instructions for L10N teams - -2003-09-05 Taneem Ahmed - - * configure.in: Added "bn" to ALL_LINGUAS. - -2003-08-27 Paolo Maggi - - * configure.in: - * README: bump version to 2.3.5, requires libgnomeprintui 2.3.1 - instead of the still to be released 2.3.2 - - * NEWS: Updated - -2003-08-26 Paolo Maggi - - * NEWS: Updated - -2003-08-26 Paolo Maggi - - * configure.in: - * README: bump version to 2.3.4, updated dependences - -2003-08-11 Christian Rose - - * configure.in: Added "ne" to ALL_LINGUAS. - -2003-07-04 John Fleck - - * autogen.sh - remove - * xmldocs.make, omf.make - Updated to new docs build system. Latest gnome-common required. - (omf.make and xmldocs.make are now pulled in from gnome-common) - -2003-07-02 Jordi Mallach - - * data/gedit.desktop.in: Add Encoding entry and fix Terminal. - -2002-06-30 Paolo Maggi - - * configure.in: - * README: bump version to 2.3.3 - - * NEWS: Updated - -2003-06-15 Frederic Crozat - - * configure.in: don't use -Wsign-promo for C. - -2002-06-12 Paolo Maggi - - * data/gedit.schemas.in: added - preferences/print/page/print_syntax_highlighting key - - * configure.in: updated dependences, set GETTEXT_PACKAGE to gedit-2.4 - -2002-06-06 Paolo Maggi - - * data/gedit.schemas.in: removed preferences/editor/load/encodings key, - added preferences/encodings/auto_detected and preferences/encodings/shown_in_menu - keys - -2003-06-04 Frederic Crozat - - * data/GNOME_Gedit.server.in: - * data/GNOME_Gedit.server.in.in: - * data/Makefile.am: - * viewer/Makefile.am: - Move bonobo factory component in $(libdir)/bonobo and don't use a - versionned module. - -2002-06-03 Paolo Maggi - - Re-moved indent, taglist, shell_output and sort plugin from - gedit-plugins. - - * configure.in (AC_OUTPUT): update to compile the moved plugins - -2002-05-21 Paolo Maggi - - [ gedit 2.3.2 released ] - -2003-05-21 Paolo Maggi - - * configure.in: bump version to 2.3.2, - requires GtkSourceView >= 0.2.1 - - * README: bump version to 2.3.2, updated requirements - - * NEWS: updated - -2002-05-12 Paolo Maggi - - * data/gedit.schemas.in: removed statusbar_show_cursor_position and - statusbar_show_overwrite_mode keys - -2002-05-12 Paolo Maggi - - * data/gedit.pc.in: fixed Requires - -2002-05-08 Paolo Maggi - - * TODO: Updated - -2002-05-07 Paolo Maggi - - [ gedit 2.3.1 released ] - -2003-05-06 Paolo Maggi - - * Makefile.am: added distcleancheck_listfiles - - * data/Makefile.am: added DISTCLEANFILES - -2003-05-06 Paolo Maggi - - * Makefile.am: added distuninstallcheck_listfiles - -2003-05-06 Paolo Maggi - - * Makefile.am: added DISTCLEANFILES - -2003-05-06 Paolo Maggi - - * configure.in: bump version to 2.3.1, - requires GtkSourceView >= 0.2.0 - - * README: bump version to 2.3.1, updated requirements - - * NEWS: updated - -2003-05-06 Danilo Šegan - - * configure.in: Added "sr" and "sr@Latn" to ALL_LINGUAS. - -2003-05-05 Telsa Gwynne - - * configure.in: Added cy to ALL_LINGUAS - * po/cy.po: Added - -2003-04-18 Jeroen Zwartepoorte - - * data/GNOME_Gedit.server.in: Remove the ".so" extension from the - viewer factory so it works on other platforms. - -2003-04-18 Paolo Maggi - - * configure.in: - * Makefile.am: fixed bug #106129 - Package should use the - AM_GCONF_SOURCE_2 macro (patch by Julio Merino ) - -2003-04-17 Paolo Maggi - - * configure.in: fix the aspell/pspell check. It should fix bug #105563: - gEdit (2.2.0.1) fail to compile with new Aspell/Pspell 0.50.3 - -2003-04-16 Paolo Maggi - - * autogen.sh: updated - -2003-04-14 Jeroen Zwartepoorte - - * Makefile.am: - * configure.in: - * data/GNOME_Gedit.server.in: - - Added new viewer control for nautilus with syntax highlighting thanks - to gtksourceview. Gedit now depends on gtksourceview - (toward-gedit-integration branch). This viewer will eventually replace - the standard text viewer in nautilus. - -2003-04-14 Mike Lei - - * configure.in: Added Makefile support for de es fr it sv - ja ko zh_CN zh_TW - * help files for above languages - -2003-03-26 James Willcox - - * NEWS: Updated - -2003-03-13 Christian Rose - - * configure.in: Added "ml" to ALL_LINGUAS. - -2003-03-07 Breda McColgan - - * help/C/gedit.xml: updated for GNOME 2.2.1 - * help/C/l10n.txt: updated for GNOME 2.2.1 - * help/C/gedit-C.omf: updated manual date and version number - * help/C/figures/gedit_window.png: updated screenshot - of the latest application - * help/C/figures/gedit_recent_files_menu_icon.png: new screenshot - -2003-02-24 James Willcox - - * Makefile.am: - * configure.in: - * data/Makefile.am: - * data/gedit.pc.in: Moved from toplevel - * gedit/Makefile.am: - - Passes distcheck now. - -2003-02-22 Roozbeh Pournader - - * configure.in: Added "fa" to ALL_LINGUAS. - -2003-02-21 James Willcox - - * Makefile.am: - * configure.in: - * po/POTFILES.in: - - Clean up the build and enable buildling the plugins again. - -2003-02-20 James Willcox - - * Makefile.am: - * configure.in: - * gedit-2.3.pc.in: - * gedit/Makefile.am: - * gedit/gedit-mdi-child.h: - * gedit/gedit-mdi.h: - * gedit/recent-files/Makefile.am: - * plugins/Makefile.am: - - Install headers and stuff so we can build plugins externally. - -2003-02-20 James Willcox - - * configure.in: - * gedit/dialogs/Makefile.am: - * plugins/*: - - It actually builds now (sigh) - -2003-02-20 James Willcox - - * Makefile.am: - * configure.in: - * src/: removed - - Copied src/ to gedit/ to prepare for external plugins, and fixed the - build accordingly. - -2003-02-09 Christian Rose - - * configure.in: Added "kn" to ALL_LINGUAS. - -2003-01-27 James Willcox - - * configure.in: - * message-of-doom: - - Restore message-of-doom (HEAD is for 2.4 now) - -2003-01-27 Paolo Maggi - - * configure.in: bump version to 2.2.0, - updated requirement, don't display message-of-doom - - * README: bump version to 2.2.0 - - * NEW: updated - -2003-01-24 Breda McColgan - - * help/C/gedit.xml: corrected DTD reference - -2003-01-24 Breda McColgan - - * help/C/gedit.xml: updated for GNOME 2.2 - * help/C/gedit-C.omf: updated manual date - and version number - * help/C/figures/gedit_window.png: updated screenshot - of the latest application - -2003-01-21 Christian Rose - - * configure.in: Added "mn" to ALL_LINGUAS. - -2003-01-21 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.91 - - * NEWS: updated - -2003-01-14 Paolo Maggi - - * TRANSLATABLE_FILES: - * TODO: - * BUGS: Updated - -2003-01-06 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.6 - - * NEWS: updated - -2002-05-08 Pablo Saratxaga - - * configure.in: Added Amharic (am) and Macedonian (mk) to ALL_LINGUAS - -2003-01-05 Paolo Maggi - - * data/gedit.1: Updated. - -2003-01-04 James Willcox - - * data/gedit.1: Updated, fixed typos, etc. - -2003-01-03 James Willcox - - * data/gedit.desktop.in: - - Enable startup notification - -2003-01-02 Paolo Maggi - - * configure.in: requires libgnomeprintui-2.2 >= 2.1.7 - -2002-12-29 John Fleck - - * configure.in - * Makefile.am - * xmldocs.make - * help/ro/Makefile.am - * help/C/Makefile.am - * omf.make - updating docs to newest build template as found in - gnome-docu/gdp/gdp-example2 - - -2002-12-29 Paolo Maggi - - * data/gedit.schemas.in: s/Mononospace/Monospace Regular - s/Sans Normal/Sans Regular - -2002-12-17 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.5 - -2002-12-14 Chema Celorio - - * configure.in: remove autoheader warnings - -2002-12-09 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.4 - -2002-12-09 Christophe Fergeau - - * data/gedit.application (added) - * data/Makefile.am: register gedit properly with gnome-vfs so that - gnome-vfs knows gedit can handle all gnome-vfs uris - -2002-12-09 Paolo Maggi - - * pixmaps/shell-output-logo.png: file removed - - * pixmaps/Makefile.am (applogo_DATA): removed - shell-output-logo.png - -2002-12-03 Fernando Herrera - - * data/gedit.desktop.in: add X-GNOME-BUGZILLA stuff - -2002-11-27 Paolo Maggi - - * TODO: Updated - -2002-11-26 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.3 - -2002-11-21 Paolo Maggi - - * configure.in (AC_OUTPUT): removed plugins/email/Makefile - -2002-11-09 Dmitry G. Mastrukov - - * configure.in: Added Belarusian to ALL_LINGUAS - -2002-11-02 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.2.1 - -2002-11-01 Jody Goldberg - - * configure.in: require libgnomeprintui >= 2.1.1 - -2002-11-01 Paolo Maggi - - * configure.in: bump version to 2.1.2, - require libgnomeprintui >= 1.120.0 - - * README: bump version to 2.1.2 - -2002-10-27 Paolo Maggi - - * data/gedit.schemas.in : update long description for - the Toolbar Buttons Style key - -2002-10-15 Paolo Maggi - - * configure.in: require libgnomeui >= 2.1.1 - - * TODO: Updated - -2002-10-14 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.1 - -2002-10-14 Paolo Maggi - - * TODO: Updated - -2002-10-12 Paolo Maggi - - * configure.in: added plugins/sort/Makefile to AC_OUTPUT - -2002-10-11 Paolo Maggi - - * data/gedit.schemas.in: added auto_indent and - insert_spaces keys - -2002-10-05 Paolo Maggi - - * TODO: Updated - -2002-10-03 Paolo Maggi - - * TODO: Updated - -2002-10-03 Paolo Maggi - - [ gedit 2.1.0.1 released ] - -2002-10-03 Paolo Maggi - - * configure.in: - * README: bump version to 2.1.0.1 - -2002-10-01 jacob berkman - - * Makefile.am (EXTRA_DIST): dist message-of-doom - -2002-09-27 Paolo Maggi - - * message-of-doom: new file - - * configure.in: print the message-of-doom - -2002-09-20 Marius Andreiana - - * help/ro/gedit.xml: small update - -2002-09-19 Jacob Berkman - - * configure.in: add hlp/ro/ - -2002-09-18 Marius Andreiana - - * help/Makefile.am: added ro subdir - * help/ro: added romanian help translation - -2002-09-16 James Willcox - - * configure.in: Add src/recent-files/Makefile.am to AC_OUTPUT - -2002-09-10 Mark McLoughlin - - * configure.in: check for pspell/pspell.h also. - -2002-09-07 Paolo Maggi - - * configure.in: added plugins/spell/Makefile to AC_OUTPUT, - checks for pspell - - * acconfig.h: added HAVE_ISPELL_MODULE and HAVE_ASPELL_MODULE - - * data/gedit.schemas.in: Courier->Monospace, Helvetica->Sans Normal - (fix bug #88076) - -2002-09-03 Irene Ryan - - * help/C/gedit.xml: updated to reflect changes to the - UI and to fix bug #91026 - * help/C/gedit-C.omf: updated to reflect new manual - version and submission date - -2002-09-01 Marius Andreiana - - * configure.in: added 'ro' to ALL_LINGUAS - -2002-08-30 Paolo Maggi - - * data/gedit.schemas.in: added and entry for - preferences/editor/load/encodings key - -2002-08-30 Paolo Maggi - - * TODO: Updated - - * configure.in: bump version to 2.1.0 - - * pixmaps/gedit-logo.png: new logo - -2002-08-28 Paolo Maggi - - * TODO: Updated - -2002-08-26 Paolo Maggi - - * TODO: Updated - -2002-08-25 Paolo Maggi - - * TODO: Updated - -2002-08-24 James Willcox - - * configure.in: added plugins/email/Makefile to AC_OUTPUT - -2002-08-24 Paolo Maggi - - * configure.in: added plugins/indent/Makefile to AC_OUTPUT - -2002-08-24 Paolo Maggi - - * TODO: Updated - -2002-08-22 Mikael Hallendal - - * help/C/gedit-C.omf: revered my category change. Thanks Irene for - pointing out the new category. - -2002-08-21 Mikael Hallendal - - * help/C/gedit-C.omf: fixed the ScrollKeeper category. Now in - GNOME|Applications. - -2002-08-20 Paolo Maggi - - * configure.in: - * README: bump version to 2.0.3 - -2002-08-16 Paolo Maggi - - * data/gedit.desktop.in: added a semicolon at the end of - the categories list (thanks to Havoc Pennington for the - patch) - -2002-07-24 Paolo Maggi - - [ gedit 2.0.2 released ] - -2002-07-24 Paolo Maggi - - * configure.in: - * README: bump version to 2.0.2 - -2002-07-18 Paolo Maggi - - * TODO: Updated - -2002-07-17 James Willcox - - * configure.in: Added AM_DISABLE_STATIC, which disables the building - of static libraries (for plugins). - -2002-07-16 Paolo Maggi - - * TODO: Updated - -2002-07-15 Paolo Maggi - - [ gedit 2.0.1 released ] - -2002-07-15 Paolo Maggi - - * configure.in: - * README: bump version to 2.0.1 - -2002-07-12 Paolo Maggi - - * TODO: Updated - -2002-07-10 Paolo Maggi - - * data/gedit.schemas.in: - s/GEDIT_SAVE_CURRENT_LOCALE_WHEN_POSSIBLE/GEDIT_SAVE_CURRENT_LOCALE_IF_POSSIBLE, - added GEDIT_SAVE_ORIGINAL_FILE_ENCODING_IF_POSSIBLE_NCL description - - * TODO: Upated - -2002-07-09 Paolo Maggi - - * TODO: Updated - -2002-07-09 Paolo Maggi - - * Makefile.am: fixed ('make distcheck' works again) - - * data/Makefile.am: ditto - -2002-07-09 Mark McLoughlin - - * data/gedit.desktop.in: use X-GNOME-DocPath instead - of DocPath. - -2002-07-08 Paolo Maggi - - * Moved gedit.schemas, gedit.1, gedit.desktop.in, gedit.spec.in, - gedit.keys.in in the data dir - -2002-07-08 Paolo Maggi - - * .cvsignore: Updated - -2002-07-05 Paolo Maggi - - * TODO: Updated - - * gedit.1: added Federico to the Authors list - -2002-07-04 Paolo Maggi - - * TODO: Updated - -2002-07-04 Paolo Maggi - - * gedit.schemas: s/GEdit/gedit, change the backup_copy_extension - default to ~ - -2002-07-03 Federico Mena Quintero - - * gedit.schemas: Rewrote the schema file for the new preferences - setup. Should be the last part to fix #84535. - -2002-07-03 Paolo Maggi - - * configure.in: now gedit depends on eel-2.0 - -2002-06-19 Paolo Maggi - - [ gedit 2.0.0 released ] - -2002-06-19 Paolo Maggi - - * help/C/gedit.xml - * help/C/gedit-C.xml - * help/C/figures/gedit_window.png: updated (thanks to - Irene Ryan) - -2002-06-14 Paolo Maggi - - * configure.in: - * README: bump version to 2.0.0 - - * AUTHORS: added Federico - -2002-06-10 Paolo Maggi - - [ gedit 1.199.0 released ] - -2002-06-10 Paolo Maggi - - * configure.in: bump version to 1.199.0, requirements updated - -2002-06-10 Naba Kumar - - * configure.in: Added hi in ALL_LINGUAS - -2002-05-31 Paolo Maggi - - [ gedit 1.121.1 released ] - -2002-05-31 Paolo Maggi - - * configure.in: bump version to 1.121.1 - -2002-05-27 Paolo Maggi - - [ gedit 1.121.0 released ] - -2002-05-27 Paolo Maggi - - * configure.in: bump version to 1.121.0, requirements updated - -2002-05-27 James Willcox - - * README: Small changes in wording - * HACKING: ditto - -2002-05-27 Yanko Kaneti - - * configure.in: (ALL_LINGUAS) Added Bulgarian (bg). - -2002-05-21 Paolo Maggi - - [ gedit 1.120.0 released ] - -2002-05-21 Paolo Maggi - - * configure.in: bump version to 1.120.0, - require intltool 0.21 - - * README: Updated (1.119.0 -> 1.120.0) - - * Makefile.am: now make distcheck should work - -2002-05-20 Paolo Maggi - - * gedit.schemas: fixed bug #81974 - -2002-05-13 Paolo Maggi - - [ gedit 1.119.0 released ] - -2002-05-13 Paolo Maggi - - * configure.in: bump version to 1.119.0 - - * README: Updated (1.118.0 -> 1.119.0) - -2002-05-08 Pablo Saratxaga - - * configure.in: Added Basque (eu) and Vietnamese (vi) to ALL_LINGUAS - -2002-04-29 Satyajit Kanungo - - * gedit.desktop.in, Added the DocPath in the desktop file - -2002-05-03 Paolo Maggi - - * HACKING: typos - -2002-05-03 Paolo Maggi - - * README: updated - -2002-04-29 Paolo Maggi - - [gedit 1.118.0 released] - -2002-04-29 Paolo Maggi - - * configure.in: bump version to 1.118.0 - -2002-04-20 Paolo Maggi - - * TODO: Updated - -2002-04-15 James Willcox - - [gedit 1.117.0 released] - -2002-04-15 James Willcox - - * configure.in: bump version to 1.117.0 - -2002-04-03 Arvind S N - - * gedit.desktop.in: added %U for Exec, will launch the application - with file dropped on the icon. - -2002-04-02 Paolo Maggi - - * gedit.schemas: set "wrap lines at word boundaries" - as default (bug #76500). - -2002-03-27 Paolo Maggi - - [gedit 1.116.0 released] - -2002-03-27 Paolo Maggi - - * configure.in: bump version to 1.116.0 - -2002-03-18 Paolo Maggi - - [gedit 1.115.0 released] - -2002-03-06 Paolo Maggi - - * configure.in: bump version to 1.115.0 - - * gedit.schemas: added max-recents key - -2002-03-05 Paolo Maggi - - [gedit 1.114.0 released] - -2002-03-05 Paolo Maggi - - * HACKING: Updated (build sheriff commits welcome) - - * configure.in (ALL_LINGUAS): re-add it - -2002-03-04 Paolo Maggi - - * configure.in: bump version to 1.114.0 - requirements updated - - * Makefile.am (EXTRA_DIST): added xmldocs.make, removed - app-docs.make - - * help/C/Makefile.am: fixed a typo - - * omf-install/Makefile.am: fixed a typo - -2002-03-01 John Fleck - - * help/C/legal.xml - * help/C/gedit.xml - * help/C/gedit-C.xml - * help/C/Makefile.am - added - * help/C/figures/gedit_window.png - removed - * help/C/gedit.sgml - adding docs from Sun - -2002-02-25 Paolo Maggi - - * configure.in: bump version to 1.114.0cvs and - added AC_PREREQ(2.52) - - * gedit.1: updated - -2002-02-25 Paolo Maggi - - [gedit 1.113.0 released] - -2002-02-25 Paolo Maggi - - * TODO: Updated - - * configure.in: bump version to 1.113.0 - -2002-02-23 John Fleck - - * added - * help/C/gedit-C.omf - * help/C/gedit.xml - * help/C/legal.xml - * omf-install/Makefile.am - * changed - * Makefile.am - * configure.in - * help/Makefile.am - * help/C/Makefile.am - add docs built infrastructure. The doc itself, gedit.xml, is just - a placeholder until we get the real docs - -2002-02-23 Gediminas Paulauskas - - * configure.in (GNOME_PLATFORM_GNOME_2): remove, obsolete - (AC_OUTPUT): remove gedit.desktop -- it is generated by Makefile rule - - * gedit.desktop.in: binary was renamed back to gedit - -2002-02-22 Paolo Maggi - - * BUGS: Updated - - * HACKING: Updated - -2002-02-21 Paolo Maggi - - Name changed: gedit2->gedit - - * configure.in: bump version to 1.113.0cvs - -2002-02-21 Paolo Maggi - - * gedit.schemas: statusbar-view-cursor-position - and statusbar-view-overwrite-mode set TRUE in the default - setting - -2002-02-21 Seth Nickell - - * pixmaps/gedit-icon.png: - - Flip icon to match recommended perspective. - -2002-02-21 Seth Nickell - - * Makefile.am: - - Install .desktop file into SHARE/applications, - and merge translations at make time rather - than configure time. - - * configure.in: - - Don't merge translations at configure time. - - * gedit.desktop.in: - * gedit2.desktop.in: - - Rename file to gedit.desktop.in. - -2002-02-20 Paolo Maggi - - * gedit2.desktop.in: updated - -2002-02-18 Paolo Maggi - - * Makefile.am: removed unused code - -2002-02-14 Tõivo Leedjärv - - * configure.in: Added et to ALL_LINGUAS. - -2002-02-13 Paolo Maggi - - * TODO: Updated - -2002-02-12 Paolo Maggi - - * configure.in: bump version to 1.112.0 - (AC_OUTPUT): added plugins/ASCII/Makefile - - * TODO: Updated - -2002-02-10 Paolo Maggi - - * configure.in: bump version to 1.111.0 - -2002-02-08 Paolo Maggi - - * configure.in (AC_OUTPUT): added plugins/diff/Makefile - -2002-02-07 Paolo Maggi - - * configure.in: bump version to 1.110.2 - (AC_OUTPUT): added plugins/taglist/Makefile - -2002-02-05 Paolo Maggi - - * configure.in: turn on additional checks for - warnings - - * CVSVERSION: new file (do not distribute) - - * TODO: Updated - -2002-02-01 Chema Celorio - - * configure.in: bump version to 1.110.1 - -2002-01-29 Paolo Maggi - - * TODO: updated - - * configure.in (AC_OUTPUT): gedit2.desktop - -2002-01-25 Paolo Maggi - - * configure.in: bump version to 1.110.0 - -2002-01-24 Paolo Maggi - - * configure.in (AC_OUTPUT): added plugins/shell_output/Makefile - - * pixmaps/shell-output-logo.png: new file - -2002-01-23 James Willcox - - * configure.in: Added option --enable-gconf-source, to specify where - to install schema files. - -2002-01-22 James Willcox - - * Fixed bug 69335, regarding the gconf schema install. - It now responds properly to GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL. - -2002-01-22 Paolo Maggi - - * AUTHORS: added James - -2002-01-21 Paolo Maggi - - * TODO: Updated - - * AUTHORS: ditto - - * HACKING: ditto - - * MAINTAINERS: ditto - -2002-01-18 Paolo Maggi - - * configure.in (AC_OUTPUT): added plugins/docinfo/Makefile - -2002-01-18 Paolo Maggi - - * configure.in: bump version to 1.109.1 - - * TODO: Updated - -2002-01-17 James Willcox - - * TODO: Updated - -2002-01-17 Hasbullah Bin Pit - - * configure.in: Added "ms" (Malay) to ALL_LINGUAS. - * po/ms.po: Added Malay translation. - -2002-01-16 Paolo Maggi - - * Makefile.am (SUBDIRS): added plugins - - * configure.in (AC_OUTPUT): added plugins/Makefile - plugins/sample/Makefile - - -2002-01-15 James Willcox - - * TODO: Updated - -2002-01-15 Paolo Maggi - - * configure.in: version number set to 1.110.0cvs - - * TODO: Updated - -2002-01-14 James Willcox - - * TODO: Updated - -2002-01-13 Paolo Maggi - - * configure.in: bump version to 1.109.0 - -2002-01-12 Paolo Maggi - - * TODO: Updated - - * gedit.schemas: updated for new statusbar - options - -2002-01-11 Paolo Maggi - - * TODO: Updated - - * gedit.schemas: updated for line numbers - -2002-01-11 Paolo Maggi - - * TODO: Updated - -2002-01-10 Jason Leach - - * TODO: Updated. - -2002-01-10 Paolo Maggi - - * TODO: Updated - -2002-01-09 Paolo Maggi - - * TODO: Updated - -2002-01-08 Paolo Maggi - - * TODO: Updated - - * gedit.schemas: Updated - -2002-01-07 Paolo Maggi - - * TODO: Updated - -2002-01-05 Paolo Maggi - - * gedit.schemas: added new printing preferences - -2002-01-04 Paolo Maggi - - * TODO: Updated - -2001-12-29 Paolo Maggi - - * gedit.schemas: Rewritten - -2001-12-17 Paolo Maggi - - * TODO: Updated - -2001-12-14 Gediminas Paulauskas - - * configure.in: add check for glib-genmarshal - -2001-12-12 Paolo Maggi - - * TODO: update - -2001-12-11 James Willcox - - * Makefile.am: fixed GConf schema installation - -2001-12-10 James Willcox - - * gedit.schemas: New file -- GConf schema, used for preferences. - - * Makefile.am: Added stuff to install the GConf schema - -2001-12-10 Paolo Maggi - - * TODO : updated - -2001-12-09 Paolo Maggi - - * TODO : updated - - * BUGS: updated - - * configure.in: bump version to 1.108.0 - -2001-12-05 Chema Celorio - - * configure.in: bump version to 1.107.0 - -2001-12-03 Carlos Perelló Marín - - * configure.in: Reverted my change about GETTEXT_PACKAGE. We should - use the "standar" name (gedit-2.0 instead of gedit-2). - -2001-12-03 Paolo Maggi - - * TODO : updated - -2001-12-02 Paolo Maggi - - * configure.in: cleaned following the suggestions of the gnome2 - porting foc. Now libgnomeprintui-2.0 is required - -2001-11-21 Carlos Perelló Marín - - * configure.in: Changed GETTEXT_PACKAGE from gedit-2.0 to gedit-2 - -2001-11-16 Carlos Perelló Marín - - * Makefile.am, configure.in: Migrated from xml-i18n-tools to intltool - and added support to AM_GLIB_GNU_GETTEXT - * acconfig.h: Added GETTEXT_PACKAGE - -2001-11-16 Paolo Maggi - - * Started the port to GNOME 2.0 - -2001-11-16 Carlos Perelló Marín - - * ChangeLog: rolled over to ChangeLog-20011116 +2005-12-12 Paolo Borelli + + * all files: too many changes to list, this is the merge of + the new_mdi cvs branch, featuring almost a rewrite of the whole + gedit codebase. + Here is an excerpt from Paolo Maggi's mail describing the merge + to the developement list: + + The "new_mdi" branch has been used for a substantial rework of + the gedit internals with the goal of fixing various longstanding + issues and improving the quality of the whole codebase. + + The main issues we wanted to fix were the ones related to the + way gedit handled its tabbed interface (see bug #131953), but + then a lot of other improvements have been put in. + + In particular: + - GtkUIManager is now used for menus and toolbar instead of + libbonoboui + - A side panel and a bottom panel have been added + - A new gobject-based plugin system has been implemented + - Plugins can now be written in Python + - Reading and writing of files are now handled in an + asynchronous way (so the user interface never blocks) + - Local files are read using mmap (when possible) + - Incremental search is supported (use Ctrl+K) + - A lot of usability improvements with some new UI experiment + are featured + - Startup time and performaces have been improved + - Remote file saving is supported (for a limited configurable + set of VFS methods) + +2005-12-12 Paolo Borelli + + * ChangeLog: fork off a new ChangeLog for the big merge of the + new_mdi branch. diff --git a/ChangeLog-20051212 b/ChangeLog-20051212 new file mode 100644 index 00000000..ca10e5d8 --- /dev/null +++ b/ChangeLog-20051212 @@ -0,0 +1,1754 @@ +==== gedit 2.12.1 ==== + +2005-10-03 Paolo Borelli + + * NEWS: + * README: + * configure.in 2.12.1 released. + +2005-09-11 Paolo Borelli + + * configure.in: readd ku. + +2005-09-11 Paolo Borelli + + * configure.in: temporarely remove the ku translation since + Erdal forgot to cvs add it. + +==== gedit 2.12.0 ==== + +2005-09-10 Erdal Ronahi + + * po/ku.po: Added Kurdish translation + +2005-09-05 Paolo Borelli + + * NEWS: + * README: + * configure.in 2.12.0 released. + +==== gedit 2.11.93 ==== + +2005-08-29 Paolo Borelli + + * NEWS: + * README: + * configure.in 2.11.93 released. + +==== gedit 2.11.92 ==== + +2005-08-23 Paolo Borelli + + * NEWS: + * README: + * configure.in 2.11.92 released. + +==== gedit 2.11.91 ==== + +2005-08-08 Paolo Borelli + + * NEWS: + * README: + * configure.in 2.11.91 released. + +2005-08-05 Paolo Maggi + + Fixed bug #101281: [ui-review] Undo preference dialog + + * data/gedit.schemas.in: deprecated key + /schemas/apps/gedit-2/preferences/editor/undo/undo_actions_limits and + added new key .../undo/max_undo_actions + +2005-08-04 Paolo Maggi + + Fixed bug #168965: Grammatical error in message + + * data/gedit.schemas.in: fixed message. + Patch by Guillaume Desmottes + +==== gedit 2.10.4 ==== + +2005-08-04 Paolo Maggi + + * NEWS: + * README: + * configure.in: 2.10.4 released + +==== gedit 2.10.3 ==== + +2005-06-08 Paolo Borelli + + * README: + * configure.in 2.10.3 released. + +2005-04-08 Sunil Mohan Adapa + + * configure.in: Added "te" to ALL_LINGUAS. + +==== gedit 2.10.2 ==== + +2005-04-04 Paolo Borelli + + * README: + * configure.in 2.10.2 released. + +2005-03-31 Steve Murphy + + * configure.in: Added "rw" to ALL_LINGUAS. + +==== gedit 2.10.1 ==== + +2005-03-25 Paolo Borelli + + * README: + * configure.in 2.10.1 released. + +2005-03-22 Adi Attar + + * configure.in: Added 'xh' to ALL_LINGUAS. + +==== gedit 2.10.0 ==== + +2005-03-08 Paolo Borelli + + * README: + * configure.in: 2.10.0 released. + +==== gedit 2.9.7 ==== + +2005-03-01 Paolo Maggi + + * README: + * NEWS: 2.9.7 released. + +2005-02-20 Paolo Maggi + + * data/gedit.1: updated + +2005-02-13 Paolo Maggi + + * data/gedit.schemas.in: fixed bug #167060 (gedit schema messages + need translator comments) + +==== gedit 2.9.6 ==== + +2005-02-07 Paolo Borelli + + * README: + * NEWS: 2.9.6 released. + +2005-02-04 Paolo Maggi + + * data/gedit.schemas.in: added savecopy to the list of default + plugins. + +==== gedit 2.9.5 ==== + +==== gedit 2.9.4 ==== + +2005-01-11 Paolo Maggi + + * configure.in: version 2.9.4 + + * README: updated + +2005-01-10 Paolo Maggi + + Based on a patch by Juerg Billeter + + * data/gedit.schemas.in: added editor/bracket_matching/bracket_matching + +2005-01-10 Paolo Maggi + + * configure.in: set GEDIT_MAJOR to 2.10 + +2005-01-08 Paolo Maggi + + * configure.in: requires GtkSourceView >= 1.1.90 + + * data/gedit.schemas.in: added editor/current_line/highlight_current_line + key + +2004-12-07 Paolo Maggi + + * configure.in: show message-of-doom, remove redundant check for + ngettext, since AM_GLIB_GNU_GETTEXT already checks for it (in both + libc and libintl). + +2004-12-05 Paolo Maggi + + * data/gedit.schemas.in: fixed bug #147664 (Please add translator + comments to gedit schema messages). + +2004-11-29 Paolo Borelli + + * README: + * NEWS: 2.9.2 released. + +2004-11-29 Paolo Borelli + + * data/gedit.desktop.in.in: use @VERSION@ for bug-buddy reports + * configure.in: modify for the above change and update for 2.9.2 + +2004-11-11 Paolo Borelli + + * configure.in: bump glib and gtk+ requirements. + +2004-11-09 Paolo Maggi + + * data/gedit.schemas.in: added new keys + /schemas/apps/gedit-2/preferences/print/fonts/print_font_body_pango, + /schemas/apps/gedit-2/preferences/print/fonts/print_font_header_pango and + /schemas/apps/gedit-2/preferences/print/fonts/print_font_numbers_pango. Patch + by Owen Taylor + +2004-11-01 Paolo Maggi + + * configure.in: removed version number from GETTEXT_PACKAGE (fixes + bug #149988: Is gedit potfile versioning needed?) + +2004-11-01 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.9.1 + +2004-10-31 Paolo Maggi + + * configure.in: set version to 2.9.0 + + * data/gedit.schemas.in: added + /schemas/apps/gedit-2/plugins/active-plugins key + +2004-10-15 Marco Pesenti Gritti + + reviewed by: Paolo Borelli + + * gedit/dialogs/gedit-encodings-dialog.c: (update_list), + (gedit_encodings_dialog_run): + + Fix trivial compile issue + +2004-10-13 Paolo Borelli + + * Makefile.am: + * configure.in: + * viewer/*.c: removed the nautilus view. + +2004-10-11 Paolo Borelli + + * Makefile.am: fix distcheck with latest gnome-common. + +2004-10-10 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.8.1 + +2004-09-14 Gora Mohanty + + * configure.in: Added 'or' to ALL_LINGUAS. + +2004-09-13 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.8.0 + +2004-08-30 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.7.92 + +2004-08-30 Paolo Borelli + + * HACKING: put patches in bugzilla + * AUTHORS: update email adresses + * MAINTAINERS: ditto + * Makefile.am: distribute MAINTAINERS + +2004-08-29 Akagic Amila + + * configure.in: Added 'bs' to ALL_LINGUAS. + +2004-08-24 Breda McColgan + + * help/C/gedit.xml: Updated for GNOME 2.8, technical review draft + * help/C/gedit-C.omf: Updated for GNOME 2.8 + * help/C/l10n.txt: Updated for GNOME 2.8 + +2004-08-16 Kjartan Maraas + + * configure.in: Added nb to ALL_LINGUAS. + +2004-08-16 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.7.91 + +2004-08-05 Paolo Borelli + + * configure.in: bump required intltool to 0.31 as + suggested by Owen Taylor in bug #149219 + +2004-08-01 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.7.90 + +2004-07-21 Ray Strode + * gedit/data/gedit.desktop.in: Add MimeType line to desktop file + new mime sytem. + +2004-07-19 Paolo Maggi + + * .cvsignore: added omf.make and xmldocs.make + +2004-07-19 Paolo Maggi + + * help/eu/.cvsignore: added + +2004-07-16 Paolo Borelli + + * data/gedit.1: document --encoding. + +2004-07-13 Paolo Borelli + + * data/gedit.1: small updates to man page. + +2004-07-05 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.7.1 + +2004-06-25 Paolo Borelli + + * merge gnome-2-6 branch fixes into HEAD. + +2004-06-25 Paolo Borelli + + * configure.in: + * README: + * NEWS: release 2.6.2 + +2004-05-29 Christian Rose + + * configure.in: Added "tk" to ALL_LINGUAS. + +2004-05-26 Mohammad DAMT + + * po/id.po: Added Indonesian translation done by Ahmad Riza H Nst + * configure.in: Added id to ALL_LINGUAS + +2004-05-05 Frederic Crozat + + * gedit/recent-files/egg-recent-item.c: (egg_recent_item_new), + (egg_recent_item_set_private), (egg_recent_item_get_private): + * gedit/recent-files/egg-recent-item.h: + * gedit/recent-files/egg-recent-util.c: (egg_recent_util_get_icon): + * gedit/recent-files/egg-recent-view.h: + Resync recent-files with latest libegg version, so it doesn't + complain when icon theme is not set. + +2002-05-08 Pablo Saratxaga + + * help/eu: Added Basque help files + +2004-04-09 Guntupalli Karunakar + + * configure.in: Added "gu" (Gujarati) to ALL_LINGUAS. + +2004-04-05 Paolo Maggi + + * data/gedit.schemas.in: fixed bug #138508 (default values + in gedit.schemas are not gettexized). Thanks to Takao Fujiwara + and Mark McLoughlin + +2004-04-05 Paolo Maggi + + * data/gedit.keys.in: bug #106911 fixed. The file contains + the right keys now. + +2004-04-05 Paolo Borelli + + * configure.in: add changecase plugin to the build. + +2004-04-03 Samúel Jón Gunnarsson + + is.po: Added "is" to ALL_LINGUAS + +2004-03-31 Christian Rose + + * configure.in: Added "af" to ALL_LINGUAS. + +2004-03-22 Paolo Borelli + + * configure.in: + * README: bump version to 2.6.0 + + * NEWS: updated + +2004-03-19 Gareth Owen + + * configure.in: Added en_GB to ALL_LINGUAS + +2004-03-18 Guntupalli Karunakar + + * configure.in: Added "mr" for Marathi to ALL_LINGUAS. + +2004-03-17 Glynn Foster + + * help/*: Add back localized documentation from Sun's translation + team for de, es, fr, it, ja, ko, sv, zh_CN, zh_HK and zh_TW. + +2004-03-16 Paolo Borelli + + * configure.in: + * README: bump version to 2.5.92 + + * NEWS: updated + +2004-03-14 Thomas Vander Stichele + + * configure.in: use ACLOCAL_AMFLAGS to make maintainer builds work + +2004-03-08 Paolo Maggi + + * configure.in: + * README: bump version to 2.5.91 + + * NEWS: updated + +2004-03-04 Guntupalli Karunakar + + * configure.in: Added "pa" for Punjabi in ALL_LINGUAS. + +2004-03-04 Glynn Foster + + * pixmaps/Makefile.am: Don't list pixmaps in SOURCES. Fixes #135824. + +2004-03-01 Breda McColgan + + * help/C/gedit.xml: Updated for GNOME 2.6, technical review draft + * help/C/gedit-C.omf: Updated for GNOME 2.6 + * help/C/l10n.txt: Updated for GNOME 2.6 + * help/C/figures/gedit_window.png: Updated for GNOME 2.6 + * help/C/figures/gedit_format_bold.png: Added for GNOME 2.6 + * help/C/figures/gedit_format_italic.png: Added for GNOME 2.6 + * help/C/figures/gedit_format_strikethrough.png: Added for GNOME 2.6 + * help/C/figures/gedit_format_underline.png: Added for GNOME 2.6 + +2004-02-25 Paolo Maggi + + * AUTHORS: added Paolo Borelli + +2004-02-24 Paolo Maggi + + [ gedit 2.5.90 released ] + +2004-02-24 Paolo Maggi + + * configure.in: requires gtksourceview 0.9, sets version + to 2.5.90 + + * README: bump version to 2.5.90 + + * NEWS: updated + +2004-02-23 Padraig O'Briain + + * gedit/dialogs/gedit-close-confirmation-dialog.c + (gedit_close_confirmation_dialog_init): Set role to ATK_ROLE_ALERT. + Fixes bug #135000. + +2004-02-21 Christian Rose + + * configure.in: Added "en_CA" to ALL_LINGUAS. + +2004-02-15 Tomasz Kłoczko + + * configure.in: Trivial cleanup: remove AC_SUBST(CFLAGS), + AC_SUBST(CPPFLAGS) and AC_SUBST(LDFLAGS). This variables are + substed by default. + +2004-02-12 Paolo Maggi + + * data/gedit.schemas.in: removed unused key + schemas/apps/gedit-2/preferences/editor/save/save_encoding + +2004-02-09 Alexander Winston + + * acinclude.m4: Quoted definitions of macros + AM_PATH_PROG_WITH_TEST, AM_LC_MESSAGES, AM_WITH_NLS, and + AM_GNU_GETTEXT. Fixes #133178. + +2004-02-06 Mark McLoughlin + + * configure.in: add a --enable-deprecations flag + to switch on the DISABLE_DEPRECATED cflags. Also + re-use the gnome-common --enable-compile-warnings + impl. which doesn't touch CFLAGS. + +2004-01-27 Christian Rose + + * configure.in: Added "mi" to ALL_LINGUAS. + +2004-01-15 Paolo Maggi + + [ gedit 2.5.3 released ] + +2004-01-15 Paolo Maggi + + * configure.in: requires intltool 0.29, sets version + to 2.5.3 + + * README: bump version to 2.5.3 + + * NEWS: updated + + * Makefile.am: Removed OrigTree.pm to EXTRA_DIST + +2004-01-06 Paolo Maggi + + * TODO: Updated + +2004-01-03 Paolo Maggi + + * configure.in: bump version to 2.5.2 + + * README: bump version to 2.5.2 + +2004-01-03 Robert Sedak + + * configure.in: Added "hr" in ALL_LINGUAS. + +2003-12-29 Paolo Maggi + + * Makefile.am: Added OrigTree.pm to EXTRA_DIST. + + * configure.in: requires intltool 0.28 + +2003-12-29 Paolo Maggi + + * data/gedit.1: removed an unknown macro in man page + (fixed bug #127693). + + * configure.in: check for the ngettext function + +2003-11-24 Paolo Maggi + + [ gedit 2.5.0 released ] + +2003-10-21 Paolo Maggi + + * data/Makefile.am: don't distribute generated files (fixes + bug #103846) + +2003-10-20 Paolo Maggi + + * configure.in: bump version to 2.5.0, set + GEDIT_MAJOR to 2.6 and GETTEXT_PACKAGE to gedit-2.6, + updated requirements + +2003-09-18 Paolo Maggi + + * TODO: Updated + + * configure.in: show message-of-doom + + * message-of-doom: updated + + * data/gedit.schemas.in: added the following keys: + display_right_margin, right_margin_position and + syntax_highlighting/enable + +2003-09-09 Paolo Maggi + + [ gedit 2.4.0 released ] + +2003-09-09 Paolo Maggi + + * configure.in: bump version to 2.4.0 + + * README: bump version to 2.4.0, updated requirements + +2003-09-06 Laurent Dhima + + * configure.in: Added "sq" to ALL_LINGUAS. + +2003-09-05 Irene Ryan + + * help/C/gedit.xml: updated the Help to reflect gedit 2.2.2 for GNOME + 2.4 release + * help/C/gedit-C.omf: updated the manual version/release information + * help/C/l10n.txt: updated instructions for L10N teams + +2003-09-05 Taneem Ahmed + + * configure.in: Added "bn" to ALL_LINGUAS. + +2003-08-27 Paolo Maggi + + * configure.in: + * README: bump version to 2.3.5, requires libgnomeprintui 2.3.1 + instead of the still to be released 2.3.2 + + * NEWS: Updated + +2003-08-26 Paolo Maggi + + * NEWS: Updated + +2003-08-26 Paolo Maggi + + * configure.in: + * README: bump version to 2.3.4, updated dependences + +2003-08-11 Christian Rose + + * configure.in: Added "ne" to ALL_LINGUAS. + +2003-07-04 John Fleck + + * autogen.sh + remove + * xmldocs.make, omf.make + Updated to new docs build system. Latest gnome-common required. + (omf.make and xmldocs.make are now pulled in from gnome-common) + +2003-07-02 Jordi Mallach + + * data/gedit.desktop.in: Add Encoding entry and fix Terminal. + +2002-06-30 Paolo Maggi + + * configure.in: + * README: bump version to 2.3.3 + + * NEWS: Updated + +2003-06-15 Frederic Crozat + + * configure.in: don't use -Wsign-promo for C. + +2002-06-12 Paolo Maggi + + * data/gedit.schemas.in: added + preferences/print/page/print_syntax_highlighting key + + * configure.in: updated dependences, set GETTEXT_PACKAGE to gedit-2.4 + +2002-06-06 Paolo Maggi + + * data/gedit.schemas.in: removed preferences/editor/load/encodings key, + added preferences/encodings/auto_detected and preferences/encodings/shown_in_menu + keys + +2003-06-04 Frederic Crozat + + * data/GNOME_Gedit.server.in: + * data/GNOME_Gedit.server.in.in: + * data/Makefile.am: + * viewer/Makefile.am: + Move bonobo factory component in $(libdir)/bonobo and don't use a + versionned module. + +2002-06-03 Paolo Maggi + + Re-moved indent, taglist, shell_output and sort plugin from + gedit-plugins. + + * configure.in (AC_OUTPUT): update to compile the moved plugins + +2002-05-21 Paolo Maggi + + [ gedit 2.3.2 released ] + +2003-05-21 Paolo Maggi + + * configure.in: bump version to 2.3.2, + requires GtkSourceView >= 0.2.1 + + * README: bump version to 2.3.2, updated requirements + + * NEWS: updated + +2002-05-12 Paolo Maggi + + * data/gedit.schemas.in: removed statusbar_show_cursor_position and + statusbar_show_overwrite_mode keys + +2002-05-12 Paolo Maggi + + * data/gedit.pc.in: fixed Requires + +2002-05-08 Paolo Maggi + + * TODO: Updated + +2002-05-07 Paolo Maggi + + [ gedit 2.3.1 released ] + +2003-05-06 Paolo Maggi + + * Makefile.am: added distcleancheck_listfiles + + * data/Makefile.am: added DISTCLEANFILES + +2003-05-06 Paolo Maggi + + * Makefile.am: added distuninstallcheck_listfiles + +2003-05-06 Paolo Maggi + + * Makefile.am: added DISTCLEANFILES + +2003-05-06 Paolo Maggi + + * configure.in: bump version to 2.3.1, + requires GtkSourceView >= 0.2.0 + + * README: bump version to 2.3.1, updated requirements + + * NEWS: updated + +2003-05-06 Danilo Šegan + + * configure.in: Added "sr" and "sr@Latn" to ALL_LINGUAS. + +2003-05-05 Telsa Gwynne + + * configure.in: Added cy to ALL_LINGUAS + * po/cy.po: Added + +2003-04-18 Jeroen Zwartepoorte + + * data/GNOME_Gedit.server.in: Remove the ".so" extension from the + viewer factory so it works on other platforms. + +2003-04-18 Paolo Maggi + + * configure.in: + * Makefile.am: fixed bug #106129 - Package should use the + AM_GCONF_SOURCE_2 macro (patch by Julio Merino ) + +2003-04-17 Paolo Maggi + + * configure.in: fix the aspell/pspell check. It should fix bug #105563: + gEdit (2.2.0.1) fail to compile with new Aspell/Pspell 0.50.3 + +2003-04-16 Paolo Maggi + + * autogen.sh: updated + +2003-04-14 Jeroen Zwartepoorte + + * Makefile.am: + * configure.in: + * data/GNOME_Gedit.server.in: + + Added new viewer control for nautilus with syntax highlighting thanks + to gtksourceview. Gedit now depends on gtksourceview + (toward-gedit-integration branch). This viewer will eventually replace + the standard text viewer in nautilus. + +2003-04-14 Mike Lei + + * configure.in: Added Makefile support for de es fr it sv + ja ko zh_CN zh_TW + * help files for above languages + +2003-03-26 James Willcox + + * NEWS: Updated + +2003-03-13 Christian Rose + + * configure.in: Added "ml" to ALL_LINGUAS. + +2003-03-07 Breda McColgan + + * help/C/gedit.xml: updated for GNOME 2.2.1 + * help/C/l10n.txt: updated for GNOME 2.2.1 + * help/C/gedit-C.omf: updated manual date and version number + * help/C/figures/gedit_window.png: updated screenshot + of the latest application + * help/C/figures/gedit_recent_files_menu_icon.png: new screenshot + +2003-02-24 James Willcox + + * Makefile.am: + * configure.in: + * data/Makefile.am: + * data/gedit.pc.in: Moved from toplevel + * gedit/Makefile.am: + + Passes distcheck now. + +2003-02-22 Roozbeh Pournader + + * configure.in: Added "fa" to ALL_LINGUAS. + +2003-02-21 James Willcox + + * Makefile.am: + * configure.in: + * po/POTFILES.in: + + Clean up the build and enable buildling the plugins again. + +2003-02-20 James Willcox + + * Makefile.am: + * configure.in: + * gedit-2.3.pc.in: + * gedit/Makefile.am: + * gedit/gedit-mdi-child.h: + * gedit/gedit-mdi.h: + * gedit/recent-files/Makefile.am: + * plugins/Makefile.am: + + Install headers and stuff so we can build plugins externally. + +2003-02-20 James Willcox + + * configure.in: + * gedit/dialogs/Makefile.am: + * plugins/*: + + It actually builds now (sigh) + +2003-02-20 James Willcox + + * Makefile.am: + * configure.in: + * src/: removed + + Copied src/ to gedit/ to prepare for external plugins, and fixed the + build accordingly. + +2003-02-09 Christian Rose + + * configure.in: Added "kn" to ALL_LINGUAS. + +2003-01-27 James Willcox + + * configure.in: + * message-of-doom: + + Restore message-of-doom (HEAD is for 2.4 now) + +2003-01-27 Paolo Maggi + + * configure.in: bump version to 2.2.0, + updated requirement, don't display message-of-doom + + * README: bump version to 2.2.0 + + * NEW: updated + +2003-01-24 Breda McColgan + + * help/C/gedit.xml: corrected DTD reference + +2003-01-24 Breda McColgan + + * help/C/gedit.xml: updated for GNOME 2.2 + * help/C/gedit-C.omf: updated manual date + and version number + * help/C/figures/gedit_window.png: updated screenshot + of the latest application + +2003-01-21 Christian Rose + + * configure.in: Added "mn" to ALL_LINGUAS. + +2003-01-21 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.91 + + * NEWS: updated + +2003-01-14 Paolo Maggi + + * TRANSLATABLE_FILES: + * TODO: + * BUGS: Updated + +2003-01-06 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.6 + + * NEWS: updated + +2002-05-08 Pablo Saratxaga + + * configure.in: Added Amharic (am) and Macedonian (mk) to ALL_LINGUAS + +2003-01-05 Paolo Maggi + + * data/gedit.1: Updated. + +2003-01-04 James Willcox + + * data/gedit.1: Updated, fixed typos, etc. + +2003-01-03 James Willcox + + * data/gedit.desktop.in: + + Enable startup notification + +2003-01-02 Paolo Maggi + + * configure.in: requires libgnomeprintui-2.2 >= 2.1.7 + +2002-12-29 John Fleck + + * configure.in + * Makefile.am + * xmldocs.make + * help/ro/Makefile.am + * help/C/Makefile.am + * omf.make + updating docs to newest build template as found in + gnome-docu/gdp/gdp-example2 + + +2002-12-29 Paolo Maggi + + * data/gedit.schemas.in: s/Mononospace/Monospace Regular + s/Sans Normal/Sans Regular + +2002-12-17 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.5 + +2002-12-14 Chema Celorio + + * configure.in: remove autoheader warnings + +2002-12-09 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.4 + +2002-12-09 Christophe Fergeau + + * data/gedit.application (added) + * data/Makefile.am: register gedit properly with gnome-vfs so that + gnome-vfs knows gedit can handle all gnome-vfs uris + +2002-12-09 Paolo Maggi + + * pixmaps/shell-output-logo.png: file removed + + * pixmaps/Makefile.am (applogo_DATA): removed + shell-output-logo.png + +2002-12-03 Fernando Herrera + + * data/gedit.desktop.in: add X-GNOME-BUGZILLA stuff + +2002-11-27 Paolo Maggi + + * TODO: Updated + +2002-11-26 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.3 + +2002-11-21 Paolo Maggi + + * configure.in (AC_OUTPUT): removed plugins/email/Makefile + +2002-11-09 Dmitry G. Mastrukov + + * configure.in: Added Belarusian to ALL_LINGUAS + +2002-11-02 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.2.1 + +2002-11-01 Jody Goldberg + + * configure.in: require libgnomeprintui >= 2.1.1 + +2002-11-01 Paolo Maggi + + * configure.in: bump version to 2.1.2, + require libgnomeprintui >= 1.120.0 + + * README: bump version to 2.1.2 + +2002-10-27 Paolo Maggi + + * data/gedit.schemas.in : update long description for + the Toolbar Buttons Style key + +2002-10-15 Paolo Maggi + + * configure.in: require libgnomeui >= 2.1.1 + + * TODO: Updated + +2002-10-14 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.1 + +2002-10-14 Paolo Maggi + + * TODO: Updated + +2002-10-12 Paolo Maggi + + * configure.in: added plugins/sort/Makefile to AC_OUTPUT + +2002-10-11 Paolo Maggi + + * data/gedit.schemas.in: added auto_indent and + insert_spaces keys + +2002-10-05 Paolo Maggi + + * TODO: Updated + +2002-10-03 Paolo Maggi + + * TODO: Updated + +2002-10-03 Paolo Maggi + + [ gedit 2.1.0.1 released ] + +2002-10-03 Paolo Maggi + + * configure.in: + * README: bump version to 2.1.0.1 + +2002-10-01 jacob berkman + + * Makefile.am (EXTRA_DIST): dist message-of-doom + +2002-09-27 Paolo Maggi + + * message-of-doom: new file + + * configure.in: print the message-of-doom + +2002-09-20 Marius Andreiana + + * help/ro/gedit.xml: small update + +2002-09-19 Jacob Berkman + + * configure.in: add hlp/ro/ + +2002-09-18 Marius Andreiana + + * help/Makefile.am: added ro subdir + * help/ro: added romanian help translation + +2002-09-16 James Willcox + + * configure.in: Add src/recent-files/Makefile.am to AC_OUTPUT + +2002-09-10 Mark McLoughlin + + * configure.in: check for pspell/pspell.h also. + +2002-09-07 Paolo Maggi + + * configure.in: added plugins/spell/Makefile to AC_OUTPUT, + checks for pspell + + * acconfig.h: added HAVE_ISPELL_MODULE and HAVE_ASPELL_MODULE + + * data/gedit.schemas.in: Courier->Monospace, Helvetica->Sans Normal + (fix bug #88076) + +2002-09-03 Irene Ryan + + * help/C/gedit.xml: updated to reflect changes to the + UI and to fix bug #91026 + * help/C/gedit-C.omf: updated to reflect new manual + version and submission date + +2002-09-01 Marius Andreiana + + * configure.in: added 'ro' to ALL_LINGUAS + +2002-08-30 Paolo Maggi + + * data/gedit.schemas.in: added and entry for + preferences/editor/load/encodings key + +2002-08-30 Paolo Maggi + + * TODO: Updated + + * configure.in: bump version to 2.1.0 + + * pixmaps/gedit-logo.png: new logo + +2002-08-28 Paolo Maggi + + * TODO: Updated + +2002-08-26 Paolo Maggi + + * TODO: Updated + +2002-08-25 Paolo Maggi + + * TODO: Updated + +2002-08-24 James Willcox + + * configure.in: added plugins/email/Makefile to AC_OUTPUT + +2002-08-24 Paolo Maggi + + * configure.in: added plugins/indent/Makefile to AC_OUTPUT + +2002-08-24 Paolo Maggi + + * TODO: Updated + +2002-08-22 Mikael Hallendal + + * help/C/gedit-C.omf: revered my category change. Thanks Irene for + pointing out the new category. + +2002-08-21 Mikael Hallendal + + * help/C/gedit-C.omf: fixed the ScrollKeeper category. Now in + GNOME|Applications. + +2002-08-20 Paolo Maggi + + * configure.in: + * README: bump version to 2.0.3 + +2002-08-16 Paolo Maggi + + * data/gedit.desktop.in: added a semicolon at the end of + the categories list (thanks to Havoc Pennington for the + patch) + +2002-07-24 Paolo Maggi + + [ gedit 2.0.2 released ] + +2002-07-24 Paolo Maggi + + * configure.in: + * README: bump version to 2.0.2 + +2002-07-18 Paolo Maggi + + * TODO: Updated + +2002-07-17 James Willcox + + * configure.in: Added AM_DISABLE_STATIC, which disables the building + of static libraries (for plugins). + +2002-07-16 Paolo Maggi + + * TODO: Updated + +2002-07-15 Paolo Maggi + + [ gedit 2.0.1 released ] + +2002-07-15 Paolo Maggi + + * configure.in: + * README: bump version to 2.0.1 + +2002-07-12 Paolo Maggi + + * TODO: Updated + +2002-07-10 Paolo Maggi + + * data/gedit.schemas.in: + s/GEDIT_SAVE_CURRENT_LOCALE_WHEN_POSSIBLE/GEDIT_SAVE_CURRENT_LOCALE_IF_POSSIBLE, + added GEDIT_SAVE_ORIGINAL_FILE_ENCODING_IF_POSSIBLE_NCL description + + * TODO: Upated + +2002-07-09 Paolo Maggi + + * TODO: Updated + +2002-07-09 Paolo Maggi + + * Makefile.am: fixed ('make distcheck' works again) + + * data/Makefile.am: ditto + +2002-07-09 Mark McLoughlin + + * data/gedit.desktop.in: use X-GNOME-DocPath instead + of DocPath. + +2002-07-08 Paolo Maggi + + * Moved gedit.schemas, gedit.1, gedit.desktop.in, gedit.spec.in, + gedit.keys.in in the data dir + +2002-07-08 Paolo Maggi + + * .cvsignore: Updated + +2002-07-05 Paolo Maggi + + * TODO: Updated + + * gedit.1: added Federico to the Authors list + +2002-07-04 Paolo Maggi + + * TODO: Updated + +2002-07-04 Paolo Maggi + + * gedit.schemas: s/GEdit/gedit, change the backup_copy_extension + default to ~ + +2002-07-03 Federico Mena Quintero + + * gedit.schemas: Rewrote the schema file for the new preferences + setup. Should be the last part to fix #84535. + +2002-07-03 Paolo Maggi + + * configure.in: now gedit depends on eel-2.0 + +2002-06-19 Paolo Maggi + + [ gedit 2.0.0 released ] + +2002-06-19 Paolo Maggi + + * help/C/gedit.xml + * help/C/gedit-C.xml + * help/C/figures/gedit_window.png: updated (thanks to + Irene Ryan) + +2002-06-14 Paolo Maggi + + * configure.in: + * README: bump version to 2.0.0 + + * AUTHORS: added Federico + +2002-06-10 Paolo Maggi + + [ gedit 1.199.0 released ] + +2002-06-10 Paolo Maggi + + * configure.in: bump version to 1.199.0, requirements updated + +2002-06-10 Naba Kumar + + * configure.in: Added hi in ALL_LINGUAS + +2002-05-31 Paolo Maggi + + [ gedit 1.121.1 released ] + +2002-05-31 Paolo Maggi + + * configure.in: bump version to 1.121.1 + +2002-05-27 Paolo Maggi + + [ gedit 1.121.0 released ] + +2002-05-27 Paolo Maggi + + * configure.in: bump version to 1.121.0, requirements updated + +2002-05-27 James Willcox + + * README: Small changes in wording + * HACKING: ditto + +2002-05-27 Yanko Kaneti + + * configure.in: (ALL_LINGUAS) Added Bulgarian (bg). + +2002-05-21 Paolo Maggi + + [ gedit 1.120.0 released ] + +2002-05-21 Paolo Maggi + + * configure.in: bump version to 1.120.0, + require intltool 0.21 + + * README: Updated (1.119.0 -> 1.120.0) + + * Makefile.am: now make distcheck should work + +2002-05-20 Paolo Maggi + + * gedit.schemas: fixed bug #81974 + +2002-05-13 Paolo Maggi + + [ gedit 1.119.0 released ] + +2002-05-13 Paolo Maggi + + * configure.in: bump version to 1.119.0 + + * README: Updated (1.118.0 -> 1.119.0) + +2002-05-08 Pablo Saratxaga + + * configure.in: Added Basque (eu) and Vietnamese (vi) to ALL_LINGUAS + +2002-04-29 Satyajit Kanungo + + * gedit.desktop.in, Added the DocPath in the desktop file + +2002-05-03 Paolo Maggi + + * HACKING: typos + +2002-05-03 Paolo Maggi + + * README: updated + +2002-04-29 Paolo Maggi + + [gedit 1.118.0 released] + +2002-04-29 Paolo Maggi + + * configure.in: bump version to 1.118.0 + +2002-04-20 Paolo Maggi + + * TODO: Updated + +2002-04-15 James Willcox + + [gedit 1.117.0 released] + +2002-04-15 James Willcox + + * configure.in: bump version to 1.117.0 + +2002-04-03 Arvind S N + + * gedit.desktop.in: added %U for Exec, will launch the application + with file dropped on the icon. + +2002-04-02 Paolo Maggi + + * gedit.schemas: set "wrap lines at word boundaries" + as default (bug #76500). + +2002-03-27 Paolo Maggi + + [gedit 1.116.0 released] + +2002-03-27 Paolo Maggi + + * configure.in: bump version to 1.116.0 + +2002-03-18 Paolo Maggi + + [gedit 1.115.0 released] + +2002-03-06 Paolo Maggi + + * configure.in: bump version to 1.115.0 + + * gedit.schemas: added max-recents key + +2002-03-05 Paolo Maggi + + [gedit 1.114.0 released] + +2002-03-05 Paolo Maggi + + * HACKING: Updated (build sheriff commits welcome) + + * configure.in (ALL_LINGUAS): re-add it + +2002-03-04 Paolo Maggi + + * configure.in: bump version to 1.114.0 + requirements updated + + * Makefile.am (EXTRA_DIST): added xmldocs.make, removed + app-docs.make + + * help/C/Makefile.am: fixed a typo + + * omf-install/Makefile.am: fixed a typo + +2002-03-01 John Fleck + + * help/C/legal.xml + * help/C/gedit.xml + * help/C/gedit-C.xml + * help/C/Makefile.am + added + * help/C/figures/gedit_window.png + removed + * help/C/gedit.sgml + adding docs from Sun + +2002-02-25 Paolo Maggi + + * configure.in: bump version to 1.114.0cvs and + added AC_PREREQ(2.52) + + * gedit.1: updated + +2002-02-25 Paolo Maggi + + [gedit 1.113.0 released] + +2002-02-25 Paolo Maggi + + * TODO: Updated + + * configure.in: bump version to 1.113.0 + +2002-02-23 John Fleck + + * added + * help/C/gedit-C.omf + * help/C/gedit.xml + * help/C/legal.xml + * omf-install/Makefile.am + * changed + * Makefile.am + * configure.in + * help/Makefile.am + * help/C/Makefile.am + add docs built infrastructure. The doc itself, gedit.xml, is just + a placeholder until we get the real docs + +2002-02-23 Gediminas Paulauskas + + * configure.in (GNOME_PLATFORM_GNOME_2): remove, obsolete + (AC_OUTPUT): remove gedit.desktop -- it is generated by Makefile rule + + * gedit.desktop.in: binary was renamed back to gedit + +2002-02-22 Paolo Maggi + + * BUGS: Updated + + * HACKING: Updated + +2002-02-21 Paolo Maggi + + Name changed: gedit2->gedit + + * configure.in: bump version to 1.113.0cvs + +2002-02-21 Paolo Maggi + + * gedit.schemas: statusbar-view-cursor-position + and statusbar-view-overwrite-mode set TRUE in the default + setting + +2002-02-21 Seth Nickell + + * pixmaps/gedit-icon.png: + + Flip icon to match recommended perspective. + +2002-02-21 Seth Nickell + + * Makefile.am: + + Install .desktop file into SHARE/applications, + and merge translations at make time rather + than configure time. + + * configure.in: + + Don't merge translations at configure time. + + * gedit.desktop.in: + * gedit2.desktop.in: + + Rename file to gedit.desktop.in. + +2002-02-20 Paolo Maggi + + * gedit2.desktop.in: updated + +2002-02-18 Paolo Maggi + + * Makefile.am: removed unused code + +2002-02-14 Tõivo Leedjärv + + * configure.in: Added et to ALL_LINGUAS. + +2002-02-13 Paolo Maggi + + * TODO: Updated + +2002-02-12 Paolo Maggi + + * configure.in: bump version to 1.112.0 + (AC_OUTPUT): added plugins/ASCII/Makefile + + * TODO: Updated + +2002-02-10 Paolo Maggi + + * configure.in: bump version to 1.111.0 + +2002-02-08 Paolo Maggi + + * configure.in (AC_OUTPUT): added plugins/diff/Makefile + +2002-02-07 Paolo Maggi + + * configure.in: bump version to 1.110.2 + (AC_OUTPUT): added plugins/taglist/Makefile + +2002-02-05 Paolo Maggi + + * configure.in: turn on additional checks for + warnings + + * CVSVERSION: new file (do not distribute) + + * TODO: Updated + +2002-02-01 Chema Celorio + + * configure.in: bump version to 1.110.1 + +2002-01-29 Paolo Maggi + + * TODO: updated + + * configure.in (AC_OUTPUT): gedit2.desktop + +2002-01-25 Paolo Maggi + + * configure.in: bump version to 1.110.0 + +2002-01-24 Paolo Maggi + + * configure.in (AC_OUTPUT): added plugins/shell_output/Makefile + + * pixmaps/shell-output-logo.png: new file + +2002-01-23 James Willcox + + * configure.in: Added option --enable-gconf-source, to specify where + to install schema files. + +2002-01-22 James Willcox + + * Fixed bug 69335, regarding the gconf schema install. + It now responds properly to GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL. + +2002-01-22 Paolo Maggi + + * AUTHORS: added James + +2002-01-21 Paolo Maggi + + * TODO: Updated + + * AUTHORS: ditto + + * HACKING: ditto + + * MAINTAINERS: ditto + +2002-01-18 Paolo Maggi + + * configure.in (AC_OUTPUT): added plugins/docinfo/Makefile + +2002-01-18 Paolo Maggi + + * configure.in: bump version to 1.109.1 + + * TODO: Updated + +2002-01-17 James Willcox + + * TODO: Updated + +2002-01-17 Hasbullah Bin Pit + + * configure.in: Added "ms" (Malay) to ALL_LINGUAS. + * po/ms.po: Added Malay translation. + +2002-01-16 Paolo Maggi + + * Makefile.am (SUBDIRS): added plugins + + * configure.in (AC_OUTPUT): added plugins/Makefile + plugins/sample/Makefile + + +2002-01-15 James Willcox + + * TODO: Updated + +2002-01-15 Paolo Maggi + + * configure.in: version number set to 1.110.0cvs + + * TODO: Updated + +2002-01-14 James Willcox + + * TODO: Updated + +2002-01-13 Paolo Maggi + + * configure.in: bump version to 1.109.0 + +2002-01-12 Paolo Maggi + + * TODO: Updated + + * gedit.schemas: updated for new statusbar + options + +2002-01-11 Paolo Maggi + + * TODO: Updated + + * gedit.schemas: updated for line numbers + +2002-01-11 Paolo Maggi + + * TODO: Updated + +2002-01-10 Jason Leach + + * TODO: Updated. + +2002-01-10 Paolo Maggi + + * TODO: Updated + +2002-01-09 Paolo Maggi + + * TODO: Updated + +2002-01-08 Paolo Maggi + + * TODO: Updated + + * gedit.schemas: Updated + +2002-01-07 Paolo Maggi + + * TODO: Updated + +2002-01-05 Paolo Maggi + + * gedit.schemas: added new printing preferences + +2002-01-04 Paolo Maggi + + * TODO: Updated + +2001-12-29 Paolo Maggi + + * gedit.schemas: Rewritten + +2001-12-17 Paolo Maggi + + * TODO: Updated + +2001-12-14 Gediminas Paulauskas + + * configure.in: add check for glib-genmarshal + +2001-12-12 Paolo Maggi + + * TODO: update + +2001-12-11 James Willcox + + * Makefile.am: fixed GConf schema installation + +2001-12-10 James Willcox + + * gedit.schemas: New file -- GConf schema, used for preferences. + + * Makefile.am: Added stuff to install the GConf schema + +2001-12-10 Paolo Maggi + + * TODO : updated + +2001-12-09 Paolo Maggi + + * TODO : updated + + * BUGS: updated + + * configure.in: bump version to 1.108.0 + +2001-12-05 Chema Celorio + + * configure.in: bump version to 1.107.0 + +2001-12-03 Carlos Perelló Marín + + * configure.in: Reverted my change about GETTEXT_PACKAGE. We should + use the "standar" name (gedit-2.0 instead of gedit-2). + +2001-12-03 Paolo Maggi + + * TODO : updated + +2001-12-02 Paolo Maggi + + * configure.in: cleaned following the suggestions of the gnome2 + porting foc. Now libgnomeprintui-2.0 is required + +2001-11-21 Carlos Perelló Marín + + * configure.in: Changed GETTEXT_PACKAGE from gedit-2.0 to gedit-2 + +2001-11-16 Carlos Perelló Marín + + * Makefile.am, configure.in: Migrated from xml-i18n-tools to intltool + and added support to AM_GLIB_GNU_GETTEXT + * acconfig.h: Added GETTEXT_PACKAGE + +2001-11-16 Paolo Maggi + + * Started the port to GNOME 2.0 + +2001-11-16 Carlos Perelló Marín + + * ChangeLog: rolled over to ChangeLog-20011116 diff --git a/Makefile.am b/Makefile.am index 456122c2..14c06918 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,7 @@ ## Process this file with automake to produce Makefile.in +ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = gedit pixmaps po help data plugins +SUBDIRS = bindings gedit pixmaps po help data plugins distuninstallcheck_listfiles = find . -type f -print | grep -v scrollkeeper diff --git a/NEWS b/NEWS index d25091c3..80a4b6bf 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,28 @@ +============ +gedit 2.13.0 +============ + +New features and fixes +====================== +Reworked codebase based on the new_mdi cvs branch, +among other things, it features: +- improved tabbed widget, for instance tabs are reorderable +- GtkUIManager is now used for menus and toolbar instead of + libbonoboui +- A side panel and a bottom panel have been added +- A new gobject-based plugin system has been implemented +- Plugins can now be written in Python +- Reading and writing of files are now handled in an + asynchronous way (so the user interface never blocks) +- Local files are read using mmap (when possible) +- Incremental search is supported (use Ctrl+K) +- A lot of usability improvements with some new UI experiment + are featured +- Startup time and performaces have been improved +- Remote file saving is supported (for a limited configurable + set of VFS methods) + + ============ gedit 2.12.1 ============ @@ -262,224 +287,3 @@ New and updated translations - Josep Puigdemont (ca) - Ilkka Tuohela (fi) - -=========== -gedit 2.9.7 -=========== - -Fixes -===== -- Fix autosave for a file that was not saved manually (Paolo Maggi) -- Specifing the line number from the command line now works (Paolo Maggi) -- Speed up search and replace (Paolo Borelli) -- Fix crash in the insert time plugin (Paolo Borelli) -- Fix small memory leak (Paolo Borelli) -- Use icon from the icon theme (Paolo Borelli) - -New and updated translations -============================ -- Rostislav Raykov (bg) -- Jordi Mallach (ca) -- Miloslav Trmac (cs) -- Ole Laursen (da) -- Frank Arnold (de) -- Kostas Papadimas (el) -- Adam Weinberger (en_CA) -- David Lodge (en_GB) -- Francisco Javier F. Serrador (es) -- Priit Laes (et) -- Sami Pesonen (fi) -- Ankit Patel (gu) -- Roberto Rosselli Del Turco (it) -- Takeshi AIHANA (ja) -- Young-Ho Cha (ko) -- Žygimantas Beručka (lt) -- Kjartan Maraas (nb) -- Reinout van Schouwen (nl) -- Kjartan Maraas (no) -- GNOME PL Team (pl) -- Duarte Loreto (pt) -- Leonid Kanter (ru) -- Marcel Telka (sk) -- Laurent Dhima (sq) -- Christian Rose (sv) -- Maxim V. Dziumanenko (uk) - - -=========== -gedit 2.9.6 -=========== - -Fixes -===== -- Fix Alt+N accelerator to switch documents (Paolo Maggi) -- Spell checker bugfixes (Paolo Maggi) -- Update the list of languages in the spell checker (Yaacov Zamir) -- Fix per display registration (Paolo Maggi) -- Fix potential crash for menus containing "/" (Paolo Borelli) -- Fix small memory leak (Paolo Borelli) - -New and updated translations -============================ -- Leonid Kanter (ru) -- Duarte Loreto (pt) -- Francisco Javier F. Serrador (es) -- Rhys Jones (cy) -- Frank Arnold (de) -- Kostas Papadimas (el) -- David Lodge (en_GB) -- Žygimantas Beručka (lt) -- Raphael Higino (pt_BR) -- Marcel Telka (sk) -- Rostislav Raykov (bg) -- Miloslav Trmac (cs) -- Vincent van Adrighem (nl) -- Theppitak Karoonboonyanan (th) -- Adam Weinberger (en_CA) -- Takeshi AIHANA (ja) - - -============================== -gedit 2.9.5 - "Paleozoic Bugs" -============================== - -Fixes -===== -- Undoing to an unmodified state resets the modified flag (Paolo Maggi) -- Fix saving in UTF-16 and others encondings (Paolo Maggi) -- ESC closes the find dialog (Paolo Maggi) -- Fix crash in Recent-files (Paolo Borelli) -- Change the cursor color when changing the text color (Paolo Maggi) -- Smarter HOME/END cursor movement (Paolo Maggi) - -New and updated translations -============================ -- Rostislav Raykov (bg) -- Funda Wang (zh_CN) -- Francisco Javier F. Serrador (es) -- Frank Arnold (de) -- Marcel Telka (sk) -- Leonid Kanter (ru) -- Priit Laes (et) -- Rhys Jones (cy) -- Nikos Charonitakis (el) -- Adam Weinberger (en_CA) -- Kjartan Maraas (nb, no) -- Žygimantas Beručka (lt) -- Takeshi AIHANA (ja) - - -=========== -gedit 2.9.4 -=========== - -New Features -============ -- optional current line highlighting (Paolo Maggi) -- optional bracket matching (Jurg Billeter) -- "Save a Copy" plugin, with gnome-vfs support (Paolo Borelli) - -Fixes -===== -- HIG fix in the close confirmation dialog (Naveen Chandranv) -- sync to latest recent-files library (Paolo Maggi) - -New and updated translations -============================ -- Laurent Dhima (sq) -- Kostas Papadimas (el) -- Kjartan Maraas (nb) -- Miloslav Trmac (cs) -- Vincent van Adrighem (nl) -- Francisco Javier F. Serrador (es) -- Žygimantas Beručka (lt) -- Adam Weinberger (en_CA) -- Takeshi AIHANA (ja) - - -=========== -gedit 2.9.3 -=========== - -Fixes -===== -- Minor UI tweaks (Paolo Maggi) -- Listen to autosave settings changes (Paolo Maggi) -- accessibility fixes (Srirama Sharma) -- Do not create backups in autosave mode (Paolo Borelli) -- do not retrieve the mime type multiple times for each document (Paolo Borelli) -- split I/O error dialogs to a separete file (Paolo Borelli) -- delay recent view initialization (Paolo Borelli) - - -New and updated translations -============================ -- Laurent Dhima (sq) -- Tommi Vainikainen (fi) -- Takeshi AIHANA (ja) -- Žygimantas Beručka (lt) -- Miloslav Trmac (cs) -- Adam Weinberger (en_CA) -- Francisco Javier F. Serrador (es) - - -=========== -gedit 2.9.2 -=========== - -Fixes -===== -- bump gtksourceview requirement to 1.1 -- improve default language detection for the spell plugin (Paolo Maggi) -- plug some memory leaks (Paolo Borelli) -- fix a bug and a critical warning when adding an encoding (Loïc Minier) -- listen to max-recents changes in gconf (Paolo Borelli) -- open new files specified on the command line in the proper order. (Paolo Borelli) -- Move to the new gtk api (about dialog, alerts etc) (Paolo Borelli) -- Fix a crash loading remote files (Paolo Maggi) -- Improve file naming in the window title (Paolo Maggi) - * modified documents are prefixed with a "*" - * the title of the window now has the format "filename (directory) - gedit" -- Use Pango fonts when printing (Owen Taylor) -- Check if the metadata file exists before trying to parse it (Marco Pesenti Gritti) -- Misc code cleanups (Paolo Borelli) - - -New and updated translations -============================ -- Kjartan Maraas (nb) -- Martin Willemoes Hansen (da) -- David Lodge (en_GB) -- Meelad Zakaria (fa) -- Vladimir Petkov (bg) -- Laurent Dhima (sq) -- Takeshi AIHANA (ja) - - -=========== -gedit 2.9.1 -=========== - -Fixes -===== -- Remove obsolete nautilus view (Paolo Borelli) -- Fix compile with picky compilers (Marco Pesenti Gritti) -- avoid duplicate key accel in the file chooser (Paolo Borelli) -- s/Untitled/Unsaved Document to be HIG v.2 compliant (Paolo Maggi) -- enable some of plugins by default. The way active plugins are stored in - gconf changed, you may have to re-select some of the plugins (Paolo Maggi) -- new methods and signals for the output window (Paolo Maggi) -- remove some obsolete gedit_document_* functions, external plugins may - need to be updated to use GtkTextView api (Paolo Borelli); -- misc cleanups (Paolo Borelli) -- fix linking issues (Chris Kelso) - - -New and updated translations -============================ -- Adam Weinberger (en_CA) -- Miloslav Trmac (cs) -- Jordi Mallach (ca) -- Mohammad DAMT (id -- Christophe Merlet (fr) - diff --git a/README b/README index acd34d54..2b9f6c36 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ General Information =================== -This is version 2.12.1 of gedit. gedit is a small and lightweight UTF-8 text +This is version 2.13.0 of gedit. gedit is a small and lightweight UTF-8 text editor for the GNOME environment. gedit is part of GNOME and uses the latest GTK+ and GNOME libraries. @@ -18,23 +18,21 @@ average text editor (plugins being the most notable of these). Although new features are always under development, currently gedit has: * Complete support for UTF-8 text - * File Revert - * Read files using the GNOME VFS - * Cut/Copy/Paste and Select All text + * Syntax highlighting + * GNOME VFS support for remote files * Complete integration with the GNOME Environment * Search and Replace + * File Revert * A complete preferences interface - * Configurable Plugins system + * Configurable Plugins system, with optional python support * Printing and Print Previewing Support - * Configurable levels of Undo/Redo - * Syntax highlighting + Some of the plugins, packaged and installed with gedit include, among others: * Word count * Spell checker * Change case of selected text - * Save a Copy * Sort * Tag list * Insert Date/Time @@ -63,12 +61,12 @@ Information about gedit mailing lists can be found at Installation ============ -gedit requires GTK+-2.6.x (x >= 3 recommended), GtkSourceView 1.2.0 and GNOME 2.8.x libraries. +gedit requires GTK+-2.8.x, GtkSourceView 1.2.0 and GNOME 2.12.x libraries. Simple install procedure: - % gzip -cd gedit-2.12.1.tar.gz | tar xvf - # unpack the sources - % cd gedit-2.12.1 # change to the toplevel directory + % gzip -cd gedit-2.13.0.tar.gz | tar xvf - # unpack the sources + % cd gedit-2.13.0 # change to the toplevel directory % ./configure # run the `configure' script % make # build gedit [ Become root if necessary ] diff --git a/autogen.sh b/autogen.sh index 14129b74..5a4abefc 100755 --- a/autogen.sh +++ b/autogen.sh @@ -6,7 +6,7 @@ test -z "$srcdir" && srcdir=. PKG_NAME="gedit" -(test -f $srcdir/configure.in \ +(test -f $srcdir/configure.ac \ && test -f $srcdir/README \ && test -d $srcdir/gedit) || { echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" @@ -19,6 +19,4 @@ which gnome-autogen.sh || { exit 1 } -REQUIRED_AUTOMAKE_VERSION=1.7.2 - -USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh +ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4" REQUIRED_AUTOMAKE_VERSION=1.8 REQUIRED_MACROS=python.m4 USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh diff --git a/bindings/.cvsignore b/bindings/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/bindings/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/bindings/Makefile.am b/bindings/Makefile.am new file mode 100644 index 00000000..1af48329 --- /dev/null +++ b/bindings/Makefile.am @@ -0,0 +1,5 @@ +SUBDIRS = + +if ENABLE_PYTHON +SUBDIRS += python +endif diff --git a/bindings/python/.cvsignore b/bindings/python/.cvsignore new file mode 100644 index 00000000..65906a63 --- /dev/null +++ b/bindings/python/.cvsignore @@ -0,0 +1,4 @@ +Makefile +Makefile.in +gedit.c +gedit.defs.new diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am new file mode 100644 index 00000000..5529e655 --- /dev/null +++ b/bindings/python/Makefile.am @@ -0,0 +1,61 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = gedit.la + +nodist_gedit_la_SOURCES = gedit.c + +gedit_la_LDFLAGS = \ + -module -avoid-version + +gedit_la_LIBADD = \ + $(PYTHON_LIBS) \ + $(PYTHON_EXTRA_LIBS) \ + $(PYGTK_LIBS) + +gedit_la_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/gedit \ + $(GEDIT_CFLAGS) \ + $(NO_STRICT_ALIASING_CFLAGS) \ + $(PYGTK_CFLAGS) \ + $(PYTHON_CFLAGS) \ + $(AM_CFLAGS) + +gedit.c: gedit.defs gedit.override + ( cd $(srcdir) && $(PYGTK_CODEGEN) \ + --register $(PYGTK_DEFSDIR)/pango-types.defs \ + --register $(PYGTK_DEFSDIR)/gdk-types.defs \ + --register $(PYGTK_DEFSDIR)/gtk-types.defs \ + --register $(PYGTK_DEFSDIR)/gtksourceview.defs \ + --override $*.override \ + --prefix py$* $( $@ + +BINDING_HEADERS_SRCDIR_IN = \ + gedit/gedit-app.h \ + gedit/gedit-document.h \ + gedit/gedit-encodings.h \ + gedit/gedit-plugin.h \ + gedit/gedit-view.h \ + gedit/gedit-tab.h \ + gedit/gedit-panel.h \ + gedit/gedit-window.h \ + gedit/gedit-help.h + +BINDING_HEADERS_BUILDDIR_IN = + +BINDING_HEADERS_SRCDIR := $(addprefix $(top_srcdir)/,$(BINDING_HEADERS_SRCDIR_IN)) +BINDING_HEADERS_BUILDDIR := $(addprefix $(top_builddir)/,$(BINDING_HEADERS_BUILDDIR_IN)) + +regenerate-python-binding: + $(PYGTK_H2DEF) $(sort $(BINDING_HEADERS_SRCDIR) $(BINDING_HEADERS_BUILDDIR)) > gedit.defs.new + +BUILT_SOURCES = gedit.c + +EXTRA_DIST = \ + gedit.override \ + gedit.defs + +CLEANFILES = $(BUILT_SOURCES) + +dist-hook: + cd $(distdir); rm -f $(BUILT_SOURCES) diff --git a/bindings/python/gedit.defs b/bindings/python/gedit.defs new file mode 100644 index 00000000..4c701635 --- /dev/null +++ b/bindings/python/gedit.defs @@ -0,0 +1,808 @@ +;; -*- scheme -*- +; object definitions ... +(define-object App + (in-module "Gedit") + (parent "GObject") + (c-name "GeditApp") + (gtype-id "GEDIT_TYPE_APP") +) + +(define-object Document + (in-module "Gedit") + (parent "GtkSourceBuffer") + (c-name "GeditDocument") + (gtype-id "GEDIT_TYPE_DOCUMENT") +) + +(define-object Panel + (in-module "Gedit") + (parent "GtkVBox") + (c-name "GeditPanel") + (gtype-id "GEDIT_TYPE_PANEL") +) + +(define-object Plugin + (in-module "Gedit") + (parent "GObject") + (c-name "GeditPlugin") + (gtype-id "GEDIT_TYPE_PLUGIN") +) + +(define-object Tab + (in-module "Gedit") + (parent "GtkVBox") + (c-name "GeditTab") + (gtype-id "GEDIT_TYPE_TAB") +) + +(define-object View + (in-module "Gedit") + (parent "GtkSourceView") + (c-name "GeditView") + (gtype-id "GEDIT_TYPE_VIEW") +) + +(define-object Window + (in-module "Gedit") + (parent "GtkWindow") + (c-name "GeditWindow") + (gtype-id "GEDIT_TYPE_WINDOW") +) + +;; Enumerations and flags ... + +(define-flags SearchFlags + (in-module "Gedit") + (c-name "GeditSearchFlags") + (values + '("dont-set-flags" "GEDIT_SEARCH_DONT_SET_FLAGS") + '("entire-word" "GEDIT_SEARCH_ENTIRE_WORD") + '("case-sensitive" "GEDIT_SEARCH_CASE_SENSITIVE") + ) +) + +(define-enum TabState + (in-module "Gedit") + (c-name "GeditTabState") + (values + '("state-normal" "GEDIT_TAB_STATE_NORMAL") + '("state-loading" "GEDIT_TAB_STATE_LOADING") + '("state-reverting" "GEDIT_TAB_STATE_REVERTING") + '("state-saving" "GEDIT_TAB_STATE_SAVING") + '("state-printing" "GEDIT_TAB_STATE_PRINTING") + '("state-print-previewing" "GEDIT_TAB_STATE_PRINT_PREVIEWING") + '("state-showing-print-preview" "GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW") + '("state-generic-not-editable" "GEDIT_TAB_STATE_GENERIC_NOT_EDITABLE") + '("state-loading-error" "GEDIT_TAB_STATE_LOADING_ERROR") + '("state-reverting-error" "GEDIT_TAB_STATE_REVERTING_ERROR") + '("state-saving-error" "GEDIT_TAB_STATE_SAVING_ERROR") + '("state-generic-error" "GEDIT_TAB_STATE_GENERIC_ERROR") + '("state-closing" "GEDIT_TAB_STATE_CLOSING") + '("num-of-states" "GEDIT_TAB_NUM_OF_STATES") + ) +) + +(define-flags WindowState + (in-module "Gedit") + (c-name "GeditWindowState") + (values + '("state-normal" "GEDIT_WINDOW_STATE_NORMAL") + '("state-saving" "GEDIT_WINDOW_STATE_SAVING") + '("state-printing" "GEDIT_WINDOW_STATE_PRINTING") + '("state-loading" "GEDIT_WINDOW_STATE_LOADING") + '("state-error" "GEDIT_WINDOW_STATE_ERROR") + '("state-saving-session" "GEDIT_WINDOW_STATE_SAVING_SESSION") + ) +) + +;; Boxed types +(define-boxed Encoding + (in-module "Gedit") + (c-name "GeditEncoding") + (gtype-id "GEDIT_TYPE_ENCODING") + (copy-func "gedit_encoding_copy") + (release-func "gedit_encoding_free") +;; (fields +;; '("gint" "index") +;; '("gchar*" "charset") +;; '("gchar*" "name") +;; ) +) + + +;; From ../../gedit/gedit-app.h + +(define-function gedit_app_get_type + (c-name "gedit_app_get_type") + (return-type "GType") +) + +(define-function gedit_app_get_default + (c-name "gedit_app_get_default") + (return-type "GeditApp*") +) + +(define-method create_window + (of-object "GeditApp") + (c-name "gedit_app_create_window") + (return-type "GeditWindow*") +) + +(define-method get_windows + (of-object "GeditApp") + (c-name "gedit_app_get_windows") + (return-type "const-GList*") +) + +(define-method get_active_window + (of-object "GeditApp") + (c-name "gedit_app_get_active_window") + (return-type "GeditWindow*") +) + +(define-method get_documents + (of-object "GeditApp") + (c-name "gedit_app_get_documents") + (return-type "GList*") +) + +(define-method get_views + (of-object "GeditApp") + (c-name "gedit_app_get_views") + (return-type "GList*") +) + + + +;; From ../../gedit/gedit-document.h + +(define-function gedit_document_error_quark + (c-name "gedit_document_error_quark") + (return-type "GQuark") +) + +(define-function gedit_document_get_type + (c-name "gedit_document_get_type") + (return-type "GType") +) + +(define-function gedit_document_new + (c-name "gedit_document_new") + (is-constructor-of "GeditDocument") + (return-type "GeditDocument*") +) + +(define-method get_uri + (of-object "GeditDocument") + (c-name "gedit_document_get_uri") + (return-type "gchar*") +) + +(define-method get_uri_for_display + (of-object "GeditDocument") + (c-name "gedit_document_get_uri_for_display") + (return-type "gchar*") +) + +(define-method get_short_name_for_display + (of-object "GeditDocument") + (c-name "gedit_document_get_short_name_for_display") + (return-type "gchar*") +) + +(define-method get_mime_type + (of-object "GeditDocument") + (c-name "gedit_document_get_mime_type") + (return-type "gchar*") +) + +(define-method get_readonly + (of-object "GeditDocument") + (c-name "gedit_document_get_readonly") + (return-type "gboolean") +) + +(define-method load + (of-object "GeditDocument") + (c-name "gedit_document_load") + (return-type "gboolean") + (parameters + '("const-gchar*" "uri") + '("const-GeditEncoding*" "encoding") + '("gint" "line_pos") + '("gboolean" "create") + ) +) + +(define-method insert_file + (of-object "GeditDocument") + (c-name "gedit_document_insert_file") + (return-type "gboolean") + (parameters + '("GtkTextIter*" "iter") + '("const-gchar*" "uri") + '("const-GeditEncoding*" "encoding") + ) +) + +(define-method load_cancel + (of-object "GeditDocument") + (c-name "gedit_document_load_cancel") + (return-type "gboolean") +) + +(define-method save + (of-object "GeditDocument") + (c-name "gedit_document_save") + (parameters + '("GeditDocumentSaveFlags" "flags") + ) + (return-type "none") +) + +(define-method save_as + (of-object "GeditDocument") + (c-name "gedit_document_save_as") + (return-type "none") + (parameters + '("const-gchar*" "uri") + '("const-GeditEncoding*" "encoding") + '("GeditDocumentSaveFlags" "flags") + ) +) + +(define-method is_untouched + (of-object "GeditDocument") + (c-name "gedit_document_is_untouched") + (return-type "gboolean") +) + +(define-method is_untitled + (of-object "GeditDocument") + (c-name "gedit_document_is_untitled") + (return-type "gboolean") +) + +(define-method get_deleted + (of-object "GeditDocument") + (c-name "gedit_document_get_deleted") + (return-type "gboolean") +) + +(define-method goto_line + (of-object "GeditDocument") + (c-name "gedit_document_goto_line") + (return-type "gboolean") + (parameters + '("gint" "line") + ) +) + +(define-method set_search_text + (of-object "GeditDocument") + (c-name "gedit_document_set_search_text") + (return-type "none") + (parameters + '("const-gchar*" "text") + '("guint" "flags") + ) +) + +(define-method get_search_text + (of-object "GeditDocument") + (c-name "gedit_document_get_search_text") + (return-type "gchar*") + (parameters + '("guint*" "flags") + ) +) + +(define-method get_can_search_again + (of-object "GeditDocument") + (c-name "gedit_document_get_can_search_again") + (return-type "gboolean") +) + +(define-method search_forward + (of-object "GeditDocument") + (c-name "gedit_document_search_forward") + (return-type "gboolean") + (parameters + '("const-GtkTextIter*" "start") + '("const-GtkTextIter*" "end") + '("GtkTextIter*" "match_start") + '("GtkTextIter*" "match_end") + ) +) + +(define-method replace_all + (of-object "GeditDocument") + (c-name "gedit_document_replace_all") + (return-type "gint") + (parameters + '("const-gchar*" "find") + '("const-gchar*" "replace") + '("guint" "flags") + ) +) + +(define-method search_backward + (of-object "GeditDocument") + (c-name "gedit_document_search_backward") + (return-type "gboolean") + (parameters + '("const-GtkTextIter*" "start") + '("const-GtkTextIter*" "end") + '("GtkTextIter*" "match_start") + '("GtkTextIter*" "match_end") + ) +) + +(define-method set_language + (of-object "GeditDocument") + (c-name "gedit_document_set_language") + (return-type "none") + (parameters + '("GtkSourceLanguage*" "lang") + ) +) + +(define-method get_language + (of-object "GeditDocument") + (c-name "gedit_document_get_language") + (return-type "GtkSourceLanguage*") +) + +(define-method get_encoding + (of-object "GeditDocument") + (c-name "gedit_document_get_encoding") + (return-type "const-GeditEncoding*") +) + +(define-method set_auto_save_enabled + (of-object "GeditDocument") + (c-name "gedit_document_set_auto_save_enabled") + (return-type "none") + (parameters + '("gboolean" "enable") + ) +) + +(define-method set_auto_save_interval + (of-object "GeditDocument") + (c-name "gedit_document_set_auto_save_interval") + (return-type "none") + (parameters + '("gint" "interval") + ) +) + + + +;; From ../../gedit/gedit-encodings.h + +(define-function gedit_encoding_get_type + (c-name "gedit_encoding_get_type") + (return-type "GType") +) + +(define-method copy + (of-object "GeditEncoding") + (c-name "gedit_encoding_copy") + (return-type "GeditEncoding*") +) + +(define-method free + (of-object "GeditEncoding") + (c-name "gedit_encoding_free") + (return-type "none") +) + +(define-function gedit_encoding_get_from_charset + (c-name "gedit_encoding_get_from_charset") + (return-type "const-GeditEncoding*") + (parameters + '("const-gchar*" "charset") + ) +) + +(define-function gedit_encoding_get_from_index + (c-name "gedit_encoding_get_from_index") + (return-type "const-GeditEncoding*") + (parameters + '("gint" "index") + ) +) + +(define-method to_string + (of-object "GeditEncoding") + (c-name "gedit_encoding_to_string") + (return-type "gchar*") +) + +(define-method get_name + (of-object "GeditEncoding") + (c-name "gedit_encoding_get_name") + (return-type "const-gchar*") +) + +(define-method get_charset + (of-object "GeditEncoding") + (c-name "gedit_encoding_get_charset") + (return-type "const-gchar*") +) + +(define-function gedit_encoding_get_utf8 + (c-name "gedit_encoding_get_utf8") + (return-type "const-GeditEncoding*") +) + +(define-function gedit_encoding_get_current + (c-name "gedit_encoding_get_current") + (return-type "const-GeditEncoding*") +) + + + +;; From ../../gedit/gedit-help.h + +(define-function help_display + (c-name "gedit_help_display") + (return-type "gboolean") + (parameters + '("GtkWindow*" "parent") + '("const-gchar*" "file_name") + '("const-gchar*" "link_id") + ) +) + + + +;; From ../../gedit/gedit-panel.h + +(define-function gedit_panel_get_type + (c-name "gedit_panel_get_type") + (return-type "GType") +) + +(define-function gedit_panel_new + (c-name "gedit_panel_new") + (is-constructor-of "GeditPanel") + (return-type "GtkWidget*") +) + +(define-method add_item + (of-object "GeditPanel") + (c-name "gedit_panel_add_item") + (return-type "none") + (parameters + '("GtkWidget*" "item") + '("const-gchar*" "name") + '("GtkWidget*" "image") + ) +) + +(define-method add_item_with_stock_icon + (of-object "GeditPanel") + (c-name "gedit_panel_add_item_with_stock_icon") + (return-type "none") + (parameters + '("GtkWidget*" "item") + '("const-gchar*" "name") + '("const-gchar*" "stock_id") + ) +) + +(define-method remove_item + (of-object "GeditPanel") + (c-name "gedit_panel_remove_item") + (return-type "gboolean") + (parameters + '("GtkWidget*" "item") + ) +) + +(define-method activate_item + (of-object "GeditPanel") + (c-name "gedit_panel_activate_item") + (return-type "gboolean") + (parameters + '("GtkWidget*" "item") + ) +) + +(define-method item_is_active + (of-object "GeditPanel") + (c-name "gedit_panel_item_is_active") + (return-type "gboolean") + (parameters + '("GtkWidget*" "item") + ) +) + + + +;; From ../../gedit/gedit-plugin.h + +(define-function gedit_plugin_get_type + (c-name "gedit_plugin_get_type") + (return-type "GType") +) + +(define-method activate + (of-object "GeditPlugin") + (c-name "gedit_plugin_activate") + (return-type "none") + (parameters + '("GeditWindow*" "window") + ) +) + +(define-method deactivate + (of-object "GeditPlugin") + (c-name "gedit_plugin_deactivate") + (return-type "none") + (parameters + '("GeditWindow*" "window") + ) +) + +(define-method update_ui + (of-object "GeditPlugin") + (c-name "gedit_plugin_update_ui") + (return-type "none") + (parameters + '("GeditWindow*" "window") + ) +) + +(define-method is_configurable + (of-object "GeditPlugin") + (c-name "gedit_plugin_is_configurable") + (return-type "gboolean") +) + +(define-method create_configure_dialog + (of-object "GeditPlugin") + (c-name "gedit_plugin_create_configure_dialog") + (return-type "GtkWidget*") +) + + + +;; From ../../gedit/gedit-tab.h + +(define-function gedit_tab_get_type + (c-name "gedit_tab_get_type") + (return-type "GType") +) + +(define-method get_view + (of-object "GeditTab") + (c-name "gedit_tab_get_view") + (return-type "GeditView*") +) + +(define-method get_document + (of-object "GeditTab") + (c-name "gedit_tab_get_document") + (return-type "GeditDocument*") +) + +(define-function gedit_tab_get_from_document + (c-name "gedit_tab_get_from_document") + (return-type "GeditTab*") + (parameters + '("GeditDocument*" "doc") + ) +) + +(define-method get_state + (of-object "GeditTab") + (c-name "gedit_tab_get_state") + (return-type "GeditTabState") +) + +;; From ../../gedit/gedit-view.h + +(define-function gedit_view_get_type + (c-name "gedit_view_get_type") + (return-type "GtkType") +) + +(define-function gedit_view_new + (c-name "gedit_view_new") + (is-constructor-of "GeditView") + (return-type "GtkWidget*") + (parameters + '("GeditDocument*" "doc") + ) +) + +(define-method cut_clipboard + (of-object "GeditView") + (c-name "gedit_view_cut_clipboard") + (return-type "none") +) + +(define-method copy_clipboard + (of-object "GeditView") + (c-name "gedit_view_copy_clipboard") + (return-type "none") +) + +(define-method paste_clipboard + (of-object "GeditView") + (c-name "gedit_view_paste_clipboard") + (return-type "none") +) + +(define-method delete_selection + (of-object "GeditView") + (c-name "gedit_view_delete_selection") + (return-type "none") +) + +(define-method select_all + (of-object "GeditView") + (c-name "gedit_view_select_all") + (return-type "none") +) + +(define-method scroll_to_cursor + (of-object "GeditView") + (c-name "gedit_view_scroll_to_cursor") + (return-type "none") +) + +(define-method set_colors + (of-object "GeditView") + (c-name "gedit_view_set_colors") + (return-type "none") + (parameters + '("gboolean" "def") + '("GdkColor*" "backgroud") + '("GdkColor*" "text") + '("GdkColor*" "selection") + '("GdkColor*" "sel_text") + ) +) + +(define-method set_font + (of-object "GeditView") + (c-name "gedit_view_set_font") + (return-type "none") + (parameters + '("gboolean" "def") + '("const-gchar*" "font_name") + ) +) + + + +;; From ../../gedit/gedit-window.h + +(define-function gedit_window_get_type + (c-name "gedit_window_get_type") + (return-type "GType") +) + +(define-method create_tab + (of-object "GeditWindow") + (c-name "gedit_window_create_tab") + (return-type "GeditTab*") + (parameters + '("gboolean" "jump_to") + ) +) + +(define-method create_tab_from_uri + (of-object "GeditWindow") + (c-name "gedit_window_create_tab_from_uri") + (return-type "GeditTab*") + (parameters + '("const-gchar*" "uri") + '("const-GeditEncoding*" "encoding") + '("gint" "line_pos") + '("gboolean" "create") + '("gboolean" "jump_to") + ) +) + +(define-method close_tab + (of-object "GeditWindow") + (c-name "gedit_window_close_tab") + (return-type "none") + (parameters + '("GeditTab*" "tab") + ) +) + +(define-method close_all_tabs + (of-object "GeditWindow") + (c-name "gedit_window_close_all_tabs") + (return-type "none") +) + +(define-method get_active_tab + (of-object "GeditWindow") + (c-name "gedit_window_get_active_tab") + (return-type "GeditTab*") +) + +(define-method set_active_tab + (of-object "GeditWindow") + (c-name "gedit_window_set_active_tab") + (return-type "none") + (parameters + '("GeditTab*" "tab") + ) +) + +(define-method get_active_view + (of-object "GeditWindow") + (c-name "gedit_window_get_active_view") + (return-type "GeditView*") +) + +(define-method get_active_document + (of-object "GeditWindow") + (c-name "gedit_window_get_active_document") + (return-type "GeditDocument*") +) + +(define-method get_documents + (of-object "GeditWindow") + (c-name "gedit_window_get_documents") + (return-type "GList*") +) + +(define-method get_unsaved_documents + (of-object "GeditWindow") + (c-name "gedit_window_get_unsaved_documents") + (return-type "GList*") +) + +(define-method get_views + (of-object "GeditWindow") + (c-name "gedit_window_get_views") + (return-type "GList*") +) + +(define-method get_group + (of-object "GeditWindow") + (c-name "gedit_window_get_group") + (return-type "GtkWindowGroup*") +) + +(define-method get_side_panel + (of-object "GeditWindow") + (c-name "gedit_window_get_side_panel") + (return-type "GeditPanel*") +) + +(define-method get_bottom_panel + (of-object "GeditWindow") + (c-name "gedit_window_get_bottom_panel") + (return-type "GeditPanel*") +) + +(define-method get_statusbar + (of-object "GeditWindow") + (c-name "gedit_window_get_statusbar") + (return-type "GtkWidget*") +) + +(define-method get_ui_manager + (of-object "GeditWindow") + (c-name "gedit_window_get_ui_manager") + (return-type "GtkUIManager*") +) + +(define-method get_state + (of-object "GeditWindow") + (c-name "gedit_window_get_state") + (return-type "GeditWindowState") +) + + diff --git a/bindings/python/gedit.override b/bindings/python/gedit.override new file mode 100644 index 00000000..2f5e9e08 --- /dev/null +++ b/bindings/python/gedit.override @@ -0,0 +1,199 @@ +%% +headers +#define NO_IMPORT_PYGOBJECT +#include "pygobject.h" +#include + +#include "gedit-plugin.h" +#include "gedit-app.h" +#include "gedit-encodings.h" + +void pygedit_register_classes (PyObject *d); +void pygedit_add_constants (PyObject *module, const gchar *strip_prefix); + +static PyObject * +_helper_wrap_gobject_glist (const GList *list) +{ + PyObject *py_list; + const GList *tmp; + + if ((py_list = PyList_New(0)) == NULL) { + return NULL; + } + for (tmp = list; tmp != NULL; tmp = tmp->next) { + PyObject *py_obj = pygobject_new(G_OBJECT(tmp->data)); + + if (py_obj == NULL) { + Py_DECREF(py_list); + return NULL; + } + PyList_Append(py_list, py_obj); + Py_DECREF(py_obj); + } + return py_list; +} + +%% +modulename gedit +%% +import gtk.Widget as PyGtkWidget_Type +import gobject.GObject as PyGObject_Type +import gtk.VBox as PyGtkVBox_Type +import gtk.Window as PyGtkWindow_Type +import gtk.Image as PyGtkImage_Type +import gtksourceview.SourceBuffer as PyGtkSourceBuffer_Type +import gtksourceview.SourceView as PyGtkSourceView_Type +import gtksourceview.SourceLanguage as PyGtkSourceLanguage_Type +%% +ignore-glob + *_get_type + gedit_document_error_quark + gedit_panel_add_item_with_stock_icon +%% +override gedit_app_get_windows +static PyObject * +_wrap_gedit_app_get_windows(PyGObject *self) +{ + const GList *list; + PyObject *py_list; + + list = gedit_app_get_windows (GEDIT_APP (self->obj)); + + py_list = _helper_wrap_gobject_glist (list); + + return py_list; +} +%% +override gedit_app_get_views +static PyObject * +_wrap_gedit_app_get_views(PyGObject *self) +{ + GList *list; + PyObject *py_list; + + list = gedit_app_get_views (GEDIT_APP (self->obj)); + + py_list = _helper_wrap_gobject_glist (list); + + g_list_free (list); + + return py_list; +} +%% +override gedit_app_get_documents +static PyObject * +_wrap_gedit_app_get_documents(PyGObject *self) +{ + GList *list; + PyObject *py_list; + + list = gedit_app_get_documents (GEDIT_APP (self->obj)); + + py_list = _helper_wrap_gobject_glist (list); + + g_list_free (list); + + return py_list; +} +%% +override gedit_window_get_documents +static PyObject * +_wrap_gedit_window_get_documents(PyGObject *self) +{ + GList *list; + PyObject *py_list; + + list = gedit_window_get_documents (GEDIT_WINDOW (self->obj)); + + py_list = _helper_wrap_gobject_glist (list); + + g_list_free(list); + + return py_list; +} +%% +override gedit_window_get_unsaved_documents +static PyObject * +_wrap_gedit_window_get_unsaved_documents(PyGObject *self) +{ + GList *list; + PyObject *py_list; + + list = gedit_window_get_unsaved_documents (GEDIT_WINDOW (self->obj)); + + py_list = _helper_wrap_gobject_glist (list); + + g_list_free(list); + + return py_list; +} +%% +override gedit_window_get_views +static PyObject * +_wrap_gedit_window_get_views(PyGObject *self) +{ + GList *list; + PyObject *py_list; + + list = gedit_window_get_views (GEDIT_WINDOW (self->obj)); + + py_list = _helper_wrap_gobject_glist (list); + + g_list_free(list); + + return py_list; +} +%% +override gedit_document_get_search_text +static PyObject * +_wrap_gedit_document_get_search_text(PyGObject *self) +{ + PyObject *tuple, *string; + guint flags; + gchar *ret; + + ret = gedit_document_get_search_text (GEDIT_DOCUMENT (self->obj), &flags); + + tuple = PyTuple_New(2); + if (ret) { + string = PyString_FromString(ret); + PyTuple_SetItem(tuple, 0, string); + Py_DECREF(string); + } else { + PyTuple_SetItem(tuple, 0, Py_None); + } + PyTuple_SetItem(tuple, 1, PyInt_FromLong(flags)); + + g_free(ret); + + return tuple; +} +%% +override gedit_panel_add_item kwargs +static PyObject * +_wrap_gedit_panel_add_item(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist1[] = { "item", "name", "image", NULL }; + static char *kwlist2[] = { "item", "name", "stock_id", NULL }; + PyGObject *item, *image; + char *name = NULL; + char *stock_id = NULL; + + if (PyArg_ParseTupleAndKeywords(args, kwargs, "O!sO!:GeditPanel.add_item", kwlist1, &PyGtkWidget_Type, &item, &name, &PyGtkImage_Type, &image)) { + gedit_panel_add_item(GEDIT_PANEL(self->obj), GTK_WIDGET(item->obj), name, GTK_WIDGET(image->obj)); + Py_INCREF(Py_None); + return Py_None; + } + + PyErr_Clear(); + + if (PyArg_ParseTupleAndKeywords(args, kwargs, "O!ss:GeditPanel.add_item", kwlist2, &PyGtkWidget_Type, &item, &name, &stock_id)) { + gedit_panel_add_item_with_stock_icon(GEDIT_PANEL(self->obj), GTK_WIDGET(item->obj), name, stock_id); + Py_INCREF(Py_None); + return Py_None; + } + + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "the last arg should be either a gtk.Image or a stock_id string"); + return NULL; +} diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..d58f1026 --- /dev/null +++ b/configure.ac @@ -0,0 +1,330 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) + +AC_INIT(gedit, 2.13.0, http://bugzilla.gnome.org/enter_bug.cgi?product=gedit) +AC_CONFIG_SRCDIR(gedit/gedit.c) +AC_CONFIG_MACRO_DIR([m4]) + +GEDIT_MAJOR=2.10 +AC_SUBST(GEDIT_MAJOR) + +AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) + +AM_MAINTAINER_MODE +AM_CONFIG_HEADER(config.h) +AM_DISABLE_STATIC + +AC_PATH_PROG(GCONFTOOL, gconftool-2) +AC_PROG_INTLTOOL([0.31]) + +AM_PROG_LIBTOOL + +AC_ISC_POSIX +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +dnl make sure we keep ACLOCAL_FLAGS around for maintainer builds to work +AC_SUBST(ACLOCAL_AMFLAGS, "$ACLOCAL_FLAGS -I m4") + + +dnl ================================================================ +dnl Gettext stuff. +dnl ================================================================ + +GETTEXT_PACKAGE=gedit +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package]) +ALL_LINGUAS="af am ar az be bg bn bs ca cs cy da de el en_CA en_GB es et eu fa fi fr ga gl gu he hi hr hu id is it ja kn ko lt lv mi mk ml mn mr ms nb ne nl nn no or pa pl pt pt_BR ro ru sk sl sq sr sr@Latn sv ta th tk tr uk vi wa zh_CN zh_TW" +AM_GLIB_GNU_GETTEXT + + +dnl ================================================================ +dnl pspell checks +dnl ================================================================ + +AC_MSG_CHECKING([for aspell/pspell]) +if pspell-config version > /dev/null 2>&1; then + pspell_ver=`pspell-config version` + pspell_num=`echo ${pspell_ver} | awk 'BEGIN {FS="."}{printf $1*10000 + $2*100 + $3;}'` + if test ${pspell_num} -lt 1200; then + AC_MSG_RESULT([pspell version .12 or later required, you have ${pspell_ver} installed]) + else + AC_MSG_RESULT([found ($pspell_ver)]) + + AC_CHECK_HEADER(pspell/pspell.h, + [AC_CHECK_LIB(aspell, new_aspell_speller, + [PSPELL_LIBS="-laspell" SPELL_PLUGIN_DIR="spell" AC_SUBST(SPELL_PLUGIN_DIR)], + [AC_CHECK_LIB(pspell, new_pspell_manager, + [PSPELL_LIBS="-lpspell" SPELL_PLUGIN_DIR="spell" AC_SUBST(SPELL_PLUGIN_DIR)], + [AC_MSG_WARN([You must have the aspell or pspell dev packages to build the spell plugin.])] + )] + )], + [AC_MSG_WARN([You must have the aspell or pspell dev packages to build the spell plugin.])] + ) + fi +else + AC_MSG_RESULT([not found]) +fi + +AC_SUBST(PSPELL_LIBS) + + +dnl ================================================================ +dnl Start of pkg-config checks +dnl ================================================================ + +PKG_CHECK_MODULES(GEDIT, [ + glib-2.0 >= 2.8.0 + gtk+-2.0 >= 2.8.0 + gtksourceview-1.0 >= 1.2.0 + libgnomeui-2.0 >= 2.6.0 + libglade-2.0 >= 2.4.0 + libgnomeprintui-2.2 >= 2.6.0 + gnome-vfs-2.0 >= 2.12.0 +]) +GEDIT_LIBS="${GEDIT_LIBS}" +AC_SUBST(GEDIT_LIBS) +AC_SUBST(GEDIT_CFLAGS) + + +dnl ================================================================ +dnl GConf related settings +dnl ================================================================ + +AM_GCONF_SOURCE_2 + +dnl +dnl Check popt +dnl + +AC_CHECK_LIB(popt, poptStrippedArgv,, AC_MSG_ERROR([popt 1.5 or newer is required to build +gedit. You can download the latest version from ftp://people.redhat.com/sopwith/popt/])) + + +dnl ================================================================ +dnl GEDIT_DATA_DIR - Sets the location of the data directory, where we install +dnl source files added to projects (such as all the Gnome m4 macros). +dnl This will substitute GEDIT_DATA_DIR in config.h. +dnl ================================================================ + +if test "x${datadir}" = 'x${prefix}/share'; then + if test "x${prefix}" = "xNONE"; then + AC_DEFINE_UNQUOTED(GEDIT_DATA_DIR, "${ac_default_prefix}/share/${PACKAGE}", [Directory of data files]) + else + AC_DEFINE_UNQUOTED(GEDIT_DATA_DIR, "${prefix}/share/${PACKAGE}", [Directory of data files]) + fi +else + AC_DEFINE_UNQUOTED(GEDIT_DATA_DIR, "${datadir}/${PACKAGE}", [Directory of data files]) +fi + + +dnl ================================================================ +dnl Python +dnl ================================================================ + +AC_MSG_CHECKING([whether Python support is requested]) +AC_ARG_ENABLE([python], + AS_HELP_STRING([--enable-python],[Enable python support]), + [enable_python=$enableval have_python=$enableval], + [enable_python=autodetect have_python=yes]) +AC_MSG_RESULT([$enable_python]) + +if test "x$have_python" != "xno"; then + AM_PATH_PYTHON([2.3],[],[no]) + if test "x$PYTHON" = "x:"; then + have_python=no + fi +fi + +if test "x$have_python" != "xno"; then + AM_CHECK_PYTHON_HEADERS([],[have_python=no]) +fi + +if test "x$have_python" != "xno"; then + PY_PREFIX=`$PYTHON -c 'import sys ; print sys.prefix'` + PY_EXEC_PREFIX=`$PYTHON -c 'import sys ; print sys.exec_prefix'` + PYTHON_LIBS="-lpython$PYTHON_VERSION" + PYTHON_LIB_LOC="-L$PY_EXEC_PREFIX/lib/python$PYTHON_VERSION/config" + PYTHON_CFLAGS="-I$PY_PREFIX/include/python$PYTHON_VERSION" + PYTHON_MAKEFILE="$PY_EXEC_PREFIX/lib/python$PYTHON_VERSION/config/Makefile" + PYTHON_LOCALMODLIBS=`sed -n -e 's/^LOCALMODLIBS=\(.*\)/\1/p' $PYTHON_MAKEFILE` + PYTHON_BASEMODLIBS=`sed -n -e 's/^BASEMODLIBS=\(.*\)/\1/p' $PYTHON_MAKEFILE` + PYTHON_OTHER_LIBS=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $PYTHON_MAKEFILE` + PYTHON_EXTRA_LIBS="$PYTHON_LOCALMODLIBS $PYTHON_BASEMODLIBS $PYTHON_OTHER_LIBS" + AC_SUBST([PYTHON_LIBS]) + AC_SUBST([PYTHON_LIB_LOC]) + AC_SUBST([PYTHON_CFLAGS]) + AC_SUBST([PYTHON_EXTRA_LIBS]) + + dnl FIXME: do we really need this test? + AC_MSG_CHECKING([whether we can build a shared library depending on libpython]) + rm -rf testpython + mkdir testpython + cd testpython + cat > testpython.c < +int testpython (void) +{ +Py_Exit (0); +} +EOF + + if /bin/sh ../libtool --mode=compile ${CC} $PYTHON_CFLAGS -c testpython.c >/dev/null 2>&1 && \ + /bin/sh ../libtool --mode=link ${CC} -o testpython.la -rpath `pwd` -module -avoid-version $PYTHON_LIB_LOC testpython.lo $PYTHON_LIBS $PYTHON_EXTRA_LIBS >/dev/null 2>&1 && \ + grep 'dlname.*testpython' testpython.la >/dev/null 2>&1; then + result=yes + else + result=no + have_python=no + fi + cd .. + rm -rf testpython + AC_MSG_RESULT([$result]) +fi + +if test "x$have_python" != "xno"; then + PYGTK_REQUIRED=2.7.1 + GNOME_PYTHON_EXTRAS_REQUIRED=2.11.4 + + PKG_CHECK_MODULES([PYGTK], [ + pygtk-2.0 >= $PYGTK_REQUIRED + gnome-python-extras-2.0 >= $GNOME_PYTHON_EXTRAS_REQUIRED], + [],[have_python=no]) + + AC_SUBST([PYGTK_CFLAGS]) + AC_SUBST([PYGTK_LIBS]) +fi + +if test "x$have_python" != "xno"; then + AC_MSG_CHECKING([for pygtk defs]) + PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0` + AC_MSG_RESULT([$PYGTK_DEFSDIR]) + + AC_MSG_CHECKING([for pygtk codegen]) + PYGTK_CODEGEN="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/codegen.py" + AC_MSG_RESULT([$PYGTK_CODEGEN]) + + AC_MSG_CHECKING([for pygtk h2def]) + PYGTK_H2DEF="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/h2def.py" + AC_MSG_RESULT([$PYGTK_H2DEF]) + + AC_SUBST([PYGTK_DEFSDIR]) + AC_SUBST([PYGTK_CODEGEN]) + AC_SUBST([PYGTK_H2DEF]) + + dnl Check for -fno-strict-aliasing + FLAGS="-fno-strict-aliasing" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $FLAGS" + AC_MSG_CHECKING([whether [$]CC understands $FLAGS]) + AC_TRY_COMPILE([], [], [compiler_has_option=yes], [compiler_has_option=no]) + CFLAGS="$save_CFLAGS" + AC_MSG_RESULT($compiler_has_option) + if test $compiler_has_option = yes; then + NO_STRICT_ALIASING_CFLAGS="$FLAGS" + fi + AC_SUBST([NO_STRICT_ALIASING_CFLAGS]) +fi + +if test "x$have_python" != "xyes"; then + if test "x$enable_python" = "xyes"; then + AC_MSG_ERROR([Python not found]) + elif test "x$enable_python" = "xautodetect"; then + enable_python=no + AC_MSG_WARN([Python not found, disabling python support]) + fi +elif test "x$enable_python" != "xno"; then + enable_python=yes + AC_DEFINE([ENABLE_PYTHON],[1],[Define to compile with python support]) +fi + +AM_CONDITIONAL([ENABLE_PYTHON],[test "x$enable_python" = "xyes"]) + +dnl ================================================================ +dnl Misc +dnl ================================================================ +AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal) + +GNOME_COMPILE_WARNINGS(yes) + +AC_ARG_ENABLE(deprecations, + [AC_HELP_STRING([--enable-deprecations], + [warn about deprecated usages [default=no]])],, + [enable_deprecations=no]) + +if test "x$enable_deprecations" = "xyes"; then + DISABLE_DEPRECATED_CFLAGS="\ +-DG_DISABLE_DEPRECATED \ +-DGDK_DISABLE_DEPRECATED \ +-DGTK_DISABLE_DEPRECATED \ +-DGDK_PIXBUF_DISABLE_DEPRECATED \ +-DGNOME_DISABLE_DEPRECATED" + AC_SUBST(DISABLE_DEPRECATED_CFLAGS) +fi + +dnl stuff for the CORBA interface + +ORBIT_IDL="`$PKG_CONFIG --variable=orbit_idl ORBit-2.0`" +AC_SUBST(ORBIT_IDL) + +LIBBONOBO_IDL="`$PKG_CONFIG --variable=idldir libbonobo-2.0`" +AC_SUBST(LIBBONOBO_IDL) + +BONOBO_ACTIVATION_IDL="`$PKG_CONFIG --variable=idldir bonobo-activation-2.0`" +AC_SUBST(BONOBO_ACTIVATION_IDL) + +PLUGIN_LIBTOOL_FLAGS="-module -avoid-version" +AC_SUBST(PLUGIN_LIBTOOL_FLAGS) + +AC_OUTPUT([ +Makefile +bindings/Makefile +bindings/python/Makefile +data/gedit.desktop.in +data/gedit.pc +data/Makefile +gedit/dialogs/Makefile +gedit/Makefile +gedit/recent-files/Makefile +help/C/Makefile +help/de/Makefile +help/es/Makefile +help/eu/Makefile +help/fr/Makefile +help/it/Makefile +help/ja/Makefile +help/ko/Makefile +help/Makefile +help/ro/Makefile +help/sv/Makefile +help/zh_CN/Makefile +help/zh_HK/Makefile +help/zh_TW/Makefile +pixmaps/Makefile +plugins/changecase/Makefile +plugins/docinfo/Makefile +plugins/indent/Makefile +plugins/Makefile +plugins/pythonconsole/Makefile +plugins/sample/Makefile +plugins/sort/Makefile +plugins/spell/Makefile +plugins/taglist/Makefile +plugins/time/Makefile +po/Makefile.in]) + + +echo " + +Configuration: + + Source code location: ${srcdir} + Compiler: ${CC} + Python Plugins Support: $enable_python + +" + +dnl uncomment this in developement releases +dnl cat $srcdir/message-of-doom diff --git a/data/GNOME_Gedit.server.in.in b/data/GNOME_Gedit.server.in.in deleted file mode 100644 index 3b29793c..00000000 --- a/data/GNOME_Gedit.server.in.in +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/Makefile.am b/data/Makefile.am index 2e3592f8..4a9af0bd 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -13,14 +13,6 @@ schemas_in_files = gedit.schemas.in schemas_DATA = $(schemas_in_files:.schemas.in=.schemas) @INTLTOOL_SCHEMAS_RULE@ -bonobodir = $(libdir)/bonobo -serverdir = $(libdir)/bonobo/servers -server_in_files = GNOME_Gedit.server.in.in -server_DATA = $(server_in_files:.server.in.in=.server) -$(server_in_files:.server.in.in=.server.in): $(server_in_files) - sed -e "s|\@BONOBODIR\@|$(bonobodir)|" $< > $@ -@INTLTOOL_SERVER_RULE@ - man_MANS = gedit.1 app_DATA = gedit.applications @@ -47,7 +39,6 @@ EXTRA_DIST = \ $(desktop_in_files) \ $(keys_in_files) \ $(schemas_in_files) \ - $(server_in_files) \ $(man_MANS) \ $(app_DATA) \ gedit.pc.in @@ -56,10 +47,7 @@ CLEANFILES = \ $(desktop_DATA) \ $(keys_DATA) \ $(schemas_DATA) \ - $(server_DATA) \ - $(pkgconfig_DATA) \ - GNOME_Gedit.server.in \ - GNOME_Gedit.server + $(pkgconfig_DATA) diff --git a/data/gedit.schemas.in b/data/gedit.schemas.in index c81d13a9..6e482288 100644 --- a/data/gedit.schemas.in +++ b/data/gedit.schemas.in @@ -344,6 +344,32 @@ + + /schemas/apps/gedit-2/preferences/ui/side_pane/side_pane_visible + /apps/gedit-2/preferences/ui/side_pane/side_pane_visible + gedit + bool + FALSE + + Side Pane is Visible + Whether the side pane at the left of the editing window + should be visible. + + + + + /schemas/apps/gedit-2/preferences/ui/bottom_panel/bottom_panel_visible + /apps/gedit-2/preferences/ui/bottom_panel/bottom_panel_visible + gedit + bool + FALSE + + Bottom Panel is Visible + Whether the bottom panel at the bottom of editing windows + should be visible. + + + /schemas/apps/gedit-2/preferences/print/page/print_syntax_highlighting /apps/gedit-2/preferences/print/page/print_syntax_highlighting @@ -564,6 +590,19 @@ the "Location" of a given plugin. - + + + /schemas/apps/gedit-2/preferences/editor/save/writable_vfs_schemes + /apps/gedit-2/preferences/editor/save/writable_vfs_schemes + gedit + list + string + [ssh,sftp,smb,dav,davs] + + Writable VFS schemes + List of VFS schemes gedit supports in write mode. The 'file' scheme + is writable by default. + + diff --git a/gedit/ChangeLog b/gedit/ChangeLog-20051212 similarity index 100% rename from gedit/ChangeLog rename to gedit/ChangeLog-20051212 diff --git a/gedit/Makefile.am b/gedit/Makefile.am index 6e81ecda..f4ff4d3b 100644 --- a/gedit/Makefile.am +++ b/gedit/Makefile.am @@ -1,5 +1,5 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS= dialogs recent-files +SUBDIRS = dialogs recent-files bin_PROGRAMS = gedit @@ -15,115 +15,144 @@ INCLUDES = \ -DGEDIT_UI_DIR=\""$(datadir)/gedit-2/ui/"\" \ -DGEDIT_PLUGINDIR=\""$(libdir)/gedit-2/plugins"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" + +if ENABLE_PYTHON +INCLUDES += \ + $(NO_STRICT_ALIASING_CFLAGS) \ + $(PYGTK_CFLAGS) \ + $(PYTHON_CFLAGS) \ + $(AM_CFLAGS) +endif -noinst_LTLIBRARIES = libgedit.la - -gedit_LDFLAGS = -export-dynamic +gedit_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*" gedit_LDADD = \ $(GEDIT_LIBS) \ - libgedit.la \ dialogs/libdialogs.la \ recent-files/librecent.la -IDL_FILE = GNOME_Gedit.idl - -IDL_SOURCES = \ - GNOME_Gedit-stubs.c \ - GNOME_Gedit-common.c \ - GNOME_Gedit-skels.c \ - GNOME_Gedit.h +if ENABLE_PYTHON +gedit_LDADD += \ + $(top_builddir)/bindings/python/gedit.la +endif BUILT_SOURCES = \ gedit-marshal.c \ - gedit-marshal.h \ - $(IDL_SOURCES) - -NON_INST_H_FILS = \ - gedit-application-server.h \ - gedit-file-selector-util.h \ - gedit-io-error-dialogs.h \ - bonobo-mdi-session.h \ + gedit-marshal.h + +NOINST_H_FILES = \ gedit-commands.h \ - gedit-plugins-engine.h \ - gedit-session.h \ + gedit-tooltips.h \ gedit-languages-manager.h \ - gedit-window-server.h \ - gedit-tooltips.h + gedit-plugin-manager.h \ + gedit-plugins-engine.h \ + gedit-module.h \ + gedit-ui.h \ + gedit-window-private.h \ + gedit-documents-panel.h \ + gedit-document-loader.h \ + gedit-document-saver.h \ + gedit-io-error-message-area.h \ + gedit-spinner.h \ + sexy-icon-entry.h \ + gedit-session.h + +if ENABLE_PYTHON +NOINST_H_FILES += \ + gedit-python-module.h \ + gedit-python-plugin.h +endif INST_H_FILES = \ - gedit2.h \ - gedit-file.h \ - gedit-encodings-option-menu.h \ - gedit-utils.h \ - gedit-mdi.h \ - gedit-mdi-child.h \ + gedit-app.h \ + gedit-convert.h \ + gedit-debug.h \ gedit-document.h \ - gedit-view.h \ - gedit-menus.h \ - bonobo-mdi.h \ - gedit-print.h \ - bonobo-mdi-child.h \ + gedit-encodings.h \ + gedit-encodings-option-menu.h \ + gedit-file-chooser-dialog.h \ + gedit-help.h \ + gedit-message-area.h \ + gedit-metadata-manager.h \ + gedit-notebook.h \ + gedit-panel.h \ gedit-plugin.h \ gedit-prefs-manager-app.h \ - gedit-recent.h \ - gedit-output-window.h - -LIB_H_FILES = \ - gedit-encodings.h \ - gedit-convert.h \ - gedit-debug.h \ gedit-prefs-manager.h \ - gedit-metadata-manager.h - + gedit-print.h \ + gedit-print-job-preview.h \ + gedit-progress-message-area.h \ + gedit-recent.h \ + gedit-statusbar.h \ + gedit-tab.h \ + gedit-utils.h \ + gedit-view.h \ + gedit-window.h headerdir = $(prefix)/include/gedit-@GEDIT_MAJOR@/gedit header_DATA = \ - $(INST_H_FILES) \ - $(LIB_H_FILES) + $(INST_H_FILES) gedit_SOURCES = \ $(BUILT_SOURCES) \ - gedit2.c \ - gedit-mdi.c \ - gedit-mdi-child.c \ + $(BACON_FILES) \ + gedit.c \ + gedit-app.c \ + gedit-commands-documents.c \ + gedit-commands-edit.c \ + gedit-commands-file.c \ + gedit-commands-file-print.c \ + gedit-commands-help.c \ + gedit-commands-search.c \ + gedit-commands-view.c \ + gedit-convert.c \ + gedit-debug.c \ gedit-document.c \ - gedit-view.c \ - gedit-menus.c \ - gedit-utils.c \ - gedit-commands.c \ - gedit-file.c \ - gedit-print.c \ - gedit-session.c \ - bonobo-mdi.c \ - bonobo-mdi-child.c \ - bonobo-mdi-session.c \ - gedit-file-selector-util.c \ - gedit-io-error-dialogs.c \ - gedit-plugins-engine.c \ + gedit-document-loader.c \ + gedit-document-saver.c \ + gedit-documents-panel.c \ + gedit-encodings.c \ + gedit-encodings-option-menu.c \ + gedit-file-chooser-dialog.c \ + gedit-help.c \ + gedit-io-error-message-area.c \ + gedit-languages-manager.c \ + gedit-message-area.c \ + gedit-metadata-manager.c \ + gedit-module.c \ + gedit-notebook.c \ + gedit-panel.c \ gedit-plugin.c \ + gedit-plugin-manager.c \ + gedit-plugins-engine.c \ gedit-prefs-manager-app.c \ + gedit-prefs-manager.c \ + gedit-prefs-manager-private.h \ + gedit-print.c \ + gedit-print-job-preview.c \ + gedit-progress-message-area.c \ gedit-recent.c \ - gedit-application-server.c \ - gedit-document-server.c \ - gedit-document-server.h \ - gedit-window-server.c \ - gedit-output-window.c \ - gedit-languages-manager.c \ - gedit-encodings-option-menu.c \ + gedit-session.c \ + gedit-spinner.c \ + gedit-statusbar.c \ + gedit-tab.c \ gedit-tooltips.c \ - $(NON_INST_H_FILS) \ + gedit-utils.c \ + gedit-view.c \ + gedit-window.c \ + sexy-icon-entry.c \ + $(NOINST_H_FILES) \ $(INST_H_FILES) -libgedit_la_SOURCES = \ - gedit-debug.c \ - gedit-convert.c \ - gedit-encodings.c \ - gedit-prefs-manager.c \ - gedit-prefs-manager-private.h \ - gedit-metadata-manager.c \ - $(LIB_H_FILES) + +if ENABLE_PYTHON +gedit_SOURCES += \ + gedit-python-module.c \ + gedit-python-module.h \ + gedit-python-plugin.c \ + gedit-python-plugin.h +endif gedit-marshal.h: gedit-marshal.list $(GLIB_GENMARSHAL) $(GLIB_GENMARSHAL) $< --header --prefix=gedit_marshal > $@ @@ -132,19 +161,12 @@ gedit-marshal.c: gedit-marshal.list $(GLIB_GENMARSHAL) echo "#include \"gedit-marshal.h\"" > $@ && \ $(GLIB_GENMARSHAL) $< --body --prefix=gedit_marshal >> $@ -$(IDL_SOURCES): $(IDL_FILE) $(ORBIT_IDL) - $(ORBIT_IDL) -I $(LIBBONOBO_IDL) -I $(BONOBO_ACTIVATION_IDL) $(srcdir)/$(IDL_FILE) - ui_DATA = gedit-ui.xml uidir = $(datadir)/gedit-2/ui/ -idl_DATA = $(IDL_FILE) -idldir = $(datadir)/idl - EXTRA_DIST = \ $(ui_DATA) \ - gedit-marshal.list \ - $(IDL_FILE) + gedit-marshal.list CLEANFILES = $(BUILT_SOURCES) @@ -155,3 +177,8 @@ install-exec-local: rm -f $(DESTDIR)$(bindir)/gnome-text-editor ln -s gedit $(DESTDIR)$(bindir)/gnome-text-editor +BACON_DIR=$(srcdir)/../../libbacon/src/ +BACON_FILES=bacon-message-connection.h bacon-message-connection.c + +regenerate-built-sources: + BACONFILES="$(BACON_FILES)" BACONDIR="$(BACON_DIR)" $(top_srcdir)/gedit/update-from-bacon.sh diff --git a/gedit/bacon-message-connection.c b/gedit/bacon-message-connection.c new file mode 100644 index 00000000..6ebb1821 --- /dev/null +++ b/gedit/bacon-message-connection.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2003 Bastien Nocera + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bacon-message-connection.h" + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +struct BaconMessageConnection { + /* A server accepts connections */ + gboolean is_server; + + /* The socket path itself */ + char *path; + + /* FD is for the connection, serverfd is for the server socket, + * it accepts incoming connections. */ + int fd, serverfd, server_conn_id, conn_id; + GIOChannel *chan; + + /* callback */ + void (*func) (const char *message, gpointer user_data); + gpointer data; +}; + +static gboolean +test_is_socket (const char *path) +{ + struct stat s; + + if (stat (path, &s) == -1) + return FALSE; + + if (S_ISSOCK (s.st_mode)) + return TRUE; + + return FALSE; +} + +static gboolean +is_owned_by_user_and_socket (const char *path) +{ + struct stat s; + + if (stat (path, &s) == -1) + return FALSE; + + if (s.st_uid != geteuid ()) + return FALSE; + + if ((s.st_mode & S_IFSOCK) != S_IFSOCK) + return FALSE; + + return TRUE; +} + +static gboolean server_cb (GIOChannel *source, + GIOCondition condition, gpointer data); + +static gboolean +setup_connection (BaconMessageConnection *conn) +{ + conn->chan = g_io_channel_unix_new (conn->fd); + if (!conn->chan) { + return FALSE; + } + g_io_channel_set_line_term (conn->chan, "\n", 1); + conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn); + + return TRUE; +} + +static gboolean +server_cb (GIOChannel *source, GIOCondition condition, gpointer data) +{ + BaconMessageConnection *conn = (BaconMessageConnection *)data; + char *message, *subs, buf; + int cd, alen, rc, offset; + gboolean finished; + + offset = 0; + if (conn->serverfd == g_io_channel_unix_get_fd (source)) { + cd = accept (conn->serverfd, NULL, (guint *)&alen); + conn->fd = cd; + setup_connection (conn); + return TRUE; + } + message = g_malloc (1); + cd = conn->fd; + rc = read (cd, &buf, 1); + while (rc > 0 && buf != '\n') + { + message = g_realloc (message, rc + offset + 1); + message[offset] = buf; + offset = offset + rc; + rc = read (cd, &buf, 1); + } + if (rc <= 0) { + g_io_channel_shutdown (conn->chan, FALSE, NULL); + g_io_channel_unref (conn->chan); + conn->chan = NULL; + close (conn->fd); + conn->fd = -1; + g_free (message); + conn->conn_id = 0; + + return FALSE; + } + message[offset] = '\0'; + + subs = message; + finished = FALSE; + + while (finished == FALSE && *subs != '\0') + { + if (conn->func != NULL) + (*conn->func) (subs, conn->data); + + subs += strlen (subs) + 1; + if (subs - message >= offset) + finished = TRUE; + } + + g_free (message); + + return TRUE; +} + +static char * +find_file_with_pattern (const char *dir, const char *pattern) +{ + GDir *filedir; + char *found_filename; + const char *filename; + GPatternSpec *pat; + + filedir = g_dir_open (dir, 0, NULL); + if (filedir == NULL) + return NULL; + + pat = g_pattern_spec_new (pattern); + if (pat == NULL) + { + g_dir_close (filedir); + return NULL; + } + + found_filename = NULL; + + while ((filename = g_dir_read_name (filedir))) + { + if (g_pattern_match_string (pat, filename)) + { + char *tmp = g_build_filename (dir, filename, NULL); + if (is_owned_by_user_and_socket (tmp)) + found_filename = g_strdup (filename); + g_free (tmp); + } + + if (found_filename != NULL) + break; + } + + g_pattern_spec_free (pat); + g_dir_close (filedir); + + return found_filename; +} + +static char * +socket_filename (const char *prefix) +{ + char *pattern, *newfile, *path, *filename; + const char *tmpdir; + + pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ()); + tmpdir = g_get_tmp_dir (); + filename = find_file_with_pattern (tmpdir, pattern); + if (filename == NULL) + { + newfile = g_strdup_printf ("%s.%s.%u", prefix, + g_get_user_name (), g_random_int ()); + path = g_build_filename (tmpdir, newfile, NULL); + g_free (newfile); + } else { + path = g_build_filename (tmpdir, filename, NULL); + g_free (filename); + } + + g_free (pattern); + return path; +} + +static gboolean +try_server (BaconMessageConnection *conn) +{ + struct sockaddr_un uaddr; + + uaddr.sun_family = AF_UNIX; + strncpy (uaddr.sun_path, conn->path, + MIN (strlen(conn->path)+1, UNIX_PATH_MAX)); + conn->serverfd = conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1) + { + conn->fd = -1; + return FALSE; + } + listen (conn->fd, 5); + + if (!setup_connection (conn)) + return FALSE; + conn->server_conn_id = conn->conn_id; + return TRUE; +} + +static gboolean +try_client (BaconMessageConnection *conn) +{ + struct sockaddr_un uaddr; + + uaddr.sun_family = AF_UNIX; + strncpy (uaddr.sun_path, conn->path, + MIN(strlen(conn->path)+1, UNIX_PATH_MAX)); + conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); + conn->serverfd = -1; + if (connect (conn->fd, (struct sockaddr *) &uaddr, + sizeof (uaddr)) == -1) + { + conn->fd = -1; + return FALSE; + } + + return setup_connection (conn); +} + +BaconMessageConnection * +bacon_message_connection_new (const char *prefix) +{ + BaconMessageConnection *conn; + + g_return_val_if_fail (prefix != NULL, NULL); + + conn = g_new0 (BaconMessageConnection, 1); + conn->path = socket_filename (prefix); + + if (test_is_socket (conn->path) == FALSE) + { + if (!try_server (conn)) + { + bacon_message_connection_free (conn); + return NULL; + } + + conn->is_server = TRUE; + return conn; + } + + if (try_client (conn) == FALSE) + { + unlink (conn->path); + try_server (conn); + if (conn->fd == -1) + { + bacon_message_connection_free (conn); + return NULL; + } + + conn->is_server = TRUE; + return conn; + } + + conn->is_server = FALSE; + return conn; +} + +void +bacon_message_connection_free (BaconMessageConnection *conn) +{ + g_return_if_fail (conn != NULL); + g_return_if_fail (conn->path != NULL); + + if (conn->server_conn_id) { + g_source_remove (conn->server_conn_id); + conn->server_conn_id = 0; + } + if (conn->conn_id) { + g_source_remove (conn->conn_id); + conn->conn_id = 0; + } + if (conn->chan) { + g_io_channel_shutdown (conn->chan, FALSE, NULL); + g_io_channel_unref (conn->chan); + } + + if (conn->is_server != FALSE) { + unlink (conn->path); + close (conn->serverfd); + } else if (conn->fd != -1) { + close (conn->fd); + } + + g_free (conn->path); + g_free (conn); +} + +void +bacon_message_connection_set_callback (BaconMessageConnection *conn, + BaconMessageReceivedFunc func, + gpointer user_data) +{ + g_return_if_fail (conn != NULL); + + conn->func = func; + conn->data = user_data; +} + +void +bacon_message_connection_send (BaconMessageConnection *conn, + const char *message) +{ + g_return_if_fail (conn != NULL); + g_return_if_fail (message != NULL); + + g_io_channel_write_chars (conn->chan, message, strlen (message), + NULL, NULL); + g_io_channel_write_chars (conn->chan, "\n", 1, NULL, NULL); + g_io_channel_flush (conn->chan, NULL); +} + +gboolean +bacon_message_connection_get_is_server (BaconMessageConnection *conn) +{ + g_return_val_if_fail (conn != NULL, FALSE); + + return conn->is_server; +} + diff --git a/gedit/bacon-message-connection.h b/gedit/bacon-message-connection.h new file mode 100644 index 00000000..57a99970 --- /dev/null +++ b/gedit/bacon-message-connection.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2003 Bastien Nocera + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef BACON_MESSAGE_CONNECTION_H +#define BACON_MESSAGE_CONNECTION_H + +#include + +G_BEGIN_DECLS + +typedef void (*BaconMessageReceivedFunc) (const char *message, + gpointer user_data); + +typedef struct BaconMessageConnection BaconMessageConnection; + +void bacon_message_connection_free (BaconMessageConnection *conn); +BaconMessageConnection *bacon_message_connection_new (const char *prefix); +void bacon_message_connection_free (BaconMessageConnection *conn); +void bacon_message_connection_set_callback (BaconMessageConnection *conn, + BaconMessageReceivedFunc func, + gpointer user_data); +void bacon_message_connection_send (BaconMessageConnection *conn, + const char *message); +gboolean bacon_message_connection_get_is_server (BaconMessageConnection *conn); + +G_END_DECLS + +#endif /* BACON_MESSAGE_CONNECTION_H */ diff --git a/gedit/dialogs/Makefile.am b/gedit/dialogs/Makefile.am index 7679dd7a..5bcd16a9 100644 --- a/gedit/dialogs/Makefile.am +++ b/gedit/dialogs/Makefile.am @@ -12,31 +12,28 @@ INCLUDES = \ noinst_LTLIBRARIES = libdialogs.la libdialogs_la_SOURCES = \ - gedit-dialog-uri.c \ - gedit-dialog-goto-line.c \ - gedit-dialog-replace.c \ - gedit-preferences-dialog.h \ - gedit-preferences-dialog.c \ - gedit-plugin-manager.c \ - gedit-plugin-manager.h \ - gedit-plugin-program-location-dialog.c \ - gedit-encodings-dialog.c \ - gedit-encodings-dialog.h \ - gedit-page-setup-dialog.c \ - gedit-page-setup-dialog.h \ - gedit-close-confirmation-dialog.c \ - gedit-close-confirmation-dialog.h \ - gedit-dialogs.h - -glade_DATA = \ - uri.glade2 \ - goto-line.glade2 \ - replace.glade2 \ - plugin-manager.glade2 \ - gedit-preferences.glade2 \ - program-location-dialog.glade2 \ - gedit-encodings-dialog.glade2 \ - page-setup-dialog.glade2 + gedit-page-setup-dialog.c \ + gedit-page-setup-dialog.h \ + gedit-preferences-dialog.h \ + gedit-preferences-dialog.c \ + gedit-close-confirmation-dialog.c \ + gedit-close-confirmation-dialog.h \ + gedit-encodings-dialog.c \ + gedit-encodings-dialog.h \ + gedit-open-location-dialog.c \ + gedit-open-location-dialog.h \ + gedit-search-dialog.h \ + gedit-search-dialog.c + + +glade_DATA = \ + gedit-encodings-dialog.glade \ + gedit-open-location-dialog.glade \ + gedit-page-setup-dialog.glade \ + gedit-preferences-dialog.glade \ + gedit-search-dialog.glade + + EXTRA_DIST = $(glade_DATA) diff --git a/gedit/dialogs/gedit-close-confirmation-dialog.c b/gedit/dialogs/gedit-close-confirmation-dialog.c index 2adbd02b..105465ab 100644 --- a/gedit/dialogs/gedit-close-confirmation-dialog.c +++ b/gedit/dialogs/gedit-close-confirmation-dialog.c @@ -2,7 +2,7 @@ * gedit-close-confirmation-dialog.c * This file is part of gedit * - * Copyright (C) 2004 GNOME Foundation + * Copyright (C) 2004-2005 GNOME Foundation * * 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 @@ -21,9 +21,11 @@ */ /* - * Modified by the gedit Team, 2004. See the AUTHORS file for a + * Modified by the gedit Team, 2004-2005. See the AUTHORS file for a * list of people on the gedit Team. - * See the ChangeLog files for a list of changes. + * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -34,12 +36,14 @@ #include "gedit-close-confirmation-dialog.h" #include +#include /* Properties */ enum { PROP_0, - PROP_UNSAVED_DOCUMENTS + PROP_UNSAVED_DOCUMENTS, + PROP_LOGOUT_MODE }; /* Mode */ @@ -57,14 +61,16 @@ enum DOC_COLUMN, /* a handy pointer to the document */ N_COLUMNS }; - + typedef struct _GeditCloseConfirmationDialogPrivate GeditCloseConfirmationDialogPrivate; struct _GeditCloseConfirmationDialogPrivate { - GSList *unsaved_documents; + gboolean logout_mode; + + GList *unsaved_documents; - GSList *selected_documents; + GList *selected_documents; GtkTreeModel *list_store; }; @@ -73,51 +79,82 @@ struct _GeditCloseConfirmationDialogPrivate #define GET_MODE(priv) (((priv->unsaved_documents != NULL) && (priv->unsaved_documents->next == NULL)) ? SINGLE_DOC_MODE : MULTIPLE_DOCS_MODE) -static void gedit_close_confirmation_dialog_init (GeditCloseConfirmationDialog *dlg); -static void gedit_close_confirmation_dialog_class_init (GeditCloseConfirmationDialogClass *klass); -static void gedit_close_confirmation_dialog_finalize (GObject *object); -static void gedit_close_confirmation_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gedit_close_confirmation_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void set_unsaved_document (GeditCloseConfirmationDialog *dlg, - const GSList *list); - -static GtkDialogClass *parent_class = NULL; - -GType -gedit_close_confirmation_dialog_get_type (void) +G_DEFINE_TYPE(GeditCloseConfirmationDialog, gedit_close_confirmation_dialog, GTK_TYPE_DIALOG) + +static void set_unsaved_document (GeditCloseConfirmationDialog *dlg, + const GList *list); + +static GList *get_selected_docs (GtkTreeModel *store); + +/* Since we connect in the costructor we are sure this handler will be called + * before the user ones + */ +static void +response_cb (GeditCloseConfirmationDialog *dlg, + gint response_id, + gpointer data) { - static GType close_confirmation_dialog_type = 0; + GeditCloseConfirmationDialogPrivate *priv; + + g_return_if_fail (GEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg)); - if (!close_confirmation_dialog_type) + priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg); + + if (priv->selected_documents != NULL) + g_list_free (priv->selected_documents); + + if (response_id == GTK_RESPONSE_YES) { - static const GTypeInfo close_confirmation_dialog_info = + if (GET_MODE (priv) == SINGLE_DOC_MODE) + priv->selected_documents = + g_list_copy (priv->unsaved_documents); + else { - sizeof (GeditCloseConfirmationDialogClass), /* size of your class struct */ - NULL, /* init method for base class */ - NULL, /* finalize method for base class */ - (GClassInitFunc) gedit_close_confirmation_dialog_class_init, - NULL, /* finalize method for your class*/ - NULL, - sizeof (GeditCloseConfirmationDialog), - 0, - (GInstanceInitFunc) gedit_close_confirmation_dialog_init - }; - - close_confirmation_dialog_type = - g_type_register_static (GTK_TYPE_DIALOG, - "GeditCloseConfirmationDialog", - &close_confirmation_dialog_info, - 0); + g_return_if_fail (priv->list_store); + + priv->selected_documents = + get_selected_docs (priv->list_store); + } + } + else + priv->selected_documents = NULL; +} + +static void +set_logout_mode (GeditCloseConfirmationDialog *dlg, + gboolean logout_mode) +{ + GeditCloseConfirmationDialogPrivate *priv; + + priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg); + + priv->logout_mode = logout_mode; + + if (logout_mode) + { + gtk_dialog_add_button (GTK_DIALOG (dlg), + _("Logout _without Saving"), + GTK_RESPONSE_NO); + + gedit_dialog_add_button (GTK_DIALOG (dlg), + _("_Cancel Logout"), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + } + else + { + gtk_dialog_add_button (GTK_DIALOG (dlg), + _("Close _without Saving"), + GTK_RESPONSE_NO); + + gtk_dialog_add_button (GTK_DIALOG (dlg), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); } + + gtk_dialog_add_button (GTK_DIALOG (dlg), + GTK_STOCK_SAVE, GTK_RESPONSE_YES); - return close_confirmation_dialog_type; + gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_YES); } static void @@ -138,41 +175,14 @@ gedit_close_confirmation_dialog_init (GeditCloseConfirmationDialog *dlg) gtk_window_set_modal (GTK_WINDOW (dlg), TRUE); gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE); - gtk_dialog_add_button (GTK_DIALOG (dlg), - _("Close _without Saving"), - GTK_RESPONSE_NO); - - gtk_dialog_add_buttons (GTK_DIALOG (dlg), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_YES, NULL); - - gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_YES); atk_obj = gtk_widget_get_accessible (GTK_WIDGET (dlg)); atk_object_set_role (atk_obj, ATK_ROLE_ALERT); atk_object_set_name (atk_obj, _("Question")); -} - -static void -gedit_close_confirmation_dialog_class_init (GeditCloseConfirmationDialogClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->set_property = gedit_close_confirmation_dialog_set_property; - gobject_class->get_property = gedit_close_confirmation_dialog_get_property; - gobject_class->finalize = gedit_close_confirmation_dialog_finalize; - - g_type_class_add_private (klass, sizeof (GeditCloseConfirmationDialogPrivate)); - - g_object_class_install_property (gobject_class, - PROP_UNSAVED_DOCUMENTS, - g_param_spec_pointer ("unsaved_documents", - "Unsaved Documents", - "List of Unsaved Documents", - (G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY))); - + + g_signal_connect (dlg, + "response", + G_CALLBACK (response_cb), + NULL); } static void @@ -183,42 +193,48 @@ gedit_close_confirmation_dialog_finalize (GObject *object) priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (object); if (priv->unsaved_documents != NULL) - g_slist_free (priv->unsaved_documents); + g_list_free (priv->unsaved_documents); - if (priv->unsaved_documents != NULL) - g_slist_free (priv->selected_documents); + if (priv->selected_documents != NULL) + g_list_free (priv->selected_documents); /* Call the parent's destructor */ - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gedit_close_confirmation_dialog_parent_class)->finalize (object); } -/*property getters and setters*/ -static void +static void gedit_close_confirmation_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GeditCloseConfirmationDialog *dlg; + GeditCloseConfirmationDialogPrivate *priv; dlg = GEDIT_CLOSE_CONFIRMATION_DIALOG (object); + priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (object); switch (prop_id) { case PROP_UNSAVED_DOCUMENTS: set_unsaved_document (dlg, g_value_get_pointer (value)); break; - + + case PROP_LOGOUT_MODE: + set_logout_mode (dlg, g_value_get_boolean (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -static void gedit_close_confirmation_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +static void +gedit_close_confirmation_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { GeditCloseConfirmationDialogPrivate *priv; @@ -229,17 +245,50 @@ static void gedit_close_confirmation_dialog_get_property (GObject *object, case PROP_UNSAVED_DOCUMENTS: g_value_set_pointer (value, priv->unsaved_documents); break; - + + case PROP_LOGOUT_MODE: + g_value_set_boolean (value, priv->logout_mode); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -static GSList * +static void +gedit_close_confirmation_dialog_class_init (GeditCloseConfirmationDialogClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gedit_close_confirmation_dialog_set_property; + gobject_class->get_property = gedit_close_confirmation_dialog_get_property; + gobject_class->finalize = gedit_close_confirmation_dialog_finalize; + + g_type_class_add_private (klass, sizeof (GeditCloseConfirmationDialogPrivate)); + + g_object_class_install_property (gobject_class, + PROP_UNSAVED_DOCUMENTS, + g_param_spec_pointer ("unsaved_documents", + "Unsaved Documents", + "List of Unsaved Documents", + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY))); + + g_object_class_install_property (gobject_class, + PROP_LOGOUT_MODE, + g_param_spec_boolean ("logout_mode", + "Logout Mode", + "Whether the dialog is in logout mode", + FALSE, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY))); +} + +static GList * get_selected_docs (GtkTreeModel *store) { - GSList *list; + GList *list; gboolean valid; GtkTreeIter iter; @@ -256,57 +305,17 @@ get_selected_docs (GtkTreeModel *store) DOC_COLUMN, &doc, -1); if (to_save) - list = g_slist_prepend (list, doc); + list = g_list_prepend (list, doc); valid = gtk_tree_model_iter_next (store, &iter); } - list = g_slist_reverse (list); + list = g_list_reverse (list); return list; } -gboolean -gedit_close_confirmation_dialog_run (GeditCloseConfirmationDialog *dlg) -{ - GeditCloseConfirmationDialogPrivate *priv; - gint ret; - - g_return_val_if_fail (GEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg), FALSE); - - priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg); - - ret = gtk_dialog_run (GTK_DIALOG (dlg)); - - switch (ret) - { - case GTK_RESPONSE_YES: - if (GET_MODE (priv) == SINGLE_DOC_MODE) - { - priv->selected_documents = - g_slist_copy (priv->unsaved_documents); - } - else - { - g_return_val_if_fail (priv->list_store, FALSE); - - priv->selected_documents = - get_selected_docs (priv->list_store); - } - - return TRUE; - - case GTK_RESPONSE_NO: - priv->selected_documents = NULL; - return TRUE; - - default: - priv->selected_documents = NULL; - return FALSE; - } -} - -GSList * +const GList * gedit_close_confirmation_dialog_get_selected_documents (GeditCloseConfirmationDialog *dlg) { GeditCloseConfirmationDialogPrivate *priv; @@ -315,40 +324,50 @@ gedit_close_confirmation_dialog_get_selected_documents (GeditCloseConfirmationDi priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg); - return g_slist_copy (priv->selected_documents); + return g_list_copy (priv->selected_documents); } GtkWidget * -gedit_close_confirmation_dialog_new (GtkWindow *parent, GSList *unsaved_documents) +gedit_close_confirmation_dialog_new (GtkWindow *parent, + GList *unsaved_documents, + gboolean logout_mode) { GtkWidget *dlg; g_return_val_if_fail (unsaved_documents != NULL, NULL); dlg = GTK_WIDGET (g_object_new (GEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, "unsaved_documents", unsaved_documents, + "logout_mode", logout_mode, NULL)); g_return_val_if_fail (dlg != NULL, NULL); if (parent != NULL) { - gtk_window_set_transient_for (GTK_WINDOW (dlg), parent); + gtk_window_group_add_window (gedit_window_get_group (GEDIT_WINDOW (parent)), + GTK_WINDOW (dlg)); + + gtk_window_set_transient_for (GTK_WINDOW (dlg), parent); } return dlg; } GtkWidget * -gedit_close_confirmation_dialog_new_single (GtkWindow *parent, GeditDocument *doc) +gedit_close_confirmation_dialog_new_single (GtkWindow *parent, + GeditDocument *doc, + gboolean logout_mode) { GtkWidget *dlg; - GSList *unsaved_documents; + GList *unsaved_documents; g_return_val_if_fail (doc != NULL, NULL); - unsaved_documents = g_slist_prepend (NULL, doc); + unsaved_documents = g_list_prepend (NULL, doc); - dlg = gedit_close_confirmation_dialog_new (parent, unsaved_documents); + dlg = gedit_close_confirmation_dialog_new (parent, + unsaved_documents, + logout_mode); - g_slist_free (unsaved_documents); + g_list_free (unsaved_documents); return dlg; } @@ -359,7 +378,7 @@ get_text_secondary_label (GeditDocument *doc) glong seconds; gchar *secondary_msg; - seconds = MAX (1, gedit_document_get_seconds_since_last_save_or_load (doc)); + seconds = MAX (1, _gedit_document_get_seconds_since_last_save_or_load (doc)); if (seconds < 55) { @@ -448,7 +467,7 @@ build_single_doc_dialog (GeditCloseConfirmationDialog *dlg) gchar *doc_name; gchar *str; gchar *markup_str; - + GeditCloseConfirmationDialogPrivate *priv; priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg); @@ -468,14 +487,14 @@ build_single_doc_dialog (GeditCloseConfirmationDialog *dlg) gtk_misc_set_alignment (GTK_MISC (primary_label), 0.0, 0.5); gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE); - doc_name = gedit_document_get_short_name (doc); + doc_name = gedit_document_get_short_name_for_display (doc); str = g_strdup_printf (_("Save the changes to document \"%s\" before closing?"), doc_name); g_free (doc_name); - + markup_str = g_strconcat ("", str, "", NULL); g_free (str); - + gtk_label_set_markup (GTK_LABEL (primary_label), markup_str); g_free (markup_str); @@ -505,12 +524,12 @@ build_single_doc_dialog (GeditCloseConfirmationDialog *dlg) FALSE, FALSE, 0); - + gtk_widget_show_all (hbox); } static void -populate_model (GtkTreeModel *store, GSList *docs) +populate_model (GtkTreeModel *store, GList *docs) { GtkTreeIter iter; @@ -521,8 +540,7 @@ populate_model (GtkTreeModel *store, GSList *docs) doc = GEDIT_DOCUMENT (docs->data); - name = gedit_document_get_short_name (doc); - g_return_if_fail (name != NULL); + name = gedit_document_get_short_name_for_display (doc); gtk_list_store_append (GTK_LIST_STORE (store), &iter); gtk_list_store_set (GTK_LIST_STORE (store), &iter, @@ -533,7 +551,7 @@ populate_model (GtkTreeModel *store, GSList *docs) g_free (name); - docs = g_slist_next (docs); + docs = g_list_next (docs); } } @@ -646,8 +664,8 @@ build_multiple_docs_dialog (GeditCloseConfirmationDialog *dlg) "Save changes before closing?", "There are %d documents with unsaved changes. " "Save changes before closing?", - g_slist_length (priv->unsaved_documents)), - g_slist_length (priv->unsaved_documents)); + g_list_length (priv->unsaved_documents)), + g_list_length (priv->unsaved_documents)); markup_str = g_strconcat ("", str, "", NULL); g_free (str); @@ -690,7 +708,7 @@ build_multiple_docs_dialog (GeditCloseConfirmationDialog *dlg) static void set_unsaved_document (GeditCloseConfirmationDialog *dlg, - const GSList *list) + const GList *list) { GeditCloseConfirmationDialogPrivate *priv; @@ -699,7 +717,7 @@ set_unsaved_document (GeditCloseConfirmationDialog *dlg, priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg); g_return_if_fail (priv->unsaved_documents == NULL); - priv->unsaved_documents = g_slist_copy ((GSList *)list); + priv->unsaved_documents = g_list_copy ((GList *)list); if (GET_MODE (priv) == SINGLE_DOC_MODE) { @@ -711,3 +729,14 @@ set_unsaved_document (GeditCloseConfirmationDialog *dlg, } } +const GList * +gedit_close_confirmation_dialog_get_unsaved_documents (GeditCloseConfirmationDialog *dlg) +{ + GeditCloseConfirmationDialogPrivate *priv; + + g_return_val_if_fail (GEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg), NULL); + + priv = GEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg); + + return priv->unsaved_documents; +} diff --git a/gedit/dialogs/gedit-close-confirmation-dialog.h b/gedit/dialogs/gedit-close-confirmation-dialog.h index 0f8f143e..6a24b4f5 100644 --- a/gedit/dialogs/gedit-close-confirmation-dialog.h +++ b/gedit/dialogs/gedit-close-confirmation-dialog.h @@ -2,7 +2,7 @@ * gedit-close-confirmation-dialog.h * This file is part of gedit * - * Copyright (C) 2004 GNOME Foundation + * Copyright (C) 2004-2005 GNOME Foundation * * 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 @@ -21,7 +21,7 @@ */ /* - * Modified by the gedit Team, 2004. See the AUTHORS file for a + * Modified by the gedit Team, 2004-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. */ @@ -58,12 +58,15 @@ struct _GeditCloseConfirmationDialogClass GType gedit_close_confirmation_dialog_get_type (void) G_GNUC_CONST; GtkWidget *gedit_close_confirmation_dialog_new (GtkWindow *parent, - GSList *unsaved_documents); + GList *unsaved_documents, + gboolean logout_mode); GtkWidget *gedit_close_confirmation_dialog_new_single (GtkWindow *parent, - GeditDocument *doc); + GeditDocument *doc, + gboolean logout_mode); -gboolean gedit_close_confirmation_dialog_run (GeditCloseConfirmationDialog *dlg); -GSList *gedit_close_confirmation_dialog_get_selected_documents (GeditCloseConfirmationDialog *dlg); +const GList *gedit_close_confirmation_dialog_get_unsaved_documents (GeditCloseConfirmationDialog *dlg); + +const GList *gedit_close_confirmation_dialog_get_selected_documents (GeditCloseConfirmationDialog *dlg); #endif /* __GEDIT_CLOSE_CONFIRMATION_DIALOG_H__ */ diff --git a/gedit/dialogs/gedit-encodings-dialog.c b/gedit/dialogs/gedit-encodings-dialog.c index acb78cec..a62addea 100644 --- a/gedit/dialogs/gedit-encodings-dialog.c +++ b/gedit/dialogs/gedit-encodings-dialog.c @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-encodings-dialog.c * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,9 +21,11 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -35,60 +36,64 @@ #include #include -#include -#include #include #include "gedit-encodings-dialog.h" #include "gedit-encodings.h" #include "gedit-prefs-manager.h" +#include "gedit-utils.h" #include "gedit-debug.h" +#include "gedit-help.h" +#define GEDIT_ENCODINGS_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \ + GEDIT_TYPE_ENCODINGS_DIALOG, \ + GeditEncodingsDialogPrivate)) -enum { - COLUMN_NAME, - COLUMN_CHARSET, - N_COLUMNS +struct _GeditEncodingsDialogPrivate +{ + GtkListStore *available_liststore; + GtkListStore *displayed_liststore; + GtkWidget *available_treeview; + GtkWidget *displayed_treeview; + GtkWidget *add_button; + GtkWidget *remove_button; + + GSList *show_in_menu_list; }; -static GSList *show_in_menu_list = NULL; +G_DEFINE_TYPE(GeditEncodingsDialog, gedit_encodings_dialog, GTK_TYPE_DIALOG) static void -show_help (GtkWidget *window) +gedit_encodings_dialog_finalize (GObject *object) { - GError *err; - err = NULL; + GeditEncodingsDialogPrivate *priv = GEDIT_ENCODINGS_DIALOG (object)->priv; - gnome_help_display ("gedit", NULL, &err); + g_slist_free (priv->show_in_menu_list); - if (err) - { - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _("There was an error displaying help: %s"), - err->message); - - g_signal_connect (G_OBJECT (dialog), - "response", - G_CALLBACK (gtk_widget_destroy), - NULL); + G_OBJECT_CLASS (gedit_encodings_dialog_parent_class)->finalize (object); +} - gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); +static void +gedit_encodings_dialog_class_init (GeditEncodingsDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); - gtk_widget_show (dialog); + object_class->finalize = gedit_encodings_dialog_finalize; - g_error_free (err); - } + g_type_class_add_private (object_class, sizeof (GeditEncodingsDialogPrivate)); } +enum { + COLUMN_NAME, + COLUMN_CHARSET, + N_COLUMNS +}; + static void -count_selected_items_func (GtkTreeModel * model, - GtkTreePath * path, - GtkTreeIter * iter, gpointer data) +count_selected_items_func (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { int *count = data; @@ -96,51 +101,38 @@ count_selected_items_func (GtkTreeModel * model, } static void -available_selection_changed_callback (GtkTreeSelection * selection, - void *data) +available_selection_changed_callback (GtkTreeSelection *selection, + GeditEncodingsDialog *dialogs) { int count; - GtkWidget *add_button; - GtkWidget *dialog; - - dialog = data; count = 0; gtk_tree_selection_selected_foreach (selection, count_selected_items_func, &count); - add_button = - g_object_get_data (G_OBJECT (dialog), "encoding-dialog-add"); - - gtk_widget_set_sensitive (add_button, count > 0); + gtk_widget_set_sensitive (dialogs->priv->add_button, count > 0); } static void -displayed_selection_changed_callback (GtkTreeSelection * selection, - void *data) +displayed_selection_changed_callback (GtkTreeSelection *selection, + GeditEncodingsDialog *dialogs) { int count; - GtkWidget *remove_button; - GtkWidget *dialog; - - dialog = data; count = 0; gtk_tree_selection_selected_foreach (selection, count_selected_items_func, &count); - remove_button = g_object_get_data (G_OBJECT (dialog), - "encoding-dialog-remove"); - - gtk_widget_set_sensitive (remove_button, count > 0); + gtk_widget_set_sensitive (dialogs->priv->remove_button, count > 0); } static void get_selected_encodings_func (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, gpointer data) + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { GSList **list = data; gchar *charset; @@ -156,20 +148,19 @@ get_selected_encodings_func (GtkTreeModel *model, } static void -update_shown_in_menu_tree_model (GtkListStore * store, GSList *list) +update_shown_in_menu_tree_model (GtkListStore *store, + GSList *list) { GtkTreeIter iter; - - gedit_debug (DEBUG_PREFS, ""); gtk_list_store_clear (store); while (list != NULL) { - const GeditEncoding* enc; + const GeditEncoding *enc; enc = (const GeditEncoding*) list->data; - + gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COLUMN_CHARSET, @@ -178,23 +169,18 @@ update_shown_in_menu_tree_model (GtkListStore * store, GSList *list) gedit_encoding_get_name (enc), -1); list = g_slist_next (list); - } + } } static void -add_button_clicked_callback (GtkWidget * button, void *data) +add_button_clicked_callback (GtkWidget *button, + GeditEncodingsDialog *dialog) { - GtkWidget *dialog; - GtkWidget *treeview; GtkTreeSelection *selection; GSList *encodings; GSList *tmp; - dialog = data; - - treeview = g_object_get_data (G_OBJECT (dialog), - "encoding-dialog-available-treeview"); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->available_treeview)); encodings = NULL; gtk_tree_selection_selected_foreach (selection, @@ -204,34 +190,28 @@ add_button_clicked_callback (GtkWidget * button, void *data) tmp = encodings; while (tmp != NULL) { - if (g_slist_find (show_in_menu_list, tmp->data) == NULL) - show_in_menu_list = g_slist_prepend (show_in_menu_list, tmp->data); + if (g_slist_find (dialog->priv->show_in_menu_list, tmp->data) == NULL) + dialog->priv->show_in_menu_list = g_slist_prepend (dialog->priv->show_in_menu_list, + tmp->data); tmp = g_slist_next (tmp); } g_slist_free (encodings); - update_shown_in_menu_tree_model ( - GTK_LIST_STORE ( - g_object_get_data (G_OBJECT (dialog), "encoding-dialog-displayed-liststore")), - show_in_menu_list); + update_shown_in_menu_tree_model (GTK_LIST_STORE (dialog->priv->displayed_liststore), + dialog->priv->show_in_menu_list); } static void -remove_button_clicked_callback (GtkWidget * button, void *data) +remove_button_clicked_callback (GtkWidget *button, + GeditEncodingsDialog *dialog) { - GtkWidget *dialog; - GtkWidget *treeview; GtkTreeSelection *selection; GSList *encodings; GSList *tmp; - dialog = data; - - treeview = g_object_get_data (G_OBJECT (dialog), - "encoding-dialog-displayed-treeview"); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->displayed_treeview)); encodings = NULL; gtk_tree_selection_selected_foreach (selection, @@ -241,51 +221,42 @@ remove_button_clicked_callback (GtkWidget * button, void *data) tmp = encodings; while (tmp != NULL) { - show_in_menu_list = g_slist_remove (show_in_menu_list, tmp->data); + dialog->priv->show_in_menu_list = g_slist_remove (dialog->priv->show_in_menu_list, + tmp->data); tmp = g_slist_next (tmp); } g_slist_free (encodings); - update_shown_in_menu_tree_model ( - GTK_LIST_STORE ( - g_object_get_data (G_OBJECT (dialog), "encoding-dialog-displayed-liststore")), - show_in_menu_list); + update_shown_in_menu_tree_model (GTK_LIST_STORE (dialog->priv->displayed_liststore), + dialog->priv->show_in_menu_list); } static void -dialog_destroyed (void *data, GObject * where_object_was) -{ - if (show_in_menu_list != NULL) - g_slist_free (show_in_menu_list); - - show_in_menu_list = NULL; -} - -static void -init_shown_in_menu_tree_model (GtkListStore * store) +init_shown_in_menu_tree_model (GeditEncodingsDialog *dialog) { GtkTreeIter iter; GSList *list, *tmp; - gedit_debug (DEBUG_PREFS, ""); - /* add data to the list store */ list = gedit_prefs_manager_get_shown_in_menu_encodings (); - + tmp = list; - + while (tmp != NULL) { - const GeditEncoding* enc; + const GeditEncoding *enc; - enc = (const GeditEncoding*) tmp->data; - - show_in_menu_list = g_slist_prepend (show_in_menu_list, tmp->data); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, + enc = (const GeditEncoding *) tmp->data; + + dialog->priv->show_in_menu_list = g_slist_prepend (dialog->priv->show_in_menu_list, + tmp->data); + + gtk_list_store_append (dialog->priv->displayed_liststore, + &iter); + gtk_list_store_set (dialog->priv->displayed_liststore, + &iter, COLUMN_CHARSET, gedit_encoding_get_charset (enc), COLUMN_NAME, @@ -297,85 +268,126 @@ init_shown_in_menu_tree_model (GtkListStore * store) g_slist_free (list); } -static GtkWidget * -gedit_encoding_dialog_new (GtkWindow *transient_parent) +static void +response_handler (GtkDialog *dialog, + gint response_id, + GeditEncodingsDialog *dlg) +{ + if (response_id == GTK_RESPONSE_HELP) + { + gedit_help_display (GTK_WINDOW (dialog), "gedit", NULL); + g_signal_stop_emission_by_name (dialog, "response"); + return; + } + + if (response_id == GTK_RESPONSE_OK) + { + g_return_if_fail (gedit_prefs_manager_shown_in_menu_encodings_can_set ()); + gedit_prefs_manager_set_shown_in_menu_encodings (dlg->priv->show_in_menu_list); + } +} + +static void +gedit_encodings_dialog_init (GeditEncodingsDialog *dlg) { - GladeXML *xml; - GtkWidget *w; + GtkWidget *content; GtkCellRenderer *cell_renderer; - int i; GtkTreeModel *sort_model; - GtkListStore *tree; GtkTreeViewColumn *column; GtkTreeIter parent_iter; GtkTreeSelection *selection; - GtkWidget *dialog; const GeditEncoding *enc; + GtkWidget *error_widget; + int i; + gboolean ret; - xml = glade_xml_new (GEDIT_GLADEDIR "gedit-encodings-dialog.glade2", - "encodings-dialog", NULL); - - if (!xml) + dlg->priv = GEDIT_ENCODINGS_DIALOG_GET_PRIVATE (dlg); + + gtk_dialog_add_buttons (GTK_DIALOG (dlg), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, + GTK_RESPONSE_OK, + GTK_STOCK_HELP, + GTK_RESPONSE_HELP, + NULL); + + gtk_window_set_title (GTK_WINDOW (dlg), _("Character Codings")); + gtk_window_set_default_size (GTK_WINDOW (dlg), 650, 400); + gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); + + gtk_dialog_set_default_response (GTK_DIALOG (dlg), + GTK_RESPONSE_OK); + + g_signal_connect (dlg, + "response", + G_CALLBACK (response_handler), + dlg); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "gedit-encodings-dialog.glade", + "encodings-dialog-contents", + &error_widget, + "encodings-dialog-contents", &content, + "add-button", &dlg->priv->add_button, + "remove-button", &dlg->priv->remove_button, + "available-treeview", &dlg->priv->available_treeview, + "displayed-treeview", &dlg->priv->displayed_treeview, + NULL); + + if (!ret) { - g_warning ("Could not find gedit-encodings-dialog.glade2, reinstall gedit.\n"); - return NULL; - } + gtk_widget_show (error_widget); - /* The dialog itself */ - dialog = glade_xml_get_widget (xml, "encodings-dialog"); + gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dlg)->vbox), + error_widget); - if (transient_parent != NULL) - gtk_window_set_transient_for (GTK_WINDOW (dialog), transient_parent); + return; + } - /* buttons */ - w = glade_xml_get_widget (xml, "add-button"); - g_object_set_data (G_OBJECT (dialog), "encoding-dialog-add", w); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), + content, TRUE, TRUE, 0); - g_signal_connect (G_OBJECT (w), "clicked", + g_signal_connect (dlg->priv->add_button, + "clicked", G_CALLBACK (add_button_clicked_callback), - dialog); - - w = glade_xml_get_widget (xml, "remove-button"); - g_object_set_data (G_OBJECT (dialog), "encoding-dialog-remove", w); - - g_signal_connect (G_OBJECT (w), "clicked", + dlg); + g_signal_connect (dlg->priv->remove_button, + "clicked", G_CALLBACK (remove_button_clicked_callback), - dialog); + dlg); /* Tree view of available encodings */ + dlg->priv->available_liststore = gtk_list_store_new (N_COLUMNS, + G_TYPE_STRING, + G_TYPE_STRING); - w = glade_xml_get_widget (xml, "available-treeview"); - g_object_set_data (G_OBJECT (dialog), - "encoding-dialog-available-treeview", w); - - tree = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); - - /* Column 1 */ cell_renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("_Description"), cell_renderer, "text", COLUMN_NAME, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (w), column); + gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->available_treeview), + column); gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME); - /* Column 2 */ cell_renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("_Encoding"), cell_renderer, "text", COLUMN_CHARSET, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (w), column); + gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->available_treeview), + column); gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET); /* Add the data */ - i = 0; while ((enc = gedit_encoding_get_from_index (i)) != NULL) { - gtk_list_store_append (tree, &parent_iter); - gtk_list_store_set (tree, &parent_iter, + gtk_list_store_append (dlg->priv->available_liststore, + &parent_iter); + gtk_list_store_set (dlg->priv->available_liststore, + &parent_iter, COLUMN_CHARSET, gedit_encoding_get_charset (enc), COLUMN_NAME, @@ -385,128 +397,83 @@ gedit_encoding_dialog_new (GtkWindow *transient_parent) } /* Sort model */ - sort_model = - gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree)); - - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE - (sort_model), COLUMN_NAME, + sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (dlg->priv->available_liststore)); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), + COLUMN_NAME, GTK_SORT_ASCENDING); - gtk_tree_view_set_model (GTK_TREE_VIEW (w), sort_model); - g_object_unref (G_OBJECT (tree)); + gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->available_treeview), + sort_model); + g_object_unref (G_OBJECT (dlg->priv->available_liststore)); g_object_unref (G_OBJECT (sort_model)); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (w)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->available_treeview)); gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection), GTK_SELECTION_MULTIPLE); - available_selection_changed_callback (selection, dialog); - g_signal_connect (G_OBJECT (selection), "changed", - G_CALLBACK - (available_selection_changed_callback), dialog); + available_selection_changed_callback (selection, dlg); + g_signal_connect (selection, + "changed", + G_CALLBACK (available_selection_changed_callback), + dlg); /* Tree view of selected encodings */ + dlg->priv->displayed_liststore = gtk_list_store_new (N_COLUMNS, + G_TYPE_STRING, + G_TYPE_STRING); - w = glade_xml_get_widget (xml, "displayed-treeview"); - g_object_set_data (G_OBJECT (dialog), - "encoding-dialog-displayed-treeview", w); - - tree = - gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); - - g_object_set_data (G_OBJECT (dialog), - "encoding-dialog-displayed-liststore", tree); - - /* Column 1 */ cell_renderer = gtk_cell_renderer_text_new (); - column = - gtk_tree_view_column_new_with_attributes (_("_Description"), - cell_renderer, - "text", COLUMN_NAME, - NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (w), column); + column = gtk_tree_view_column_new_with_attributes (_("_Description"), + cell_renderer, + "text", COLUMN_NAME, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->displayed_treeview), + column); gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME); - /* Column 2 */ cell_renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("_Encoding"), cell_renderer, "text", COLUMN_CHARSET, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (w), column); + gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->displayed_treeview), + column); gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET); /* Add the data */ - init_shown_in_menu_tree_model (tree); - + init_shown_in_menu_tree_model (dlg); + /* Sort model */ - sort_model = - gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree)); + sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (dlg->priv->displayed_liststore)); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), COLUMN_NAME, GTK_SORT_ASCENDING); - gtk_tree_view_set_model (GTK_TREE_VIEW (w), sort_model); + gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->displayed_treeview), + sort_model); g_object_unref (G_OBJECT (sort_model)); - g_object_unref (G_OBJECT (tree)); + g_object_unref (G_OBJECT (dlg->priv->displayed_liststore)); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (w)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->displayed_treeview)); gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection), GTK_SELECTION_MULTIPLE); - displayed_selection_changed_callback (selection, dialog); - g_signal_connect (G_OBJECT (selection), "changed", - G_CALLBACK - (displayed_selection_changed_callback), dialog); - - g_object_unref (G_OBJECT (xml)); - - g_object_weak_ref (G_OBJECT (dialog), dialog_destroyed, NULL); - - return dialog; + displayed_selection_changed_callback (selection, dlg); + g_signal_connect (selection, + "changed", + G_CALLBACK (displayed_selection_changed_callback), + dlg); } -static void -update_list (void) -{ - g_return_if_fail (gedit_prefs_manager_shown_in_menu_encodings_can_set ()); - - gedit_prefs_manager_set_shown_in_menu_encodings (show_in_menu_list); -} - -gboolean -gedit_encodings_dialog_run (GtkWindow *parent) +GtkWidget * +gedit_encodings_dialog_new (void) { - gint id; - GtkWidget *dialog; - - dialog = gedit_encoding_dialog_new (parent); - - do - { - id = gtk_dialog_run (GTK_DIALOG (dialog)); - - switch (id) { - case GTK_RESPONSE_HELP: - show_help (dialog); - break; - - case GTK_RESPONSE_OK: - update_list (); - gtk_widget_hide (dialog); - - break; - - default: - gtk_widget_hide (dialog); - } - - } while (GTK_WIDGET_VISIBLE (dialog)); + GtkWidget *dlg; - gtk_widget_destroy (dialog); + dlg = GTK_WIDGET (g_object_new (GEDIT_TYPE_ENCODINGS_DIALOG, NULL)); - return (id == GTK_RESPONSE_OK); + return dlg; } diff --git a/gedit/dialogs/gedit-encodings-dialog.glade b/gedit/dialogs/gedit-encodings-dialog.glade new file mode 100644 index 00000000..add85afd --- /dev/null +++ b/gedit/dialogs/gedit-encodings-dialog.glade @@ -0,0 +1,278 @@ + + + + + + + + 650 + 400 + Character codings + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + True + False + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-help + True + GTK_RELIEF_NORMAL + -11 + + + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + -6 + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 6 + True + True + 6 + + + + True + False + 6 + + + + True + A_vailable encodings: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + available-treeview + + + 0 + False + False + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_ETCHED_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + gtk-add + True + GTK_RELIEF_NORMAL + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + 6 + + + + True + E_ncodings shown in menu: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + displayed-treeview + + + 0 + False + False + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_ETCHED_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + gtk-remove + True + GTK_RELIEF_NORMAL + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + diff --git a/gedit/dialogs/gedit-encodings-dialog.h b/gedit/dialogs/gedit-encodings-dialog.h index fd6bc383..555c913b 100644 --- a/gedit/dialogs/gedit-encodings-dialog.h +++ b/gedit/dialogs/gedit-encodings-dialog.h @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-encodings-dialog.h * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,18 +21,66 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2003-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_ENCODINGS_DIALOG_H__ #define __GEDIT_ENCODINGS_DIALOG_H__ -#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_ENCODINGS_DIALOG (gedit_encodings_dialog_get_type()) +#define GEDIT_ENCODINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialog)) +#define GEDIT_ENCODINGS_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialog const)) +#define GEDIT_ENCODINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialogClass)) +#define GEDIT_IS_ENCODINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_ENCODINGS_DIALOG)) +#define GEDIT_IS_ENCODINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_ENCODINGS_DIALOG)) +#define GEDIT_ENCODINGS_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_ENCODINGS_DIALOG, GeditEncodingsDialogClass)) + + +/* Private structure type */ +typedef struct _GeditEncodingsDialogPrivate GeditEncodingsDialogPrivate; + +/* + * Main object structure + */ +typedef struct _GeditEncodingsDialog GeditEncodingsDialog; + +struct _GeditEncodingsDialog +{ + GtkDialog dialog; + + /*< private > */ + GeditEncodingsDialogPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditEncodingsDialogClass GeditEncodingsDialogClass; + +struct _GeditEncodingsDialogClass +{ + GtkDialogClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_encodings_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_encodings_dialog_new (void); -gboolean gedit_encodings_dialog_run (GtkWindow *parent); +G_END_DECLS #endif /* __GEDIT_ENCODINGS_DIALOG_H__ */ - diff --git a/gedit/dialogs/gedit-open-location-dialog.c b/gedit/dialogs/gedit-open-location-dialog.c new file mode 100644 index 00000000..6339ea2c --- /dev/null +++ b/gedit/dialogs/gedit-open-location-dialog.c @@ -0,0 +1,251 @@ +/* + * gedit-open-location-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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2001-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-open-location-dialog.h" + +#include + +#include +#include + +#include "gedit-encodings-option-menu.h" +#include "gedit-utils.h" +#include "gedit-help.h" + +#define GEDIT_OPEN_LOCATION_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_OPEN_LOCATION_DIALOG, GeditOpenLocationDialogPrivate)) + +struct _GeditOpenLocationDialogPrivate +{ + GtkWidget *uri; + GtkWidget *uri_list; + GtkWidget *encoding_menu; +}; + +G_DEFINE_TYPE(GeditOpenLocationDialog, gedit_open_location_dialog, GTK_TYPE_DIALOG) + +static void +gedit_open_location_dialog_class_init (GeditOpenLocationDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (GeditOpenLocationDialogPrivate)); +} + +static void +entry_changed (GtkEditable *editable, + GeditOpenLocationDialog *dlg) +{ + const gchar *str; + + str = gtk_entry_get_text (GTK_ENTRY (dlg->priv->uri)); + g_return_if_fail (str != NULL); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg), + GTK_RESPONSE_OK, + (str[0] != '\0')); +} + +static void +response_handler (GeditOpenLocationDialog *dlg, + gint response_id, + gpointer data) +{ + gchar *uri; + + switch (response_id) + { + case GTK_RESPONSE_HELP: + gedit_help_display (GTK_WINDOW (dlg), + NULL, + NULL); + + g_signal_stop_emission_by_name (dlg, "response"); + + break; + + case GTK_RESPONSE_OK: + uri = gedit_open_location_dialog_get_uri (dlg); + if (uri != NULL) + { + g_free (uri); + uri = gtk_editable_get_chars (GTK_EDITABLE (dlg->priv->uri), + 0, + -1); + gnome_entry_prepend_history (GNOME_ENTRY (dlg->priv->uri_list), + TRUE, + uri); + g_free (uri); + } + + break; + } +} + +static void +gedit_open_location_dialog_init (GeditOpenLocationDialog *dlg) +{ + GtkWidget *content; + GtkWidget *encoding_label; + GtkWidget *encoding_hbox; + GtkWidget *error_widget; + gboolean ret; + + dlg->priv = GEDIT_OPEN_LOCATION_DIALOG_GET_PRIVATE (dlg); + + gtk_dialog_add_buttons (GTK_DIALOG (dlg), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, + GTK_RESPONSE_OK, + GTK_STOCK_HELP, + GTK_RESPONSE_HELP, + NULL); + + gtk_window_set_title (GTK_WINDOW (dlg), _("Open Location")); + gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE); + gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); + gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE); + + gtk_dialog_set_default_response (GTK_DIALOG (dlg), + GTK_RESPONSE_OK); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg), + GTK_RESPONSE_OK, FALSE); + + g_signal_connect (G_OBJECT (dlg), + "response", + G_CALLBACK (response_handler), + NULL); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "gedit-open-location-dialog.glade", + "open_uri_dialog_content", + &error_widget, + "open_uri_dialog_content", &content, + "uri", &dlg->priv->uri, + "uri_list", &dlg->priv->uri_list, + "encoding_label", &encoding_label, + "encoding_hbox", &encoding_hbox, + NULL); + + if (!ret) + { + gtk_widget_show (error_widget); + + gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dlg)->vbox), + error_widget); + + return; + } + + dlg->priv->encoding_menu = gedit_encodings_option_menu_new (FALSE); + + gtk_label_set_mnemonic_widget (GTK_LABEL (encoding_label), + dlg->priv->encoding_menu); + + gtk_box_pack_end (GTK_BOX (encoding_hbox), + dlg->priv->encoding_menu, + TRUE, + TRUE, + 0); + + gtk_widget_show (dlg->priv->encoding_menu); + + g_signal_connect (G_OBJECT (dlg->priv->uri), + "changed", + G_CALLBACK (entry_changed), + dlg); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), + content, FALSE, FALSE, 0); + +} + +GtkWidget * +gedit_open_location_dialog_new (GtkWindow *parent) +{ + GtkWidget *dlg; + + dlg = GTK_WIDGET (g_object_new (GEDIT_TYPE_OPEN_LOCATION_DIALOG, NULL)); + + if (parent != NULL) + gtk_window_set_transient_for (GTK_WINDOW (dlg), + parent); + + return dlg; +} + +/* Always return a valid gnome vfs uri or NULL */ +gchar * +gedit_open_location_dialog_get_uri (GeditOpenLocationDialog *dlg) +{ + const gchar *str; + gchar *uri; + gchar *canonical_uri; + GnomeVFSURI *vfs_uri; + + g_return_val_if_fail (GEDIT_IS_OPEN_LOCATION_DIALOG (dlg), NULL); + + str = gtk_entry_get_text (GTK_ENTRY (dlg->priv->uri)); + g_return_val_if_fail (str != NULL, NULL); + + if (str[0] == '\0') + return NULL; + + uri = gnome_vfs_make_uri_from_input_with_dirs (str, + GNOME_VFS_MAKE_URI_DIR_CURRENT); + g_return_val_if_fail (uri != NULL, NULL); + + canonical_uri = gnome_vfs_make_uri_canonical (uri); + g_free (uri); + + g_return_val_if_fail (canonical_uri != NULL, NULL); + + vfs_uri = gnome_vfs_uri_new (canonical_uri); + if (vfs_uri == NULL) + { + g_free (canonical_uri); + return NULL; + } + + gnome_vfs_uri_unref (vfs_uri); + return canonical_uri; +} + +const GeditEncoding * +gedit_open_location_dialog_get_encoding (GeditOpenLocationDialog *dlg) +{ + g_return_val_if_fail (GEDIT_IS_OPEN_LOCATION_DIALOG (dlg), NULL); + + return gedit_encodings_option_menu_get_selected_encoding ( + GEDIT_ENCODINGS_OPTION_MENU (dlg->priv->encoding_menu)); +} diff --git a/gedit/dialogs/gedit-open-location-dialog.glade b/gedit/dialogs/gedit-open-location-dialog.glade new file mode 100644 index 00000000..eeb9b14a --- /dev/null +++ b/gedit/dialogs/gedit-open-location-dialog.glade @@ -0,0 +1,208 @@ + + + + + + + + Open Location + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + False + True + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + gtk-open + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + True + True + True + gtk-help + True + GTK_RELIEF_NORMAL + True + -11 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 6 + True + False + 12 + + + + True + False + 6 + + + + True + Enter the _location (URI) of the file you would like to open: + True + False + GTK_JUSTIFY_LEFT + True + False + 0 + 0.5 + 0 + 0 + uri_list + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + gedit2_uri_list + 10 + + + + True + True + True + True + True + 0 + + True + * + True + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 6 + + + + True + Ch_aracter coding: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + + diff --git a/gedit/dialogs/gedit-open-location-dialog.h b/gedit/dialogs/gedit-open-location-dialog.h new file mode 100644 index 00000000..2819388c --- /dev/null +++ b/gedit/dialogs/gedit-open-location-dialog.h @@ -0,0 +1,96 @@ +/* + * gedit-open-location-dialog.h + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2001-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_OPEN_LOCATION_DIALOG_H__ +#define __GEDIT_OPEN_LOCATION_DIALOG_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_OPEN_LOCATION_DIALOG (gedit_open_location_dialog_get_type()) +#define GEDIT_OPEN_LOCATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_OPEN_LOCATION_DIALOG, GeditOpenLocationDialog)) +#define GEDIT_OPEN_LOCATION_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_OPEN_LOCATION_DIALOG, GeditOpenLocationDialog const)) +#define GEDIT_OPEN_LOCATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_OPEN_LOCATION_DIALOG, GeditOpenLocationDialogClass)) +#define GEDIT_IS_OPEN_LOCATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_OPEN_LOCATION_DIALOG)) +#define GEDIT_IS_OPEN_LOCATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_OPEN_LOCATION_DIALOG)) +#define GEDIT_OPEN_LOCATION_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_OPEN_LOCATION_DIALOG, GeditOpenLocationDialogClass)) + +/* Private structure type */ +typedef struct _GeditOpenLocationDialogPrivate GeditOpenLocationDialogPrivate; + +/* + * Main object structure + */ +typedef struct _GeditOpenLocationDialog GeditOpenLocationDialog; + +struct _GeditOpenLocationDialog +{ + GtkDialog dialog; + + /*< private > */ + GeditOpenLocationDialogPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditOpenLocationDialogClass GeditOpenLocationDialogClass; + +struct _GeditOpenLocationDialogClass +{ + GtkDialogClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_open_location_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_open_location_dialog_new (GtkWindow *parent); + +gchar *gedit_open_location_dialog_get_uri (GeditOpenLocationDialog *dlg); + +const GeditEncoding *gedit_open_location_dialog_get_encoding (GeditOpenLocationDialog *dlg); + +/* + * The widget automatically runs the help viewer when the Help button is pressed, + * so there is no need to catch the GTK_RESPONSE_HELP response. + * + * GTK_RESPONSE_OK response is emitted when the "Open" button is pressed. + */ + +G_END_DECLS + +#endif /* __GEDIT_OPEN_LOCATION_DIALOG_H__ */ diff --git a/gedit/dialogs/gedit-page-setup-dialog.c b/gedit/dialogs/gedit-page-setup-dialog.c index aec61e60..d2cc631e 100644 --- a/gedit/dialogs/gedit-page-setup-dialog.c +++ b/gedit/dialogs/gedit-page-setup-dialog.c @@ -3,7 +3,7 @@ * gedit-page-setup-dialog.c * This file is part of gedit * - * Copyright (C) 2003 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 @@ -25,6 +25,8 @@ * Modified by the gedit Team, 2003. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -34,26 +36,38 @@ #include #include +#include #include -#include #include #include #include "gedit-page-setup-dialog.h" -#include "gedit2.h" #include "gedit-utils.h" #include "gedit-debug.h" +#include "gedit-help.h" + +/* + * gedit-page-setup dialog is a singleton since we don't + * want two dialogs showing an inconsistent state of the + * preferences. + * When gedit_show_page_setup_dialog is called and there + * is already a page setup dialog open, it is reparented + * and shown. + */ -typedef struct _GeditPageSetupDialog GeditPageSetupDialog; +static GtkWidget *page_setup_dialog = NULL; -struct _GeditPageSetupDialog { - GtkWidget *dialog; +#define GEDIT_PAGE_SETUP_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PAGE_SETUP_DIALOG, GeditPageSetupDialogPrivate)) + + +struct _GeditPageSetupDialogPrivate +{ GtkWidget *syntax_checkbutton; GtkWidget *page_header_checkbutton; - + GtkWidget *line_numbers_checkbutton; GtkWidget *line_numbers_hbox; GtkWidget *line_numbers_spinbutton; @@ -74,92 +88,98 @@ struct _GeditPageSetupDialog { GtkWidget *restore_button; }; + +G_DEFINE_TYPE(GeditPageSetupDialog, gedit_page_setup_dialog, GTK_TYPE_DIALOG) + + +/* these are used to keep a consistent init value + * of preferences not currently stored in gconf + * across multiple instances. + */ static gboolean split_button_state = TRUE; static gint old_line_numbers_value = 1; -static void dialog_destroyed (GtkObject *obj, void **dialog_pointer); -static void -dialog_destroyed (GtkObject *obj, void **dialog_pointer) +static void +gedit_page_setup_dialog_class_init (GeditPageSetupDialogClass *klass) { - gedit_debug (DEBUG_PRINT, ""); - - if (dialog_pointer != NULL) - { - g_free (*dialog_pointer); - *dialog_pointer = NULL; - } + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (GeditPageSetupDialogPrivate)); } static void -dialog_response_handler (GtkDialog *dlg, gint res_id, GeditPageSetupDialog *dialog) +dialog_response_handler (GeditPageSetupDialog *dlg, + gint res_id, + gpointer data) { - GError *error = NULL; + switch (res_id) + { + case GTK_RESPONSE_HELP: + gedit_help_display (GTK_WINDOW (dlg), + "gedit.xml", + "gedit-page-setup"); - gedit_debug (DEBUG_PRINT, ""); + g_signal_stop_emission_by_name (dlg, "response"); - switch (res_id) { - case GTK_RESPONSE_HELP: - gnome_help_display ("gedit.xml", "gedit-page-setup", &error); - if (error != NULL) - { - gedit_warning (GTK_WINDOW (dlg), error->message); - g_error_free (error); - } break; - + default: - gtk_widget_destroy (dialog->dialog); + gtk_widget_destroy (GTK_WIDGET(dlg)); } } static void -syntax_checkbutton_toggled (GtkToggleButton *button, GeditPageSetupDialog *dlg) +syntax_checkbutton_toggled (GtkToggleButton *button, + GeditPageSetupDialog *dlg) { - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); + + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->syntax_checkbutton)); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->syntax_checkbutton)); - gedit_prefs_manager_set_print_syntax_hl (gtk_toggle_button_get_active (button)); } static void -page_header_checkbutton_toggled (GtkToggleButton *button, GeditPageSetupDialog *dlg) +page_header_checkbutton_toggled (GtkToggleButton *button, + GeditPageSetupDialog *dlg) { - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->page_header_checkbutton)); + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->page_header_checkbutton)); gedit_prefs_manager_set_print_header (gtk_toggle_button_get_active (button)); } static void -line_numbers_checkbutton_toggled (GtkToggleButton *button, GeditPageSetupDialog *dlg) +line_numbers_checkbutton_toggled (GtkToggleButton *button, + GeditPageSetupDialog *dlg) { - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); + + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->line_numbers_checkbutton)); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->line_numbers_checkbutton)); - if (gtk_toggle_button_get_active (button)) { - gtk_widget_set_sensitive (dlg->line_numbers_hbox, + gtk_widget_set_sensitive (dlg->priv->line_numbers_hbox, gedit_prefs_manager_print_line_numbers_can_set ()); - + gedit_prefs_manager_set_print_line_numbers ( MAX (1, gtk_spin_button_get_value_as_int ( - GTK_SPIN_BUTTON (dlg->line_numbers_spinbutton)))); + GTK_SPIN_BUTTON (dlg->priv->line_numbers_spinbutton)))); } - else + else { - gtk_widget_set_sensitive (dlg->line_numbers_hbox, FALSE); + gtk_widget_set_sensitive (dlg->priv->line_numbers_hbox, FALSE); gedit_prefs_manager_set_print_line_numbers (0); } } static void -line_numbers_spinbutton_value_changed (GtkSpinButton *spin_button, GeditPageSetupDialog *dlg) +line_numbers_spinbutton_value_changed (GtkSpinButton *spin_button, + GeditPageSetupDialog *dlg) { - g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->line_numbers_spinbutton)); + g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->priv->line_numbers_spinbutton)); old_line_numbers_value = MAX (1, gtk_spin_button_get_value_as_int (spin_button)); @@ -167,40 +187,37 @@ line_numbers_spinbutton_value_changed (GtkSpinButton *spin_button, GeditPageSetu } static void -wrap_mode_checkbutton_toggled (GtkToggleButton *button, GeditPageSetupDialog *dlg) +wrap_mode_checkbutton_toggled (GtkToggleButton *button, + GeditPageSetupDialog *dlg) { - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->text_wrapping_checkbutton))) + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->priv->text_wrapping_checkbutton))) { gedit_prefs_manager_set_print_wrap_mode (GTK_WRAP_NONE); - gtk_widget_set_sensitive (dlg->do_not_split_checkbutton, + gtk_widget_set_sensitive (dlg->priv->do_not_split_checkbutton, FALSE); gtk_toggle_button_set_inconsistent ( - GTK_TOGGLE_BUTTON (dlg->do_not_split_checkbutton), TRUE); - + GTK_TOGGLE_BUTTON (dlg->priv->do_not_split_checkbutton), TRUE); } else { - gtk_widget_set_sensitive (dlg->do_not_split_checkbutton, - TRUE); + gtk_widget_set_sensitive (dlg->priv->do_not_split_checkbutton, TRUE); gtk_toggle_button_set_inconsistent ( - GTK_TOGGLE_BUTTON (dlg->do_not_split_checkbutton), FALSE); + GTK_TOGGLE_BUTTON (dlg->priv->do_not_split_checkbutton), FALSE); - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->do_not_split_checkbutton))) + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->priv->do_not_split_checkbutton))) { split_button_state = TRUE; - + gedit_prefs_manager_set_print_wrap_mode (GTK_WRAP_WORD); } else { split_button_state = FALSE; - + gedit_prefs_manager_set_print_wrap_mode (GTK_WRAP_CHAR); - } - + } } } @@ -212,38 +229,38 @@ setup_general_page (GeditPageSetupDialog *dialog) GtkWrapMode wrap_mode; /* Print syntax */ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->syntax_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->syntax_checkbutton), gedit_prefs_manager_get_print_syntax_hl ()); - gtk_widget_set_sensitive (dialog->syntax_checkbutton, + gtk_widget_set_sensitive (dialog->priv->syntax_checkbutton, gedit_prefs_manager_print_syntax_hl_can_set ()); /* Print page headers */ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->page_header_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->page_header_checkbutton), gedit_prefs_manager_get_print_header ()); - gtk_widget_set_sensitive (dialog->page_header_checkbutton, + gtk_widget_set_sensitive (dialog->priv->page_header_checkbutton, gedit_prefs_manager_print_header_can_set ()); /* Line numbers */ line_numbers = gedit_prefs_manager_get_print_line_numbers (); can_set = gedit_prefs_manager_print_line_numbers_can_set (); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->line_numbers_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->line_numbers_checkbutton), line_numbers > 0); - gtk_widget_set_sensitive (dialog->line_numbers_checkbutton, + gtk_widget_set_sensitive (dialog->priv->line_numbers_checkbutton, can_set); if (line_numbers > 0) { - gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->line_numbers_spinbutton), + gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->line_numbers_spinbutton), (guint) line_numbers); - gtk_widget_set_sensitive (dialog->line_numbers_hbox, + gtk_widget_set_sensitive (dialog->priv->line_numbers_hbox, can_set); } else { - gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->line_numbers_spinbutton), + gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->line_numbers_spinbutton), (guint)old_line_numbers_value); - gtk_widget_set_sensitive (dialog->line_numbers_hbox, FALSE); + gtk_widget_set_sensitive (dialog->priv->line_numbers_hbox, FALSE); } /* Text wrapping */ @@ -251,127 +268,137 @@ setup_general_page (GeditPageSetupDialog *dialog) switch (wrap_mode ) { - case GTK_WRAP_WORD: - gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dialog->text_wrapping_checkbutton), TRUE); - gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dialog->do_not_split_checkbutton), TRUE); - break; - case GTK_WRAP_CHAR: - gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dialog->text_wrapping_checkbutton), TRUE); - gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dialog->do_not_split_checkbutton), FALSE); - break; - default: - gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dialog->text_wrapping_checkbutton), FALSE); - gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dialog->do_not_split_checkbutton), - split_button_state); - gtk_toggle_button_set_inconsistent ( - GTK_TOGGLE_BUTTON (dialog->do_not_split_checkbutton), TRUE); - + case GTK_WRAP_WORD: + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (dialog->priv->text_wrapping_checkbutton), TRUE); + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (dialog->priv->do_not_split_checkbutton), TRUE); + break; + case GTK_WRAP_CHAR: + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (dialog->priv->text_wrapping_checkbutton), TRUE); + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (dialog->priv->do_not_split_checkbutton), FALSE); + break; + default: + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (dialog->priv->text_wrapping_checkbutton), FALSE); + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (dialog->priv->do_not_split_checkbutton), + split_button_state); + gtk_toggle_button_set_inconsistent ( + GTK_TOGGLE_BUTTON (dialog->priv->do_not_split_checkbutton), TRUE); } can_set = gedit_prefs_manager_print_wrap_mode_can_set (); - gtk_widget_set_sensitive (dialog->text_wrapping_checkbutton, + gtk_widget_set_sensitive (dialog->priv->text_wrapping_checkbutton, can_set); - gtk_widget_set_sensitive (dialog->do_not_split_checkbutton, + gtk_widget_set_sensitive (dialog->priv->do_not_split_checkbutton, can_set && (wrap_mode != GTK_WRAP_NONE)); - g_signal_connect (G_OBJECT (dialog->syntax_checkbutton), "toggled", - G_CALLBACK (syntax_checkbutton_toggled), dialog); - - g_signal_connect (G_OBJECT (dialog->page_header_checkbutton), "toggled", - G_CALLBACK (page_header_checkbutton_toggled), dialog); - - g_signal_connect (G_OBJECT (dialog->line_numbers_checkbutton), "toggled", - G_CALLBACK (line_numbers_checkbutton_toggled), dialog); - - g_signal_connect (G_OBJECT (dialog->line_numbers_spinbutton), "value_changed", - G_CALLBACK (line_numbers_spinbutton_value_changed), dialog); - - g_signal_connect (G_OBJECT (dialog->text_wrapping_checkbutton), "toggled", - G_CALLBACK (wrap_mode_checkbutton_toggled), dialog); - - g_signal_connect (G_OBJECT (dialog->do_not_split_checkbutton), "toggled", - G_CALLBACK (wrap_mode_checkbutton_toggled), dialog); - + g_signal_connect (dialog->priv->syntax_checkbutton, + "toggled", + G_CALLBACK (syntax_checkbutton_toggled), + dialog); + g_signal_connect (dialog->priv->page_header_checkbutton, + "toggled", + G_CALLBACK (page_header_checkbutton_toggled), + dialog); + g_signal_connect (dialog->priv->line_numbers_checkbutton, + "toggled", + G_CALLBACK (line_numbers_checkbutton_toggled), + dialog); + g_signal_connect (dialog->priv->line_numbers_spinbutton, + "value_changed", + G_CALLBACK (line_numbers_spinbutton_value_changed), + dialog); + g_signal_connect (dialog->priv->text_wrapping_checkbutton, + "toggled", + G_CALLBACK (wrap_mode_checkbutton_toggled), + dialog); + g_signal_connect (dialog->priv->do_not_split_checkbutton, + "toggled", + G_CALLBACK (wrap_mode_checkbutton_toggled), + dialog); } static void -restore_button_clicked (GtkButton *button, GeditPageSetupDialog *dlg) +restore_button_clicked (GtkButton *button, + GeditPageSetupDialog *dlg) { - g_return_if_fail (dlg->body_fontbutton != NULL); - g_return_if_fail (dlg->headers_fontbutton != NULL); - g_return_if_fail (dlg->numbers_fontbutton != NULL); + g_return_if_fail (dlg->priv->body_fontbutton != NULL); + g_return_if_fail (dlg->priv->headers_fontbutton != NULL); + g_return_if_fail (dlg->priv->numbers_fontbutton != NULL); if (gedit_prefs_manager_print_font_body_can_set ()) { const gchar* font = gedit_prefs_manager_get_default_print_font_body (); gtk_font_button_set_font_name ( - GTK_FONT_BUTTON (dlg->body_fontbutton), + GTK_FONT_BUTTON (dlg->priv->body_fontbutton), font); - + gedit_prefs_manager_set_print_font_body (font); } if (gedit_prefs_manager_print_font_header_can_set ()) { - const gchar* font = gedit_prefs_manager_get_default_print_font_header (); + const gchar *font; + + font = gedit_prefs_manager_get_default_print_font_header (); gtk_font_button_set_font_name ( - GTK_FONT_BUTTON (dlg->headers_fontbutton), + GTK_FONT_BUTTON (dlg->priv->headers_fontbutton), font); - + gedit_prefs_manager_set_print_font_header (font); } - + if (gedit_prefs_manager_print_font_numbers_can_set ()) { - const gchar* font = gedit_prefs_manager_get_default_print_font_numbers (); - + const gchar *font; + + font = gedit_prefs_manager_get_default_print_font_numbers (); + gtk_font_button_set_font_name ( - GTK_FONT_BUTTON (dlg->numbers_fontbutton), + GTK_FONT_BUTTON (dlg->priv->numbers_fontbutton), font); - + gedit_prefs_manager_set_print_font_numbers (font); } } static void -body_font_button_font_set (GtkFontButton *fb, +body_font_button_font_set (GtkFontButton *fb, GeditPageSetupDialog *dlg) { - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); - g_return_if_fail (fb == GTK_FONT_BUTTON (dlg->body_fontbutton)); + g_return_if_fail (fb == GTK_FONT_BUTTON (dlg->priv->body_fontbutton)); gedit_prefs_manager_set_print_font_body (gtk_font_button_get_font_name (fb)); } static void -headers_font_button_font_set (GtkFontButton *fb, +headers_font_button_font_set (GtkFontButton *fb, GeditPageSetupDialog *dlg) { - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); - g_return_if_fail (fb == GTK_FONT_BUTTON (dlg->headers_fontbutton)); + g_return_if_fail (fb == GTK_FONT_BUTTON (dlg->priv->headers_fontbutton)); gedit_prefs_manager_set_print_font_header (gtk_font_button_get_font_name (fb)); } static void -numbers_font_button_font_set (GtkFontButton *fb, +numbers_font_button_font_set (GtkFontButton *fb, GeditPageSetupDialog *dlg) { - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); - g_return_if_fail (fb == GTK_FONT_BUTTON (dlg->numbers_fontbutton)); + g_return_if_fail (fb == GTK_FONT_BUTTON (dlg->priv->numbers_fontbutton)); gedit_prefs_manager_set_print_font_numbers (gtk_font_button_get_font_name (fb)); } @@ -387,6 +414,8 @@ font_button_new (void) gtk_font_button_set_show_style (GTK_FONT_BUTTON (button), FALSE); gtk_font_button_set_show_size (GTK_FONT_BUTTON (button), TRUE); + gtk_widget_show (button); + return button; } @@ -396,42 +425,37 @@ setup_font_page (GeditPageSetupDialog *dlg) gboolean can_set; gchar* font; - gedit_debug (DEBUG_PRINT, ""); - /* Body font button */ - dlg->body_fontbutton = font_button_new (); + dlg->priv->body_fontbutton = font_button_new (); - gtk_table_attach_defaults (GTK_TABLE (dlg->fonts_table), - dlg->body_fontbutton, 1, 2, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (dlg->priv->fonts_table), + dlg->priv->body_fontbutton, 1, 2, 0, 1); /* Headers font button */ - dlg->headers_fontbutton = font_button_new (); + dlg->priv->headers_fontbutton = font_button_new (); - gtk_table_attach_defaults (GTK_TABLE (dlg->fonts_table), - dlg->headers_fontbutton, 1, 2, 2, 3); + gtk_table_attach_defaults (GTK_TABLE (dlg->priv->fonts_table), + dlg->priv->headers_fontbutton, 1, 2, 2, 3); /* Numbers font button */ - dlg->numbers_fontbutton = font_button_new (); - - gtk_table_attach_defaults (GTK_TABLE (dlg->fonts_table), - dlg->numbers_fontbutton, 1, 2, 1, 2); - - gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->body_font_label), - dlg->body_fontbutton); - - gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->headers_font_label), - dlg->headers_fontbutton); + dlg->priv->numbers_fontbutton = font_button_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->numbers_font_label), - dlg->numbers_fontbutton); + gtk_table_attach_defaults (GTK_TABLE (dlg->priv->fonts_table), + dlg->priv->numbers_fontbutton, 1, 2, 1, 2); + gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->priv->body_font_label), + dlg->priv->body_fontbutton); + gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->priv->headers_font_label), + dlg->priv->headers_fontbutton); + gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->priv->numbers_font_label), + dlg->priv->numbers_fontbutton); /* Set initial values */ font = gedit_prefs_manager_get_print_font_body (); g_return_if_fail (font); gtk_font_button_set_font_name ( - GTK_FONT_BUTTON (dlg->body_fontbutton), + GTK_FONT_BUTTON (dlg->priv->body_fontbutton), font); g_free (font); @@ -440,7 +464,7 @@ setup_font_page (GeditPageSetupDialog *dlg) g_return_if_fail (font); gtk_font_button_set_font_name ( - GTK_FONT_BUTTON (dlg->headers_fontbutton), + GTK_FONT_BUTTON (dlg->priv->headers_fontbutton), font); g_free (font); @@ -449,153 +473,126 @@ setup_font_page (GeditPageSetupDialog *dlg) g_return_if_fail (font); gtk_font_button_set_font_name ( - GTK_FONT_BUTTON (dlg->numbers_fontbutton), + GTK_FONT_BUTTON (dlg->priv->numbers_fontbutton), font); g_free (font); - /* Set widgets sensitivity */ can_set = gedit_prefs_manager_print_font_body_can_set (); - gtk_widget_set_sensitive (dlg->body_fontbutton, can_set); - gtk_widget_set_sensitive (dlg->body_font_label, can_set); - + gtk_widget_set_sensitive (dlg->priv->body_fontbutton, can_set); + gtk_widget_set_sensitive (dlg->priv->body_font_label, can_set); + can_set = gedit_prefs_manager_print_font_header_can_set (); - gtk_widget_set_sensitive (dlg->headers_fontbutton, can_set); - gtk_widget_set_sensitive (dlg->headers_font_label, can_set); + gtk_widget_set_sensitive (dlg->priv->headers_fontbutton, can_set); + gtk_widget_set_sensitive (dlg->priv->headers_font_label, can_set); can_set = gedit_prefs_manager_print_font_numbers_can_set (); - gtk_widget_set_sensitive (dlg->numbers_fontbutton, can_set); - gtk_widget_set_sensitive (dlg->numbers_font_label, can_set); - - /* Connect signals */ - g_signal_connect (G_OBJECT (dlg->restore_button), "clicked", + gtk_widget_set_sensitive (dlg->priv->numbers_fontbutton, can_set); + gtk_widget_set_sensitive (dlg->priv->numbers_font_label, can_set); + + g_signal_connect (dlg->priv->restore_button, + "clicked", G_CALLBACK (restore_button_clicked), dlg); - - g_signal_connect (G_OBJECT (dlg->body_fontbutton), "font_set", + g_signal_connect (dlg->priv->body_fontbutton, + "font_set", G_CALLBACK (body_font_button_font_set), dlg); - - g_signal_connect (G_OBJECT (dlg->headers_fontbutton), "font_set", + g_signal_connect (dlg->priv->headers_fontbutton, + "font_set", G_CALLBACK (headers_font_button_font_set), dlg); - - g_signal_connect (G_OBJECT (dlg->numbers_fontbutton), "font_set", + g_signal_connect (dlg->priv->numbers_fontbutton, + "font_set", G_CALLBACK (numbers_font_button_font_set), dlg); } -static GeditPageSetupDialog * -page_setup_get_dialog (GtkWindow *parent) +static void +gedit_page_setup_dialog_init (GeditPageSetupDialog *dlg) { - static GeditPageSetupDialog *dialog = NULL; - GladeXML *gui; - - gedit_debug (DEBUG_PRINT, ""); - - if (dialog != NULL) - { - gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), - parent); - gtk_window_present (GTK_WINDOW (dialog->dialog)); - - return dialog; - } - - gui = glade_xml_new (GEDIT_GLADEDIR "page-setup-dialog.glade2", - "dialog", NULL); - if (!gui) - { - gedit_warning (parent, - MISSING_FILE, - GEDIT_GLADEDIR "page-setup-dialog.glade2"); - return NULL; - } - - dialog = g_new0 (GeditPageSetupDialog, 1); - - dialog->dialog = glade_xml_get_widget (gui, "dialog"); - - dialog->syntax_checkbutton = glade_xml_get_widget (gui, "syntax_checkbutton"); - dialog->page_header_checkbutton = glade_xml_get_widget (gui, "page_header_checkbutton"); - - dialog->line_numbers_checkbutton = glade_xml_get_widget (gui, "line_numbers_checkbutton"); - dialog->line_numbers_hbox = glade_xml_get_widget (gui, "line_numbers_hbox"); - dialog->line_numbers_spinbutton = glade_xml_get_widget (gui, "line_numbers_spinbutton"); - - dialog->text_wrapping_checkbutton = glade_xml_get_widget (gui, "text_wrapping_checkbutton"); - dialog->do_not_split_checkbutton = glade_xml_get_widget (gui, "do_not_split_checkbutton"); - - dialog->fonts_table = glade_xml_get_widget (gui, "fonts_table"); - - dialog->body_font_label = glade_xml_get_widget (gui, "body_font_label"); - dialog->headers_font_label = glade_xml_get_widget (gui, "headers_font_label"); - dialog->numbers_font_label = glade_xml_get_widget (gui, "numbers_font_label"); - - dialog->restore_button = glade_xml_get_widget (gui, "restore_button"); - - if (!dialog->dialog || - !dialog->syntax_checkbutton || - !dialog->page_header_checkbutton || - !dialog->line_numbers_checkbutton || - !dialog->line_numbers_hbox || - !dialog->line_numbers_spinbutton || - !dialog->text_wrapping_checkbutton || - !dialog->do_not_split_checkbutton || - !dialog->fonts_table || - !dialog->body_font_label || - !dialog->headers_font_label || - !dialog->numbers_font_label || - !dialog->restore_button) + GtkWidget *content = NULL; + GtkWidget *error_widget = NULL; + gboolean ret = FALSE; + + dlg->priv = GEDIT_PAGE_SETUP_DIALOG_GET_PRIVATE (dlg); + + gtk_dialog_add_buttons (GTK_DIALOG (dlg), + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + GTK_STOCK_HELP, + GTK_RESPONSE_HELP, + NULL); + + gtk_window_set_title (GTK_WINDOW (dlg), _("Page Setup")); + gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE); + gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); + gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE); + + gtk_dialog_set_default_response (GTK_DIALOG (dlg), + GTK_RESPONSE_CLOSE); + + g_signal_connect (G_OBJECT (dlg), + "response", + G_CALLBACK (dialog_response_handler), + NULL); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "gedit-page-setup-dialog.glade", + "notebook1", + &error_widget, + "notebook1", &content, + "syntax_checkbutton", &dlg->priv->syntax_checkbutton, + "page_header_checkbutton", &dlg->priv->page_header_checkbutton, + "line_numbers_checkbutton", &dlg->priv->line_numbers_checkbutton, + "line_numbers_hbox", &dlg->priv->line_numbers_hbox, + "line_numbers_spinbutton", &dlg->priv->line_numbers_spinbutton, + "text_wrapping_checkbutton", &dlg->priv->text_wrapping_checkbutton, + "do_not_split_checkbutton", &dlg->priv->do_not_split_checkbutton, + "fonts_table", &dlg->priv->fonts_table, + "body_font_label", &dlg->priv->body_font_label, + "headers_font_label", &dlg->priv->headers_font_label, + "numbers_font_label", &dlg->priv->numbers_font_label, + "restore_button", &dlg->priv->restore_button, + NULL); + + if (!ret) { - gedit_warning (parent, - MISSING_WIDGETS, - GEDIT_GLADEDIR "page-setup-dialog.glade2"); - - if (!dialog->dialog) - gtk_widget_destroy (dialog->dialog); - - g_object_unref (gui); - g_free (dialog); - dialog = NULL; + gtk_widget_show (error_widget); + + gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dlg)->vbox), + error_widget); - return NULL; + return; } - setup_general_page (dialog); - setup_font_page (dialog); - - gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), - parent); - - g_signal_connect (G_OBJECT (dialog->dialog), "destroy", - G_CALLBACK (dialog_destroyed), &dialog); - - g_signal_connect (G_OBJECT (dialog->dialog), "response", - G_CALLBACK (dialog_response_handler), dialog); - - g_object_unref (gui); - - gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); - - return dialog; + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), + content, FALSE, FALSE, 0); + setup_general_page (dlg); + setup_font_page (dlg); } void gedit_show_page_setup_dialog (GtkWindow *parent) { - GeditPageSetupDialog *dialog; - - gedit_debug (DEBUG_PRINT, ""); + g_return_if_fail (GTK_IS_WINDOW (parent)); - g_return_if_fail (parent != NULL); + if (page_setup_dialog == NULL) + { + page_setup_dialog = GTK_WIDGET (g_object_new (GEDIT_TYPE_PAGE_SETUP_DIALOG, NULL)); + g_signal_connect (page_setup_dialog, + "destroy", + G_CALLBACK (gtk_widget_destroyed), + &page_setup_dialog); + } - dialog = page_setup_get_dialog (parent); - if (!dialog) - return; + if (parent != gtk_window_get_transient_for (GTK_WINDOW (page_setup_dialog))) + { + gtk_window_set_transient_for (GTK_WINDOW (page_setup_dialog), + parent); + gtk_window_set_destroy_with_parent (GTK_WINDOW (page_setup_dialog), + TRUE); + } - if (!GTK_WIDGET_VISIBLE (dialog->dialog)) - gtk_widget_show_all (dialog->dialog); + gtk_window_present (GTK_WINDOW (page_setup_dialog)); } - diff --git a/gedit/dialogs/gedit-page-setup-dialog.glade b/gedit/dialogs/gedit-page-setup-dialog.glade new file mode 100644 index 00000000..60d4dab8 --- /dev/null +++ b/gedit/dialogs/gedit-page-setup-dialog.glade @@ -0,0 +1,654 @@ + + + + + + + Page Setup + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + False + True + False + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-help + True + GTK_RELIEF_NORMAL + -11 + + + + + + True + True + True + gtk-close + True + GTK_RELIEF_NORMAL + -7 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 6 + True + True + True + True + GTK_POS_TOP + False + False + + + + 12 + True + False + 18 + + + + True + False + 6 + + + + True + True + Print s_yntax highlighting + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + + True + True + _Print page headers + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + False + 6 + + + + True + <b>Line Numbers</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + Print _line numbers + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + + True + False + 6 + + + + True + _Number every + True + False + GTK_JUSTIFY_LEFT + False + False + 0.48 + 0.5 + 0 + 0 + line_numbers_spinbutton + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 1 100 1 10 10 + + + 0 + False + False + + + + + + True + lines + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 6 + + + + True + <b>Text Wrapping</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + Enable text _wrapping + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + + True + False + 0 + + + + True + True + Do not _split words over two lines + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + + + + False + True + + + + + + True + General + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 12 + True + False + 12 + + + + True + 3 + 2 + False + 12 + 12 + + + + True + _Body: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + _Line numbers: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + He_aders and footers: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + 0 + False + True + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + True + True + _Restore Default Fonts + True + GTK_RELIEF_NORMAL + + + 0 + False + False + + + + + 0 + False + True + + + + + True + True + + + + + + True + Fonts + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + 0 + True + True + + + + + + + diff --git a/gedit/dialogs/gedit-page-setup-dialog.h b/gedit/dialogs/gedit-page-setup-dialog.h index 06eccae8..f97695c7 100644 --- a/gedit/dialogs/gedit-page-setup-dialog.h +++ b/gedit/dialogs/gedit-page-setup-dialog.h @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * gedit-page-setup-dialog.c + * gedit-page-setup-dialog.h * This file is part of gedit * - * Copyright (C) 2003 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 @@ -25,6 +24,8 @@ * Modified by the gedit Team, 2003. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_PAGE_SETUP_DIALOG_H__ @@ -32,7 +33,54 @@ #include -void gedit_show_page_setup_dialog (GtkWindow *parent); +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_PAGE_SETUP_DIALOG (gedit_page_setup_dialog_get_type()) +#define GEDIT_PAGE_SETUP_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PAGE_SETUP_DIALOG, GeditPageSetupDialog)) +#define GEDIT_PAGE_SETUP_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PAGE_SETUP_DIALOG, GeditPageSetupDialog const)) +#define GEDIT_PAGE_SETUP_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PAGE_SETUP_DIALOG, GeditPageSetupDialogClass)) +#define GEDIT_IS_PAGE_SETUP_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PAGE_SETUP_DIALOG)) +#define GEDIT_IS_PAGE_SETUP_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PAGE_SETUP_DIALOG)) +#define GEDIT_PAGE_SETUP_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PAGE_SETUP_DIALOG, GeditPageSetupDialogClass)) + + +/* Private structure type */ +typedef struct _GeditPageSetupDialogPrivate GeditPageSetupDialogPrivate; + +/* + * Main object structure + */ +typedef struct _GeditPageSetupDialog GeditPageSetupDialog; + +struct _GeditPageSetupDialog +{ + GtkDialog dialog; + + /*< private > */ + GeditPageSetupDialogPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditPageSetupDialogClass GeditPageSetupDialogClass; + +struct _GeditPageSetupDialogClass +{ + GtkDialogClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_page_setup_dialog_get_type (void) G_GNUC_CONST; + +void gedit_show_page_setup_dialog (GtkWindow *parent); + +G_END_DECLS #endif /* __GEDIT_PAGE_SETUP_DIALOG_H__ */ diff --git a/gedit/dialogs/gedit-preferences-dialog.c b/gedit/dialogs/gedit-preferences-dialog.c index 3fb1445a..dee70844 100644 --- a/gedit/dialogs/gedit-preferences-dialog.c +++ b/gedit/dialogs/gedit-preferences-dialog.c @@ -3,7 +3,7 @@ * gedit-preferences-dialog.c * This file is part of gedit * - * Copyright (C) 2001-2003 Paolo Maggi + * 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 @@ -25,6 +25,8 @@ * Modified by the gedit Team, 2001-2003. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -34,8 +36,6 @@ #include #include -#include -#include #include #include #include @@ -44,11 +44,24 @@ #include #include "gedit-preferences-dialog.h" -#include "gedit2.h" #include "gedit-utils.h" #include "gedit-debug.h" +#include "gedit-document.h" #include "gedit-plugin-manager.h" #include "gedit-languages-manager.h" +#include "gedit-help.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; + enum { @@ -57,14 +70,14 @@ enum NUM_COLUMNS }; -typedef struct _GeditPreferencesDialog GeditPreferencesDialog; -struct _GeditPreferencesDialog +#define GEDIT_PREFERENCES_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialogPrivate)) + + +struct _GeditPreferencesDialogPrivate { - GtkWidget *dialog; - GtkTooltips *tooltips; - + /* Font & Colors */ GtkWidget *default_font_checkbutton; GtkWidget *default_colors_checkbutton; @@ -75,12 +88,12 @@ struct _GeditPreferencesDialog GtkWidget *selection_colorbutton; GtkWidget *colors_table; GtkWidget *font_hbox; - + /* Tabs */ GtkWidget *tabs_width_spinbutton; GtkWidget *insert_spaces_checkbutton; GtkWidget *tabs_width_hbox; - + /* Auto indentation */ GtkWidget *auto_indent_checkbutton; @@ -111,7 +124,7 @@ struct _GeditPreferencesDialog /* Syntax Highlighting */ GtkWidget *enable_syntax_hl_checkbutton; GtkWidget *hl_vbox; - GtkWidget *hl_mode_optionmenu; + GtkWidget *hl_mode_combobox; GtkListStore *tags_treeview_model; GtkWidget *tags_treeview; GtkWidget *bold_togglebutton; @@ -129,47 +142,46 @@ struct _GeditPreferencesDialog }; +G_DEFINE_TYPE(GeditPreferencesDialog, gedit_preferences_dialog, GTK_TYPE_DIALOG) + + static void -dialog_destroyed (GtkObject *obj, - void **dialog_pointer) +gedit_preferences_dialog_finalize (GObject *object) { - gedit_debug (DEBUG_PREFS, ""); + GeditPreferencesDialog *dialog = GEDIT_PREFERENCES_DIALOG(object); - if (dialog_pointer != NULL) - { - g_free (*dialog_pointer); - *dialog_pointer = NULL; - } + g_object_unref (dialog->priv->tooltips); + G_OBJECT_CLASS (gedit_preferences_dialog_parent_class)->finalize (object); } -static void -destroy_dialog (GeditPreferencesDialog *dialog) +static void +gedit_preferences_dialog_class_init (GeditPreferencesDialogClass *klass) { - g_object_unref (dialog->tooltips); - gtk_widget_destroy (dialog->dialog); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_preferences_dialog_finalize; + g_type_class_add_private (object_class, sizeof (GeditPreferencesDialogPrivate)); } static void -dialog_response_handler (GtkDialog *dlg, - gint res_id, - GeditPreferencesDialog *dialog) +dialog_response_handler (GtkDialog *dlg, + gint res_id) { - GError *error = NULL; + gedit_debug (DEBUG_PREFS); - gedit_debug (DEBUG_PREFS, ""); - - switch (res_id) { + switch (res_id) + { case GTK_RESPONSE_HELP: - gnome_help_display ("gedit.xml", "gedit-prefs", &error); - if (error != NULL) - { - gedit_warning (GTK_WINDOW (dlg), error->message); - g_error_free (error); - } + gedit_help_display (GTK_WINDOW (dlg), + "gedit.xml", + "gedit-prefs"); + + g_signal_stop_emission_by_name (dlg, "response"); + break; default: - destroy_dialog (dialog); + gtk_widget_destroy (GTK_WIDGET(dlg)); } } @@ -177,9 +189,9 @@ static void tabs_width_spinbutton_value_changed (GtkSpinButton *spin_button, GeditPreferencesDialog *dlg) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->tabs_width_spinbutton)); + g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->priv->tabs_width_spinbutton)); gedit_prefs_manager_set_tabs_size (gtk_spin_button_get_value_as_int (spin_button)); } @@ -188,9 +200,9 @@ static void insert_spaces_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->insert_spaces_checkbutton)); + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->insert_spaces_checkbutton)); gedit_prefs_manager_set_insert_spaces (gtk_toggle_button_get_active (button)); } @@ -199,9 +211,9 @@ static void auto_indent_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->auto_indent_checkbutton)); + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->auto_indent_checkbutton)); gedit_prefs_manager_set_auto_indent (gtk_toggle_button_get_active (button)); } @@ -210,20 +222,20 @@ static void auto_save_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); + + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->auto_save_checkbutton)); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->auto_save_checkbutton)); - if (gtk_toggle_button_get_active (button)) { - gtk_widget_set_sensitive (dlg->auto_save_spinbutton, + gtk_widget_set_sensitive (dlg->priv->auto_save_spinbutton, gedit_prefs_manager_auto_save_interval_can_set()); - + gedit_prefs_manager_set_auto_save (TRUE); } else { - gtk_widget_set_sensitive (dlg->auto_save_spinbutton, FALSE); + gtk_widget_set_sensitive (dlg->priv->auto_save_spinbutton, FALSE); gedit_prefs_manager_set_auto_save (FALSE); } } @@ -232,9 +244,9 @@ static void backup_copy_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->backup_copy_checkbutton)); + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->backup_copy_checkbutton)); gedit_prefs_manager_set_create_backup_copy (gtk_toggle_button_get_active (button)); } @@ -243,7 +255,7 @@ static void auto_save_spinbutton_value_changed (GtkSpinButton *spin_button, GeditPreferencesDialog *dlg) { - g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->auto_save_spinbutton)); + g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->priv->auto_save_spinbutton)); gedit_prefs_manager_set_auto_save_interval ( MAX (1, gtk_spin_button_get_value_as_int (spin_button))); @@ -255,73 +267,67 @@ setup_editor_page (GeditPreferencesDialog *dlg) gboolean auto_save; gint auto_save_interval; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); /* Set initial state */ - gtk_spin_button_set_value (GTK_SPIN_BUTTON (dlg->tabs_width_spinbutton), + gtk_spin_button_set_value (GTK_SPIN_BUTTON (dlg->priv->tabs_width_spinbutton), (guint) gedit_prefs_manager_get_tabs_size ()); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->insert_spaces_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->insert_spaces_checkbutton), gedit_prefs_manager_get_insert_spaces ()); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->auto_indent_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->auto_indent_checkbutton), gedit_prefs_manager_get_auto_indent ()); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->backup_copy_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->backup_copy_checkbutton), gedit_prefs_manager_get_create_backup_copy ()); auto_save = gedit_prefs_manager_get_auto_save (); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->auto_save_checkbutton), - auto_save ); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->auto_save_checkbutton), + auto_save); auto_save_interval = gedit_prefs_manager_get_auto_save_interval (); if (auto_save_interval <= 0) auto_save_interval = GPM_DEFAULT_AUTO_SAVE_INTERVAL; - gtk_spin_button_set_value (GTK_SPIN_BUTTON (dlg->auto_save_spinbutton), + gtk_spin_button_set_value (GTK_SPIN_BUTTON (dlg->priv->auto_save_spinbutton), auto_save_interval); /* Set widget sensitivity */ - gtk_widget_set_sensitive (dlg->tabs_width_hbox, + gtk_widget_set_sensitive (dlg->priv->tabs_width_hbox, gedit_prefs_manager_tabs_size_can_set ()); - gtk_widget_set_sensitive (dlg->insert_spaces_checkbutton, + gtk_widget_set_sensitive (dlg->priv->insert_spaces_checkbutton, gedit_prefs_manager_insert_spaces_can_set ()); - - gtk_widget_set_sensitive (dlg->auto_indent_checkbutton, + gtk_widget_set_sensitive (dlg->priv->auto_indent_checkbutton, gedit_prefs_manager_auto_indent_can_set ()); - - gtk_widget_set_sensitive (dlg->backup_copy_checkbutton, + gtk_widget_set_sensitive (dlg->priv->backup_copy_checkbutton, gedit_prefs_manager_create_backup_copy_can_set ()); - - gtk_widget_set_sensitive (dlg->autosave_hbox, + gtk_widget_set_sensitive (dlg->priv->autosave_hbox, gedit_prefs_manager_auto_save_can_set ()); - - gtk_widget_set_sensitive (dlg->auto_save_spinbutton, + gtk_widget_set_sensitive (dlg->priv->auto_save_spinbutton, auto_save && gedit_prefs_manager_auto_save_interval_can_set ()); /* Connect signal */ - g_signal_connect (G_OBJECT (dlg->tabs_width_spinbutton), "value_changed", + g_signal_connect (dlg->priv->tabs_width_spinbutton, + "value_changed", G_CALLBACK (tabs_width_spinbutton_value_changed), dlg); - - g_signal_connect (G_OBJECT (dlg->insert_spaces_checkbutton), "toggled", - G_CALLBACK (insert_spaces_checkbutton_toggled), + g_signal_connect (dlg->priv->insert_spaces_checkbutton, + "toggled", + G_CALLBACK (insert_spaces_checkbutton_toggled), dlg); - - g_signal_connect (G_OBJECT (dlg->auto_indent_checkbutton), "toggled", - G_CALLBACK (auto_indent_checkbutton_toggled), + g_signal_connect (dlg->priv->auto_indent_checkbutton, + "toggled", + G_CALLBACK (auto_indent_checkbutton_toggled), dlg); - - g_signal_connect (G_OBJECT (dlg->auto_save_checkbutton), "toggled", - G_CALLBACK (auto_save_checkbutton_toggled), + g_signal_connect (dlg->priv->auto_save_checkbutton, + "toggled", + G_CALLBACK (auto_save_checkbutton_toggled), dlg); - - g_signal_connect (G_OBJECT (dlg->backup_copy_checkbutton), "toggled", - G_CALLBACK (backup_copy_checkbutton_toggled), + g_signal_connect (dlg->priv->backup_copy_checkbutton, + "toggled", + G_CALLBACK (backup_copy_checkbutton_toggled), dlg); - - g_signal_connect (G_OBJECT (dlg->auto_save_spinbutton), "value_changed", + g_signal_connect (dlg->priv->auto_save_spinbutton, + "value_changed", G_CALLBACK (auto_save_spinbutton_value_changed), dlg); } @@ -331,17 +337,17 @@ display_line_numbers_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { g_return_if_fail (button == - GTK_TOGGLE_BUTTON (dlg->display_line_numbers_checkbutton)); + GTK_TOGGLE_BUTTON (dlg->priv->display_line_numbers_checkbutton)); gedit_prefs_manager_set_display_line_numbers (gtk_toggle_button_get_active (button)); } static void highlight_current_line_checkbutton_toggled (GtkToggleButton *button, - GeditPreferencesDialog *dlg) + GeditPreferencesDialog *dlg) { g_return_if_fail (button == - GTK_TOGGLE_BUTTON (dlg->highlight_current_line_checkbutton)); + GTK_TOGGLE_BUTTON (dlg->priv->highlight_current_line_checkbutton)); gedit_prefs_manager_set_highlight_current_line (gtk_toggle_button_get_active (button)); } @@ -351,7 +357,7 @@ bracket_matching_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { g_return_if_fail (button == - GTK_TOGGLE_BUTTON (dlg->bracket_matching_checkbutton)); + GTK_TOGGLE_BUTTON (dlg->priv->bracket_matching_checkbutton)); gedit_prefs_manager_set_bracket_matching ( gtk_toggle_button_get_active (button)); @@ -363,26 +369,25 @@ static void wrap_mode_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton))) + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton))) { gedit_prefs_manager_set_wrap_mode (GTK_WRAP_NONE); - gtk_widget_set_sensitive (dlg->split_checkbutton, + gtk_widget_set_sensitive (dlg->priv->split_checkbutton, FALSE); gtk_toggle_button_set_inconsistent ( - GTK_TOGGLE_BUTTON (dlg->split_checkbutton), TRUE); - + GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), TRUE); } else { - gtk_widget_set_sensitive (dlg->split_checkbutton, + gtk_widget_set_sensitive (dlg->priv->split_checkbutton, TRUE); gtk_toggle_button_set_inconsistent ( - GTK_TOGGLE_BUTTON (dlg->split_checkbutton), FALSE); + GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), FALSE); - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->split_checkbutton))) + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton))) { split_button_state = TRUE; @@ -394,7 +399,6 @@ wrap_mode_checkbutton_toggled (GtkToggleButton *button, gedit_prefs_manager_set_wrap_mode (GTK_WRAP_CHAR); } - } } @@ -404,13 +408,13 @@ right_margin_checkbutton_toggled (GtkToggleButton *button, { gboolean active; - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->right_margin_checkbutton)); + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->right_margin_checkbutton)); active = gtk_toggle_button_get_active (button); gedit_prefs_manager_set_display_right_margin (active); - gtk_widget_set_sensitive (dlg->right_margin_position_hbox, + gtk_widget_set_sensitive (dlg->priv->right_margin_position_hbox, active && gedit_prefs_manager_right_margin_position_can_set ()); } @@ -421,7 +425,7 @@ right_margin_position_spinbutton_value_changed (GtkSpinButton *spin_but { gint value; - g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->right_margin_position_spinbutton)); + g_return_if_fail (spin_button == GTK_SPIN_BUTTON (dlg->priv->right_margin_position_spinbutton)); value = CLAMP (gtk_spin_button_get_value_as_int (spin_button), 1, 160); @@ -435,16 +439,16 @@ setup_view_page (GeditPreferencesDialog *dlg) gboolean display_right_margin; gboolean wrap_mode_can_set; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); /* Set initial state */ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->display_line_numbers_checkbutton), - gedit_prefs_manager_get_display_line_numbers ()); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->display_line_numbers_checkbutton), + gedit_prefs_manager_get_display_line_numbers ()); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->highlight_current_line_checkbutton), - gedit_prefs_manager_get_highlight_current_line ()); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->highlight_current_line_checkbutton), + gedit_prefs_manager_get_highlight_current_line ()); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->bracket_matching_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->bracket_matching_checkbutton), gedit_prefs_manager_get_bracket_matching ()); wrap_mode = gedit_prefs_manager_get_wrap_mode (); @@ -452,104 +456,102 @@ setup_view_page (GeditPreferencesDialog *dlg) { case GTK_WRAP_WORD: gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton), TRUE); + GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton), TRUE); gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dlg->split_checkbutton), TRUE); + GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), TRUE); break; case GTK_WRAP_CHAR: gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton), TRUE); + GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton), TRUE); gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dlg->split_checkbutton), FALSE); + GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), FALSE); break; default: gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton), FALSE); + GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton), FALSE); gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dlg->split_checkbutton), split_button_state); + GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), split_button_state); gtk_toggle_button_set_inconsistent ( - GTK_TOGGLE_BUTTON (dlg->split_checkbutton), TRUE); + GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), TRUE); } display_right_margin = gedit_prefs_manager_get_display_right_margin (); gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (dlg->right_margin_checkbutton), + GTK_TOGGLE_BUTTON (dlg->priv->right_margin_checkbutton), display_right_margin); gtk_spin_button_set_value ( - GTK_SPIN_BUTTON (dlg->right_margin_position_spinbutton), + GTK_SPIN_BUTTON (dlg->priv->right_margin_position_spinbutton), (guint)CLAMP (gedit_prefs_manager_get_right_margin_position (), 1, 160)); /* Set widgets sensitivity */ - gtk_widget_set_sensitive (dlg->display_line_numbers_checkbutton, + gtk_widget_set_sensitive (dlg->priv->display_line_numbers_checkbutton, gedit_prefs_manager_display_line_numbers_can_set ()); - - gtk_widget_set_sensitive (dlg->highlight_current_line_checkbutton, + gtk_widget_set_sensitive (dlg->priv->highlight_current_line_checkbutton, gedit_prefs_manager_highlight_current_line_can_set ()); - - gtk_widget_set_sensitive (dlg->bracket_matching_checkbutton, + gtk_widget_set_sensitive (dlg->priv->bracket_matching_checkbutton, gedit_prefs_manager_bracket_matching_can_set ()); - wrap_mode_can_set = gedit_prefs_manager_wrap_mode_can_set (); - - gtk_widget_set_sensitive (dlg->wrap_text_checkbutton, + gtk_widget_set_sensitive (dlg->priv->wrap_text_checkbutton, wrap_mode_can_set); - - gtk_widget_set_sensitive (dlg->split_checkbutton, + gtk_widget_set_sensitive (dlg->priv->split_checkbutton, wrap_mode_can_set && (wrap_mode != GTK_WRAP_NONE)); - - gtk_widget_set_sensitive (dlg->right_margin_checkbutton, + gtk_widget_set_sensitive (dlg->priv->right_margin_checkbutton, gedit_prefs_manager_display_right_margin_can_set ()); - - gtk_widget_set_sensitive (dlg->right_margin_position_hbox, + gtk_widget_set_sensitive (dlg->priv->right_margin_position_hbox, display_right_margin && gedit_prefs_manager_right_margin_position_can_set ()); /* Connect signals */ - g_signal_connect (G_OBJECT (dlg->display_line_numbers_checkbutton), "toggled", + g_signal_connect (dlg->priv->display_line_numbers_checkbutton, + "toggled", G_CALLBACK (display_line_numbers_checkbutton_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->highlight_current_line_checkbutton), "toggled", + g_signal_connect (dlg->priv->highlight_current_line_checkbutton, + "toggled", G_CALLBACK (highlight_current_line_checkbutton_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->bracket_matching_checkbutton), "toggled", + g_signal_connect (dlg->priv->bracket_matching_checkbutton, + "toggled", G_CALLBACK (bracket_matching_checkbutton_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->wrap_text_checkbutton), "toggled", + g_signal_connect (dlg->priv->wrap_text_checkbutton, + "toggled", G_CALLBACK (wrap_mode_checkbutton_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->split_checkbutton), "toggled", + g_signal_connect (dlg->priv->split_checkbutton, + "toggled", G_CALLBACK (wrap_mode_checkbutton_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->right_margin_checkbutton), "toggled", + g_signal_connect (dlg->priv->right_margin_checkbutton, + "toggled", G_CALLBACK (right_margin_checkbutton_toggled), dlg); - - g_signal_connect (G_OBJECT (dlg->right_margin_position_spinbutton), "value_changed", + g_signal_connect (dlg->priv->right_margin_position_spinbutton, + "value_changed", G_CALLBACK (right_margin_position_spinbutton_value_changed), dlg); - } static void default_font_font_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->default_font_checkbutton)); + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->default_font_checkbutton)); if (gtk_toggle_button_get_active (button)) { - gtk_widget_set_sensitive (dlg->font_hbox, FALSE); + gtk_widget_set_sensitive (dlg->priv->font_hbox, FALSE); gedit_prefs_manager_set_use_default_font (TRUE); } else { - gtk_widget_set_sensitive (dlg->font_hbox, + gtk_widget_set_sensitive (dlg->priv->font_hbox, gedit_prefs_manager_editor_font_can_set ()); gedit_prefs_manager_set_use_default_font (FALSE); } @@ -559,19 +561,19 @@ static void default_font_colors_checkbutton_toggled (GtkToggleButton *button, GeditPreferencesDialog *dlg) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->default_colors_checkbutton)); + g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->default_colors_checkbutton)); if (gtk_toggle_button_get_active (button)) { - gtk_widget_set_sensitive (dlg->colors_table, FALSE); + gtk_widget_set_sensitive (dlg->priv->colors_table, FALSE); gedit_prefs_manager_set_use_default_colors (TRUE); } else { gedit_prefs_manager_set_use_default_colors (FALSE); - gtk_widget_set_sensitive (dlg->colors_table, + gtk_widget_set_sensitive (dlg->priv->colors_table, gedit_prefs_manager_background_color_can_set () && gedit_prefs_manager_text_color_can_set () && gedit_prefs_manager_selection_color_can_set () && @@ -585,9 +587,9 @@ editor_font_button_font_set (GtkFontButton *font_button, { const gchar *font_name; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - g_return_if_fail (font_button == GTK_FONT_BUTTON (dlg->font_button)); + g_return_if_fail (font_button == GTK_FONT_BUTTON (dlg->priv->font_button)); /* FIXME: Can this fail? Gtk docs are a bit terse... 21-02-2004 pbor */ font_name = gtk_font_button_get_font_name (font_button); @@ -608,25 +610,25 @@ editor_color_button_color_set (GtkColorButton *button, gtk_color_button_get_color (button, &color); - if (button == GTK_COLOR_BUTTON (dlg->text_colorbutton)) + if (button == GTK_COLOR_BUTTON (dlg->priv->text_colorbutton)) { gedit_prefs_manager_set_text_color (color); return; } - if (button == GTK_COLOR_BUTTON (dlg->background_colorbutton)) + if (button == GTK_COLOR_BUTTON (dlg->priv->background_colorbutton)) { gedit_prefs_manager_set_background_color (color); return; } - if (button == GTK_COLOR_BUTTON (dlg->seltext_colorbutton)) + if (button == GTK_COLOR_BUTTON (dlg->priv->seltext_colorbutton)) { gedit_prefs_manager_set_selected_text_color (color); return; } - if (button == GTK_COLOR_BUTTON (dlg->selection_colorbutton)) + if (button == GTK_COLOR_BUTTON (dlg->priv->selection_colorbutton)) { gedit_prefs_manager_set_selection_color (color); return; @@ -643,90 +645,104 @@ setup_font_colors_page (GeditPreferencesDialog *dlg) gchar *editor_font = NULL; GdkColor color; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); - gtk_tooltips_set_tip (dlg->tooltips, dlg->font_button, + gtk_tooltips_set_tip (dlg->priv->tooltips, dlg->priv->font_button, _("Push this button to select the font to be used by the editor"), NULL); - gtk_tooltips_set_tip (dlg->tooltips, dlg->text_colorbutton, + gtk_tooltips_set_tip (dlg->priv->tooltips, dlg->priv->text_colorbutton, _("Push this button to configure text color"), NULL); - gtk_tooltips_set_tip (dlg->tooltips, dlg->background_colorbutton, + gtk_tooltips_set_tip (dlg->priv->tooltips, dlg->priv->background_colorbutton, _("Push this button to configure background color"), NULL); - gtk_tooltips_set_tip (dlg->tooltips, dlg->seltext_colorbutton, + gtk_tooltips_set_tip (dlg->priv->tooltips, dlg->priv->seltext_colorbutton, _("Push this button to configure the color in which the selected " "text should appear"), NULL); - gtk_tooltips_set_tip (dlg->tooltips, dlg->selection_colorbutton, + gtk_tooltips_set_tip (dlg->priv->tooltips, dlg->priv->selection_colorbutton, _("Push this button to configure the color in which the selected " "text should be marked"), NULL); - gedit_utils_set_atk_relation (dlg->font_button, dlg->default_font_checkbutton, + gedit_utils_set_atk_relation (dlg->priv->font_button, dlg->priv->default_font_checkbutton, ATK_RELATION_CONTROLLED_BY); - gedit_utils_set_atk_relation (dlg->default_font_checkbutton, dlg->font_button, + gedit_utils_set_atk_relation (dlg->priv->default_font_checkbutton, dlg->priv->font_button, ATK_RELATION_CONTROLLER_FOR); /* read current config and setup initial state */ use_default_font = gedit_prefs_manager_get_use_default_font (); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->default_font_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->default_font_checkbutton), use_default_font); use_default_colors = gedit_prefs_manager_get_use_default_colors (); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->default_colors_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->default_colors_checkbutton), use_default_colors); editor_font = gedit_prefs_manager_get_editor_font (); if (editor_font != NULL) - gtk_font_button_set_font_name (GTK_FONT_BUTTON (dlg->font_button), + gtk_font_button_set_font_name (GTK_FONT_BUTTON (dlg->priv->font_button), editor_font); g_free (editor_font); color = gedit_prefs_manager_get_text_color (); - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->text_colorbutton), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->text_colorbutton), &color); color = gedit_prefs_manager_get_background_color (); - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->background_colorbutton), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->background_colorbutton), &color); color = gedit_prefs_manager_get_selected_text_color (); - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->seltext_colorbutton), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->seltext_colorbutton), &color); color = gedit_prefs_manager_get_selection_color (); - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->selection_colorbutton), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->selection_colorbutton), &color); /* Connect signals */ - g_signal_connect (G_OBJECT (dlg->default_font_checkbutton), "toggled", - G_CALLBACK (default_font_font_checkbutton_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->default_colors_checkbutton), "toggled", - G_CALLBACK (default_font_colors_checkbutton_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->font_button), "font_set", - G_CALLBACK (editor_font_button_font_set), dlg); - g_signal_connect (G_OBJECT (dlg->text_colorbutton), "color_set", - G_CALLBACK (editor_color_button_color_set), dlg); - g_signal_connect (G_OBJECT (dlg->background_colorbutton), "color_set", - G_CALLBACK (editor_color_button_color_set), dlg); - g_signal_connect (G_OBJECT (dlg->seltext_colorbutton), "color_set", - G_CALLBACK (editor_color_button_color_set), dlg); - g_signal_connect (G_OBJECT (dlg->selection_colorbutton), "color_set", - G_CALLBACK (editor_color_button_color_set), dlg); + g_signal_connect (dlg->priv->default_font_checkbutton, + "toggled", + G_CALLBACK (default_font_font_checkbutton_toggled), + dlg); + g_signal_connect (dlg->priv->default_colors_checkbutton, + "toggled", + G_CALLBACK (default_font_colors_checkbutton_toggled), + dlg); + g_signal_connect (dlg->priv->font_button, + "font_set", + G_CALLBACK (editor_font_button_font_set), + dlg); + g_signal_connect (dlg->priv->text_colorbutton, + "color_set", + G_CALLBACK (editor_color_button_color_set), + dlg); + g_signal_connect (dlg->priv->background_colorbutton, + "color_set", + G_CALLBACK (editor_color_button_color_set), + dlg); + g_signal_connect (dlg->priv->seltext_colorbutton, + "color_set", + G_CALLBACK (editor_color_button_color_set), + dlg); + g_signal_connect (dlg->priv->selection_colorbutton, + "color_set", + G_CALLBACK (editor_color_button_color_set), + dlg); /* Set initial widget sensitivity */ - gtk_widget_set_sensitive (dlg->default_font_checkbutton, + gtk_widget_set_sensitive (dlg->priv->default_font_checkbutton, gedit_prefs_manager_use_default_font_can_set ()); - gtk_widget_set_sensitive (dlg->default_colors_checkbutton, + gtk_widget_set_sensitive (dlg->priv->default_colors_checkbutton, gedit_prefs_manager_use_default_colors_can_set ()); if (use_default_font) - gtk_widget_set_sensitive (dlg->font_hbox, FALSE); + gtk_widget_set_sensitive (dlg->priv->font_hbox, FALSE); else - gtk_widget_set_sensitive (dlg->font_hbox, + gtk_widget_set_sensitive (dlg->priv->font_hbox, gedit_prefs_manager_editor_font_can_set ()); if (use_default_colors) - gtk_widget_set_sensitive (dlg->colors_table, FALSE); + gtk_widget_set_sensitive (dlg->priv->colors_table, FALSE); else - gtk_widget_set_sensitive (dlg->colors_table, + gtk_widget_set_sensitive (dlg->priv->colors_table, gedit_prefs_manager_background_color_can_set () && gedit_prefs_manager_text_color_can_set () && gedit_prefs_manager_selection_color_can_set () && @@ -737,22 +753,22 @@ static void enable_syntax_hl_button_toggled (GtkWidget *button, GeditPreferencesDialog *dlg) { - g_return_if_fail (button == dlg->enable_syntax_hl_checkbutton); + g_return_if_fail (button == dlg->priv->enable_syntax_hl_checkbutton); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { gedit_prefs_manager_set_enable_syntax_highlighting (TRUE); - gtk_widget_set_sensitive (dlg->hl_vbox, TRUE); + gtk_widget_set_sensitive (dlg->priv->hl_vbox, TRUE); } else { gedit_prefs_manager_set_enable_syntax_highlighting (FALSE); - gtk_widget_set_sensitive (dlg->hl_vbox, FALSE); + gtk_widget_set_sensitive (dlg->priv->hl_vbox, FALSE); } } static void -language_changed_cb (GtkOptionMenu *optionmenu, +language_changed_cb (GtkComboBox *combobox, GeditPreferencesDialog *dlg) { const GSList *languages; @@ -764,9 +780,9 @@ language_changed_cb (GtkOptionMenu *optionmenu, languages = gedit_languages_manager_get_available_languages_sorted ( gedit_get_languages_manager ()); - lang = g_slist_nth_data ((GSList*)languages, gtk_option_menu_get_history (optionmenu)); + lang = g_slist_nth_data ((GSList*)languages, gtk_combo_box_get_active (combobox)); - gtk_list_store_clear (dlg->tags_treeview_model); + gtk_list_store_clear (dlg->priv->tags_treeview_model); tags = gtk_source_language_get_tags (lang); l = tags; @@ -776,26 +792,28 @@ language_changed_cb (GtkOptionMenu *optionmenu, gchar *name; gchar *id; GtkSourceTag *tag; - + tag = GTK_SOURCE_TAG (l->data); - + g_object_get (tag, "name", &name, "id", &id, NULL); - gtk_list_store_append (dlg->tags_treeview_model, &iter); - gtk_list_store_set (dlg->tags_treeview_model, + gtk_list_store_append (dlg->priv->tags_treeview_model, &iter); + gtk_list_store_set (dlg->priv->tags_treeview_model, &iter, NAME_COLUMN, name, ID_COLUMN, id, -1); + g_free (name); + g_free (id); l = g_slist_next (l); } - + g_slist_foreach (tags, (GFunc)g_object_unref, NULL); g_slist_free (tags); /* Trigger styles_cb on first item so color & font widgets get set. */ path = gtk_tree_path_new_first (); - gtk_tree_view_set_cursor (GTK_TREE_VIEW (dlg->tags_treeview), path, NULL, FALSE); + gtk_tree_view_set_cursor (GTK_TREE_VIEW (dlg->priv->tags_treeview), path, NULL, FALSE); gtk_tree_path_free (path); } @@ -808,7 +826,7 @@ get_selected_language (GeditPreferencesDialog *dlg) languages = gedit_languages_manager_get_available_languages_sorted ( gedit_get_languages_manager ()); lang = g_slist_nth_data ((GSList*)languages, - gtk_option_menu_get_history (GTK_OPTION_MENU (dlg->hl_mode_optionmenu))); + gtk_combo_box_get_active (GTK_COMBO_BOX (dlg->priv->hl_mode_combobox))); return lang; } @@ -823,11 +841,11 @@ get_selected_style (GeditPreferencesDialog *dlg) GtkSourceTagStyle *style; GtkSourceTagStyle *def_style; - gtk_tree_view_get_cursor (GTK_TREE_VIEW (dlg->tags_treeview), &path, NULL); - gtk_tree_model_get_iter (GTK_TREE_MODEL (dlg->tags_treeview_model), + gtk_tree_view_get_cursor (GTK_TREE_VIEW (dlg->priv->tags_treeview), &path, NULL); + gtk_tree_model_get_iter (GTK_TREE_MODEL (dlg->priv->tags_treeview_model), &iter, path); gtk_tree_path_free (path); - gtk_tree_model_get (GTK_TREE_MODEL (dlg->tags_treeview_model), + gtk_tree_model_get (GTK_TREE_MODEL (dlg->priv->tags_treeview_model), &iter, ID_COLUMN, &id, -1); lang = get_selected_language (dlg); @@ -860,11 +878,11 @@ style_button_toggled (GtkToggleButton *button, GtkSourceTagStyle *style; GtkSourceTagStyle *new_style; - gtk_tree_view_get_cursor (GTK_TREE_VIEW (dlg->tags_treeview), &path, NULL); - gtk_tree_model_get_iter (GTK_TREE_MODEL (dlg->tags_treeview_model), + gtk_tree_view_get_cursor (GTK_TREE_VIEW (dlg->priv->tags_treeview), &path, NULL); + gtk_tree_model_get_iter (GTK_TREE_MODEL (dlg->priv->tags_treeview_model), &iter, path); gtk_tree_path_free (path); - gtk_tree_model_get (GTK_TREE_MODEL (dlg->tags_treeview_model), + gtk_tree_model_get (GTK_TREE_MODEL (dlg->priv->tags_treeview_model), &iter, ID_COLUMN, &id, -1); lang = get_selected_language (dlg); @@ -878,43 +896,43 @@ style_button_toggled (GtkToggleButton *button, new_style = gtk_source_tag_style_copy (style); new_style->bold = gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (dlg->bold_togglebutton)); + GTK_TOGGLE_BUTTON (dlg->priv->bold_togglebutton)); new_style->italic = gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (dlg->italic_togglebutton)); + GTK_TOGGLE_BUTTON (dlg->priv->italic_togglebutton)); new_style->underline = gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (dlg->underline_togglebutton)); + GTK_TOGGLE_BUTTON (dlg->priv->underline_togglebutton)); new_style->strikethrough = gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (dlg->strikethrough_togglebutton)); + GTK_TOGGLE_BUTTON (dlg->priv->strikethrough_togglebutton)); if (gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (dlg->foreground_checkbutton))) + GTK_TOGGLE_BUTTON (dlg->priv->foreground_checkbutton))) { new_style->mask |= GTK_SOURCE_TAG_STYLE_USE_FOREGROUND; - gtk_color_button_get_color (GTK_COLOR_BUTTON (dlg->foreground_colorbutton), + gtk_color_button_get_color (GTK_COLOR_BUTTON (dlg->priv->foreground_colorbutton), &new_style->foreground); - gtk_widget_set_sensitive (dlg->foreground_colorbutton, + gtk_widget_set_sensitive (dlg->priv->foreground_colorbutton, TRUE); } else { new_style->mask &= ~GTK_SOURCE_TAG_STYLE_USE_FOREGROUND; - gtk_widget_set_sensitive (dlg->foreground_colorbutton, + gtk_widget_set_sensitive (dlg->priv->foreground_colorbutton, FALSE); } if (gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (dlg->background_checkbutton))) + GTK_TOGGLE_BUTTON (dlg->priv->background_checkbutton))) { new_style->mask |= GTK_SOURCE_TAG_STYLE_USE_BACKGROUND; - gtk_color_button_get_color (GTK_COLOR_BUTTON (dlg->background_colorbutton_2), + gtk_color_button_get_color (GTK_COLOR_BUTTON (dlg->priv->background_colorbutton_2), &new_style->background); - gtk_widget_set_sensitive (dlg->background_colorbutton_2, + gtk_widget_set_sensitive (dlg->priv->background_colorbutton_2, TRUE); } else { new_style->mask &= ~GTK_SOURCE_TAG_STYLE_USE_BACKGROUND; - gtk_widget_set_sensitive (dlg->background_colorbutton_2, + gtk_widget_set_sensitive (dlg->priv->background_colorbutton_2, FALSE); } @@ -934,13 +952,12 @@ style_button_toggled (GtkToggleButton *button, new_style->foreground = def_style->foreground; } - gtk_widget_set_sensitive (dlg->reset_button, + gtk_widget_set_sensitive (dlg->priv->reset_button, memcmp (new_style, def_style, sizeof (GtkSourceTagStyle)) != 0); gedit_language_set_tag_style (lang, id, new_style); gtk_source_tag_style_free (def_style); - } gtk_source_tag_style_free (style); @@ -966,38 +983,38 @@ styles_cb (GtkWidget *treeview, g_return_if_fail (style != NULL); /* we must block callbacks while setting the new values */ - g_signal_handlers_block_by_func (G_OBJECT (dlg->bold_togglebutton), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->bold_togglebutton), G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_block_by_func (G_OBJECT (dlg->italic_togglebutton), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->italic_togglebutton), G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_block_by_func (G_OBJECT (dlg->underline_togglebutton), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->underline_togglebutton), G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_block_by_func (G_OBJECT (dlg->strikethrough_togglebutton), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->strikethrough_togglebutton), G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_block_by_func (G_OBJECT (dlg->foreground_checkbutton), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->foreground_checkbutton), G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_block_by_func (G_OBJECT (dlg->background_checkbutton), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->background_checkbutton), G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_block_by_func (G_OBJECT (dlg->foreground_colorbutton), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->foreground_colorbutton), G_CALLBACK (style_color_set), dlg); - g_signal_handlers_block_by_func (G_OBJECT (dlg->background_colorbutton_2), + g_signal_handlers_block_by_func (G_OBJECT (dlg->priv->background_colorbutton_2), G_CALLBACK (style_color_set), dlg); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->bold_togglebutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->bold_togglebutton), style->bold); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->italic_togglebutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->italic_togglebutton), style->italic); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->underline_togglebutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->underline_togglebutton), style->underline); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->strikethrough_togglebutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->strikethrough_togglebutton), style->strikethrough); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->foreground_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->foreground_checkbutton), style->mask & GTK_SOURCE_TAG_STYLE_USE_FOREGROUND); if ((style->mask & GTK_SOURCE_TAG_STYLE_USE_FOREGROUND) == GTK_SOURCE_TAG_STYLE_USE_FOREGROUND) { - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->foreground_colorbutton), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->foreground_colorbutton), &style->foreground); } else @@ -1005,19 +1022,19 @@ styles_cb (GtkWidget *treeview, GdkColor text_color; text_color = gedit_prefs_manager_get_text_color (); - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->foreground_colorbutton), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->foreground_colorbutton), &text_color); } - gtk_widget_set_sensitive (dlg->foreground_colorbutton, + gtk_widget_set_sensitive (dlg->priv->foreground_colorbutton, style->mask & GTK_SOURCE_TAG_STYLE_USE_FOREGROUND); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->background_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->background_checkbutton), style->mask & GTK_SOURCE_TAG_STYLE_USE_BACKGROUND); if ((style->mask & GTK_SOURCE_TAG_STYLE_USE_BACKGROUND) == GTK_SOURCE_TAG_STYLE_USE_BACKGROUND) { - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->background_colorbutton_2), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->background_colorbutton_2), &style->background); } else @@ -1025,31 +1042,31 @@ styles_cb (GtkWidget *treeview, GdkColor background_color; background_color = gedit_prefs_manager_get_background_color (); - gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->background_colorbutton_2), + gtk_color_button_set_color (GTK_COLOR_BUTTON (dlg->priv->background_colorbutton_2), &background_color); } - gtk_widget_set_sensitive (dlg->background_colorbutton_2, + gtk_widget_set_sensitive (dlg->priv->background_colorbutton_2, style->mask & GTK_SOURCE_TAG_STYLE_USE_BACKGROUND); - gtk_widget_set_sensitive (dlg->reset_button, !style->is_default); + gtk_widget_set_sensitive (dlg->priv->reset_button, !style->is_default); /* reenable callbacks */ - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->bold_togglebutton), + g_signal_handlers_unblock_by_func (dlg->priv->bold_togglebutton, G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->italic_togglebutton), + g_signal_handlers_unblock_by_func (dlg->priv->italic_togglebutton, G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->underline_togglebutton), + g_signal_handlers_unblock_by_func (dlg->priv->underline_togglebutton, G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->strikethrough_togglebutton), + g_signal_handlers_unblock_by_func (dlg->priv->strikethrough_togglebutton, G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->foreground_checkbutton), + g_signal_handlers_unblock_by_func (dlg->priv->foreground_checkbutton, G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->background_checkbutton), + g_signal_handlers_unblock_by_func (dlg->priv->background_checkbutton, G_CALLBACK (style_button_toggled), dlg); - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->foreground_colorbutton), + g_signal_handlers_unblock_by_func (dlg->priv->foreground_colorbutton, G_CALLBACK (style_color_set), dlg); - g_signal_handlers_unblock_by_func (G_OBJECT (dlg->background_colorbutton_2), + g_signal_handlers_unblock_by_func (dlg->priv->background_colorbutton_2, G_CALLBACK (style_color_set), dlg); gtk_source_tag_style_free (style); @@ -1064,11 +1081,11 @@ reset_button_clicked (GtkButton *button, gchar *id; GtkSourceLanguage *lang; - gtk_tree_view_get_cursor (GTK_TREE_VIEW (dlg->tags_treeview), &path, NULL); - gtk_tree_model_get_iter (GTK_TREE_MODEL (dlg->tags_treeview_model), + gtk_tree_view_get_cursor (GTK_TREE_VIEW (dlg->priv->tags_treeview), &path, NULL); + gtk_tree_model_get_iter (GTK_TREE_MODEL (dlg->priv->tags_treeview_model), &iter, path); gtk_tree_path_free (path); - gtk_tree_model_get (GTK_TREE_MODEL (dlg->tags_treeview_model), + gtk_tree_model_get (GTK_TREE_MODEL (dlg->priv->tags_treeview_model), &iter, ID_COLUMN, &id, -1); lang = get_selected_language (dlg); @@ -1078,311 +1095,291 @@ reset_button_clicked (GtkButton *button, styles_cb (NULL, dlg); } +static void +select_default_language (GeditPreferencesDialog *dlg) +{ + const GSList *languages, *l; + GeditDocument *current_document; + GtkSourceLanguage *current_document_language; + int current_item; + + current_document = gedit_window_get_active_document (GEDIT_WINDOW( + gtk_window_get_transient_for (GTK_WINDOW(dlg)))); + if (current_document != NULL) + current_document_language = gedit_document_get_language (current_document); + else + current_document_language = NULL; + + languages = gedit_languages_manager_get_available_languages_sorted ( + gedit_get_languages_manager ()); + + l = languages; + current_item = 0; + + while (l != NULL) + { + GtkSourceLanguage *lang = GTK_SOURCE_LANGUAGE (l->data); + + if (lang == current_document_language) + break; + + current_item++; + l = g_slist_next (l); + } + + if (l != NULL) + gtk_combo_box_set_active (GTK_COMBO_BOX (dlg->priv->hl_mode_combobox), + current_item); +} + static void setup_syntax_highlighting_page (GeditPreferencesDialog *dlg) { gboolean hl_enabled; - GtkWidget *menu; const GSList *languages, *l; GtkCellRenderer *renderer; GtkTreeViewColumn *column; - GeditDocument *current_document; - GtkSourceLanguage *current_document_language; - gint selected_language, current_item; /* Set initial state */ hl_enabled = gedit_prefs_manager_get_enable_syntax_highlighting (); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->enable_syntax_hl_checkbutton), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->enable_syntax_hl_checkbutton), hl_enabled); - gtk_widget_set_sensitive (dlg->hl_vbox, hl_enabled); + gtk_widget_set_sensitive (dlg->priv->hl_vbox, hl_enabled); /* Create GtkListStore for styles & setup treeview. */ - dlg->tags_treeview_model = gtk_list_store_new (NUM_COLUMNS, - G_TYPE_STRING, - G_TYPE_STRING); + dlg->priv->tags_treeview_model = gtk_list_store_new (NUM_COLUMNS, + G_TYPE_STRING, + G_TYPE_STRING); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dlg->tags_treeview_model), + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dlg->priv->tags_treeview_model), 0, GTK_SORT_ASCENDING); - gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->tags_treeview), - GTK_TREE_MODEL (dlg->tags_treeview_model)); + gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->tags_treeview), + GTK_TREE_MODEL (dlg->priv->tags_treeview_model)); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Elements"), renderer, "text", NAME_COLUMN, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->tags_treeview), column); + gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->tags_treeview), column); /* Connect signals */ - g_signal_connect (G_OBJECT (dlg->hl_mode_optionmenu), "changed", - G_CALLBACK (language_changed_cb), dlg); - - g_signal_connect (G_OBJECT (dlg->tags_treeview), "cursor-changed", - G_CALLBACK (styles_cb), dlg); - - /* Add languages to optionmenu. */ - menu = gtk_menu_new (); + g_signal_connect (dlg->priv->hl_mode_combobox, + "changed", + G_CALLBACK (language_changed_cb), + dlg); + g_signal_connect (dlg->priv->tags_treeview, + "cursor-changed", + G_CALLBACK (styles_cb), + dlg); languages = gedit_languages_manager_get_available_languages_sorted ( gedit_get_languages_manager ()); l = languages; - current_document = gedit_get_active_document (); - if (current_document != NULL) - current_document_language = gedit_document_get_language ( - current_document); - else - current_document_language = NULL; - - selected_language = 0; - current_item = 0; - while (l != NULL) { GtkSourceLanguage *lang = GTK_SOURCE_LANGUAGE (l->data); - GtkWidget *menuitem; - gchar *name; + gchar *name = gtk_source_language_get_name (lang); - lang = GTK_SOURCE_LANGUAGE (l->data); - - name = gtk_source_language_get_name (lang); - menuitem = gtk_menu_item_new_with_label (name); + gtk_combo_box_append_text (GTK_COMBO_BOX (dlg->priv->hl_mode_combobox), name); g_free (name); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - - if (current_document_language == lang) - selected_language = current_item; - ++current_item; - l = g_slist_next (l); } - - gtk_widget_show_all (menu); - - gtk_option_menu_set_menu (GTK_OPTION_MENU (dlg->hl_mode_optionmenu), menu); - gtk_option_menu_set_history (GTK_OPTION_MENU (dlg->hl_mode_optionmenu), - selected_language); - - g_signal_connect (G_OBJECT (dlg->enable_syntax_hl_checkbutton), "toggled", - G_CALLBACK (enable_syntax_hl_button_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->bold_togglebutton), "toggled", - G_CALLBACK (style_button_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->italic_togglebutton), "toggled", - G_CALLBACK (style_button_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->underline_togglebutton), "toggled", - G_CALLBACK (style_button_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->strikethrough_togglebutton), "toggled", - G_CALLBACK (style_button_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->foreground_checkbutton), "toggled", - G_CALLBACK (style_button_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->background_checkbutton), "toggled", - G_CALLBACK (style_button_toggled), dlg); - g_signal_connect (G_OBJECT (dlg->foreground_colorbutton), "color_set", - G_CALLBACK (style_color_set), dlg); - g_signal_connect (G_OBJECT (dlg->background_colorbutton_2), "color_set", - G_CALLBACK (style_color_set), dlg); - g_signal_connect (G_OBJECT (dlg->reset_button), "clicked", - G_CALLBACK (reset_button_clicked), dlg); + + gtk_combo_box_set_active (GTK_COMBO_BOX (dlg->priv->hl_mode_combobox), 0); + + g_signal_connect (dlg->priv->enable_syntax_hl_checkbutton, + "toggled", + G_CALLBACK (enable_syntax_hl_button_toggled), + dlg); + g_signal_connect (dlg->priv->bold_togglebutton, + "toggled", + G_CALLBACK (style_button_toggled), + dlg); + g_signal_connect (dlg->priv->italic_togglebutton, + "toggled", + G_CALLBACK (style_button_toggled), + dlg); + g_signal_connect (dlg->priv->underline_togglebutton, + "toggled", + G_CALLBACK (style_button_toggled), + dlg); + g_signal_connect (dlg->priv->strikethrough_togglebutton, + "toggled", + G_CALLBACK (style_button_toggled), + dlg); + g_signal_connect (dlg->priv->foreground_checkbutton, + "toggled", + G_CALLBACK (style_button_toggled), + dlg); + g_signal_connect (dlg->priv->background_checkbutton, + "toggled", + G_CALLBACK (style_button_toggled), + dlg); + g_signal_connect (dlg->priv->foreground_colorbutton, + "color_set", + G_CALLBACK (style_color_set), + dlg); + g_signal_connect (dlg->priv->background_colorbutton_2, + "color_set", + G_CALLBACK (style_color_set), + dlg); + g_signal_connect (dlg->priv->reset_button, + "clicked", + G_CALLBACK (reset_button_clicked), + dlg); } static void setup_plugins_page (GeditPreferencesDialog *dlg) { GtkWidget *page_content; - - gedit_debug (DEBUG_PREFS, ""); - page_content = gedit_plugin_manager_get_page (); + gedit_debug (DEBUG_PREFS); + + page_content = gedit_plugin_manager_new (); g_return_if_fail (page_content != NULL); - - gtk_box_pack_start (GTK_BOX (dlg->plugin_manager_place_holder), - page_content, - TRUE, - TRUE, + + gtk_box_pack_start (GTK_BOX (dlg->priv->plugin_manager_place_holder), + page_content, + TRUE, + TRUE, 0); + gtk_widget_show_all (page_content); } -static GeditPreferencesDialog * -get_preferences_dialog (GtkWindow *parent) +static void +gedit_preferences_dialog_init (GeditPreferencesDialog *dlg) { - static GeditPreferencesDialog *dialog = NULL; - GladeXML *gui; - - gedit_debug (DEBUG_PREFS, ""); - - if (dialog != NULL) + GtkWidget *content; + GtkWidget *error_widget; + gboolean ret; + + gedit_debug (DEBUG_PREFS); + + dlg->priv = GEDIT_PREFERENCES_DIALOG_GET_PRIVATE (dlg); + + gtk_dialog_add_buttons (GTK_DIALOG (dlg), + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + GTK_STOCK_HELP, + GTK_RESPONSE_HELP, + NULL); + + gtk_window_set_title (GTK_WINDOW (dlg), _("gedit Preferences")); + gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE); + gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); + gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE); + + g_signal_connect (dlg, "response", + G_CALLBACK (dialog_response_handler), NULL); + + dlg->priv->tooltips = gtk_tooltips_new (); + g_object_ref (dlg->priv->tooltips); + gtk_object_sink (GTK_OBJECT (dlg->priv->tooltips)); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "gedit-preferences-dialog.glade", + "notebook", + &error_widget, + + "notebook", &content, + "display_line_numbers_checkbutton", &dlg->priv->display_line_numbers_checkbutton, + "highlight_current_line_checkbutton", &dlg->priv->highlight_current_line_checkbutton, + + "bracket_matching_checkbutton", &dlg->priv->bracket_matching_checkbutton, + "wrap_text_checkbutton", &dlg->priv->wrap_text_checkbutton, + "split_checkbutton", &dlg->priv->split_checkbutton, + "default_font_checkbutton", &dlg->priv->default_font_checkbutton, + "default_colors_checkbutton", &dlg->priv->default_colors_checkbutton, + + "font_button", &dlg->priv->font_button, + "text_colorbutton", &dlg->priv->text_colorbutton, + "background_colorbutton", &dlg->priv->background_colorbutton, + "seltext_colorbutton", &dlg->priv->seltext_colorbutton, + "selection_colorbutton", &dlg->priv->selection_colorbutton, + + "colors_table", &dlg->priv->colors_table, + "font_hbox", &dlg->priv->font_hbox, + + "right_margin_checkbutton", &dlg->priv->right_margin_checkbutton, + "right_margin_position_spinbutton", &dlg->priv->right_margin_position_spinbutton, + "right_margin_position_hbox", &dlg->priv->right_margin_position_hbox, + + "tabs_width_spinbutton", &dlg->priv->tabs_width_spinbutton, + "tabs_width_hbox", &dlg->priv->tabs_width_hbox, + "insert_spaces_checkbutton", &dlg->priv->insert_spaces_checkbutton, + + "auto_indent_checkbutton", &dlg->priv->auto_indent_checkbutton, + + "autosave_hbox", &dlg->priv->autosave_hbox, + "backup_copy_checkbutton", &dlg->priv->backup_copy_checkbutton, + "auto_save_checkbutton", &dlg->priv->auto_save_checkbutton, + "auto_save_spinbutton", &dlg->priv->auto_save_spinbutton, + + "plugin_manager_place_holder", &dlg->priv->plugin_manager_place_holder, + + "enable_syntax_hl_checkbutton", &dlg->priv->enable_syntax_hl_checkbutton, + "hl_vbox", &dlg->priv->hl_vbox, + "hl_mode_combobox", &dlg->priv->hl_mode_combobox, + "tags_treeview", &dlg->priv->tags_treeview, + + "bold_togglebutton", &dlg->priv->bold_togglebutton, + "italic_togglebutton", &dlg->priv->italic_togglebutton, + "underline_togglebutton", &dlg->priv->underline_togglebutton, + "strikethrough_togglebutton", &dlg->priv->strikethrough_togglebutton, + "foreground_checkbutton", &dlg->priv->foreground_checkbutton, + "foreground_colorbutton", &dlg->priv->foreground_colorbutton, + "background_checkbutton", &dlg->priv->background_checkbutton, + "background_colorbutton_2", &dlg->priv->background_colorbutton_2, + "reset_button", &dlg->priv->reset_button, + NULL); + + if (!ret) { - gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), - parent); - gtk_window_present (GTK_WINDOW (dialog->dialog)); - - return dialog; - } - - gui = glade_xml_new (GEDIT_GLADEDIR "gedit-preferences.glade2", - "preferences_dialog", NULL); - if (!gui) - { - gedit_warning (parent, - MISSING_FILE, - GEDIT_GLADEDIR "gedit-preferences.glade2"); - return NULL; - } - - dialog = g_new0 (GeditPreferencesDialog, 1); - - dialog->dialog = glade_xml_get_widget (gui, "preferences_dialog"); - dialog->display_line_numbers_checkbutton = glade_xml_get_widget (gui, "display_line_numbers_checkbutton"); - dialog->highlight_current_line_checkbutton = glade_xml_get_widget (gui, "highlight_current_line_checkbutton"); - - dialog->bracket_matching_checkbutton = glade_xml_get_widget (gui, "bracket_matching_checkbutton"); - - dialog->wrap_text_checkbutton = glade_xml_get_widget (gui, "wrap_text_checkbutton"); - dialog->split_checkbutton = glade_xml_get_widget (gui, "split_checkbutton"); - - dialog->default_font_checkbutton = glade_xml_get_widget (gui, "default_font_checkbutton"); - dialog->default_colors_checkbutton = glade_xml_get_widget (gui, "default_colors_checkbutton"); - - dialog->font_button = glade_xml_get_widget (gui, "font_button"); - dialog->text_colorbutton = glade_xml_get_widget (gui, "text_colorbutton"); - dialog->background_colorbutton = glade_xml_get_widget (gui, "background_colorbutton"); - dialog->seltext_colorbutton = glade_xml_get_widget (gui, "seltext_colorbutton"); - dialog->selection_colorbutton = glade_xml_get_widget (gui, "selection_colorbutton"); - - dialog->colors_table = glade_xml_get_widget (gui, "colors_table"); - dialog->font_hbox = glade_xml_get_widget (gui, "font_hbox"); - - dialog->right_margin_checkbutton = glade_xml_get_widget (gui, "right_margin_checkbutton"); - dialog->right_margin_position_spinbutton = glade_xml_get_widget (gui, "right_margin_position_spinbutton"); - dialog->right_margin_position_hbox = glade_xml_get_widget (gui, "right_margin_position_hbox"); - - dialog->tabs_width_spinbutton = glade_xml_get_widget (gui, "tabs_width_spinbutton"); - dialog->tabs_width_hbox = glade_xml_get_widget (gui, "tabs_width_hbox"); - dialog->insert_spaces_checkbutton = glade_xml_get_widget (gui, "insert_spaces_checkbutton"); - - dialog->auto_indent_checkbutton = glade_xml_get_widget (gui, "auto_indent_checkbutton"); - - dialog->autosave_hbox = glade_xml_get_widget (gui, "autosave_hbox"); - dialog->backup_copy_checkbutton = glade_xml_get_widget (gui, "backup_copy_checkbutton"); - dialog->auto_save_checkbutton = glade_xml_get_widget (gui, "auto_save_checkbutton"); - dialog->auto_save_spinbutton = glade_xml_get_widget (gui, "auto_save_spinbutton"); - - dialog->plugin_manager_place_holder = glade_xml_get_widget (gui, "plugin_manager_place_holder"); - - dialog->enable_syntax_hl_checkbutton = glade_xml_get_widget (gui, "enable_syntax_hl_checkbutton"); - dialog->hl_vbox = glade_xml_get_widget (gui, "hl_vbox"); - dialog->hl_mode_optionmenu = glade_xml_get_widget (gui, "hl_mode_optionmenu"); - dialog->tags_treeview = glade_xml_get_widget (gui, "tags_treeview"); - - dialog->bold_togglebutton = glade_xml_get_widget (gui, "bold_togglebutton"); - dialog->italic_togglebutton = glade_xml_get_widget (gui, "italic_togglebutton"); - dialog->underline_togglebutton = glade_xml_get_widget (gui, "underline_togglebutton"); - dialog->strikethrough_togglebutton = glade_xml_get_widget (gui, "strikethrough_togglebutton"); - dialog->foreground_checkbutton = glade_xml_get_widget (gui, "foreground_checkbutton"); - dialog->foreground_colorbutton = glade_xml_get_widget (gui, "foreground_colorbutton"); - dialog->background_checkbutton = glade_xml_get_widget (gui, "background_checkbutton"); - dialog->background_colorbutton_2 = glade_xml_get_widget (gui, "background_colorbutton_2"); - dialog->reset_button = glade_xml_get_widget (gui, "reset_button"); - - if (!dialog->dialog || - !dialog->display_line_numbers_checkbutton || - !dialog->highlight_current_line_checkbutton || - !dialog->bracket_matching_checkbutton || - !dialog->wrap_text_checkbutton || - !dialog->split_checkbutton || - !dialog->default_font_checkbutton || - !dialog->default_colors_checkbutton || - !dialog->font_button || - !dialog->text_colorbutton || - !dialog->background_colorbutton || - !dialog->seltext_colorbutton || - !dialog->selection_colorbutton || - !dialog->colors_table || - !dialog->font_hbox || - !dialog->right_margin_checkbutton || - !dialog->right_margin_position_spinbutton || - !dialog->right_margin_position_hbox || - !dialog->tabs_width_spinbutton || - !dialog->tabs_width_hbox || - !dialog->insert_spaces_checkbutton || - !dialog->auto_indent_checkbutton || - !dialog->autosave_hbox || - !dialog->backup_copy_checkbutton || - !dialog->auto_save_checkbutton || - !dialog->auto_save_spinbutton || - !dialog->plugin_manager_place_holder || - !dialog->enable_syntax_hl_checkbutton || - !dialog->hl_vbox || - !dialog->hl_mode_optionmenu || - !dialog->tags_treeview || - !dialog->bold_togglebutton || - !dialog->italic_togglebutton || - !dialog->underline_togglebutton || - !dialog->strikethrough_togglebutton || - !dialog->foreground_checkbutton || - !dialog->foreground_colorbutton || - !dialog->background_checkbutton || - !dialog->background_colorbutton_2 || - !dialog->reset_button) - { - gedit_warning (parent, - MISSING_WIDGETS, - GEDIT_GLADEDIR "gedit-preferences.glade2"); - - if (!dialog->dialog) - gtk_widget_destroy (dialog->dialog); - - g_object_unref (gui); - g_free (dialog); - dialog = NULL; + gtk_widget_show (error_widget); + + gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dlg)->vbox), + error_widget); - return NULL; + return; } - dialog->tooltips = gtk_tooltips_new (); - g_object_ref (dialog->tooltips); - gtk_object_sink (GTK_OBJECT (dialog->tooltips)); - - setup_editor_page (dialog); - setup_view_page (dialog); - setup_font_colors_page (dialog); - setup_syntax_highlighting_page (dialog); - setup_plugins_page (dialog); - - gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), - parent); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), + content, FALSE, FALSE, 0); - g_signal_connect (G_OBJECT (dialog->dialog), "destroy", - G_CALLBACK (dialog_destroyed), &dialog); - - g_signal_connect (G_OBJECT (dialog->dialog), "response", - G_CALLBACK (dialog_response_handler), dialog); - - g_object_unref (gui); - - gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); - - return dialog; + setup_editor_page (dlg); + setup_view_page (dlg); + setup_font_colors_page (dlg); + setup_syntax_highlighting_page (dlg); + setup_plugins_page (dlg); } void -gedit_show_preferences_dialog (GtkWindow *parent) +gedit_show_preferences_dialog (GeditWindow *parent) { - GeditPreferencesDialog *dialog; + gedit_debug (DEBUG_PREFS); - gedit_debug (DEBUG_PREFS, ""); + g_return_if_fail (GEDIT_IS_WINDOW (parent)); - g_return_if_fail (parent != NULL); + if (preferences_dialog == NULL) + { + preferences_dialog = GTK_WIDGET (g_object_new (GEDIT_TYPE_PREFERENCES_DIALOG, NULL)); + g_signal_connect (preferences_dialog, + "destroy", + G_CALLBACK (gtk_widget_destroyed), + &preferences_dialog); + } - dialog = get_preferences_dialog (parent); - if (!dialog) - return; + if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (preferences_dialog))) + { + gtk_window_set_transient_for (GTK_WINDOW (preferences_dialog), + GTK_WINDOW (parent)); + select_default_language (GEDIT_PREFERENCES_DIALOG (preferences_dialog)); + } - if (!GTK_WIDGET_VISIBLE (dialog->dialog)) - gtk_widget_show_all (dialog->dialog); + gtk_window_present (GTK_WINDOW (preferences_dialog)); } - diff --git a/gedit/dialogs/gedit-preferences-dialog.glade b/gedit/dialogs/gedit-preferences-dialog.glade new file mode 100644 index 00000000..e06feb7b --- /dev/null +++ b/gedit/dialogs/gedit-preferences-dialog.glade @@ -0,0 +1,2360 @@ + + + + + + + + Preferences + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + False + True + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-help + True + GTK_RELIEF_NORMAL + True + -11 + + + + + + True + True + True + gtk-close + True + GTK_RELIEF_NORMAL + True + -7 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 6 + True + True + True + True + GTK_POS_TOP + False + False + + + + 12 + True + False + 18 + + + + True + False + 6 + + + + True + <b>Text Wrapping</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + Enable text _wrapping + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Do not _split words over two lines + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 6 + + + + True + <b>Line Numbers</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + _Display line numbers + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + False + 6 + + + + True + <b>Current Line</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + Hi_ghlight current line + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 6 + + + + True + <b>Right Margin</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + Display right _margin + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + False + 6 + + + + True + _Right margin at column: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + right_margin_position_spinbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + True + False + 80 1 160 1 10 10 + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + False + 6 + + + + True + <b>Bracket Matching</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + Highlight matching _bracket + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + View + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + 12 + True + False + 18 + + + + True + False + 6 + + + + True + <b>Tab Stops</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + False + 6 + + + + True + _Tab width: + True + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + tabs_width_spinbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 8 1 24 1 4 8 + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + True + Insert _spaces instead of tabs + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + False + 6 + + + + True + <b>Automatic Indentation</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + _Enable automatic indentation + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + False + 6 + + + + True + <b>File Saving</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + Create a _backup copy of files before saving + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + _Autosave files every + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 8 1 100 1 10 10 + + + 0 + False + False + + + + + + True + _minutes + True + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + auto_save_spinbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + False + False + + + + + False + True + + + + + + True + Editor + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + 12 + True + False + 18 + + + + True + False + 6 + + + + True + <b>Font</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + _Use default theme font + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + False + 12 + + + + True + Editor _font: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + font_button + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + Pick the editor font + True + True + True + False + True + + + 0 + True + True + + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + False + 6 + + + + True + <span weight="bold">Colors</span> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + True + U_se default theme colors + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + 4 + 2 + False + 6 + 12 + + + + True + _Background color: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + background_colorbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Selecte_d text color: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + seltext_colorbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + Se_lection color: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + selection_colorbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + Normal _text color: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + text_colorbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + False + Pick the normal text color + True + + + 1 + 2 + 0 + 1 + + + + + + True + True + False + Pick the background color + True + + + 1 + 2 + 1 + 2 + + + + + + True + True + False + Pick the selected text color + True + + + 1 + 2 + 2 + 3 + + + + + + True + True + False + Pick the selection color + True + + + 1 + 2 + 3 + 4 + + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Font & Colors + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + 12 + True + False + 18 + + + + True + True + _Enable syntax highlighting + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 12 + + + + True + False + 6 + + + + True + Highlight _mode: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + hl_mode_combobox + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + + False + True + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + False + 6 + + + + True + <b>Elements</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 12 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_ETCHED_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + False + True + False + False + False + + + + + 0 + True + True + + + + + + True + False + 12 + + + + True + True + 0 + + + + True + Bold + GTK_RELIEF_NONE + True + False + False + + + + True + gtk-bold + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Italic + GTK_RELIEF_NONE + True + False + False + + + + True + gtk-italic + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Underline + True + GTK_RELIEF_NONE + True + False + False + + + + True + gtk-underline + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Strikethrough + True + GTK_RELIEF_NONE + True + False + False + + + + True + gtk-strikethrough + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + 2 + 2 + False + 12 + 12 + + + + True + True + _Foreground: + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + _Background: + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + False + Pick a color + True + + + 1 + 2 + 0 + 1 + + + + + + + + True + True + False + Pick a color + True + + + 1 + 2 + 1 + 2 + + + + + + + 0 + False + False + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-undo + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Reset to Default + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Syntax Highlighting + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + 12 + True + False + 0 + + + + + + + False + True + + + + + + True + Plugins + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + + diff --git a/gedit/dialogs/gedit-preferences-dialog.h b/gedit/dialogs/gedit-preferences-dialog.h index e2434d08..bafebb06 100644 --- a/gedit/dialogs/gedit-preferences-dialog.h +++ b/gedit/dialogs/gedit-preferences-dialog.h @@ -3,7 +3,7 @@ * gedit-preferences-dialog.c * This file is part of gedit * - * Copyright (C) 2001-2003 Paolo Maggi + * 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 @@ -25,14 +25,63 @@ * Modified by the gedit Team, 2003. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_PREFERENCES_DIALOG_H__ #define __GEDIT_PREFERENCES_DIALOG_H__ -#include +#include "gedit-window.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_PREFERENCES_DIALOG (gedit_preferences_dialog_get_type()) +#define GEDIT_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialog)) +#define GEDIT_PREFERENCES_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialog const)) +#define GEDIT_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialogClass)) +#define GEDIT_IS_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PREFERENCES_DIALOG)) +#define GEDIT_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PREFERENCES_DIALOG)) +#define GEDIT_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PREFERENCES_DIALOG, GeditPreferencesDialogClass)) + + +/* Private structure type */ +typedef struct _GeditPreferencesDialogPrivate GeditPreferencesDialogPrivate; + +/* + * Main object structure + */ +typedef struct _GeditPreferencesDialog GeditPreferencesDialog; + +struct _GeditPreferencesDialog +{ + GtkDialog dialog; + + /*< private > */ + GeditPreferencesDialogPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditPreferencesDialogClass GeditPreferencesDialogClass; + +struct _GeditPreferencesDialogClass +{ + GtkDialogClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_preferences_dialog_get_type (void) G_GNUC_CONST; + +void gedit_show_preferences_dialog (GeditWindow *parent); -void gedit_show_preferences_dialog (GtkWindow *parent); +G_END_DECLS #endif /* __GEDIT_PREFERENCES_DIALOG_H__ */ diff --git a/gedit/dialogs/gedit-search-dialog.c b/gedit/dialogs/gedit-search-dialog.c new file mode 100644 index 00000000..bb05b87b --- /dev/null +++ b/gedit/dialogs/gedit-search-dialog.c @@ -0,0 +1,499 @@ +/* + * gedit-search-dialog.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "gedit-search-dialog.h" +#include "gedit-utils.h" + +#define GEDIT_SEARCH_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \ + GEDIT_TYPE_SEARCH_DIALOG, \ + GeditSearchDialogPrivate)) + +struct _GeditSearchDialogPrivate +{ + gboolean show_replace; + + GtkWidget *table; + GtkWidget *search_entry; + GtkWidget *replace_label; + GtkWidget *replace_entry; + GtkWidget *search_list; + GtkWidget *replace_list; + GtkWidget *match_case_checkbutton; + GtkWidget *entire_word_checkbutton; + GtkWidget *backwards_checkbutton; + GtkWidget *wrap_around_checkbutton; + GtkWidget *find_button; + GtkWidget *replace_button; + GtkWidget *replace_all_button; + + gboolean glade_error; +}; + +G_DEFINE_TYPE(GeditSearchDialog, gedit_search_dialog, GTK_TYPE_DIALOG) + +enum +{ + PROP_0, + PROP_SHOW_REPLACE +}; + +static void +gedit_search_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeditSearchDialog *dlg = GEDIT_SEARCH_DIALOG (object); + + switch (prop_id) + { + case PROP_SHOW_REPLACE: + gedit_search_dialog_set_show_replace (dlg, + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_search_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditSearchDialog *dlg = GEDIT_SEARCH_DIALOG (object); + + switch (prop_id) + { + case PROP_SHOW_REPLACE: + g_value_set_boolean (value, dlg->priv->show_replace); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_search_dialog_class_init (GeditSearchDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = gedit_search_dialog_set_property; + object_class->get_property = gedit_search_dialog_get_property; + + g_object_class_install_property (object_class, PROP_SHOW_REPLACE, + g_param_spec_boolean ("show-replace", + "Show Replace", + "Whether the dialog is used for Search&Replace", + FALSE, + G_PARAM_READWRITE)); + + g_type_class_add_private (object_class, sizeof (GeditSearchDialogPrivate)); +} + +static void +insert_text_handler (GtkEditable *editable, + const gchar *text, + gint length, + gint *position) +{ + static gboolean insert_text = FALSE; + gchar *escaped_text; + gint new_len; + + /* To avoid recursive behavior */ + if (insert_text) + return; + + escaped_text = gedit_utils_escape_search_text (text); + + new_len = strlen (escaped_text); + + if (new_len == length) + { + g_free (escaped_text); + return; + } + + insert_text = TRUE; + + g_signal_stop_emission_by_name (editable, "insert_text"); + + gtk_editable_insert_text (editable, escaped_text, new_len, position); + + insert_text = FALSE; + + g_free (escaped_text); +} + +static void +search_entry_changed (GtkEditable *editable, + GeditSearchDialog *dialog) +{ + const gchar *search_string; + + search_string = gtk_entry_get_text (GTK_ENTRY (dialog->priv->search_entry)); + g_return_if_fail (search_string != NULL); + + if (*search_string != '\0') + { + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_FIND_RESPONSE, TRUE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, TRUE); + } + else + { + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_FIND_RESPONSE, FALSE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE, FALSE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, FALSE); + } +} + +static void +response_handler (GeditSearchDialog *dialog, + gint response_id, + gpointer data) +{ + const gchar *str; + + switch (response_id) + { + case GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE: + case GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE: + str = gtk_entry_get_text (GTK_ENTRY (dialog->priv->replace_entry)); + if (*str != '\0') + gnome_entry_prepend_history (GNOME_ENTRY (dialog->priv->replace_list), + TRUE, + str); + /* fall through, so that we also save the find entry */ + case GEDIT_SEARCH_DIALOG_FIND_RESPONSE: + str = gtk_entry_get_text (GTK_ENTRY (dialog->priv->search_entry)); + if (*str != '\0') + gnome_entry_prepend_history (GNOME_ENTRY (dialog->priv->search_list), + TRUE, + str); + } +} + +static void +show_replace_widgets (GeditSearchDialog *dlg, + gboolean show_replace) +{ + if (show_replace) + { + gtk_widget_show (dlg->priv->replace_label); + gtk_widget_show (dlg->priv->replace_entry); + gtk_widget_show (dlg->priv->replace_list); + gtk_widget_show (dlg->priv->replace_all_button); + gtk_widget_show (dlg->priv->replace_button); + + gtk_table_set_row_spacings (GTK_TABLE (dlg->priv->table), 12); + + gtk_window_set_title (GTK_WINDOW (dlg), _("Replace")); + } + else + { + gtk_widget_hide (dlg->priv->replace_label); + gtk_widget_hide (dlg->priv->replace_entry); + gtk_widget_hide (dlg->priv->replace_list); + gtk_widget_hide (dlg->priv->replace_all_button); + gtk_widget_hide (dlg->priv->replace_button); + + gtk_table_set_row_spacings (GTK_TABLE (dlg->priv->table), 0); + + gtk_window_set_title (GTK_WINDOW (dlg), _("Find")); + } + + gtk_widget_show (dlg->priv->find_button); +} + +static void +gedit_search_dialog_init (GeditSearchDialog *dlg) +{ + GtkWidget *content; + GtkWidget *error_widget; + gboolean ret; + + dlg->priv = GEDIT_SEARCH_DIALOG_GET_PRIVATE (dlg); + + gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE); + gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); + gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE); + + gtk_dialog_add_buttons (GTK_DIALOG (dlg), + GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, + NULL); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "gedit-search-dialog.glade", + "search_dialog_content", + &error_widget, + "search_dialog_content", &content, + "table", &dlg->priv->table, + "search_for_text_entry", &dlg->priv->search_entry, + "replace_with_text_entry", &dlg->priv->replace_entry, + "search_for_text_entry_list", &dlg->priv->search_list, + "replace_with_text_entry_list", &dlg->priv->replace_list, + "replace_with_label", &dlg->priv->replace_label, + "match_case_checkbutton", &dlg->priv->match_case_checkbutton, + "entire_word_checkbutton", &dlg->priv->entire_word_checkbutton, + "search_backwards_checkbutton", &dlg->priv->backwards_checkbutton, + "wrap_around_checkbutton", &dlg->priv->wrap_around_checkbutton, + NULL); + + if (!ret) + { + gtk_widget_show (error_widget); + + gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dlg)->vbox), + error_widget); + + dlg->priv->glade_error = TRUE; + + return; + } + + dlg->priv->find_button = gtk_button_new_from_stock (GTK_STOCK_FIND); + dlg->priv->replace_all_button = gtk_button_new_with_mnemonic (_("Replace _All")); + dlg->priv->replace_button = gedit_gtk_button_new_with_stock_icon (_("_Replace"), + GTK_STOCK_FIND_AND_REPLACE); + + gtk_dialog_add_action_widget (GTK_DIALOG (dlg), + dlg->priv->replace_all_button, GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE); + gtk_dialog_add_action_widget (GTK_DIALOG (dlg), + dlg->priv->replace_button, GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE); + gtk_dialog_add_action_widget (GTK_DIALOG (dlg), + dlg->priv->find_button, GEDIT_SEARCH_DIALOG_FIND_RESPONSE); + g_object_set (G_OBJECT (dlg->priv->find_button), "can-default", TRUE, NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (dlg), + GEDIT_SEARCH_DIALOG_FIND_RESPONSE); + + /* insensitive by default */ + gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg), + GEDIT_SEARCH_DIALOG_FIND_RESPONSE, + FALSE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg), + GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE, + FALSE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg), + GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, + FALSE); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), + content, FALSE, FALSE, 0); + + g_signal_connect (dlg->priv->search_entry, + "insert_text", + G_CALLBACK (insert_text_handler), + NULL); + g_signal_connect (dlg->priv->replace_entry, + "insert_text", + G_CALLBACK (insert_text_handler), + NULL); + g_signal_connect (dlg->priv->search_list, + "changed", + G_CALLBACK (search_entry_changed), + dlg); + + g_signal_connect (dlg, + "response", + G_CALLBACK (response_handler), + NULL); +} + +GtkWidget * +gedit_search_dialog_new (GtkWindow *parent, + gboolean show_replace) +{ + GeditSearchDialog *dlg; + + dlg = g_object_new (GEDIT_TYPE_SEARCH_DIALOG, + "show-replace", show_replace, + NULL); + + if (parent != NULL) + gtk_window_set_transient_for (GTK_WINDOW (dlg), + parent); + + return GTK_WIDGET (dlg); +} + +gboolean +gedit_search_dialog_get_show_replace (GeditSearchDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE); + + return dialog->priv->show_replace; +} + +void +gedit_search_dialog_set_show_replace (GeditSearchDialog *dialog, + gboolean show_replace) +{ + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog)); + + if (dialog->priv->glade_error) + return; + + dialog->priv->show_replace = show_replace != FALSE; + show_replace_widgets (dialog, dialog->priv->show_replace); + + g_object_notify (G_OBJECT (dialog), "show-replace"); +} + +void +gedit_search_dialog_set_search_text (GeditSearchDialog *dialog, + const gchar *text) +{ + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog)); + g_return_if_fail (text != NULL); + + gtk_entry_set_text (GTK_ENTRY (dialog->priv->search_entry), text); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_FIND_RESPONSE, + (text != '\0')); +} + +/* + * The text must be unescaped before searching. + */ +const gchar * +gedit_search_dialog_get_search_text (GeditSearchDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), NULL); + + return gtk_entry_get_text (GTK_ENTRY (dialog->priv->search_entry)); +} + +void +gedit_search_dialog_set_replace_text (GeditSearchDialog *dialog, + const gchar *text) +{ + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog)); + g_return_if_fail (text != NULL); + + gtk_entry_set_text (GTK_ENTRY (dialog->priv->replace_entry), text); +} + +const gchar * +gedit_search_dialog_get_replace_text (GeditSearchDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), NULL); + + return gtk_entry_get_text (GTK_ENTRY (dialog->priv->replace_entry)); +} + +void +gedit_search_dialog_set_match_case (GeditSearchDialog *dialog, + gboolean match_case) +{ + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->match_case_checkbutton), + match_case); +} + +gboolean +gedit_search_dialog_get_match_case (GeditSearchDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->match_case_checkbutton)); +} + +void +gedit_search_dialog_set_entire_word (GeditSearchDialog *dialog, + gboolean entire_word) +{ + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->entire_word_checkbutton), + entire_word); +} + +gboolean +gedit_search_dialog_get_entire_word (GeditSearchDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->entire_word_checkbutton)); +} + +void +gedit_search_dialog_set_backwards (GeditSearchDialog *dialog, + gboolean backwards) +{ + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->backwards_checkbutton), + backwards); +} + +gboolean +gedit_search_dialog_get_backwards (GeditSearchDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->backwards_checkbutton)); +} + +void +gedit_search_dialog_set_wrap_around (GeditSearchDialog *dialog, + gboolean wrap_around) +{ + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->wrap_around_checkbutton), + wrap_around); +} + +gboolean +gedit_search_dialog_get_wrap_around (GeditSearchDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_SEARCH_DIALOG (dialog), FALSE); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->wrap_around_checkbutton)); +} diff --git a/gedit/dialogs/gedit-search-dialog.glade b/gedit/dialogs/gedit-search-dialog.glade new file mode 100644 index 00000000..ea3ecb5b --- /dev/null +++ b/gedit/dialogs/gedit-search-dialog.glade @@ -0,0 +1,334 @@ + + + + + + + + Replace + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + False + + + + True + False + 8 + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + + + + True + True + True + gtk-close + True + GTK_RELIEF_NORMAL + True + 0 + + + + + + True + True + True + Replace All + True + GTK_RELIEF_NORMAL + True + 0 + + + + + + True + True + True + Replace + True + GTK_RELIEF_NORMAL + True + 0 + + + + + + True + True + True + gtk-find + True + GTK_RELIEF_NORMAL + True + 0 + + + + + 0 + False + False + GTK_PACK_END + + + + + + 10 + True + False + 18 + + + + True + 2 + 2 + False + 12 + 12 + + + + True + _Search for: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + search_for_text_entry_list + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Replace _with: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + replace_with_text_entry_list + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + 300 + True + gedit2_search_for_entry + 10 + + + + True + True + True + True + 0 + + True + * + True + + + + + 1 + 2 + 0 + 1 + + + + + + + 300 + True + gedit2_replace_with_entry + 10 + + + + True + True + True + True + 0 + + True + * + True + + + + + 1 + 2 + 1 + 2 + + + + + + 0 + True + True + + + + + + True + False + 12 + + + + True + True + _Match case + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Match _entire word only + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Search _backwards + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + _Wrap around + True + GTK_RELIEF_NORMAL + True + True + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + diff --git a/gedit/dialogs/gedit-search-dialog.h b/gedit/dialogs/gedit-search-dialog.h new file mode 100644 index 00000000..1a233389 --- /dev/null +++ b/gedit/dialogs/gedit-search-dialog.h @@ -0,0 +1,122 @@ +/* + * gedit-search-dialog.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_SEARCH_DIALOG_H__ +#define __GEDIT_SEARCH_DIALOG_H__ + +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_SEARCH_DIALOG (gedit_search_dialog_get_type()) +#define GEDIT_SEARCH_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialog)) +#define GEDIT_SEARCH_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialog const)) +#define GEDIT_SEARCH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialogClass)) +#define GEDIT_IS_SEARCH_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_SEARCH_DIALOG)) +#define GEDIT_IS_SEARCH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_SEARCH_DIALOG)) +#define GEDIT_SEARCH_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_SEARCH_DIALOG, GeditSearchDialogClass)) + +/* Private structure type */ +typedef struct _GeditSearchDialogPrivate GeditSearchDialogPrivate; + +/* + * Main object structure + */ +typedef struct _GeditSearchDialog GeditSearchDialog; + +struct _GeditSearchDialog +{ + GtkDialog dialog; + + /*< private > */ + GeditSearchDialogPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditSearchDialogClass GeditSearchDialogClass; + +struct _GeditSearchDialogClass +{ + GtkDialogClass parent_class; +}; + +enum +{ + GEDIT_SEARCH_DIALOG_FIND_RESPONSE = 100, + GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE, + GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE +}; + +/* + * Public methods + */ +GType gedit_search_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_search_dialog_new (GtkWindow *parent, + gboolean show_replace); + +gboolean gedit_search_dialog_get_show_replace (GeditSearchDialog *dialog); + +void gedit_search_dialog_set_show_replace (GeditSearchDialog *dialog, + gboolean show_replace); + + +void gedit_search_dialog_set_search_text (GeditSearchDialog *dialog, + const gchar *text); +const gchar *gedit_search_dialog_get_search_text (GeditSearchDialog *dialog); + +void gedit_search_dialog_set_replace_text (GeditSearchDialog *dialog, + const gchar *text); +const gchar *gedit_search_dialog_get_replace_text (GeditSearchDialog *dialog); + +void gedit_search_dialog_set_match_case (GeditSearchDialog *dialog, + gboolean match_case); +gboolean gedit_search_dialog_get_match_case (GeditSearchDialog *dialog); + +void gedit_search_dialog_set_entire_word (GeditSearchDialog *dialog, + gboolean entire_word); +gboolean gedit_search_dialog_get_entire_word (GeditSearchDialog *dialog); + +void gedit_search_dialog_set_backwards (GeditSearchDialog *dialog, + gboolean backwards); +gboolean gedit_search_dialog_get_backwards (GeditSearchDialog *dialog); + +void gedit_search_dialog_set_wrap_around (GeditSearchDialog *dialog, + gboolean wrap_around); +gboolean gedit_search_dialog_get_wrap_around (GeditSearchDialog *dialog); + +G_END_DECLS + +#endif /* __GEDIT_SEARCH_DIALOG_H__ */ diff --git a/gedit/gedit-app.c b/gedit/gedit-app.c new file mode 100644 index 00000000..f7335328 --- /dev/null +++ b/gedit/gedit-app.c @@ -0,0 +1,376 @@ +/* + * gedit-app.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "gedit-app.h" +#include "gedit-prefs-manager-app.h" +#include "gedit-commands.h" +#include "gedit-notebook.h" +#include "gedit-debug.h" +#include "gedit-utils.h" + +#define GEDIT_APP_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_APP, GeditAppPrivate)) + +struct _GeditAppPrivate +{ + GList *windows; + GeditWindow *active_window; +}; + +G_DEFINE_TYPE(GeditApp, gedit_app, G_TYPE_OBJECT) + +static void +gedit_app_finalize (GObject *object) +{ + GeditApp *app = GEDIT_APP (object); + + g_list_free (app->priv->windows); + + G_OBJECT_CLASS (gedit_app_parent_class)->finalize (object); +} + +static void +gedit_app_class_init (GeditAppClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_app_finalize; + + g_type_class_add_private (object_class, sizeof(GeditAppPrivate)); +} + +static void +gedit_app_init (GeditApp *app) +{ + app->priv = GEDIT_APP_GET_PRIVATE (app); +} + +static void +app_weak_notify (gpointer data, + GObject *where_the_app_was) +{ + gtk_main_quit (); +} + +GeditApp * +gedit_app_get_default (void) +{ + static GeditApp *app = NULL; + + if (app != NULL) + return app; + + app = GEDIT_APP (g_object_new (GEDIT_TYPE_APP, NULL)); + + g_object_add_weak_pointer (G_OBJECT (app), + (gpointer) &app); + g_object_weak_ref (G_OBJECT (app), + app_weak_notify, + NULL); + + return app; +} + +static gboolean +window_focus_in_event (GeditWindow *window, + GdkEventFocus *event, + GeditApp *app) +{ + /* updates active_view and active_child when a new toplevel receives focus */ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), FALSE); + + app->priv->active_window = window; + + return FALSE; +} + +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 | + GEDIT_WINDOW_STATE_SAVING_SESSION)) + return TRUE; + + gedit_cmd_file_quit (NULL, window); + + /* Do not destroy the window */ + return TRUE; +} + +static void +window_destroy (GeditWindow *window, + GeditApp *app) +{ + app->priv->windows = g_list_remove (app->priv->windows, + window); + + if (window == app->priv->active_window) + { + app->priv->active_window = app->priv->windows != NULL ? + app->priv->windows->data : NULL; + } + +/* CHECK: I don't think we have to disconnect this function, since windows + is being destroyed */ +/* + g_signal_handlers_disconnect_by_func (window, + G_CALLBACK (window_focus_in_event), + app); + g_signal_handlers_disconnect_by_func (window, + G_CALLBACK (window_destroy), + app); +*/ + if (app->priv->windows == NULL) + { + g_object_unref (app); + } +} + +/* Generates a unique string for a window role */ +static gchar * +gen_role (void) +{ + time_t t; + static gint serial; + + t = time (NULL); + + return g_strdup_printf ("gedit-window-%d-%d-%d-%ld-%d@%s", + getpid (), + getgid (), + getppid (), + (long) t, + serial++, + g_get_host_name ()); +} + +static GeditWindow * +gedit_app_create_window_real (GeditApp *app, + gboolean set_geometry, + const gchar *role) +{ + GtkWindow *window; + + gedit_debug (DEBUG_APP); + + window = GTK_WINDOW (g_object_new (GEDIT_TYPE_WINDOW, NULL)); + + gedit_debug_message (DEBUG_APP, "Window created"); + + if (role != NULL) + { + gtk_window_set_role (GTK_WINDOW (window), role); + } + else + { + gchar *newrole; + + newrole = gen_role (); + gtk_window_set_role (GTK_WINDOW (window), newrole); + g_free (newrole); + } + + if (set_geometry) + { + GdkWindowState state; + + state = gedit_prefs_manager_get_window_state (); + + if ((state & GDK_WINDOW_STATE_MAXIMIZED) != 0) + { + gtk_window_set_default_size (window, + gedit_prefs_manager_get_default_window_width (), + gedit_prefs_manager_get_default_window_height ()); + + gtk_window_maximize (window); + } + else + { + gtk_window_set_default_size (window, + gedit_prefs_manager_get_window_width (), + gedit_prefs_manager_get_window_height ()); + + gtk_window_unmaximize (window); + } + + if ((state & GDK_WINDOW_STATE_STICKY ) != 0) + gtk_window_stick (window); + else + gtk_window_unstick (window); + } + + app->priv->windows = g_list_prepend (app->priv->windows, + window); + + g_signal_connect (window, + "focus_in_event", + G_CALLBACK (window_focus_in_event), + app); + g_signal_connect (window, + "delete_event", + G_CALLBACK (window_delete_event), + app); + g_signal_connect (window, + "destroy", + G_CALLBACK (window_destroy), + app); + + return GEDIT_WINDOW (window); +} + +GeditWindow * +gedit_app_create_window (GeditApp *app) +{ + return gedit_app_create_window_real (app, TRUE, NULL); +} + +/* + * Same as _create_window, but doesn't set the geometry. + * The session manager takes care of it. Used in gnome-session. + */ +GeditWindow * +_gedit_app_restore_window (GeditApp *app, + const gchar *role) +{ + GeditWindow *window; + + window = gedit_app_create_window_real (app, FALSE, role); + + return window; +} + +const GList * +gedit_app_get_windows (GeditApp *app) +{ + g_return_val_if_fail (GEDIT_IS_APP (app), NULL); + + return app->priv->windows; +} + +GeditWindow * +gedit_app_get_active_window (GeditApp *app) +{ + g_return_val_if_fail (GEDIT_IS_APP (app), NULL); + + return app->priv->active_window; +} + +GeditWindow * +_gedit_app_get_window_in_workspace (GeditApp *app, + gint workspace) +{ + GeditWindow *window; + gint ws; + + g_return_val_if_fail (GEDIT_IS_APP (app), NULL); + + /* first try if the active window */ + window = app->priv->active_window; + ws = gedit_utils_get_window_workspace (GTK_WINDOW (window)); + + if (ws != workspace && ws != GEDIT_ALL_WORKSPACES) + { + GList *l; + + /* try to see if there is a window on this workspace */ + l = app->priv->windows; + while (l != NULL) + { + ws = gedit_utils_get_window_workspace (GTK_WINDOW (l->data)); + if (ws == workspace || ws == GEDIT_ALL_WORKSPACES) + break; + + l = g_list_next (l); + } + + /* no window on this workspace... create a new one */ + if (l == NULL) + window = gedit_app_create_window (app); + } + + return window; +} + +/* Returns a newly allocated list with all the documents */ +GList * +gedit_app_get_documents (GeditApp *app) +{ + GList *res = NULL; + GList *windows; + + g_return_val_if_fail (GEDIT_IS_APP (app), NULL); + + windows = app->priv->windows; + + while (windows != NULL) + { + res = g_list_concat (res, + gedit_window_get_documents (GEDIT_WINDOW (windows->data))); + + windows = g_list_next (windows); + } + + return res; +} + +/* Returns a newly allocated list with all the views */ +GList * +gedit_app_get_views (GeditApp *app) +{ + GList *res = NULL; + GList *windows; + + g_return_val_if_fail (GEDIT_IS_APP (app), NULL); + + windows = app->priv->windows; + + while (windows != NULL) + { + res = g_list_concat (res, + gedit_window_get_views (GEDIT_WINDOW (windows->data))); + + windows = g_list_next (windows); + } + + return res; +} diff --git a/gedit/gedit-app.h b/gedit/gedit-app.h new file mode 100644 index 00000000..4e9d9479 --- /dev/null +++ b/gedit/gedit-app.h @@ -0,0 +1,105 @@ +/* + * gedit-app.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_APP_H__ +#define __GEDIT_APP_H__ + +#include + +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_APP (gedit_app_get_type()) +#define GEDIT_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_APP, GeditApp)) +#define GEDIT_APP_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_APP, GeditApp const)) +#define GEDIT_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_APP, GeditAppClass)) +#define GEDIT_IS_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_APP)) +#define GEDIT_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_APP)) +#define GEDIT_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_APP, GeditAppClass)) + +/* Private structure type */ +typedef struct _GeditAppPrivate GeditAppPrivate; + +/* + * Main object structure + */ +typedef struct _GeditApp GeditApp; + +struct _GeditApp +{ + GObject object; + + /*< private > */ + GeditAppPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditAppClass GeditAppClass; + +struct _GeditAppClass +{ + GObjectClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_app_get_type (void) G_GNUC_CONST; + +GeditApp *gedit_app_get_default (void); + +GeditWindow *gedit_app_create_window (GeditApp *app); + +const GList *gedit_app_get_windows (GeditApp *app); +GeditWindow *gedit_app_get_active_window (GeditApp *app); + +/* Returns a newly allocated list with all the documents */ +GList *gedit_app_get_documents (GeditApp *app); + +/* Returns a newly allocated list with all the views */ +GList *gedit_app_get_views (GeditApp *app); + +/* + * Non exported functions + */ +GeditWindow *_gedit_app_restore_window (GeditApp *app, + const gchar *role); +GeditWindow *_gedit_app_get_window_in_workspace (GeditApp *app, + gint workspace); + +G_END_DECLS + +#endif /* __GEDIT_APP_H__ */ diff --git a/gedit/gedit-commands-documents.c b/gedit/gedit-commands-documents.c new file mode 100644 index 00000000..d06b62a4 --- /dev/null +++ b/gedit/gedit-commands-documents.c @@ -0,0 +1,63 @@ +/* + * gedit-documents-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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "gedit-commands.h" +#include "gedit-window.h" +#include "gedit-notebook.h" +#include "gedit-debug.h" + +void +gedit_cmd_documents_move_to_new_window (GtkAction *action, + GeditWindow *window) +{ + GeditNotebook *old_notebook; + GeditTab *tab; + + gedit_debug (DEBUG_COMMANDS); + + tab = gedit_window_get_active_tab (window); + + if (tab == NULL) + return; + + old_notebook = GEDIT_NOTEBOOK (_gedit_window_get_notebook (window)); + + g_return_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (old_notebook)) > 1); + + _gedit_window_move_tab_to_new_window (window, tab); +} diff --git a/gedit/gedit-commands-edit.c b/gedit/gedit-commands-edit.c new file mode 100644 index 00000000..8254f0ad --- /dev/null +++ b/gedit/gedit-commands-edit.c @@ -0,0 +1,174 @@ +/* + * gedit-commands-edit.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "gedit-commands.h" +#include "gedit-window.h" +#include "gedit-debug.h" +#include "gedit-view.h" +#include "dialogs/gedit-preferences-dialog.h" + +void +gedit_cmd_edit_undo (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + GtkSourceBuffer *active_document; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + 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); + + gedit_view_scroll_to_cursor (active_view); + + gtk_widget_grab_focus (GTK_WIDGET (active_view)); +} + +void +gedit_cmd_edit_redo (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + GtkSourceBuffer *active_document; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + 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); + + gedit_view_scroll_to_cursor (active_view); + + gtk_widget_grab_focus (GTK_WIDGET (active_view)); +} + +void +gedit_cmd_edit_cut (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + g_return_if_fail (active_view); + + gedit_view_cut_clipboard (active_view); + + gtk_widget_grab_focus (GTK_WIDGET (active_view)); +} + +void +gedit_cmd_edit_copy (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + g_return_if_fail (active_view); + + gedit_view_copy_clipboard (active_view); + + gtk_widget_grab_focus (GTK_WIDGET (active_view)); +} + +void +gedit_cmd_edit_paste (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + g_return_if_fail (active_view); + + gedit_view_paste_clipboard (active_view); + + gtk_widget_grab_focus (GTK_WIDGET (active_view)); +} + +void +gedit_cmd_edit_delete (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + g_return_if_fail (active_view); + + gedit_view_delete_selection (active_view); + + gtk_widget_grab_focus (GTK_WIDGET (active_view)); +} + +void +gedit_cmd_edit_select_all (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + g_return_if_fail (active_view); + + gedit_view_select_all (active_view); + + gtk_widget_grab_focus (GTK_WIDGET (active_view)); +} + +void +gedit_cmd_edit_preferences (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + gedit_show_preferences_dialog (window); +} diff --git a/gedit/gedit-commands-file-print.c b/gedit/gedit-commands-file-print.c new file mode 100644 index 00000000..3de342ec --- /dev/null +++ b/gedit/gedit-commands-file-print.c @@ -0,0 +1,191 @@ +/* + * gedit-commands-file-print.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "gedit-commands.h" +#include "gedit-window.h" +#include "gedit-debug.h" +#include "gedit-print.h" +#include "dialogs/gedit-page-setup-dialog.h" + + +void +gedit_cmd_file_page_setup (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + gedit_show_page_setup_dialog (GTK_WINDOW (window)); +} + +void +gedit_cmd_file_print_preview (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + GeditTab *tab; + GeditPrintJob *pjob; + GtkTextIter start; + GtkTextIter end; + + gedit_debug (DEBUG_COMMANDS); + + tab = gedit_window_get_active_tab (window); + if (tab == NULL) + return; + + doc = gedit_tab_get_document (tab); + + pjob = gedit_print_job_new (doc); + + gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc) , &start, &end); + + _gedit_tab_print_preview (tab, pjob, &start, &end); + g_object_unref (pjob); +} + +static void +print_dialog_response_cb (GtkWidget *dialog, + gint response, + GeditPrintJob *pjob) +{ + GtkTextIter start; + GtkTextIter end; + gint line_start; + gint line_end; + GnomePrintRangeType range_type; + GtkTextBuffer *buffer; + GeditTab *tab; + + gedit_debug (DEBUG_COMMANDS); + + range_type = gnome_print_dialog_get_range (GNOME_PRINT_DIALOG (dialog)); + + buffer = GTK_TEXT_BUFFER ( + gtk_source_print_job_get_buffer (GTK_SOURCE_PRINT_JOB (pjob))); + + gtk_text_buffer_get_bounds (buffer, &start, &end); + + tab = gedit_tab_get_from_document (GEDIT_DOCUMENT (buffer)); + + switch (range_type) + { + case GNOME_PRINT_RANGE_ALL: + break; + + case GNOME_PRINT_RANGE_SELECTION: + gtk_text_buffer_get_selection_bounds (buffer, + &start, + &end); + break; + + case GNOME_PRINT_RANGE_RANGE: + gnome_print_dialog_get_range_page (GNOME_PRINT_DIALOG (dialog), + &line_start, + &line_end); + + gtk_text_iter_set_line (&start, line_start - 1); + gtk_text_iter_set_line (&end, line_end - 1); + + gtk_text_iter_forward_to_line_end (&end); + + break; + + default: + g_return_if_reached (); + } + + switch (response) + { + case GNOME_PRINT_DIALOG_RESPONSE_PRINT: + gedit_debug_message (DEBUG_PRINT, + "Print button pressed."); + + _gedit_tab_print (tab, pjob, &start, &end); + + break; + + case GNOME_PRINT_DIALOG_RESPONSE_PREVIEW: + gedit_debug_message (DEBUG_PRINT, + "Preview button pressed."); + + _gedit_tab_print_preview (tab, pjob, &start, &end); + + break; + } + + g_object_unref (pjob); + gtk_widget_destroy (dialog); +} + +void +gedit_cmd_file_print (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + GeditPrintJob *pjob; + GtkWidget *print_dialog; + GtkWindowGroup *wg; + + gedit_debug (DEBUG_COMMANDS); + + doc = gedit_window_get_active_document (window); + if (doc == NULL) + return; + + pjob = gedit_print_job_new (doc); + + print_dialog = gedit_print_dialog_new (pjob); + + wg = gedit_window_get_group (window); + + gtk_window_group_add_window (wg, + GTK_WINDOW (print_dialog)); + + gtk_window_set_transient_for (GTK_WINDOW (print_dialog), + GTK_WINDOW (window)); + gtk_window_set_modal (GTK_WINDOW (print_dialog), TRUE); + + g_signal_connect (print_dialog, + "response", + G_CALLBACK (print_dialog_response_cb), + pjob); + + gtk_widget_show (print_dialog); +} + diff --git a/gedit/gedit-commands-file.c b/gedit/gedit-commands-file.c new file mode 100644 index 00000000..bbb59e55 --- /dev/null +++ b/gedit/gedit-commands-file.c @@ -0,0 +1,1721 @@ +/* + * 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 + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include /* For strlen and strcmp */ + +#include +#include +#include + +#include "gedit-commands.h" +#include "gedit-window.h" +#include "gedit-window-private.h" +#include "gedit-statusbar.h" +#include "gedit-debug.h" +#include "gedit-utils.h" +#include "gedit-recent.h" +#include "dialogs/gedit-close-confirmation-dialog.h" +#include "dialogs/gedit-open-location-dialog.h" +#include "gedit-file-chooser-dialog.h" + + +/* Defined constants */ +#define GEDIT_OPEN_DIALOG_KEY "gedit-open-dialog-key" +#define GEDIT_OPEN_LOCATION_DIALOG_KEY "gedit-open-location-dialog-key" +#define GEDIT_TAB_TO_SAVE_AS "gedit-tab-to-save-as" +#define GEDIT_LIST_OF_TABS_TO_SAVE_AS "gedit-list-of-tabs-to-save-as" +#define GEDIT_IS_CLOSING_ALL "gedit-is-closing-all" +#define GEDIT_IS_QUITTING "gedit-is-quitting" +#define GEDIT_IS_CLOSING_TAB "gedit-is-closing-tab" + + +static void tab_state_changed_while_saving (GeditTab *tab, + GParamSpec *pspec, + GeditWindow *window); + +void +gedit_cmd_file_new (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + gedit_window_create_tab (window, TRUE); +} + +/* File loading */ +static gint +load_file_list (GeditWindow *window, + const GSList *uris, + const GeditEncoding *encoding, + gint line_pos, + gboolean create) +{ + GeditTab *tab; + + gint loaded_files = 0; /* Number of files to load */ + gboolean jump_to = TRUE; /* Whether to jump to the new tab */ + gboolean flash = TRUE; /* Whether to flash a message in the statusbar */ + + gedit_debug (DEBUG_COMMANDS); + + g_return_val_if_fail ((uris != NULL) && (uris->data != NULL), 0); + + tab = gedit_window_get_active_tab (window); + if (tab != NULL) + { + GeditDocument *doc; + + doc = gedit_tab_get_document (tab); + + if (gedit_document_is_untouched (doc) && + (gedit_tab_get_state (tab) == GEDIT_TAB_STATE_NORMAL)) + { + const gchar *uri; + gboolean ret; + + uri = (const gchar *)uris->data; + ret = _gedit_tab_load (tab, + uri, + encoding, + line_pos, + create); + + uris = g_slist_next (uris); + jump_to = FALSE; + + if (ret) + { + if (uris == NULL) + { + /* There is only a single file to load */ + gchar *uri_for_display; + + uri_for_display = gnome_vfs_format_uri_for_display (uri); + + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Loading file '%s'\342\200\246"), + uri_for_display); + + g_free (uri_for_display); + + flash = FALSE; + } + + ++loaded_files; + } + } + } + + while (uris != NULL) + { + g_return_val_if_fail (uris->data != NULL, 0); + + tab = gedit_window_create_tab_from_uri (window, + (const gchar *)uris->data, + encoding, + line_pos, + create, + jump_to); + + if (tab != NULL) + { + jump_to = FALSE; + ++loaded_files; + } + + uris = g_slist_next (uris); + } + + if (flash) + { + if (loaded_files == 1) + { + GeditDocument *doc; + gchar *uri_for_display; + + g_return_val_if_fail (tab != NULL, loaded_files); + + doc = gedit_tab_get_document (tab); + uri_for_display = gedit_document_get_uri_for_display (doc); + + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Loading file '%s'\342\200\246"), + uri_for_display); + + g_free (uri_for_display); + } + else + { + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + ngettext("Loading %d file\342\200\246", + "Loading %d files\342\200\246", + loaded_files), + loaded_files); + } + } + + return loaded_files; +} + +/* Exported so it can be used for drag'n'drop */ +gint +gedit_cmd_load_files (GeditWindow *window, + const GSList *uris, + const GeditEncoding *encoding) +{ + gedit_debug (DEBUG_COMMANDS); + + return load_file_list (window, uris, encoding, 0, FALSE); +} + +/* + * From the command line we can specify a line position for the + * first doc. Beside specifying a not existing uri crates a + * titled document. + */ +gint +gedit_cmd_load_files_from_prompt (GeditWindow *window, + const GSList *uris, + const GeditEncoding *encoding, + gint line_pos) +{ + gedit_debug (DEBUG_COMMANDS); + + return load_file_list (window, uris, encoding, line_pos, TRUE); +} + + +static void +open_dialog_destroyed (GeditWindow *window, + GeditFileChooserDialog *dialog) +{ + gedit_debug (DEBUG_COMMANDS); + + g_object_set_data (G_OBJECT (window), + GEDIT_OPEN_DIALOG_KEY, + NULL); +} + +static void +open_dialog_response_cb (GeditFileChooserDialog *dialog, + gint response_id, + GeditWindow *window) +{ + GSList *uris; + const GeditEncoding *encoding; + + gedit_debug (DEBUG_COMMANDS); + + if (response_id != GTK_RESPONSE_OK) + { + gtk_widget_destroy (GTK_WIDGET (dialog)); + + return; + } + + uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog)); + g_return_if_fail (uris != NULL); + + encoding = gedit_file_chooser_dialog_get_encoding (dialog); + + gtk_widget_destroy (GTK_WIDGET (dialog)); + + gedit_cmd_load_files (window, + uris, + encoding); + + g_slist_foreach (uris, (GFunc) g_free, NULL); + g_slist_free (uris); +} + +void +gedit_cmd_file_open (GtkAction *action, + GeditWindow *window) +{ + GtkWidget *open_dialog; + gpointer data; + GeditDocument *doc; + gchar *default_path = NULL; + + gedit_debug (DEBUG_COMMANDS); + + data = g_object_get_data (G_OBJECT (window), GEDIT_OPEN_DIALOG_KEY); + + if (data != NULL) + { + g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (data)); + + gtk_window_present (GTK_WINDOW (data)); + + return; + } + + open_dialog = gedit_file_chooser_dialog_new (_("Open Files\342\200\246"), + GTK_WINDOW (window), + GTK_FILE_CHOOSER_ACTION_OPEN, + NULL, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_OK, + NULL); + + g_object_set_data (G_OBJECT (window), + GEDIT_OPEN_DIALOG_KEY, + open_dialog); + + g_object_weak_ref (G_OBJECT (open_dialog), + (GWeakNotify) open_dialog_destroyed, + window); + + /* Set the curret folder uri */ + doc = gedit_window_get_active_document (window); + if (doc != NULL) + { + gchar *uri; + + uri = gedit_document_get_uri (doc); + + if ((uri != NULL) && + gedit_utils_uri_has_file_scheme (uri)) + { + default_path = g_path_get_dirname (uri); + + g_return_if_fail (strlen (default_path) >= 5 /* strlen ("file:") */); + if (strcmp (default_path, "file:") == 0) + { + g_free (default_path); + + default_path = g_strdup ("file:///"); + } + } + + g_free (uri); + } + + if (default_path == NULL) + default_path = g_strdup (_gedit_window_get_default_path (window)); + + if (default_path != NULL) + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (open_dialog), + default_path); + + g_free (default_path); + + g_signal_connect (open_dialog, + "response", + G_CALLBACK (open_dialog_response_cb), + window); + + gtk_widget_show (open_dialog); +} + +static void +open_location_dialog_destroyed (GeditWindow *window, + gpointer data) +{ + gedit_debug (DEBUG_COMMANDS); + + g_object_set_data (G_OBJECT (window), + GEDIT_OPEN_LOCATION_DIALOG_KEY, + NULL); +} + +static void +open_location_dialog_response_cb (GeditOpenLocationDialog *dlg, + gint response_id, + GeditWindow *window) +{ + gchar *uri; + GSList *uris = NULL; + const GeditEncoding *encoding; + + gedit_debug (DEBUG_COMMANDS); + + if (response_id != GTK_RESPONSE_OK) + { + gtk_widget_destroy (GTK_WIDGET (dlg)); + + return; + } + + uri = gedit_open_location_dialog_get_uri (dlg); + if (uri == NULL) + { + GtkWidget *msg; + GtkWindowGroup *wg; + + wg = GTK_WINDOW (dlg)->group; + + if (wg == NULL) + { + wg = gtk_window_group_new (); + + gtk_window_group_add_window (wg, GTK_WINDOW (dlg)); + } + + msg = gtk_message_dialog_new (GTK_WINDOW (dlg), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("The entered location is not valid.")); + + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (msg), + _("Please, check that you typed the " + "location correctly and try again.")); + + gtk_window_group_add_window (wg, GTK_WINDOW (msg)); + + g_signal_connect (G_OBJECT (msg), + "response", + G_CALLBACK (gtk_widget_destroy), + NULL); + + gtk_window_set_resizable (GTK_WINDOW (msg), FALSE); + gtk_window_set_modal (GTK_WINDOW (msg), TRUE); + + gtk_widget_show (msg); + + return; + } + + encoding = gedit_open_location_dialog_get_encoding (dlg); + uris = g_slist_prepend (uris, uri); + + gtk_widget_destroy (GTK_WIDGET (dlg)); + + gedit_cmd_load_files (window, + uris, + encoding); + + g_slist_foreach (uris, (GFunc) g_free, NULL); + g_slist_free (uris); +} + +void +gedit_cmd_file_open_uri (GtkAction *action, + GeditWindow *window) +{ + GtkWidget *dlg; + gpointer data; + + gedit_debug (DEBUG_COMMANDS); + + data = g_object_get_data (G_OBJECT (window), GEDIT_OPEN_LOCATION_DIALOG_KEY); + + if (data != NULL) + { + g_return_if_fail (GEDIT_IS_OPEN_LOCATION_DIALOG (data)); + + gtk_window_present (GTK_WINDOW (data)); + + return; + } + + dlg = gedit_open_location_dialog_new (GTK_WINDOW (window)); + + g_object_set_data (G_OBJECT (window), + GEDIT_OPEN_LOCATION_DIALOG_KEY, + dlg); + + g_object_weak_ref (G_OBJECT (dlg), + (GWeakNotify) open_location_dialog_destroyed, + window); + + g_signal_connect (dlg, + "response", + G_CALLBACK (open_location_dialog_response_cb), + window); + + gtk_widget_show (dlg); +} + +void +gedit_cmd_file_open_recent (EggRecentItem *item, + GeditWindow *window) +{ + GSList *uris = NULL; + gchar *uri; + + gedit_debug (DEBUG_COMMANDS); + + uri = egg_recent_item_get_uri (item); + + uris = g_slist_prepend (uris, uri); + + if (gedit_cmd_load_files (window, uris, NULL) != 1) + gedit_recent_remove (uri); + + g_slist_foreach (uris, (GFunc) g_free, NULL); + g_slist_free (uris); +} + +/* File saving */ +static void file_save_as (GeditTab *tab, GeditWindow *window); + +/* CHECK: move to utils? If so, do not include vfs.h */ +static gboolean +is_read_only (const gchar *uri) +{ + gboolean ret = TRUE; /* default to read only */ + GnomeVFSFileInfo *info; + + gedit_debug (DEBUG_COMMANDS); + + g_return_val_if_fail (uri != NULL, FALSE); + + info = gnome_vfs_file_info_new (); + + /* FIXME: is GNOME_VFS_FILE_INFO_FOLLOW_LINKS right in this case? - Paolo */ + if (gnome_vfs_get_file_info (uri, + info, + GNOME_VFS_FILE_INFO_FOLLOW_LINKS | + GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS) == GNOME_VFS_OK) + { + if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ACCESS) + ret = !(info->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE); + } + + gnome_vfs_file_info_unref (info); + + return ret; +} + +/* 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, + const gchar *uri) +{ + GtkWidget *dialog; + gint ret; + gchar *full_formatted_uri; + gchar *uri_for_display; + gchar *message_with_uri; + + gedit_debug (DEBUG_COMMANDS); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + g_return_val_if_fail (full_formatted_uri != NULL, FALSE); + + /* 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. + */ + uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri, 50); + g_return_val_if_fail (uri_for_display != NULL, FALSE); + g_free (full_formatted_uri); + + message_with_uri = g_strdup_printf (_("The file \"%s\" is read-only."), + uri_for_display); + g_free (uri_for_display); + + dialog = gtk_message_dialog_new (parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + message_with_uri); + + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("Do you want to try to replace it " + "with the one you are saving?")); + g_free (message_with_uri); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + + gedit_dialog_add_button (GTK_DIALOG (dialog), + _("_Replace"), + GTK_STOCK_SAVE_AS, + GTK_RESPONSE_YES); + + 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 void +save_dialog_response_cb (GeditFileChooserDialog *dialog, + gint response_id, + GeditWindow *window) +{ + gchar *uri; + const GeditEncoding *encoding; + GeditTab *tab; + gpointer data; + GSList *tabs_to_save_as; + + gedit_debug (DEBUG_COMMANDS); + + tab = GEDIT_TAB (g_object_get_data (G_OBJECT (dialog), + GEDIT_TAB_TO_SAVE_AS)); + + if (response_id != GTK_RESPONSE_OK) + { + gtk_widget_destroy (GTK_WIDGET (dialog)); + + goto save_next_tab; + } + + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + g_return_if_fail (uri != NULL); + + encoding = gedit_file_chooser_dialog_get_encoding (dialog); + + gtk_widget_destroy (GTK_WIDGET (dialog)); + + if (tab != NULL) + { + GeditDocument *doc; + gchar *uri_for_display; + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + uri_for_display = gnome_vfs_format_uri_for_display (uri); + + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Saving file '%s'\342\200\246"), + uri_for_display); + + _gedit_tab_save_as (tab, uri, encoding); + } + + g_free (uri); + +save_next_tab: + + data = g_object_get_data (G_OBJECT (window), + GEDIT_LIST_OF_TABS_TO_SAVE_AS); + if (data == NULL) + return; + + /* Save As the next tab of the list (we are Saving All files) */ + tabs_to_save_as = (GSList *)data; + g_return_if_fail (tab == GEDIT_TAB (tabs_to_save_as->data)); + + /* Remove the first item of the list */ + tabs_to_save_as = g_slist_delete_link (tabs_to_save_as, + tabs_to_save_as); + + g_object_set_data (G_OBJECT (window), + GEDIT_LIST_OF_TABS_TO_SAVE_AS, + tabs_to_save_as); + + if (tabs_to_save_as != NULL) + { + tab = GEDIT_TAB (tabs_to_save_as->data); + + if (GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (tab), + GEDIT_IS_CLOSING_TAB)) == TRUE) + { + g_object_set_data (G_OBJECT (tab), + GEDIT_IS_CLOSING_TAB, + NULL); + + /* Trace tab state changes */ + g_signal_connect (tab, + "notify::state", + G_CALLBACK (tab_state_changed_while_saving), + window); + } + + gedit_window_set_active_tab (window, tab); + file_save_as (tab, window); + } +} + +static GtkFileChooserConfirmation +confirm_overwrite_callback (GtkFileChooser *dialog, + gpointer data) +{ + gchar *uri; + + gedit_debug (DEBUG_COMMANDS); + + uri = gtk_file_chooser_get_uri (dialog); + + if (is_read_only (uri)) + { + if (replace_read_only_file (GTK_WINDOW (dialog), uri)) + return GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME; + else + return GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN; + } + else + { + /* fall back to the default confirmation dialog */ + return GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM; + } +} + +static void +file_save_as (GeditTab *tab, + GeditWindow *window) +{ + GtkWidget *save_dialog; + GtkWindowGroup *wg; + GeditDocument *doc; + gchar *uri; + gboolean uri_set = FALSE; + const GeditEncoding *encoding; + + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + gedit_debug (DEBUG_COMMANDS); + + save_dialog = gedit_file_chooser_dialog_new (_("Save As\342\200\246"), + GTK_WINDOW (window), + GTK_FILE_CHOOSER_ACTION_SAVE, + NULL, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_OK, + NULL); + + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (save_dialog), + TRUE); + g_signal_connect (save_dialog, + "confirm-overwrite", + G_CALLBACK (confirm_overwrite_callback), + NULL); + + wg = gedit_window_get_group (window); + + gtk_window_group_add_window (wg, + GTK_WINDOW (save_dialog)); + + /* Save As dialog is modal to its main window */ + gtk_window_set_modal (GTK_WINDOW (save_dialog), TRUE); + + /* Set the suggested file name */ + doc = gedit_tab_get_document (tab); + uri = gedit_document_get_uri (doc); + + if ((uri != NULL) && + gedit_utils_uri_has_file_scheme (uri)) + { + uri_set = gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (save_dialog), + uri); + } + + g_free (uri); + + if (!uri_set) + { + const gchar *default_path; + gchar *docname; + + default_path = _gedit_window_get_default_path (window); + docname = gedit_document_get_short_name_for_display (doc); + + if (default_path != NULL) + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (save_dialog), + default_path); + + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog), + docname); + + g_free (docname); + } + + /* Set suggested encoding */ + encoding = gedit_document_get_encoding (doc); + g_return_if_fail (encoding != NULL); + + gedit_file_chooser_dialog_set_encoding (GEDIT_FILE_CHOOSER_DIALOG (save_dialog), + encoding); + + + g_object_set_data (G_OBJECT (save_dialog), + GEDIT_TAB_TO_SAVE_AS, + tab); + + g_signal_connect (save_dialog, + "response", + G_CALLBACK (save_dialog_response_cb), + window); + + gtk_widget_show (save_dialog); +} + +static void +file_save (GeditTab *tab, + GeditWindow *window) +{ + GeditDocument *doc; + gchar *uri_for_display; + + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + if (gedit_document_is_untitled (doc)) + { + gedit_debug_message (DEBUG_COMMANDS, "Untitled"); + + file_save_as (tab, window); + + return; + } + + uri_for_display = gedit_document_get_uri_for_display (doc); + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Saving file '%s'\342\200\246"), + uri_for_display); + + g_free (uri_for_display); + + _gedit_tab_save (tab); +} + +void +gedit_cmd_file_save (GtkAction *action, + GeditWindow *window) +{ + GeditTab *tab; + + gedit_debug (DEBUG_COMMANDS); + + tab = gedit_window_get_active_tab (window); + if (tab == NULL) + return; + + file_save (tab, window); +} + +void +gedit_cmd_file_save_as (GtkAction *action, + GeditWindow *window) +{ + GeditTab *tab; + + gedit_debug (DEBUG_COMMANDS); + + tab = gedit_window_get_active_tab (window); + if (tab == NULL) + return; + + file_save_as (tab, window); +} + +/* + * The docs in the list must belong to the same GeditWindow. + */ +void +_gedit_cmd_file_save_documents_list (GeditWindow *window, + GList *docs) +{ + GList *l; + GSList *tabs_to_save_as = NULL; + + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (!(gedit_window_get_state (window) & + (GEDIT_WINDOW_STATE_PRINTING | + GEDIT_WINDOW_STATE_SAVING_SESSION))); + + l = docs; + while (l != NULL) + { + GeditDocument *doc; + GeditTab *t; + GeditTabState state; + + g_return_if_fail (GEDIT_IS_DOCUMENT (l->data)); + + doc = GEDIT_DOCUMENT (l->data); + t = gedit_tab_get_from_document (doc); + state = gedit_tab_get_state (t); + + g_return_if_fail (state != GEDIT_TAB_STATE_PRINTING); + g_return_if_fail (state != GEDIT_TAB_STATE_PRINT_PREVIEWING); + g_return_if_fail (state != GEDIT_TAB_STATE_CLOSING); + + if ((state == GEDIT_TAB_STATE_NORMAL) || + (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW) || + (state == GEDIT_TAB_STATE_GENERIC_NOT_EDITABLE)) + { + /* FIXME: manage the case of local readonly files owned by the + user is running gedit - Paolo (Dec. 8, 2005) */ + if (gedit_document_is_untitled (doc) || + gedit_document_get_readonly (doc)) + { + /* Do not save unmodified utitled or readonly documents */ + if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)) || + gedit_document_get_deleted (doc)) + { + tabs_to_save_as = g_slist_prepend (tabs_to_save_as, + t); + } + } + else + { + file_save (t, window); + } + } + else + { + /* If the state is: + - GEDIT_TAB_STATE_LOADING: we do not save since we are sure the file is unmodified + - GEDIT_TAB_STATE_REVERTING: we do not save since the user wants + to return back to the version of the file she previously saved + - GEDIT_TAB_STATE_SAVING: well, we are already saving (no need to save again) + - GEDIT_TAB_STATE_PRINTING, GEDIT_TAB_STATE_PRINT_PREVIEWING: there is not a + real reason for not saving in this case, we do not save to avoid to run + two operations using the message area at the same time (may be we can remove + this limitation in the future). Note that SaveAll, ClosAll + and Quit are unsensitive if the window state is PRINTING. + - GEDIT_TAB_STATE_GENERIC_ERROR: we do not save since the document contains + errors (I don't think this is a very frequent case, we should probably remove + this state) + - GEDIT_TAB_STATE_LOADING_ERROR: there is nothing to save + - GEDIT_TAB_STATE_REVERTING_ERROR: there is nothing to save and saving the current + document will overwrite the copy of the file the user wants to go back to + - GEDIT_TAB_STATE_SAVING_ERROR: we do not save since we just failed to save, so there is + no reason to automatically retry... we wait for user intervention + - GEDIT_TAB_STATE_CLOSING: this state is invalid in this case + */ + + gchar *uri_for_display; + + uri_for_display = gedit_document_get_uri_for_display (doc); + gedit_debug_message (DEBUG_COMMANDS, + "File '%s' not saved. State: %d", + uri_for_display, + state); + g_free (uri_for_display); + } + + l = g_list_next (l); + } + + if (tabs_to_save_as != NULL) + { + GeditTab *tab; + + tabs_to_save_as = g_slist_reverse (tabs_to_save_as ); + + g_return_if_fail (g_object_get_data (G_OBJECT (window), + GEDIT_LIST_OF_TABS_TO_SAVE_AS) == NULL); + + g_object_set_data (G_OBJECT (window), + GEDIT_LIST_OF_TABS_TO_SAVE_AS, + tabs_to_save_as); + + tab = GEDIT_TAB (tabs_to_save_as->data); + + gedit_window_set_active_tab (window, tab); + file_save_as (tab, window); + } +} + +void +gedit_cmd_file_save_all (GtkAction *action, + GeditWindow *window) +{ + GList *docs; + + gedit_debug (DEBUG_COMMANDS); + + docs = gedit_window_get_documents (window); + + _gedit_cmd_file_save_documents_list (window, docs); + + g_list_free (docs); +} + +/* File revert */ +static void +revert_dialog_response_cb (GtkDialog *dialog, + gint response_id, + GeditWindow *window) +{ + GeditTab *tab; + GeditDocument *doc; + gchar *docname; + + gedit_debug (DEBUG_COMMANDS); + + /* FIXME: we are relying on the fact that the dialog is + modal so the active tab can't be changed... + not very nice - Paolo (Oct 11, 2005) */ + tab = gedit_window_get_active_tab (window); + if (tab == NULL) + return; + + if (response_id != GTK_RESPONSE_OK) + { + gtk_widget_destroy (GTK_WIDGET (dialog)); + + return; + } + + doc = gedit_tab_get_document (tab); + docname = gedit_document_get_short_name_for_display (doc); + + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Reverting the document '%s'\342\200\246"), + docname); + + g_free (docname); + gtk_widget_destroy (GTK_WIDGET (dialog)); + + _gedit_tab_revert (tab); +} + +static GtkWidget * +revert_dialog (GeditWindow *window, + GeditDocument *doc) +{ + GtkWidget *dialog; + gchar *docname; + gchar *primary_msg; + gchar *secondary_msg; + glong seconds; + + gedit_debug (DEBUG_COMMANDS); + + docname = gedit_document_get_short_name_for_display (doc); + primary_msg = g_strdup_printf (_("Revert unsaved changes to document '%s'?"), + docname); + g_free (docname); + + seconds = MAX (1, _gedit_document_get_seconds_since_last_save_or_load (doc)); + + if (seconds < 55) + { + secondary_msg = g_strdup_printf ( + ngettext ("Changes made to the document in the last %ld second " + "will be permanently lost.", + "Changes made to the document in the last %ld seconds " + "will be permanently lost.", + seconds), + seconds); + } + else if (seconds < 75) /* 55 <= seconds < 75 */ + { + secondary_msg = g_strdup (_("Changes made to the document in the last minute " + "will be permanently lost.")); + } + else if (seconds < 110) /* 75 <= seconds < 110 */ + { + secondary_msg = g_strdup_printf ( + ngettext ("Changes made to the document in the last minute and " + "%ld second will be permanently lost.", + "Changes made to the document in the last minute and " + "%ld seconds will be permanently lost.", + seconds - 60 ), + seconds - 60); + } + else if (seconds < 3600) + { + secondary_msg = g_strdup_printf ( + ngettext ("Changes made to the document in the last %ld minute " + "will be permanently lost.", + "Changes made to the document in the last %ld minutes " + "will be permanently lost.", + seconds / 60), + seconds / 60); + } + else if (seconds < 7200) + { + gint minutes; + seconds -= 3600; + + minutes = seconds / 60; + if (minutes < 5) + { + secondary_msg = g_strdup (_("Changes made to the document in the last hour " + "will be permanently lost.")); + } + else + { + secondary_msg = g_strdup_printf ( + ngettext ("Changes made to the document in the last hour and " + "%d minute will be permanently lost.", + "Changes made to the document in the last hour and " + "%d minutes will be permanently lost.", + minutes), + minutes); + } + } + else + { + gint hours; + + hours = seconds / 3600; + + secondary_msg = g_strdup_printf ( + ngettext ("Changes made to the document in the last hour " + "will be permanently lost.", + "Changes made to the document in the last %d hours " + "will be permanently lost.", + hours), + hours); + } + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + primary_msg); + + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + secondary_msg); + g_free (primary_msg); + g_free (secondary_msg); + + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + + gedit_dialog_add_button (GTK_DIALOG (dialog), + _("_Revert"), + GTK_STOCK_REVERT_TO_SAVED, + GTK_RESPONSE_OK); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_CANCEL); + + return dialog; +} + +void +gedit_cmd_file_revert (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + GtkWidget *dialog; + GtkWindowGroup *wg; + + gedit_debug (DEBUG_COMMANDS); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + g_return_if_fail (!gedit_document_is_untitled (doc)); + + dialog = revert_dialog (window, doc); + + wg = gedit_window_get_group (window); + + gtk_window_group_add_window (wg, GTK_WINDOW (dialog)); + + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + g_signal_connect (dialog, + "response", + G_CALLBACK (revert_dialog_response_cb), + window); + + gtk_widget_show (dialog); +} + +/* Close tab */ +static gboolean +really_close_tab (GeditTab *tab) +{ + GtkWidget *toplevel; + GeditWindow *window; + + gedit_debug (DEBUG_COMMANDS); + + g_return_val_if_fail (gedit_tab_get_state (tab) == GEDIT_TAB_STATE_CLOSING, + FALSE); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab)); + g_return_val_if_fail (GEDIT_IS_WINDOW (toplevel), FALSE); + + window = GEDIT_WINDOW (toplevel); + + gedit_window_close_tab (window, tab); + + if (gedit_window_get_active_tab (window) == NULL) + { + gboolean is_quitting; + + is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), + GEDIT_IS_QUITTING)); + + if (is_quitting) + gtk_widget_destroy (GTK_WIDGET (window)); + } + + return FALSE; +} + +static void +tab_state_changed_while_saving (GeditTab *tab, + GParamSpec *pspec, + GeditWindow *window) +{ + GeditTabState ts; + + ts = gedit_tab_get_state (tab); + + gedit_debug_message (DEBUG_COMMANDS, "State while saving: %d\n", ts); + + /* When the state become NORMAL, it means the saving operation is + finished */ + if (ts == GEDIT_TAB_STATE_NORMAL) + { + GeditDocument *doc; + + g_signal_handlers_disconnect_by_func (tab, + G_CALLBACK (tab_state_changed_while_saving), + window); + + doc = gedit_tab_get_document (tab); + g_return_if_fail (doc != NULL); + + /* If the saving operation failed or was interrupted, then the + document is still "modified" -> do not close the tab */ + if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)) || + gedit_document_get_deleted (doc)) + return; + + /* Close the document only if it has been succesfully saved. + Tab state is set to CLOSING (it is a state without exiting + transitions) and the tab is closed in a idle handler */ + _gedit_tab_mark_for_closing (tab); + + g_idle_add_full (G_PRIORITY_HIGH_IDLE, + (GSourceFunc)really_close_tab, + tab, + NULL); + } +} + +static void +save_and_close (GeditTab *tab, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + /* Trace tab state changes */ + g_signal_connect (tab, + "notify::state", + G_CALLBACK (tab_state_changed_while_saving), + window); + + file_save (tab, window); +} + +static void +save_as_and_close (GeditTab *tab, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + g_object_set_data (G_OBJECT (tab), + GEDIT_IS_CLOSING_TAB, + NULL); + + /* Trace tab state changes */ + g_signal_connect (tab, + "notify::state", + G_CALLBACK (tab_state_changed_while_saving), + window); + + gedit_window_set_active_tab (window, tab); + file_save_as (tab, window); +} + +static void +save_and_close_all_documents (const GList *docs, + GeditWindow *window) +{ + GList *tabs; + GList *l; + GSList *sl; + GSList *tabs_to_save_as; + GSList *tabs_to_save_and_close; + GList *tabs_to_close; + + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (!(gedit_window_get_state (window) & GEDIT_WINDOW_STATE_PRINTING)); + + tabs = gtk_container_get_children ( + GTK_CONTAINER (_gedit_window_get_notebook (window))); + + tabs_to_save_as = NULL; + tabs_to_save_and_close = NULL; + tabs_to_close = NULL; + + l = tabs; + while (l != NULL) + { + GeditTab *t; + GeditTabState state; + GeditDocument *doc; + + t = GEDIT_TAB (l->data); + + state = gedit_tab_get_state (t); + doc = gedit_tab_get_document (t); + + /* If the state is: ([*] invalid states) + - GEDIT_TAB_STATE_NORMAL: close (and if needed save) + - GEDIT_TAB_STATE_LOADING: close, we are sure the file is unmodified + - GEDIT_TAB_STATE_REVERTING: since the user wants + to return back to the version of the file she previously saved, we can close + without saving (CHECK: are we sure this is the right behavior, suppose the case + the original file has been deleted) + - [*] GEDIT_TAB_STATE_SAVING: invalid, ClosAll + and Quit are unsensitive if the window state is SAVING. + - [*] GEDIT_TAB_STATE_PRINTING, GEDIT_TAB_STATE_PRINT_PREVIEWING: there is not a + real reason for not closing in this case, we do not save to avoid to run + two operations using the message area at the same time (may be we can remove + this limitation in the future). Note that ClosAll + and Quit are unsensitive if the window state is PRINTING. + - GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW: close (and if needed save) + - GEDIT_TAB_STATE_LOADING_ERROR: close without saving (if the state is LOADING_ERROR then the + document is not modified) + - GEDIT_TAB_STATE_REVERTING_ERROR: we do not close since the document contains errors + - GEDIT_TAB_STATE_SAVING_ERROR: we do not close since the document contains errors + - GEDIT_TAB_STATE_GENERIC_ERROR: we do not close since the document contains + errors (CHECK: we should problably remove this state) + - [*] GEDIT_TAB_STATE_CLOSING: this state is invalid in this case + */ + + g_return_if_fail (state != GEDIT_TAB_STATE_PRINTING); + g_return_if_fail (state != GEDIT_TAB_STATE_PRINT_PREVIEWING); + g_return_if_fail (state != GEDIT_TAB_STATE_CLOSING); + g_return_if_fail (state != GEDIT_TAB_STATE_SAVING); + + if ((state != GEDIT_TAB_STATE_SAVING_ERROR) && + (state != GEDIT_TAB_STATE_GENERIC_ERROR) && + (state != GEDIT_TAB_STATE_REVERTING_ERROR)) + { + if ((g_list_index ((GList *)docs, doc) >= 0) && + (state != GEDIT_TAB_STATE_LOADING) && + (state != GEDIT_TAB_STATE_LOADING_ERROR) && + (state != GEDIT_TAB_STATE_REVERTING)) /* CHECK: is this the right behavior with REVERTING ?*/ + { + /* The document must be saved before closing */ + g_return_if_fail (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)) || + gedit_document_get_deleted (doc)); + + /* FIXME: manage the case of local readonly files owned by the + user is running gedit - Paolo (Dec. 8, 2005) */ + if (gedit_document_is_untitled (doc) || + gedit_document_get_readonly (doc)) + { + g_object_set_data (G_OBJECT (t), + GEDIT_IS_CLOSING_TAB, + GBOOLEAN_TO_POINTER (TRUE)); + + tabs_to_save_as = g_slist_prepend (tabs_to_save_as, + t); + } + else + { + tabs_to_save_and_close = g_slist_prepend (tabs_to_save_and_close, + t); + } + } + else + { + /* The document must be closed without saving */ + tabs_to_close = g_list_prepend (tabs_to_close, + t); + } + } + + l = g_list_next (l); + } + + g_list_free (tabs); + + /* Close all tabs to close (in a sync way) */ + gedit_window_close_tabs (window, tabs_to_close); + g_list_free (tabs_to_close); + + /* Save and close all the files in tabs_to_save_and_close */ + sl = tabs_to_save_and_close; + while (sl != NULL) + { + save_and_close (GEDIT_TAB (sl->data), + window); + sl = g_slist_next (sl); + } + g_slist_free (tabs_to_save_and_close); + + /* Save As and close all the files in tabs_to_save_as */ + if (tabs_to_save_as != NULL) + { + GeditTab *tab; + + tabs_to_save_as = g_slist_reverse (tabs_to_save_as ); + + g_return_if_fail (g_object_get_data (G_OBJECT (window), + GEDIT_LIST_OF_TABS_TO_SAVE_AS) == NULL); + + g_object_set_data (G_OBJECT (window), + GEDIT_LIST_OF_TABS_TO_SAVE_AS, + tabs_to_save_as); + + tab = GEDIT_TAB (tabs_to_save_as->data); + + save_as_and_close (tab, window); + } +} + +static void +save_and_close_document (const GList *docs, + GeditWindow *window) +{ + GeditTab *tab; + + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (docs->next == NULL); + + tab = gedit_tab_get_from_document (GEDIT_DOCUMENT (docs->data)); + g_return_if_fail (tab != NULL); + + save_and_close (tab, window); +} + +static void +close_all_tabs (GeditWindow *window) +{ + gboolean is_quitting; + + gedit_debug (DEBUG_COMMANDS); + + /* There is no document to save -> close all tabs */ + gedit_window_close_all_tabs (window); + + is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), + GEDIT_IS_QUITTING)); + + if (is_quitting) + gtk_widget_destroy (GTK_WIDGET (window)); + + return; +} + +static void +close_document (GeditWindow *window, + GeditDocument *doc) +{ + GeditTab *tab; + + gedit_debug (DEBUG_COMMANDS); + + tab = gedit_tab_get_from_document (doc); + g_return_if_fail (tab != NULL); + + gedit_window_close_tab (window, tab); +} + +static void +close_confirmation_dialog_response_handler (GeditCloseConfirmationDialog *dlg, + gint response_id, + GeditWindow *window) +{ + const GList *unsaved_documents; + const GList *selected_documents; + gboolean is_closing_all; + + gedit_debug (DEBUG_COMMANDS); + + is_closing_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), + GEDIT_IS_CLOSING_ALL)); + + gtk_widget_hide (GTK_WIDGET (dlg)); + + unsaved_documents = gedit_close_confirmation_dialog_get_unsaved_documents (dlg); + + switch (response_id) + { + case GTK_RESPONSE_YES: /* Save and Close */ + selected_documents = gedit_close_confirmation_dialog_get_selected_documents (dlg); + if (selected_documents == NULL) + { + if (is_closing_all) + { + /* There is no document to save -> close all tabs */ + /* We call gtk_widget_destroy before close_all_tabs + * because close_all_tabs could destroy the gedit window */ + gtk_widget_destroy (GTK_WIDGET (dlg)); + + close_all_tabs (window); + + return; + } + else + g_return_if_reached (); + } + else + { + if (is_closing_all) + { + save_and_close_all_documents (selected_documents, + window); + } + else + { + save_and_close_document (selected_documents, + window); + } + } + break; + + case GTK_RESPONSE_NO: /* Close without Saving */ + if (is_closing_all) + { + /* We call gtk_widget_destroy before close_all_tabs + * because close_all_tabs could destroy the gedit window */ + gtk_widget_destroy (GTK_WIDGET (dlg)); + + close_all_tabs (window); + + return; + } + else + { + g_return_if_fail (unsaved_documents->next == NULL); + + close_document (window, + GEDIT_DOCUMENT (unsaved_documents->data)); + } + + break; + default: /* Do not close */ + + /* Reset is_quitting flag */ + g_object_set_data (G_OBJECT (window), + GEDIT_IS_QUITTING, + GBOOLEAN_TO_POINTER (FALSE)); + break; + } + + gtk_widget_destroy (GTK_WIDGET (dlg)); +} + +/* Returns TRUE if the tab can be immediately closed */ +static gboolean +tab_can_close (GeditTab *tab, + GtkWindow *window) +{ + GeditDocument *doc; + + gedit_debug (DEBUG_COMMANDS); + + doc = gedit_tab_get_document (tab); + + if (!_gedit_tab_can_close (tab)) + { + GtkWidget *dlg; + + dlg = gedit_close_confirmation_dialog_new_single ( + window, + doc, + FALSE); + + g_signal_connect (dlg, + "response", + G_CALLBACK (close_confirmation_dialog_response_handler), + window); + + gtk_widget_show (dlg); + + return FALSE; + } + + return TRUE; +} + +/* CHECK: we probably need this one public for plugins... + * maybe even a _list variant. Or maybe it's better make + * gedit_window_close_tab always run the confirm dialog? + * we should not allow closing a tab without resetting the + * GEDIT_IS_CLOSING_ALL flag! + */ +void +_gedit_cmd_file_close_tab (GeditTab *tab, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (GTK_WIDGET (window) == gtk_widget_get_toplevel (GTK_WIDGET (tab))); + + g_object_set_data (G_OBJECT (window), + GEDIT_IS_CLOSING_ALL, + GBOOLEAN_TO_POINTER (FALSE)); + + g_object_set_data (G_OBJECT (window), + GEDIT_IS_QUITTING, + GBOOLEAN_TO_POINTER (FALSE)); + + if (tab_can_close (tab, GTK_WINDOW (window))) + gedit_window_close_tab (window, tab); +} + +void +gedit_cmd_file_close (GtkAction *action, + GeditWindow *window) +{ + GeditTab *active_tab; + + gedit_debug (DEBUG_COMMANDS); + + active_tab = gedit_window_get_active_tab (window); + if (active_tab == NULL) + return; + + _gedit_cmd_file_close_tab (active_tab, window); +} + +/* Close all tabs */ +static void +file_close_all (GeditWindow *window, + gboolean is_quitting) +{ + GList *unsaved_docs; + GtkWidget *dlg; + + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (!(gedit_window_get_state (window) & + (GEDIT_WINDOW_STATE_SAVING | + GEDIT_WINDOW_STATE_PRINTING | + GEDIT_WINDOW_STATE_SAVING_SESSION))); + + g_object_set_data (G_OBJECT (window), + GEDIT_IS_CLOSING_ALL, + GBOOLEAN_TO_POINTER (TRUE)); + + g_object_set_data (G_OBJECT (window), + GEDIT_IS_QUITTING, + GBOOLEAN_TO_POINTER (is_quitting)); + + unsaved_docs = gedit_window_get_unsaved_documents (window); + + if (unsaved_docs == NULL) + { + /* There is no document to save -> close all tabs */ + gedit_window_close_all_tabs (window); + + if (is_quitting) + gtk_widget_destroy (GTK_WIDGET (window)); + + return; + } + + if (unsaved_docs->next == NULL) + { + /* There is only one unsaved document */ + GeditTab *tab; + GeditDocument *doc; + + doc = GEDIT_DOCUMENT (unsaved_docs->data); + + tab = gedit_tab_get_from_document (doc); + g_return_if_fail (tab != NULL); + + gedit_window_set_active_tab (window, tab); + + dlg = gedit_close_confirmation_dialog_new_single ( + GTK_WINDOW (window), + doc, + FALSE); + } + else + { + dlg = gedit_close_confirmation_dialog_new (GTK_WINDOW (window), + unsaved_docs, + FALSE); + } + + g_list_free (unsaved_docs); + + g_signal_connect (dlg, + "response", + G_CALLBACK (close_confirmation_dialog_response_handler), + window); + + gtk_widget_show (dlg); +} + +void +gedit_cmd_file_close_all (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (!(gedit_window_get_state (window) & + (GEDIT_WINDOW_STATE_SAVING | + GEDIT_WINDOW_STATE_PRINTING | + GEDIT_WINDOW_STATE_SAVING_SESSION))); + + file_close_all (window, FALSE); +} + +/* Quit */ +void +gedit_cmd_file_quit (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + g_return_if_fail (!(gedit_window_get_state (window) & + (GEDIT_WINDOW_STATE_SAVING | + GEDIT_WINDOW_STATE_PRINTING | + GEDIT_WINDOW_STATE_SAVING_SESSION))); + + file_close_all (window, TRUE); +} diff --git a/gedit/gedit-commands-help.c b/gedit/gedit-commands-help.c new file mode 100644 index 00000000..785f16da --- /dev/null +++ b/gedit/gedit-commands-help.c @@ -0,0 +1,103 @@ +/* + * gedit-help-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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "gedit-commands.h" +#include "gedit-debug.h" +#include "gedit-help.h" + +void +gedit_cmd_help_contents (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + gedit_help_display (GTK_WINDOW (window), NULL, NULL); +} + +void +gedit_cmd_help_about (GtkAction *action, + GeditWindow *window) +{ + static const gchar * const authors[] = { + "Paolo Maggi ", + "Paolo Borelli ", + "James Willcox ", + "Chema Celorio", + "Federico Mena Quintero ", + NULL + }; + + static const gchar * const documenters[] = { + "Sun GNOME Documentation Team ", + "Eric Baudais ", + NULL + }; + + static const gchar copyright[] = \ + "Copyright \xc2\xa9 1998-2000 Evan Lawrence, Alex Robert\n" + "Copyright \xc2\xa9 2000-2002 Chema Celorio, Paolo Maggi\n" + "Copyright \xc2\xa9 2003-2005 Paolo Maggi"; + + static const gchar comments[] = \ + N_("gedit is a small and lightweight text editor for the " + "GNOME Desktop"); + + static GdkPixbuf *logo = NULL; + + gedit_debug (DEBUG_COMMANDS); + + if(!logo) + { + logo = gdk_pixbuf_new_from_file ( + GNOME_ICONDIR "/gedit-logo.png", + NULL); + } + + gtk_show_about_dialog (GTK_WINDOW (window), + "authors", authors, + "comments", _(comments), + "copyright", copyright, + "documenters", documenters, + "logo", logo, + "translator-credits", _("translator-credits"), + "version", VERSION, + "website", "http://www.gedit.org", + "name", _("gedit"), + NULL); +} diff --git a/gedit/gedit-commands-search.c b/gedit/gedit-commands-search.c new file mode 100644 index 00000000..293020d8 --- /dev/null +++ b/gedit/gedit-commands-search.c @@ -0,0 +1,727 @@ +/* + * gedit-search-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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "gedit-commands.h" +#include "gedit-debug.h" +#include "gedit-statusbar.h" +#include "gedit-window.h" +#include "gedit-window-private.h" +#include "gedit-utils.h" +#include "dialogs/gedit-search-dialog.h" + + +#define GEDIT_SEARCH_DIALOG_KEY "gedit-search-dialog-key" +#define GEDIT_LAST_SEARCH_DATA_KEY "gedit-last-search-data-key" + + +/* data stored in the document + * to persist the last searched + * words and options + */ +typedef struct _LastSearchData LastSearchData; +struct _LastSearchData +{ + gchar *find_text; + gchar *replace_text; + + gint match_case :1; + gint entire_word :1; + gint backwards :1; + gint wrap_around :1; +}; + +static void +last_search_data_free (LastSearchData *data) +{ + g_free (data->find_text); + g_free (data->replace_text); + g_free (data); +} + +static void +last_search_data_set (LastSearchData *data, + GeditSearchDialog *dialog) +{ + const gchar *str; + + str = gedit_search_dialog_get_search_text (dialog); + if (str != NULL && *str != '\0') + { + g_free (data->find_text); + data->find_text = g_strdup (str); + } + + str = gedit_search_dialog_get_replace_text (dialog); + if (str != NULL && *str != '\0') + { + g_free (data->replace_text); + data->replace_text = g_strdup (str); + } + + data->match_case = gedit_search_dialog_get_match_case (dialog); + data->entire_word = gedit_search_dialog_get_entire_word (dialog); + data->backwards = gedit_search_dialog_get_backwards (dialog); + data->wrap_around = gedit_search_dialog_get_wrap_around (dialog); +} + +static void +search_dialog_set_last_find_text (GeditSearchDialog *dialog, + LastSearchData *data) +{ + if (data->find_text) + gedit_search_dialog_set_search_text (dialog, data->find_text); +} + +static void +search_dialog_set_last_replace_text (GeditSearchDialog *dialog, + LastSearchData *data) +{ + if (data->replace_text) + gedit_search_dialog_set_search_text (dialog, data->replace_text); +} + +static void +search_dialog_set_last_options (GeditSearchDialog *dialog, + LastSearchData *data) +{ + gedit_search_dialog_set_match_case (dialog, data->match_case); + gedit_search_dialog_set_entire_word (dialog, data->entire_word); + gedit_search_dialog_set_backwards (dialog, data->backwards); + gedit_search_dialog_set_wrap_around (dialog, data->wrap_around); +} + +static void +restore_last_searched_data (GeditSearchDialog *dialog, + GeditDocument *doc) +{ + LastSearchData *data; + + data = g_object_get_data (G_OBJECT (doc), GEDIT_LAST_SEARCH_DATA_KEY); + + if (data == NULL) + { + data = g_new0 (LastSearchData, 1); + last_search_data_set (data, dialog); + + g_object_set_data (G_OBJECT (doc), + GEDIT_LAST_SEARCH_DATA_KEY, + data); + + g_object_weak_ref (G_OBJECT (doc), + (GWeakNotify) last_search_data_free, + data); + } + else + { + last_search_data_set (data, dialog); + } +} + +/* Use occurences only for Replace All */ +static void +phrase_found (GeditWindow *window, + gint occurrences) +{ + if (occurrences > 0) + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + ngettext("Found and replaced %d occurrence.", + "Found and replaced %d occurrences.", + occurrences), + occurrences); + else + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + " "); +} + +static void +phrase_not_found (GeditWindow *window) +{ + gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Phrase not found")); +} + +static gboolean +run_search (GeditView *view, + gboolean wrap_around, + gboolean search_backwards) +{ + GeditDocument *doc; + GtkTextIter start_iter; + GtkTextIter match_start; + GtkTextIter match_end; + gboolean found = FALSE; + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + + if (!search_backwards) + { + gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + NULL, + &start_iter); + + found = gedit_document_search_forward (doc, + &start_iter, + NULL, + &match_start, + &match_end); + } + else + { + gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &start_iter, + NULL); + + found = gedit_document_search_backward (doc, + NULL, + &start_iter, + &match_start, + &match_end); + } + + if (!found && wrap_around) + { + if (!search_backwards) + found = gedit_document_search_forward (doc, + NULL, + NULL, /* FIXME: set the end_inter */ + &match_start, + &match_end); + else + found = gedit_document_search_backward (doc, + NULL, /* FIXME: set the start_inter */ + NULL, + &match_start, + &match_end); + } + + if (found) + { + gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), + &match_start); + + gtk_text_buffer_move_mark_by_name (GTK_TEXT_BUFFER (doc), + "selection_bound", + &match_end); + + gedit_view_scroll_to_cursor (view); + } + else + { + gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), + &start_iter); + } + + return found; +} + +static void +do_find (GeditSearchDialog *dialog, + GeditWindow *window) +{ + GeditView *active_view; + GeditDocument *doc; + gchar *search_text; + const gchar *entry_text; + gboolean match_case; + gboolean entire_word; + gboolean wrap_around; + gboolean search_backwards; + guint flags = 0; + guint old_flags = 0; + gboolean found; + + /* TODO: make the dialog insensitive when all the tabs are closed + * and assert here that the view is not NULL */ + active_view = gedit_window_get_active_view (window); + if (active_view == NULL) + return; + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view))); + + entry_text = gedit_search_dialog_get_search_text (dialog); + + match_case = gedit_search_dialog_get_match_case (dialog); + entire_word = gedit_search_dialog_get_entire_word (dialog); + search_backwards = gedit_search_dialog_get_backwards (dialog); + wrap_around = gedit_search_dialog_get_wrap_around (dialog); + + GEDIT_SEARCH_SET_CASE_SENSITIVE (flags, match_case); + GEDIT_SEARCH_SET_ENTIRE_WORD (flags, entire_word); + + search_text = gedit_document_get_search_text (doc, &old_flags); + + if ((search_text == NULL) || + (strcmp (search_text, entry_text) != 0) || + (flags != old_flags)) + { + gedit_document_set_search_text (doc, entry_text, flags); + } + + g_free (search_text); + + found = run_search (active_view, + wrap_around, + search_backwards); + + if (found) + phrase_found (window, 0); + else + phrase_not_found (window); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE, + found); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, + found); + + restore_last_searched_data (dialog, doc); +} + +/* FIXME: move in gedit-document.c and share it with gedit-view */ +static gboolean +get_selected_text (GtkTextBuffer *doc, + gchar **selected_text, + gint *len) +{ + GtkTextIter start, end; + + g_return_val_if_fail (selected_text != NULL, FALSE); + g_return_val_if_fail (*selected_text == NULL, FALSE); + + if (!gtk_text_buffer_get_selection_bounds (doc, &start, &end)) + { + if (len != NULL) + len = 0; + + return FALSE; + } + + *selected_text = gtk_text_buffer_get_slice (doc, &start, &end, TRUE); + + if (len != NULL) + *len = g_utf8_strlen (*selected_text, -1); + + return TRUE; +} + +static void +replace_selected_text (GtkTextBuffer *buffer, + const gchar *replace) +{ + g_return_if_fail (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL)); + g_return_if_fail (replace != NULL); + + gtk_text_buffer_begin_user_action (buffer); + + gtk_text_buffer_delete_selection (buffer, FALSE, TRUE); + + gtk_text_buffer_insert_at_cursor (buffer, replace, strlen (replace)); + + gtk_text_buffer_end_user_action (buffer); +} + +static void +do_replace (GeditSearchDialog *dialog, + GeditWindow *window) +{ + GeditDocument *doc; + const gchar *search_entry_text; + const gchar *replace_entry_text; + gchar *unescaped_search_text; + gchar *unescaped_replace_text; + gchar *selected_text = NULL; + gboolean match_case; + gboolean search_backwards; + + doc = gedit_window_get_active_document (window); + if (doc == NULL) + return; + + search_entry_text = gedit_search_dialog_get_search_text (dialog); + g_return_if_fail ((search_entry_text) != NULL); + g_return_if_fail ((*search_entry_text) != '\0'); + + /* replace text may be "", we just delete */ + replace_entry_text = gedit_search_dialog_get_replace_text (dialog); + g_return_if_fail ((search_entry_text) != NULL); + + unescaped_search_text = gedit_utils_unescape_search_text (search_entry_text); + + get_selected_text (GTK_TEXT_BUFFER (doc), + &selected_text, + NULL); + + match_case = gedit_search_dialog_get_match_case (dialog); + search_backwards = gedit_search_dialog_get_backwards (dialog); + + if ((selected_text == NULL) || + (match_case && (strcmp (selected_text, unescaped_search_text) != 0)) || + (!match_case && !g_utf8_caselessnmatch (selected_text, + unescaped_search_text, + strlen (selected_text), + strlen (unescaped_search_text)) != 0)) + { + do_find (dialog, window); + g_free (unescaped_search_text); + g_free (selected_text); + + return; + } + + unescaped_replace_text = gedit_utils_unescape_search_text (replace_entry_text); + replace_selected_text (GTK_TEXT_BUFFER (doc), unescaped_replace_text); + + g_free (unescaped_search_text); + g_free (selected_text); + g_free (unescaped_replace_text); + + do_find (dialog, window); +} + +static void +do_replace_all (GeditSearchDialog *dialog, + GeditWindow *window) +{ + GeditView *active_view; + GeditDocument *doc; + const gchar *search_entry_text; + const gchar *replace_entry_text; + gboolean match_case; + gboolean entire_word; + guint flags = 0; + gint count; + + active_view = gedit_window_get_active_view (window); + if (active_view == NULL) + return; + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view))); + + search_entry_text = gedit_search_dialog_get_search_text (dialog); + g_return_if_fail ((search_entry_text) != NULL); + g_return_if_fail ((*search_entry_text) != '\0'); + + /* replace text may be "", we just delete all occurrencies */ + replace_entry_text = gedit_search_dialog_get_replace_text (dialog); + g_return_if_fail ((search_entry_text) != NULL); + + match_case = gedit_search_dialog_get_match_case (dialog); + entire_word = gedit_search_dialog_get_entire_word (dialog); + + GEDIT_SEARCH_SET_CASE_SENSITIVE (flags, match_case); + GEDIT_SEARCH_SET_ENTIRE_WORD (flags, entire_word); + + count = gedit_document_replace_all (doc, + search_entry_text, + replace_entry_text, + flags); + + if (count > 0) + { + phrase_found (window, count); + } + else + { + phrase_not_found (window); + } + + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE, + FALSE); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, + FALSE); + + restore_last_searched_data (dialog, doc); +} + +static void +search_dialog_response_cb (GeditSearchDialog *dialog, + gint response_id, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + switch (response_id) + { + case GEDIT_SEARCH_DIALOG_FIND_RESPONSE: + do_find (dialog, window); + break; + case GEDIT_SEARCH_DIALOG_REPLACE_RESPONSE: + do_replace (dialog, window); + break; + case GEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE: + do_replace_all (dialog, window); + break; + default: + gtk_widget_destroy (GTK_WIDGET (dialog)); + } +} + +static void +search_dialog_destroyed (GeditWindow *window, + GeditSearchDialog *dialog) +{ + gedit_debug (DEBUG_COMMANDS); + + g_object_set_data (G_OBJECT (window), + GEDIT_SEARCH_DIALOG_KEY, + NULL); +} + +void +gedit_cmd_search_find (GtkAction *action, + GeditWindow *window) +{ + gpointer data; + GtkWidget *search_dialog; + GeditDocument *doc; + gboolean selection_exists; + gchar *find_text = NULL; + gint sel_len; + LastSearchData *last_search_data; + + gedit_debug (DEBUG_COMMANDS); + + data = g_object_get_data (G_OBJECT (window), GEDIT_SEARCH_DIALOG_KEY); + + if (data != NULL) + { + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (data)); + + /* note that we rise a search&replace dialog if + * it is already open + */ + + gtk_window_present (GTK_WINDOW (data)); + + return; + } + + search_dialog = gedit_search_dialog_new (GTK_WINDOW (window), + FALSE); + + g_object_set_data (G_OBJECT (window), + GEDIT_SEARCH_DIALOG_KEY, + search_dialog); + + g_object_weak_ref (G_OBJECT (search_dialog), + (GWeakNotify) search_dialog_destroyed, + window); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + last_search_data = g_object_get_data (G_OBJECT (doc), + GEDIT_LAST_SEARCH_DATA_KEY); + + selection_exists = get_selected_text (GTK_TEXT_BUFFER (doc), + &find_text, + &sel_len); + + if (selection_exists && find_text != NULL && sel_len < 80) + { + gedit_search_dialog_set_search_text (GEDIT_SEARCH_DIALOG (search_dialog), + find_text); + g_free (find_text); + } + else + { + g_free (find_text); + + if (last_search_data != NULL) + search_dialog_set_last_find_text (GEDIT_SEARCH_DIALOG (search_dialog), + last_search_data); + } + + if (last_search_data != NULL) + search_dialog_set_last_replace_text (GEDIT_SEARCH_DIALOG (search_dialog), + last_search_data); + + if (last_search_data != NULL) + search_dialog_set_last_options (GEDIT_SEARCH_DIALOG (search_dialog), + last_search_data); + + g_signal_connect (search_dialog, + "response", + G_CALLBACK (search_dialog_response_cb), + window); + + gtk_widget_show (search_dialog); +} + +void +gedit_cmd_search_replace (GtkAction *action, + GeditWindow *window) +{ + gpointer data; + GtkWidget *replace_dialog; + GeditDocument *doc; + gboolean selection_exists; + gchar *find_text = NULL; + gint sel_len; + LastSearchData *last_search_data; + + gedit_debug (DEBUG_COMMANDS); + + data = g_object_get_data (G_OBJECT (window), GEDIT_SEARCH_DIALOG_KEY); + + if (data != NULL) + { + g_return_if_fail (GEDIT_IS_SEARCH_DIALOG (data)); + + /* turn the dialog into a replace dialog if needed */ + if (!gedit_search_dialog_get_show_replace (GEDIT_SEARCH_DIALOG (data))) + gedit_search_dialog_set_show_replace (GEDIT_SEARCH_DIALOG (data), + TRUE); + + gtk_window_present (GTK_WINDOW (data)); + + return; + } + + replace_dialog = gedit_search_dialog_new (GTK_WINDOW (window), + TRUE); + + g_object_set_data (G_OBJECT (window), + GEDIT_SEARCH_DIALOG_KEY, + replace_dialog); + + g_object_weak_ref (G_OBJECT (replace_dialog), + (GWeakNotify) search_dialog_destroyed, + window); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + last_search_data = g_object_get_data (G_OBJECT (doc), + GEDIT_LAST_SEARCH_DATA_KEY); + + + selection_exists = get_selected_text (GTK_TEXT_BUFFER (doc), + &find_text, + &sel_len); + + if (selection_exists && find_text != NULL && sel_len < 80) + { + gedit_search_dialog_set_search_text (GEDIT_SEARCH_DIALOG (replace_dialog), + find_text); + g_free (find_text); + } + else + { + g_free (find_text); + + if (last_search_data != NULL) + search_dialog_set_last_find_text (GEDIT_SEARCH_DIALOG (replace_dialog), + last_search_data); + } + + if (last_search_data != NULL) + search_dialog_set_last_replace_text (GEDIT_SEARCH_DIALOG (replace_dialog), + last_search_data); + + if (last_search_data != NULL) + search_dialog_set_last_options (GEDIT_SEARCH_DIALOG (replace_dialog), + last_search_data); + + g_signal_connect (replace_dialog, + "response", + G_CALLBACK (search_dialog_response_cb), + window); + + gtk_widget_show (replace_dialog); +} + +static void +do_find_again (GeditWindow *window, + gboolean backward) +{ + GeditView *active_view; + + active_view = gedit_window_get_active_view (window); + g_return_if_fail (active_view != NULL); + + run_search (active_view, + TRUE, + backward); +} + +void +gedit_cmd_search_find_next (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + do_find_again (window, FALSE); +} + +void +gedit_cmd_search_find_prev (GtkAction *action, + GeditWindow *window) +{ + gedit_debug (DEBUG_COMMANDS); + + do_find_again (window, TRUE); +} + +void +gedit_cmd_search_goto_line (GtkAction *action, + GeditWindow *window) +{ + GeditView *active_view; + + gedit_debug (DEBUG_COMMANDS); + + active_view = gedit_window_get_active_view (window); + if (active_view == NULL) + return; + + /* goto line is builtin in GeditView, just activate + * the corrisponding binding. + */ + gtk_bindings_activate (GTK_OBJECT (active_view), + GDK_i, + GDK_CONTROL_MASK); +} diff --git a/gedit/gedit-commands-view.c b/gedit/gedit-commands-view.c new file mode 100644 index 00000000..0414e543 --- /dev/null +++ b/gedit/gedit-commands-view.c @@ -0,0 +1,93 @@ +/* + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "gedit-commands.h" +#include "gedit-window.h" +#include "gedit-debug.h" + +void +gedit_cmd_view_show_toolbar (GtkAction *action, + GeditWindow *window) +{ + gboolean visible; + + gedit_debug (DEBUG_COMMANDS); + + visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + + _gedit_window_set_toolbar_visible (window, visible); +} + +void +gedit_cmd_view_show_statusbar (GtkAction *action, + GeditWindow *window) +{ + gboolean visible; + + gedit_debug (DEBUG_COMMANDS); + + visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + + _gedit_window_set_statusbar_visible (window, visible); +} + +void +gedit_cmd_view_show_side_pane (GtkAction *action, + GeditWindow *window) +{ + gboolean visible; + + gedit_debug (DEBUG_COMMANDS); + + visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + + _gedit_window_set_side_panel_visible (window, visible); +} + +void +gedit_cmd_view_show_bottom_panel (GtkAction *action, + GeditWindow *window) +{ + gboolean visible; + + gedit_debug (DEBUG_COMMANDS); + + visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + + _gedit_window_set_bottom_panel_visible (window, visible); +} diff --git a/gedit/gedit-commands.h b/gedit/gedit-commands.h index adfd2f2f..6964395e 100644 --- a/gedit/gedit-commands.h +++ b/gedit/gedit-commands.h @@ -5,6 +5,7 @@ * * 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 @@ -19,56 +20,117 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. * * + * Boston, MA 02111-1307, USA. */ /* - * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_COMMANDS_H__ #define __GEDIT_COMMANDS_H__ -#include +#include +#include "recent-files/egg-recent-item.h" +#include "gedit-window.h" + +G_BEGIN_DECLS + +gint gedit_cmd_load_files (GeditWindow *window, + const GSList *uris, + const GeditEncoding *encoding); +gint gedit_cmd_load_files_from_prompt (GeditWindow *window, + const GSList *uris, + const GeditEncoding *encoding, + gint line_pos); + +void gedit_cmd_file_new (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_open (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_open_recent (EggRecentItem *item, + GeditWindow *window); +void gedit_cmd_file_save (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_save_as (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_save_all (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_revert (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_open_uri (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_page_setup (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_print_preview (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_print (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_close (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_close_all (GtkAction *action, + GeditWindow *window); +void gedit_cmd_file_quit (GtkAction *action, + GeditWindow *window); -void gedit_cmd_file_new (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_open (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_save (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_save_as (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_save_all (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_revert (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_open_uri (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_page_setup (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_print (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_print_preview - (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_close (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_close_all (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_file_exit (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); +void gedit_cmd_edit_undo (GtkAction *action, + GeditWindow *window); +void gedit_cmd_edit_redo (GtkAction *action, + GeditWindow *window); +void gedit_cmd_edit_cut (GtkAction *action, + GeditWindow *window); +void gedit_cmd_edit_copy (GtkAction *action, + GeditWindow *window); +void gedit_cmd_edit_paste (GtkAction *action, + GeditWindow *window); +void gedit_cmd_edit_delete (GtkAction *action, + GeditWindow *window); +void gedit_cmd_edit_select_all (GtkAction *action, + GeditWindow *window); +void gedit_cmd_edit_preferences (GtkAction *action, + GeditWindow *window); -void gedit_cmd_edit_undo (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_edit_redo (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_edit_cut (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_edit_copy (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_edit_paste (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_edit_clear (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_edit_select_all (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); +void gedit_cmd_view_show_toolbar (GtkAction *action, + GeditWindow *window); +void gedit_cmd_view_show_statusbar (GtkAction *action, + GeditWindow *window); +void gedit_cmd_view_show_side_pane (GtkAction *action, + GeditWindow *window); +void gedit_cmd_view_show_bottom_panel (GtkAction *action, + GeditWindow *window); -void gedit_cmd_search_find (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_search_find_next (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_search_find_prev (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_search_replace (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_search_goto_line (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); +void gedit_cmd_search_find (GtkAction *action, + GeditWindow *window); +void gedit_cmd_search_find_next (GtkAction *action, + GeditWindow *window); +void gedit_cmd_search_find_prev (GtkAction *action, + GeditWindow *window); +void gedit_cmd_search_replace (GtkAction *action, + GeditWindow *window); +void gedit_cmd_search_goto_line (GtkAction *action, + GeditWindow *window); -void gedit_cmd_settings_preferences - (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); +void gedit_cmd_documents_move_to_new_window (GtkAction *action, + GeditWindow *window); + +void gedit_cmd_help_contents (GtkAction *action, + GeditWindow *window); +void gedit_cmd_help_about (GtkAction *action, + GeditWindow *window); + +/* + * Non-exported function + */ +void _gedit_cmd_file_close_tab (GeditTab *tab, + GeditWindow *window); -void gedit_cmd_documents_move_to_new_window - (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); +void _gedit_cmd_file_save_documents_list (GeditWindow *window, + GList *docs); -void gedit_cmd_help_contents (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); -void gedit_cmd_help_about (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname); +G_END_DECLS #endif /* __GEDIT_COMMANDS_H__ */ diff --git a/gedit/gedit-convert.c b/gedit/gedit-convert.c index 18a69ccc..fd84062e 100644 --- a/gedit/gedit-convert.c +++ b/gedit/gedit-convert.c @@ -33,7 +33,6 @@ #include #include "gedit-convert.h" -#include "gedit-encodings.h" #include "gedit-debug.h" #include "gedit-prefs-manager.h" @@ -51,31 +50,63 @@ static gchar * gedit_convert_to_utf8_from_charset (const gchar *content, gsize len, const gchar *charset, + gsize *new_len, GError **error) { gchar *utf8_content = NULL; GError *conv_error = NULL; - gchar* converted_contents; - gsize bytes_written; - + gchar* converted_contents = NULL; + gsize bytes_read; + g_return_val_if_fail (content != NULL, NULL); g_return_val_if_fail (len > 0, NULL); g_return_val_if_fail (charset != NULL, NULL); - gedit_debug (DEBUG_UTILS, "Trying to convert from %s to UTF-8", charset); - + gedit_debug_message (DEBUG_UTILS, "Trying to convert from %s to UTF-8", charset); + + if (strcmp (charset, "UTF-8") == 0) + { + if (g_utf8_validate (content, len, NULL)) + { + if (new_len != NULL) + *new_len = len; + + return g_strndup (content, len); + } + else + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + "The file you are trying to open contains an invalid byte sequence."); + + return NULL; + } + converted_contents = g_convert (content, len, "UTF-8", charset, - NULL, - &bytes_written, + &bytes_read, + new_len, &conv_error); - - if ((conv_error != NULL) || !g_utf8_validate (converted_contents, bytes_written, NULL)) + + gedit_debug_message (DEBUG_UTILS, "Bytes read: %d", bytes_read); + + /* There is no way we can avoid to run g_utf8_validate on the converted text. + * + * hmmm... but in that case g_convert should fail + * paolo: g_convert() doesn't necessarily have the same definition + * GLib just uses the system's iconv + * paolo: I think we've explained what's going on. + * I have to define it as NOTABUG since g_convert() isn't going to + * start post-processing or checking what iconv() does and + * changing g_utf8_valdidate() wouldn't be API compatible even if I + * thought it was right + */ + if ((conv_error != NULL) || + !g_utf8_validate (converted_contents, *new_len, NULL) || + (bytes_read != len)) { - gedit_debug (DEBUG_UTILS, "Couldn't convert from %s to UTF-8.", - charset); + gedit_debug_message (DEBUG_UTILS, "Couldn't convert from %s to UTF-8.", + charset); if (converted_contents != NULL) g_free (converted_contents); @@ -84,19 +115,20 @@ gedit_convert_to_utf8_from_charset (const gchar *content, g_propagate_error (error, conv_error); else { - gedit_debug (DEBUG_UTILS, "The file you are trying to open contains " - "an invalid byte sequence."); + gedit_debug_message (DEBUG_UTILS, "The file you are trying to open contains " + "an invalid byte sequence."); - g_set_error (error, GEDIT_CONVERT_ERROR, GEDIT_CONVERT_ERROR_ILLEGAL_SEQUENCE, - _("The file you are trying to open contains an invalid byte sequence.")); - } + g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + "The file you are trying to open contains an invalid byte sequence."); + } } else { - g_return_val_if_fail (converted_contents != NULL, NULL); - - gedit_debug (DEBUG_UTILS, "Converted from %s to UTF-8.", charset); + gedit_debug_message (DEBUG_UTILS, "Converted from %s to UTF-8 (newlen = %d).", + charset, *new_len); + g_return_val_if_fail (converted_contents != NULL, NULL); + utf8_content = converted_contents; } @@ -104,16 +136,17 @@ gedit_convert_to_utf8_from_charset (const gchar *content, } gchar * -gedit_convert_to_utf8 (const gchar *content, - gsize len, - const GeditEncoding **encoding, - GError **error) +gedit_convert_to_utf8 (const gchar *content, + gsize len, + const GeditEncoding **encoding, + gsize *new_len, + GError **error) { - gedit_debug (DEBUG_UTILS, ""); - + gedit_debug (DEBUG_UTILS); + g_return_val_if_fail (content != NULL, NULL); g_return_val_if_fail (encoding != NULL, NULL); - + if (len < 0) len = strlen (content); @@ -128,46 +161,52 @@ gedit_convert_to_utf8 (const gchar *content, return gedit_convert_to_utf8_from_charset (content, len, charset, + new_len, error); } else { /* Automatically detect the encoding used */ - GSList *encodings = NULL; + GSList *encodings; GSList *start; + gchar *ret = NULL; - gedit_debug (DEBUG_UTILS, "Automatically detect the encoding used"); + gedit_debug_message (DEBUG_UTILS, + "Automatically detect the encoding used"); encodings = gedit_prefs_manager_get_auto_detected_encodings (); if (encodings == NULL) { - gedit_debug (DEBUG_UTILS, "encodings == NULL"); - + gedit_debug_message (DEBUG_UTILS, "encodings == NULL"); + if (g_utf8_validate (content, len, NULL)) { - gedit_debug (DEBUG_UTILS, "validate OK."); + gedit_debug_message (DEBUG_UTILS, "validate OK."); + if (new_len != NULL) + *new_len = len; + return g_strndup (content, len); } else { - gedit_debug (DEBUG_UTILS, "validate failed."); + gedit_debug_message (DEBUG_UTILS, "validate failed."); g_set_error (error, GEDIT_CONVERT_ERROR, GEDIT_CONVERT_ERROR_AUTO_DETECTION_FAILED, - _("gedit was not able to automatically determine " - "the encoding of the file you want to open.")); + "gedit was not able to automatically determine " + "the encoding of the file you want to open."); return NULL; } } - gedit_debug (DEBUG_UTILS, "encodings != NULL"); + gedit_debug_message (DEBUG_UTILS, "encodings != NULL"); start = encodings; - + while (encodings != NULL) { const GeditEncoding *enc; @@ -176,38 +215,48 @@ gedit_convert_to_utf8 (const gchar *content, enc = (const GeditEncoding *)encodings->data; - gedit_debug (DEBUG_UTILS, "Get charset"); + gedit_debug_message (DEBUG_UTILS, "Get charset"); charset = gedit_encoding_get_charset (enc); g_return_val_if_fail (charset != NULL, NULL); - gedit_debug (DEBUG_UTILS, "Trying to convert %ld bytes of data from ' %s'to 'UTF-8'.", - len, charset); + gedit_debug_message (DEBUG_UTILS, "Trying to convert %lu bytes of data from '%s' to 'UTF-8'.", + (unsigned long) len, charset); - utf8_content = gedit_convert_to_utf8_from_charset (content, len, charset, NULL); + utf8_content = gedit_convert_to_utf8_from_charset (content, + len, + charset, + new_len, + NULL); if (utf8_content != NULL) { *encoding = enc; + ret = utf8_content; - return utf8_content; + break; } encodings = g_slist_next (encodings); } - gedit_debug (DEBUG_UTILS, "gedit has not been able to automatically determine the encoding of " - "the file you want to open."); - - g_set_error (error, GEDIT_CONVERT_ERROR, - GEDIT_CONVERT_ERROR_AUTO_DETECTION_FAILED, - _("gedit was not able to automatically determine " - "the encoding of the file you want to open.")); + if (ret == NULL) + { + gedit_debug_message (DEBUG_UTILS, "gedit has not been able to automatically determine the encoding of " + "the file you want to open."); + + g_set_error (error, GEDIT_CONVERT_ERROR, + GEDIT_CONVERT_ERROR_AUTO_DETECTION_FAILED, + "gedit was not able to automatically determine " + "the encoding of the file you want to open."); + } g_slist_free (start); + + return ret; } - - return NULL; + + g_return_val_if_reached (NULL); } gchar * @@ -221,7 +270,7 @@ gedit_convert_from_utf8 (const gchar *content, gchar *converted_contents = NULL; gsize bytes_written = 0; - gedit_debug (DEBUG_UTILS, ""); + gedit_debug (DEBUG_UTILS); g_return_val_if_fail (content != NULL, NULL); g_return_val_if_fail (g_utf8_validate (content, len, NULL), NULL); @@ -243,8 +292,8 @@ gedit_convert_from_utf8 (const gchar *content, if (conv_error != NULL) { - gedit_debug (DEBUG_UTILS, "Cannot convert from UTF-8 to %s", - gedit_encoding_get_charset (encoding)); + gedit_debug_message (DEBUG_UTILS, "Cannot convert from UTF-8 to %s", + gedit_encoding_get_charset (encoding)); if (converted_contents != NULL) { diff --git a/gedit/gedit-convert.h b/gedit/gedit-convert.h index a6c3fb3e..694341bf 100644 --- a/gedit/gedit-convert.h +++ b/gedit/gedit-convert.h @@ -35,9 +35,7 @@ typedef enum { - GEDIT_CONVERT_ERROR_AUTO_DETECTION_FAILED = 1100, - GEDIT_CONVERT_ERROR_BINARY_FILE, - GEDIT_CONVERT_ERROR_ILLEGAL_SEQUENCE + GEDIT_CONVERT_ERROR_AUTO_DETECTION_FAILED = 1100 } GeditConvertError; #define GEDIT_CONVERT_ERROR gedit_convert_error_quark() @@ -47,6 +45,7 @@ GQuark gedit_convert_error_quark (void); gchar *gedit_convert_to_utf8 (const gchar *content, gsize len, const GeditEncoding **encoding, + gsize *new_len, GError **error); gchar *gedit_convert_from_utf8 (const gchar *content, diff --git a/gedit/gedit-debug.c b/gedit/gedit-debug.c index 2905969d..5ecac193 100644 --- a/gedit/gedit-debug.c +++ b/gedit/gedit-debug.c @@ -1,10 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-debug.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) 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 @@ -19,23 +19,31 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. * * + * Boston, MA 02111-1307, USA. */ /* - * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. - * See the ChangeLog files for a list of changes. + * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H #include #endif -#include #include #include "gedit-debug.h" +#define ENABLE_PROFILING + +#ifdef ENABLE_PROFILING +static GTimer *timer = NULL; +static gdouble last = 0.0; +#endif + static GeditDebugSection debug = GEDIT_NO_DEBUG; void @@ -45,13 +53,11 @@ gedit_debug_init () { /* enable all debugging */ debug = ~GEDIT_NO_DEBUG; - return; + goto out; } if (g_getenv ("GEDIT_DEBUG_VIEW") != NULL) debug = debug | GEDIT_DEBUG_VIEW; - if (g_getenv ("GEDIT_DEBUG_UNDO") != NULL) - debug = debug | GEDIT_DEBUG_UNDO; if (g_getenv ("GEDIT_DEBUG_SEARCH") != NULL) debug = debug | GEDIT_DEBUG_SEARCH; if (g_getenv ("GEDIT_DEBUG_PREFS") != NULL) @@ -66,24 +72,39 @@ gedit_debug_init () debug = debug | GEDIT_DEBUG_DOCUMENT; if (g_getenv ("GEDIT_DEBUG_COMMANDS") != NULL) debug = debug | GEDIT_DEBUG_COMMANDS; - if (g_getenv ("GEDIT_DEBUG_RECENT") != NULL) - debug = debug | GEDIT_DEBUG_RECENT; - if (g_getenv ("GEDIT_DEBUG_MDI") != NULL) - debug = debug | GEDIT_DEBUG_MDI; + if (g_getenv ("GEDIT_DEBUG_APP") != NULL) + debug = debug | GEDIT_DEBUG_APP; if (g_getenv ("GEDIT_DEBUG_SESSION") != NULL) debug = debug | GEDIT_DEBUG_SESSION; if (g_getenv ("GEDIT_DEBUG_UTILS") != NULL) debug = debug | GEDIT_DEBUG_UTILS; if (g_getenv ("GEDIT_DEBUG_METADATA") != NULL) debug = debug | GEDIT_DEBUG_METADATA; + if (g_getenv ("GEDIT_DEBUG_WINDOW") != NULL) + debug = debug | GEDIT_DEBUG_WINDOW; + +out: + +#ifdef ENABLE_PROFILING + if (debug != GEDIT_NO_DEBUG) + timer = g_timer_new (); +#endif + return; } void -gedit_debug (GeditDebugSection section, const gchar *file, - gint line, const gchar* function, const gchar* format, ...) +gedit_debug_message (GeditDebugSection section, + const gchar *file, + gint line, + const gchar *function, + const gchar *format, ...) { - if (debug & section) - { + if (G_UNLIKELY (debug & section)) + { +#ifdef ENABLE_PROFILING + gdouble seconds; +#endif + va_list args; gchar *msg; @@ -93,10 +114,42 @@ gedit_debug (GeditDebugSection section, const gchar *file, msg = g_strdup_vprintf (format, args); va_end (args); - g_print ("%s:%d (%s) %s\n", file, line, function, msg); - g_free (msg); +#ifdef ENABLE_PROFILING + g_return_if_fail (timer != NULL); + + seconds = g_timer_elapsed (timer, NULL); + g_print ("[%f (%f)] %s:%d (%s) %s\n", + seconds, seconds - last, file, line, function, msg); + last = seconds; +#else + g_print ("%s:%d (%s) %s\n", file, line, function, msg); +#endif fflush (stdout); + + g_free (msg); } } +void gedit_debug (GeditDebugSection section, + const gchar *file, + gint line, + const gchar *function) +{ + if (G_UNLIKELY (debug & section)) + { +#ifdef ENABLE_PROFILING + gdouble seconds; + + g_return_if_fail (timer != NULL); + + seconds = g_timer_elapsed (timer, NULL); + g_print ("[%f (%f)] %s:%d (%s)\n", + seconds, seconds - last, file, line, function); + last = seconds; +#else + g_print ("%s:%d (%s)\n", file, line, function); +#endif + fflush (stdout); + } +} diff --git a/gedit/gedit-debug.h b/gedit/gedit-debug.h index 7b7845e4..7b02a2f6 100644 --- a/gedit/gedit-debug.h +++ b/gedit/gedit-debug.h @@ -1,10 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-debug.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) 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 @@ -19,13 +19,15 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. * * + * Boston, MA 02111-1307, USA. */ /* - * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. - * See the ChangeLog files for a list of changes. + * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_DEBUG_H__ @@ -41,43 +43,47 @@ typedef enum { GEDIT_NO_DEBUG = 0, GEDIT_DEBUG_VIEW = 1 << 0, - GEDIT_DEBUG_UNDO = 1 << 1, - GEDIT_DEBUG_SEARCH = 1 << 2, - GEDIT_DEBUG_PRINT = 1 << 3, - GEDIT_DEBUG_PREFS = 1 << 4, - GEDIT_DEBUG_PLUGINS = 1 << 5, - GEDIT_DEBUG_FILE = 1 << 6, - GEDIT_DEBUG_DOCUMENT = 1 << 7, - GEDIT_DEBUG_RECENT = 1 << 8, - GEDIT_DEBUG_COMMANDS = 1 << 9, - GEDIT_DEBUG_MDI = 1 << 10, - GEDIT_DEBUG_SESSION = 1 << 11, - GEDIT_DEBUG_UTILS = 1 << 12, - GEDIT_DEBUG_METADATA = 1 << 13 + GEDIT_DEBUG_SEARCH = 1 << 1, + GEDIT_DEBUG_PRINT = 1 << 2, + GEDIT_DEBUG_PREFS = 1 << 3, + GEDIT_DEBUG_PLUGINS = 1 << 4, + GEDIT_DEBUG_FILE = 1 << 5, + GEDIT_DEBUG_DOCUMENT = 1 << 6, + GEDIT_DEBUG_COMMANDS = 1 << 7, + GEDIT_DEBUG_APP = 1 << 8, + GEDIT_DEBUG_SESSION = 1 << 9, + GEDIT_DEBUG_UTILS = 1 << 10, + GEDIT_DEBUG_METADATA = 1 << 11, + GEDIT_DEBUG_WINDOW = 1 << 12, } GeditDebugSection; #define DEBUG_VIEW GEDIT_DEBUG_VIEW, __FILE__, __LINE__, G_STRFUNC -#define DEBUG_UNDO GEDIT_DEBUG_UNDO, __FILE__, __LINE__, G_STRFUNC #define DEBUG_SEARCH GEDIT_DEBUG_SEARCH, __FILE__, __LINE__, G_STRFUNC #define DEBUG_PRINT GEDIT_DEBUG_PRINT, __FILE__, __LINE__, G_STRFUNC #define DEBUG_PREFS GEDIT_DEBUG_PREFS, __FILE__, __LINE__, G_STRFUNC #define DEBUG_PLUGINS GEDIT_DEBUG_PLUGINS, __FILE__, __LINE__, G_STRFUNC #define DEBUG_FILE GEDIT_DEBUG_FILE, __FILE__, __LINE__, G_STRFUNC #define DEBUG_DOCUMENT GEDIT_DEBUG_DOCUMENT,__FILE__, __LINE__, G_STRFUNC -#define DEBUG_RECENT GEDIT_DEBUG_RECENT, __FILE__, __LINE__, G_STRFUNC #define DEBUG_COMMANDS GEDIT_DEBUG_COMMANDS,__FILE__, __LINE__, G_STRFUNC -#define DEBUG_MDI GEDIT_DEBUG_MDI, __FILE__, __LINE__, G_STRFUNC +#define DEBUG_APP GEDIT_DEBUG_APP, __FILE__, __LINE__, G_STRFUNC #define DEBUG_SESSION GEDIT_DEBUG_SESSION, __FILE__, __LINE__, G_STRFUNC #define DEBUG_UTILS GEDIT_DEBUG_UTILS, __FILE__, __LINE__, G_STRFUNC #define DEBUG_METADATA GEDIT_DEBUG_METADATA,__FILE__, __LINE__, G_STRFUNC +#define DEBUG_WINDOW GEDIT_DEBUG_WINDOW, __FILE__, __LINE__, G_STRFUNC void gedit_debug_init (void); void gedit_debug (GeditDebugSection section, const gchar *file, gint line, - const gchar *function, - const gchar *format, ...); + 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); + #endif /* __GEDIT_DEBUG_H__ */ diff --git a/gedit/gedit-document-loader.c b/gedit/gedit-document-loader.c new file mode 100644 index 00000000..6372bdcb --- /dev/null +++ b/gedit/gedit-document-loader.c @@ -0,0 +1,1045 @@ +/* + * gedit-document-loader.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gedit-document-loader.h" +#include "gedit-convert.h" +#include "gedit-debug.h" +#include "gedit-metadata-manager.h" +#include "gedit-utils.h" + +#include "gedit-marshal.h" + +#define READ_CHUNK_SIZE 8192 + +#define GEDIT_DOCUMENT_LOADER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoaderPrivate)) + +static void async_close_cb (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer data); + + +struct _GeditDocumentLoaderPrivate +{ + GeditDocument *document; + + gboolean used; + + /* Info on the current file */ + gchar *uri; + const GeditEncoding *encoding; + + GnomeVFSURI *vfs_uri; + + GnomeVFSFileInfo *info; + GnomeVFSFileSize bytes_read; + + /* Handle for local files */ + gint fd; + gchar *local_file_name; + + /* Handle for remote files */ + GnomeVFSAsyncHandle *handle; + GnomeVFSAsyncHandle *info_handle; + + gchar *buffer; + + const GeditEncoding *auto_detected_encoding; + + GError *error; +}; + +G_DEFINE_TYPE(GeditDocumentLoader, gedit_document_loader, G_TYPE_OBJECT) + +/* Signals */ + +enum { + LOADING, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/* Properties */ + +enum +{ + PROP_0, + PROP_DOCUMENT, +}; + +static void +gedit_document_loader_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeditDocumentLoader *dl = GEDIT_DOCUMENT_LOADER (object); + + switch (prop_id) + { + case PROP_DOCUMENT: + g_return_if_fail (dl->priv->document == NULL); + dl->priv->document = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_document_loader_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditDocumentLoader *dl = GEDIT_DOCUMENT_LOADER (object); + + switch (prop_id) + { + case PROP_DOCUMENT: + g_value_set_object (value, + dl->priv->document); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_document_loader_finalize (GObject *object) +{ + GeditDocumentLoaderPrivate *priv = GEDIT_DOCUMENT_LOADER (object)->priv; + + if (priv->handle != NULL) + { + if (priv->info_handle != NULL) + { + gnome_vfs_async_cancel (priv->info_handle); + gnome_vfs_async_close (priv->info_handle, + async_close_cb, + NULL); + } + + gnome_vfs_async_cancel (priv->handle); + gnome_vfs_async_close (priv->handle, + async_close_cb, + NULL); + } + + g_free (priv->uri); + + if (priv->info) + gnome_vfs_file_info_unref (priv->info); + + + g_free (priv->local_file_name); + g_free (priv->buffer); + + if (priv->vfs_uri) + gnome_vfs_uri_unref (priv->vfs_uri); + + if (priv->error) + g_error_free (priv->error); + + G_OBJECT_CLASS (gedit_document_loader_parent_class)->finalize (object); +} + +static void +gedit_document_loader_class_init (GeditDocumentLoaderClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_document_loader_finalize; + object_class->get_property = gedit_document_loader_get_property; + object_class->set_property = gedit_document_loader_set_property; + + g_object_class_install_property (object_class, + PROP_DOCUMENT, + g_param_spec_object ("document", + "Document", + "The GeditDocument this GeditDocumentLoader is associated with", + GEDIT_TYPE_DOCUMENT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[LOADING] = + g_signal_new ("loading", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GeditDocumentLoaderClass, loading), + NULL, NULL, + gedit_marshal_VOID__BOOLEAN_POINTER, + G_TYPE_NONE, + 2, + G_TYPE_BOOLEAN, + G_TYPE_POINTER); + + g_type_class_add_private (object_class, sizeof(GeditDocumentLoaderPrivate)); +} + +static void +gedit_document_loader_init (GeditDocumentLoader *loader) +{ + loader->priv = GEDIT_DOCUMENT_LOADER_GET_PRIVATE (loader); + + loader->priv->used = FALSE; + + loader->priv->fd = -1; + + loader->priv->error = NULL; +} + +GeditDocumentLoader * +gedit_document_loader_new (GeditDocument *doc) +{ + GeditDocumentLoader *dl; + + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL); + + dl = GEDIT_DOCUMENT_LOADER (g_object_new (GEDIT_TYPE_DOCUMENT_LOADER, + "document", doc, + NULL)); + + return dl; +} + +static void +insert_text_in_document (GeditDocumentLoader *loader, + const gchar *text, + gint len) +{ + gtk_source_buffer_begin_not_undoable_action ( + GTK_SOURCE_BUFFER (loader->priv->document)); + + /* Insert text in the buffer */ + gtk_text_buffer_set_text (GTK_TEXT_BUFFER (loader->priv->document), + text, + len); + + gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (loader->priv->document), + FALSE); + + gtk_source_buffer_end_not_undoable_action ( + GTK_SOURCE_BUFFER (loader->priv->document)); +} + +static gboolean +update_document_contents (GeditDocumentLoader *loader, + const gchar *file_contents, + gint file_size, + GError **error) +{ + g_return_val_if_fail (file_size > 0, FALSE); + g_return_val_if_fail (file_contents != NULL, FALSE); + + if (loader->priv->encoding == gedit_encoding_get_utf8 ()) + { + if (g_utf8_validate (file_contents, file_size, NULL)) + { + insert_text_in_document (loader, + file_contents, + file_size); + + return TRUE; + } + else + { + g_set_error (error, + G_CONVERT_ERROR, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + "The file you are trying to open contains an invalid byte sequence."); + + return FALSE; + } + } + else + { + GError *conv_error = NULL; + gchar *converted_text = NULL; + gsize new_len = file_size; + + if (loader->priv->encoding == NULL) + { + /* Autodetecting the encoding: first try with the encoding + stored in the metadata, if any */ + + const GeditEncoding *enc; + gchar *charset; + + charset = gedit_metadata_manager_get (loader->priv->uri, "encoding"); + + if (charset != NULL) + { + enc = gedit_encoding_get_from_charset (charset); + + if (enc != NULL) + { + converted_text = gedit_convert_to_utf8 ( + file_contents, + file_size, + &enc, + &new_len, + NULL); + + if (converted_text != NULL) + loader->priv->auto_detected_encoding = enc; + } + + g_free (charset); + } + } + + if (converted_text == NULL) + { + loader->priv->auto_detected_encoding = loader->priv->encoding; + + converted_text = gedit_convert_to_utf8 ( + file_contents, + file_size, + &loader->priv->auto_detected_encoding, + &new_len, + &conv_error); + } + + if (converted_text == NULL) + { + g_return_val_if_fail (conv_error != NULL, FALSE); + + g_propagate_error (error, conv_error); + + return FALSE; + } + else + { + insert_text_in_document (loader, + converted_text, + new_len); + + g_free (converted_text); + + return TRUE; + } + } + + g_return_val_if_reached (FALSE); +} + +/* The following function has been copied from gnome-vfs + (modules/file-method.c) file */ +static void +get_access_info (GnomeVFSFileInfo *file_info, + const gchar *full_name) +{ + /* FIXME: should check errno after calling access because we don't + * want to set valid_fields if something bad happened during one + * of the access calls + */ + if (g_access (full_name, W_OK) == 0) + file_info->permissions |= GNOME_VFS_PERM_ACCESS_WRITABLE; + + /* + * We don't need to know if a local file is readable or + * executable so I have commented the followig code to avoid + * multiple g_access calls - Paolo (Oct. 18, 2005) + */ + + /* + * if (g_access (full_name, R_OK) == 0) + * file_info->permissions |= GNOME_VFS_PERM_ACCESS_READABLE; + * + * #ifdef G_OS_WIN32 + * if (g_file_test (full_name, G_FILE_TEST_IS_EXECUTABLE)) + * file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE; + * #else + * if (g_access (full_name, X_OK) == 0) + * file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE; + * #endif + */ + + file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACCESS; +} + +/* The following function has been copied from gnome-vfs + (gnome-vfs-module-shared.c) file */ +static void +stat_to_file_info (GnomeVFSFileInfo *file_info, + const struct stat *statptr) +{ + if (S_ISDIR (statptr->st_mode)) + file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY; + else if (S_ISCHR (statptr->st_mode)) + file_info->type = GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE; + else if (S_ISBLK (statptr->st_mode)) + file_info->type = GNOME_VFS_FILE_TYPE_BLOCK_DEVICE; + else if (S_ISFIFO (statptr->st_mode)) + file_info->type = GNOME_VFS_FILE_TYPE_FIFO; + else if (S_ISSOCK (statptr->st_mode)) + file_info->type = GNOME_VFS_FILE_TYPE_SOCKET; + else if (S_ISREG (statptr->st_mode)) + file_info->type = GNOME_VFS_FILE_TYPE_REGULAR; + else if (S_ISLNK (statptr->st_mode)) + file_info->type = GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK; + else + file_info->type = GNOME_VFS_FILE_TYPE_UNKNOWN; + + file_info->permissions + = statptr->st_mode & (GNOME_VFS_PERM_USER_ALL + | GNOME_VFS_PERM_GROUP_ALL + | GNOME_VFS_PERM_OTHER_ALL + | GNOME_VFS_PERM_SUID + | GNOME_VFS_PERM_SGID + | GNOME_VFS_PERM_STICKY); + + file_info->device = statptr->st_dev; + file_info->inode = statptr->st_ino; + + file_info->link_count = statptr->st_nlink; + + file_info->uid = statptr->st_uid; + file_info->gid = statptr->st_gid; + + file_info->size = statptr->st_size; + file_info->block_count = statptr->st_blocks; + file_info->io_block_size = statptr->st_blksize; + if (file_info->io_block_size > 0 && + file_info->io_block_size < 4096) { + /* Never use smaller block than 4k, + should probably be pagesize.. */ + file_info->io_block_size = 4096; + } + + file_info->atime = statptr->st_atime; + file_info->ctime = statptr->st_ctime; + file_info->mtime = statptr->st_mtime; + + file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_TYPE | + GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS | GNOME_VFS_FILE_INFO_FIELDS_FLAGS | + GNOME_VFS_FILE_INFO_FIELDS_DEVICE | GNOME_VFS_FILE_INFO_FIELDS_INODE | + GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT | GNOME_VFS_FILE_INFO_FIELDS_SIZE | + GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT | GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE | + GNOME_VFS_FILE_INFO_FIELDS_ATIME | GNOME_VFS_FILE_INFO_FIELDS_MTIME | + GNOME_VFS_FILE_INFO_FIELDS_CTIME; +} + +/* FIXME: this is ugly for multiple reasons: it refetches all the info, + * it doesn't use fd etc... we need something better, possibly in gnome-vfs + * public api. + */ +static gchar * +get_slow_mime_type (const char *text_uri) +{ + GnomeVFSFileInfo *info; + char *mime_type; + GnomeVFSResult result; + + info = gnome_vfs_file_info_new (); + result = gnome_vfs_get_file_info (text_uri, info, + GNOME_VFS_FILE_INFO_GET_MIME_TYPE | + GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | + GNOME_VFS_FILE_INFO_FOLLOW_LINKS); + if (info->mime_type == NULL || result != GNOME_VFS_OK) { + mime_type = NULL; + } else { + mime_type = g_strdup (info->mime_type); + } + gnome_vfs_file_info_unref (info); + + return mime_type; +} + +static void +load_completed_or_failed (GeditDocumentLoader *loader) +{ + gedit_debug (DEBUG_DOCUMENT); + + /* the object will be unrefed in the callback of the loading + * signal, so we need to prevent finalization. + */ + g_object_ref (loader); + + g_signal_emit (loader, + signals[LOADING], + 0, + TRUE, /* completed */ + loader->priv->error); + + gedit_debug_message (DEBUG_DOCUMENT, "unref"); + + g_object_unref (loader); +} + +/* ----------- local files ----------- */ + +static gboolean +load_local_file_real (GeditDocumentLoader *loader) +{ + struct stat statbuf; + GnomeVFSResult result; + gint ret; + + g_return_val_if_fail (loader->priv->fd != -1, FALSE); + + if (fstat (loader->priv->fd, &statbuf) != 0) + { + result = gnome_vfs_result_from_errno (); + + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + goto done; + } + + loader->priv->info = gnome_vfs_file_info_new (); + stat_to_file_info (loader->priv->info, &statbuf); + GNOME_VFS_FILE_INFO_SET_LOCAL (loader->priv->info, TRUE); + get_access_info (loader->priv->info, loader->priv->local_file_name); + + if (loader->priv->info->size == 0) + { + if (loader->priv->encoding == NULL) + loader->priv->auto_detected_encoding = gedit_encoding_get_current (); + } + else + { + gchar *mapped_file; + + /* CHECK: should we lock the file */ + g_print ("load_local_file_real: before mmap\n"); + + mapped_file = mmap (0, /* start */ + loader->priv->info->size, + PROT_READ, + MAP_PRIVATE, /* flags */ + loader->priv->fd, + 0 /* offset */); + + if (mapped_file == MAP_FAILED) + { + result = gnome_vfs_result_from_errno (); + + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + goto done; + } + + loader->priv->bytes_read = loader->priv->info->size; + + if (!update_document_contents (loader, + mapped_file, + loader->priv->info->size, + &loader->priv->error)) + { + ret = munmap (mapped_file, loader->priv->info->size); + if (ret != 0) + g_warning ("File '%s' has not been correctly unmapped: %s", + loader->priv->uri, + strerror (errno)); + + goto done; + } + + ret = munmap (mapped_file, loader->priv->info->size); + + if (ret != 0) + g_warning ("File '%s' has not been correctly unmapped: %s", + loader->priv->uri, + strerror (errno)); + } + + /* mime type hack. Do it before closing the fd to avoid race conditions */ + loader->priv->info->mime_type = get_slow_mime_type (loader->priv->uri); + loader->priv->info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE; + + ret = close (loader->priv->fd); + + if (ret != 0) + g_warning ("File '%s' has not been correctly closed: %s", + loader->priv->uri, + strerror (errno)); + + loader->priv->fd = -1; + + done: + + load_completed_or_failed (loader); + + return FALSE; +} + +static gboolean +open_local_failed (GeditDocumentLoader *loader) +{ + load_completed_or_failed (loader); + + /* stop the timeout */ + return FALSE; +} + +static void +load_local_file (GeditDocumentLoader *loader, + const gchar *fname) +{ + g_signal_emit (loader, + signals[LOADING], + 0, + FALSE, + NULL); + + loader->priv->fd = open (fname, O_RDONLY); + if (loader->priv->fd == -1) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + g_timeout_add_full (G_PRIORITY_HIGH, + 0, + (GSourceFunc) open_local_failed, + loader, + NULL); + + return; + } + + g_free (loader->priv->local_file_name); + loader->priv->local_file_name = g_strdup (fname); + + g_timeout_add_full (G_PRIORITY_HIGH, + 0, + (GSourceFunc) load_local_file_real, + loader, + NULL); +} + +/* ----------- remote files ----------- */ + +static void +async_close_cb (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer data) +{ + /* nothing to do... no point in reporting an error */ +} + +static void +remote_load_completed_or_failed (GeditDocumentLoader *loader) +{ + gedit_debug (DEBUG_DOCUMENT); + + /* free the buffer and close the handle */ + gnome_vfs_async_close (loader->priv->handle, + async_close_cb, + NULL); + + loader->priv->handle = NULL; + + g_free (loader->priv->buffer); + loader->priv->buffer = NULL; + + load_completed_or_failed (loader); +} + +/* prototype, because they call each other... isn't C lovely */ +static void read_file_chunk (GeditDocumentLoader *loader); + +static void +async_read_cb (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer buffer, + GnomeVFSFileSize bytes_requested, + GnomeVFSFileSize bytes_read, + gpointer data) +{ + GeditDocumentLoader *loader = GEDIT_DOCUMENT_LOADER (data); + + /* reality checks. */ + g_return_if_fail (bytes_requested == READ_CHUNK_SIZE); + g_return_if_fail (loader->priv->handle == handle); + g_return_if_fail (loader->priv->buffer + loader->priv->bytes_read == buffer); + g_return_if_fail (bytes_read <= bytes_requested); + + /* error occurred */ + if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) + { + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + remote_load_completed_or_failed (loader); + + return; + } + + /* Check for the extremely unlikely case where the file size overflows. */ + if (loader->priv->bytes_read + bytes_read < loader->priv->bytes_read) + { + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + GNOME_VFS_ERROR_TOO_BIG, + gnome_vfs_result_to_string (GNOME_VFS_ERROR_TOO_BIG)); + + remote_load_completed_or_failed (loader); + + return; + } + + /* Bump the size. */ + loader->priv->bytes_read += bytes_read; + + /* end of the file, we are done! */ + if (bytes_read == 0 || result != GNOME_VFS_OK) + { + update_document_contents (loader, + loader->priv->buffer, + loader->priv->bytes_read, + &loader->priv->error); + + remote_load_completed_or_failed (loader); + + return; + } + + /* otherwise emit progress and read some more */ + + /* note that this signal blocks the read... check if it isn't + * a performance problem + */ + g_signal_emit (loader, + signals[LOADING], + 0, + FALSE, + NULL); + + read_file_chunk (loader); +} + +static void +read_file_chunk (GeditDocumentLoader *loader) +{ + loader->priv->buffer = g_realloc (loader->priv->buffer, + loader->priv->bytes_read + READ_CHUNK_SIZE); + + gnome_vfs_async_read (loader->priv->handle, + loader->priv->buffer + loader->priv->bytes_read, + READ_CHUNK_SIZE, + async_read_cb, + loader); +} + +static void +remote_get_info_cb (GnomeVFSAsyncHandle *handle, + GList *results, + gpointer data) +{ + GeditDocumentLoader *loader = GEDIT_DOCUMENT_LOADER (data); + GnomeVFSGetFileInfoResult *info_result; + + /* assert that the list has one and only one item */ + g_return_if_fail (results != NULL && results->next == NULL); + + loader->priv->info_handle = NULL; + + info_result = (GnomeVFSGetFileInfoResult *) results->data; + g_return_if_fail (info_result != NULL); + + if (info_result->result != GNOME_VFS_OK) + { + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + info_result->result, + gnome_vfs_result_to_string (info_result->result)); + + remote_load_completed_or_failed (loader); + + return; + } + + /* CHECK: ref is necessary, right? or the info will go away... */ + loader->priv->info = info_result->file_info; + gnome_vfs_file_info_ref (loader->priv->info); + + /* if it's not a regular file, error out... */ + if (info_result->file_info->type != GNOME_VFS_FILE_TYPE_REGULAR) + { + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + GNOME_VFS_ERROR_GENERIC, // FIXME + gnome_vfs_result_to_string (GNOME_VFS_ERROR_GENERIC)); + + remote_load_completed_or_failed (loader); + + return; + } + + /* start reading */ + read_file_chunk (loader); +} + +static void +async_open_callback (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + GeditDocumentLoader *loader) +{ + GList *uri_list = NULL; + + g_return_if_fail (loader->priv->handle == handle); + + if (result != GNOME_VFS_OK) + { + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + /* in this case we don't need to close the handle */ + load_completed_or_failed (loader); + + return; + } + + /* get the file info after open to avoid races... this really + * should be async_get_file_info_from_handle (fstat equivalent) + * but gnome-vfs lacks that. + */ + + uri_list = g_list_prepend (uri_list, loader->priv->vfs_uri); + + gnome_vfs_async_get_file_info (&loader->priv->info_handle, + uri_list, + GNOME_VFS_FILE_INFO_DEFAULT | + GNOME_VFS_FILE_INFO_GET_MIME_TYPE | + GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | + GNOME_VFS_FILE_INFO_FOLLOW_LINKS, + GNOME_VFS_PRIORITY_MAX, + remote_get_info_cb, + loader); + + g_list_free (uri_list); +} + +static void +load_remote_file (GeditDocumentLoader *loader) +{ + g_return_if_fail (loader->priv->handle == NULL); + + /* loading start */ + g_signal_emit (loader, + signals[LOADING], + 0, + FALSE, + NULL); + + gnome_vfs_async_open_uri (&loader->priv->handle, + loader->priv->vfs_uri, + GNOME_VFS_OPEN_READ, + GNOME_VFS_PRIORITY_MAX, + (GnomeVFSAsyncOpenCallback) async_open_callback, + loader); +} + +/* ---------- public api ---------- */ + +/* If enconding == NULL, the encoding will be autodetected */ +gboolean +gedit_document_loader_load (GeditDocumentLoader *loader, + const gchar *uri, + const GeditEncoding *encoding) +{ + gchar *local_path; + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), FALSE); + g_return_val_if_fail (uri != NULL, FALSE); + + /* the loader can be used just once, then it must be thrown away */ + g_return_val_if_fail (loader->priv->used == FALSE, FALSE); + loader->priv->used = TRUE; + + loader->priv->vfs_uri = gnome_vfs_uri_new (uri); + if (loader->priv->vfs_uri == NULL) + return FALSE; + + loader->priv->encoding = encoding; + + loader->priv->uri = g_strdup (uri); + + local_path = gnome_vfs_get_local_path_from_uri (uri); + if (local_path != NULL) + { + load_local_file (loader, local_path); + g_free (local_path); + } + else + { + load_remote_file (loader); + } + + return TRUE; +} + +/* Returns STDIN_URI if loading from stdin */ +const gchar * +gedit_document_loader_get_uri (GeditDocumentLoader *loader) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL); + + return loader->priv->uri; +} + +/* it may return NULL, it's up to gedit-document handle it */ +const gchar * +gedit_document_loader_get_mime_type (GeditDocumentLoader *loader) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL); + + if (loader->priv->info && + (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE)) + return loader->priv->info->mime_type; + else + return NULL; +} + +time_t +gedit_document_loader_get_mtime (GeditDocumentLoader *loader) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), 0); + + if (loader->priv->info && + (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME)) + return loader->priv->info->mtime; + else + return 0; +} + +/* Returns 0 if file size is unknown */ +GnomeVFSFileSize +gedit_document_loader_get_file_size (GeditDocumentLoader *loader) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), 0); + + if (loader->priv->info == NULL) + return 0; + + return loader->priv->info->size; +} + +GnomeVFSFileSize +gedit_document_loader_get_bytes_read (GeditDocumentLoader *loader) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), 0); + + return loader->priv->bytes_read; +} + +gboolean +gedit_document_loader_cancel (GeditDocumentLoader *loader) +{ + gedit_debug (DEBUG_DOCUMENT); + + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), FALSE); + + if (loader->priv->handle == NULL) + return FALSE; + + if (loader->priv->info_handle != NULL) + { + gnome_vfs_async_cancel (loader->priv->info_handle); + gnome_vfs_async_close (loader->priv->info_handle, + async_close_cb, + NULL); + } + + gnome_vfs_async_cancel (loader->priv->handle); + + g_set_error (&loader->priv->error, + GEDIT_DOCUMENT_ERROR, + GNOME_VFS_ERROR_CANCELLED, + gnome_vfs_result_to_string (GNOME_VFS_ERROR_CANCELLED)); + + remote_load_completed_or_failed (loader); + + return TRUE; +} + +/* In the case the loader does not know if the file is readonly, for example + for most remote files, the function returns FALSE, so that we can try writing + and if needed handle the error. */ +gboolean +gedit_document_loader_get_readonly (GeditDocumentLoader *loader) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), FALSE); + + if (!gedit_utils_uri_has_writable_scheme (loader->priv->uri)) + return TRUE; + + if (loader->priv->info && + (loader->priv->info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ACCESS)) + return (loader->priv->info->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE) ? FALSE : TRUE; + else + return FALSE; +} + +const GeditEncoding * +gedit_document_loader_get_encoding (GeditDocumentLoader *loader) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader), NULL); + + if (loader->priv->encoding != NULL) + return loader->priv->encoding; + + g_return_val_if_fail (loader->priv->auto_detected_encoding != NULL, + gedit_encoding_get_current ()); + + return loader->priv->auto_detected_encoding; +} diff --git a/gedit/gedit-document-loader.h b/gedit/gedit-document-loader.h new file mode 100644 index 00000000..efbde5a0 --- /dev/null +++ b/gedit/gedit-document-loader.h @@ -0,0 +1,119 @@ +/* + * gedit-document-loader.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_DOCUMENT_LOADER_H__ +#define __GEDIT_DOCUMENT_LOADER_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_DOCUMENT_LOADER (gedit_document_loader_get_type()) +#define GEDIT_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoader)) +#define GEDIT_DOCUMENT_LOADER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoader const)) +#define GEDIT_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoaderClass)) +#define GEDIT_IS_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENT_LOADER)) +#define GEDIT_IS_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT_LOADER)) +#define GEDIT_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENT_LOADER, GeditDocumentLoaderClass)) + +/* Private structure type */ +typedef struct _GeditDocumentLoaderPrivate GeditDocumentLoaderPrivate; + +/* + * Main object structure + */ +typedef struct _GeditDocumentLoader GeditDocumentLoader; + +struct _GeditDocumentLoader +{ + GObject object; + + /*< private > */ + GeditDocumentLoaderPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditDocumentLoaderClass GeditDocumentLoaderClass; + +struct _GeditDocumentLoaderClass +{ + GObjectClass parent_class; + + void (* loading) (GeditDocumentLoader *loader, + gboolean completed, + const GError *error); +}; + +/* + * Public methods + */ +GType gedit_document_loader_get_type (void) G_GNUC_CONST; + +GeditDocumentLoader *gedit_document_loader_new (GeditDocument *doc); + +/* If enconding == NULL, the encoding will be autodetected */ +gboolean gedit_document_loader_load (GeditDocumentLoader *loader, + const gchar *uri, + const GeditEncoding *encoding); +#if 0 +gboolean gedit_document_loader_load_from_stdin (GeditDocumentLoader *loader); +#endif +gboolean gedit_document_loader_cancel (GeditDocumentLoader *loader); + + +/* Returns STDIN_URI if loading from stdin */ +#define STDIN_URI "stdin:" +const gchar *gedit_document_loader_get_uri (GeditDocumentLoader *loader); + +const gchar *gedit_document_loader_get_mime_type (GeditDocumentLoader *loader); + +time_t gedit_document_loader_get_mtime (GeditDocumentLoader *loader); + +/* In the case the loader does not know if the file is readonly, for example for most +remote files, the function returns FALSE */ +gboolean gedit_document_loader_get_readonly (GeditDocumentLoader *loader); + +const GeditEncoding *gedit_document_loader_get_encoding (GeditDocumentLoader *loader); + +/* Returns 0 if file size is unknown */ +GnomeVFSFileSize gedit_document_loader_get_file_size (GeditDocumentLoader *loader); + +GnomeVFSFileSize gedit_document_loader_get_bytes_read (GeditDocumentLoader *loader); + + +G_END_DECLS + +#endif /* __GEDIT_DOCUMENT_LOADER_H__ */ diff --git a/gedit/gedit-document-saver.c b/gedit/gedit-document-saver.c new file mode 100644 index 00000000..d842f2ed --- /dev/null +++ b/gedit/gedit-document-saver.c @@ -0,0 +1,1299 @@ +/* + * gedit-document-saver.c + * This file is part of gedit + * + * Copyright (C) 2005 - Paolo Borelli and 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gedit-document-saver.h" +#include "gedit-convert.h" +#include "gedit-metadata-manager.h" +#include "gedit-prefs-manager.h" +#include "gedit-marshal.h" +#include "gedit-utils.h" + +#define GEDIT_DOCUMENT_SAVER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaverPrivate)) + +struct _GeditDocumentSaverPrivate +{ + GeditDocument *document; + + gchar *uri; + const GeditEncoding *encoding; + + GeditDocumentSaveFlags flags; + + gboolean keep_backup; + gchar *backup_ext; + gboolean backups_in_curr_dir; + + time_t doc_mtime; + gchar *mime_type; //CHECK use FileInfo instead? + + GnomeVFSFileSize size; + GnomeVFSFileSize bytes_written; + + /* temp data for local files */ + gint fd; + gchar *local_path; + + /* temp data for remote files */ + GnomeVFSURI *vfs_uri; + GnomeVFSAsyncHandle *handle; + GnomeVFSAsyncHandle *info_handle; + gint tmpfd; + gchar *tmp_fname; + GnomeVFSFileInfo *orig_info; /* used to restore permissions */ + + GError *error; +}; + +G_DEFINE_TYPE(GeditDocumentSaver, gedit_document_saver, G_TYPE_OBJECT) + +/* Signals */ + +enum { + SAVING, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +gedit_document_saver_finalize (GObject *object) +{ + GeditDocumentSaverPrivate *priv = GEDIT_DOCUMENT_SAVER (object)->priv; + + g_free (priv->uri); + + if (priv->vfs_uri) + gnome_vfs_uri_unref (priv->vfs_uri); + + g_free (priv->backup_ext); + + g_free (priv->local_path); + g_free (priv->mime_type); + g_free (priv->tmp_fname); + + if (priv->orig_info) + gnome_vfs_file_info_unref (priv->orig_info); + + if (priv->error) + g_error_free (priv->error); + + G_OBJECT_CLASS (gedit_document_saver_parent_class)->finalize (object); +} + +static void +gedit_document_saver_class_init (GeditDocumentSaverClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_document_saver_finalize; + + signals[SAVING] = + g_signal_new ("saving", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GeditDocumentSaverClass, saving), + NULL, NULL, + gedit_marshal_VOID__BOOLEAN_POINTER, + G_TYPE_NONE, + 2, + G_TYPE_BOOLEAN, + G_TYPE_POINTER); + + g_type_class_add_private (object_class, sizeof(GeditDocumentSaverPrivate)); +} + +static void +gedit_document_saver_init (GeditDocumentSaver *saver) +{ + saver->priv = GEDIT_DOCUMENT_SAVER_GET_PRIVATE (saver); + + saver->priv->fd = -1; + + saver->priv->tmpfd = -1; + + saver->priv->error = NULL; +} + +GeditDocumentSaver * +gedit_document_saver_new (GeditDocument *doc) +{ + GeditDocumentSaver *saver; + + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL); + + saver = GEDIT_DOCUMENT_SAVER (g_object_new (GEDIT_TYPE_DOCUMENT_SAVER, NULL)); + + saver->priv->document = doc; + + return saver; +} + +/* + * Write the document contents in fd. + */ +static gboolean +write_document_contents (gint fd, + GtkTextBuffer *doc, + const GeditEncoding *encoding, + GError **error) +{ + GtkTextIter start_iter; + GtkTextIter end_iter; + gchar *contents; + gsize len; + gboolean add_cr; + ssize_t written; + gboolean res; + + gtk_text_buffer_get_bounds (doc, &start_iter, &end_iter); + contents = gtk_text_buffer_get_slice (doc, &start_iter, &end_iter, TRUE); + + len = strlen (contents); + + if (len >= 1) + add_cr = (*(contents + len - 1) != '\n'); + else + add_cr = FALSE; + + if (encoding != gedit_encoding_get_utf8 ()) + { + gchar *converted_contents; + gsize new_len; + + converted_contents = gedit_convert_from_utf8 (contents, + len, + encoding, + &new_len, + error); + g_free (contents); + + if (*error != NULL) + { + /* Conversion error */ + return FALSE; + } + else + { + contents = converted_contents; + len = new_len; + } + } + + /* make sure we are at the start */ + res = (lseek (fd, 0, SEEK_SET) != -1); + + /* Truncate the file to 0, in case it was not empty */ + if (res) + res = (ftruncate (fd, 0) == 0); + + /* Save the file content */ + if (res) + { + written = write (fd, contents, len); + res = ((written != -1) && ((gsize) written == len)); + } + + /* Add \n at the end if needed */ + if (res && add_cr) + { + if (encoding != gedit_encoding_get_utf8 ()) + { + gchar *converted_n = NULL; + gsize n_len; + + converted_n = gedit_convert_from_utf8 ("\n", + -1, + encoding, + &n_len, + NULL); + + if (converted_n == NULL) + { + /* we do not error out for this */ + g_warning ("Cannot add '\\n' at the end of the file."); + } + else + { + written = write (fd, converted_n, n_len); + res = ((written != -1) && ((gsize) written == n_len)); + g_free (converted_n); + } + } + else + { + res = (write (fd, "\n", 1) == 1); + } + } + + g_free (contents); + + if (!res) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + } + + return res; +} + +static void +save_completed_or_failed (GeditDocumentSaver *saver) +{ + /* the object will be unrefed in the callback of the saving + * signal, so we need to prevent finalization. + */ + g_object_ref (saver); + + g_signal_emit (saver, + signals[SAVING], + 0, + TRUE, /* completed */ + saver->priv->error); + + g_object_unref (saver); +} + +static gchar * +get_backup_filename (GeditDocumentSaver *saver) +{ + gchar *fname; + gchar *bak_ext = NULL; + + if ((saver->priv->backup_ext != NULL) && + (strlen (saver->priv->backup_ext) > 0)) + bak_ext = saver->priv->backup_ext; + else + bak_ext = "~"; + + fname = g_strconcat (saver->priv->local_path, bak_ext, NULL); + + /* If we are not going to keep the backup file and fname + * already exists, try to use another name. + * Change one character, just before the extension. + */ + if (!saver->priv->keep_backup && + g_file_test (fname, G_FILE_TEST_EXISTS)) + { + gchar *wp; + + wp = fname + strlen (fname) - 1 - strlen (bak_ext); + g_return_val_if_fail (wp > fname, NULL); + + *wp = 'z'; + while ((*wp > 'a') && g_file_test (fname, G_FILE_TEST_EXISTS)) + --*wp; + + /* They all exist??? Must be something wrong. */ + if (*wp == 'a') + { + g_free (fname); + fname = NULL; + } + } + + return fname; +} + +/* like unlink, but doesn't fail if the file wasn't there at all */ +static gboolean +remove_file (const gchar *name) +{ + gint res; + + res = unlink (name); + + return (res == 0) || ((res == -1) && (errno == ENOENT)); +} + +#define BUFSIZE 8192 /* size of normal write buffer */ + +static gboolean +copy_file_data (gint sfd, + gint dfd, + GError **error) +{ + gboolean ret = TRUE; + GError *err = NULL; + gpointer buffer; + const gchar *write_buffer; + ssize_t bytes_read; + ssize_t bytes_to_write; + ssize_t bytes_written; + + buffer = g_malloc (BUFSIZE); + + do + { + bytes_read = read (sfd, buffer, BUFSIZE); + if (bytes_read == -1) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&err, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + ret = FALSE; + + break; + } + + bytes_to_write = bytes_read; + write_buffer = buffer; + + do + { + bytes_written = write (dfd, write_buffer, bytes_to_write); + if (bytes_written == -1) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&err, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + ret = FALSE; + + break; + } + + bytes_to_write -= bytes_written; + write_buffer += bytes_written; + } + while (bytes_to_write > 0); + + } while ((bytes_read != 0) && (ret == TRUE)); + + if (error) + *error = err; + + return ret; +} + +/* FIXME: this is ugly for multple reasons: it refetches all the info, + * it doesn't use fd etc... we need something better, possibly in gnome-vfs + * public api. + */ +static gchar * +get_slow_mime_type (const char *text_uri) +{ + GnomeVFSFileInfo *info; + char *mime_type; + GnomeVFSResult result; + + info = gnome_vfs_file_info_new (); + result = gnome_vfs_get_file_info (text_uri, info, + GNOME_VFS_FILE_INFO_GET_MIME_TYPE | + GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | + GNOME_VFS_FILE_INFO_FOLLOW_LINKS); + if (info->mime_type == NULL || result != GNOME_VFS_OK) { + mime_type = NULL; + } else { + mime_type = g_strdup (info->mime_type); + } + gnome_vfs_file_info_unref (info); + + return mime_type; +} + +/* ----------- local files ----------- */ + +static gboolean +save_existing_local_file (GeditDocumentSaver *saver) +{ + mode_t saved_umask; + struct stat statbuf; + struct stat new_statbuf; + gchar *backup_filename = NULL; + gint bfd; + + if (fstat (saver->priv->fd, &statbuf) != 0) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + goto out; + } + + /* not a regular file */ + if (!S_ISREG (statbuf.st_mode)) + { + if (S_ISDIR (statbuf.st_mode)) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GNOME_VFS_ERROR_IS_DIRECTORY, + gnome_vfs_result_to_string (GNOME_VFS_ERROR_IS_DIRECTORY)); + } + else + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GEDIT_DOCUMENT_ERROR_NOT_REGULAR_FILE, + "Not a regular file"); + } + + goto out; + } + + /* check if the file is actually writable */ + if ((statbuf.st_mode & 0222) == 0) //FIXME... check better what else vim does + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GNOME_VFS_ERROR_READ_ONLY, + gnome_vfs_result_to_string (GNOME_VFS_ERROR_READ_ONLY)); + + goto out; + } + + /* check if someone else modified the file externally, + * except when "saving as", when saving a new doc (mtime = 0) + * or when the mtime check is explicitely disabled + */ + if (saver->priv->doc_mtime > 0 && + statbuf.st_mtime != saver->priv->doc_mtime && + ((saver->priv->flags & GEDIT_DOCUMENT_SAVE_IGNORE_MTIME) == 0)) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED, + "Externally modified"); + + goto out; + } + + /* prepare the backup name */ + backup_filename = get_backup_filename (saver); + if (backup_filename == NULL) + { + /* bad bad luck... */ + g_warning (_("Could not obtain backup filename")); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GNOME_VFS_ERROR_GENERIC, + gnome_vfs_result_to_string (GNOME_VFS_ERROR_GENERIC)); + + goto out; + } + + /* We now use two backup strategies. + * The first one (which is faster) consist in saving to a + * tmp file then rename the original file to the backup and the + * tmp file to the original name. This is fast but doesn't work + * when the file is a link (hard or symbolic) or when we can't + * write to the current dir or can't set the permissions on the + * new file. We also do not use it when the backup is not in the + * current dir, since if it isn't on the same FS rename wont work. + * The second strategy consist simply in copying the old file + * to a backup file and rewrite the contents of the file. + */ + + if (saver->priv->backups_in_curr_dir && + !(statbuf.st_nlink > 1) && + !g_file_test (saver->priv->local_path, G_FILE_TEST_IS_SYMLINK)) + { + gchar *dirname; + gchar *tmp_filename; + gint tmpfd; + + dirname = g_path_get_dirname (saver->priv->local_path); + tmp_filename = g_build_filename (dirname, ".gedit-save-XXXXXX", NULL); + g_free (dirname); + + /* We set the umask because some (buggy) implementations + * of mkstemp() use permissions 0666 and we want 0600. + */ + saved_umask = umask (0077); + tmpfd = g_mkstemp (tmp_filename); + umask (saved_umask); + + if (tmpfd == -1) + { + g_free (tmp_filename); + goto fallback_strategy; + } + + /* try to set permissions */ + if (fchown (tmpfd, statbuf.st_uid, statbuf.st_gid) == -1 || + fchmod (tmpfd, statbuf.st_mode) == -1) + { + close (tmpfd); + unlink (tmp_filename); + g_free (tmp_filename); + goto fallback_strategy; + } + + if (!write_document_contents (tmpfd, + GTK_TEXT_BUFFER (saver->priv->document), + saver->priv->encoding, + &saver->priv->error)) + { + close (tmpfd); + unlink (tmp_filename); + g_free (tmp_filename); + goto out; + } + + /* original -> backup */ + if (rename (saver->priv->local_path, backup_filename) != 0) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + close (tmpfd); + unlink (tmp_filename); + g_free (tmp_filename); + goto out; + } + + /* tmp -> original */ + if (rename (tmp_filename, saver->priv->local_path) != 0) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + /* try to restore... no error checking */ + rename (backup_filename, saver->priv->local_path); + + close (tmpfd); + unlink (tmp_filename); + g_free (tmp_filename); + goto out; + } + + g_free (tmp_filename); + + /* restat and get the mime type */ + if (fstat (tmpfd, &new_statbuf) != 0) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + close (tmpfd); + goto out; + } + + saver->priv->doc_mtime = new_statbuf.st_mtime; + + saver->priv->mime_type = get_slow_mime_type (saver->priv->uri); + + if (!saver->priv->keep_backup) + unlink (backup_filename); + + close (tmpfd); + + goto out; + } + + fallback_strategy: + + /* try to copy the old contents in a backup for safety + * unless we are explicetely told not to. + */ + if ((saver->priv->flags & GEDIT_DOCUMENT_SAVE_IGNORE_BACKUP) == 0) + { + /* move away old backups */ + if (!remove_file (backup_filename)) + { + /* we don't care about which was the problem, just + * that a backup was not possible. + */ + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP, + "No backup created"); + + goto out; + } + + bfd = open (backup_filename, + O_WRONLY | O_CREAT | O_EXCL, + statbuf.st_mode & 0777); + + if (bfd == -1) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP, + "No backup created"); + + goto out; + } + + /* Try to set the group of the backup same as the + * original file. If this fails, set the protection + * bits for the group same as the protection bits for + * others. */ + if (fchown (bfd, (uid_t) -1, statbuf.st_gid) != 0) + { + if (fchmod (bfd, + (statbuf.st_mode& 0707) | + ((statbuf.st_mode & 07) << 3)) != 0) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP, + "No backup created"); + + unlink (backup_filename); + + goto out; + } + } + + if (!copy_file_data (saver->priv->fd, bfd, NULL)) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP, + "No backup created"); + + unlink (backup_filename); + + goto out; + } + } + + /* finally overwrite the original */ + if (!write_document_contents (saver->priv->fd, + GTK_TEXT_BUFFER (saver->priv->document), + saver->priv->encoding, + &saver->priv->error)) + { + goto out; + } + + /* re stat the file and refetch the mime type */ + if (fstat (saver->priv->fd, &new_statbuf) != 0) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + goto out; + } + + saver->priv->doc_mtime = new_statbuf.st_mtime; + + g_free (saver->priv->mime_type); + saver->priv->mime_type = get_slow_mime_type (saver->priv->uri); + + out: + if (close (saver->priv->fd)) + g_warning ("File '%s' has not been correctly closed: %s", + saver->priv->uri, + strerror (errno)); + saver->priv->fd = -1; + + g_free (backup_filename); + + save_completed_or_failed (saver); + + /* stop the timeout */ + return FALSE; +} + +static gboolean +save_new_local_file (GeditDocumentSaver *saver) +{ + struct stat statbuf; + + if (!write_document_contents (saver->priv->fd, + GTK_TEXT_BUFFER (saver->priv->document), + saver->priv->encoding, + &saver->priv->error)) + { + goto out; + } + + /* stat the file and fetch the mime type */ + if (fstat (saver->priv->fd, &statbuf) != 0) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + goto out; + } + + saver->priv->doc_mtime = statbuf.st_mtime; + + g_free (saver->priv->mime_type); + saver->priv->mime_type = get_slow_mime_type (saver->priv->uri); + + out: + if (close (saver->priv->fd)) + g_warning ("File '%s' has not been correctly closed: %s", + saver->priv->uri, + strerror (errno)); + + saver->priv->fd = -1; + + save_completed_or_failed (saver); + + /* stop the timeout */ + return FALSE; +} + +static gboolean +open_local_failed (GeditDocumentSaver *saver) +{ + save_completed_or_failed (saver); + + /* stop the timeout */ + return FALSE; +} + +static void +save_local_file (GeditDocumentSaver *saver) +{ + GSourceFunc next_phase; + + /* saving start */ + g_signal_emit (saver, + signals[SAVING], + 0, + FALSE, + NULL); + + /* the file doesn't exist, create it */ + saver->priv->fd = open (saver->priv->local_path, + O_CREAT | O_EXCL | O_WRONLY, + 0666); + if (saver->priv->fd != -1) + { + next_phase = (GSourceFunc) save_new_local_file; + goto out; + } + + /* the file already exist */ + else if (errno == EEXIST) + { + saver->priv->fd = open (saver->priv->local_path, O_RDWR); + if (saver->priv->fd != -1) + { + next_phase = (GSourceFunc) save_existing_local_file; + goto out; + } + } + + /* else error */ + GnomeVFSResult result = gnome_vfs_result_from_errno (); //may it happen that no errno? + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + next_phase = (GSourceFunc) open_local_failed; + + out: + g_timeout_add_full (G_PRIORITY_HIGH, + 0, + next_phase, + saver, + NULL); +} + +/* ----------- remote files ----------- */ + +static void +remote_save_completed_or_failed (GeditDocumentSaver *saver) +{ + /* we can now close and unlink the tmp file */ + close (saver->priv->tmpfd); + unlink (saver->priv->tmp_fname); + + save_completed_or_failed (saver); +} + +static void +remote_get_info_cb (GnomeVFSAsyncHandle *handle, + GList *results, + gpointer data) +{ + GeditDocumentSaver *saver = GEDIT_DOCUMENT_SAVER (data); + GnomeVFSGetFileInfoResult *info_result; + + /* assert that the list has one and only one item */ + g_return_if_fail (results != NULL && results->next == NULL); + + info_result = (GnomeVFSGetFileInfoResult *) results->data; + g_return_if_fail (info_result != NULL); + + if (info_result->result != GNOME_VFS_OK) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + info_result->result, + gnome_vfs_result_to_string (info_result->result)); + + remote_save_completed_or_failed (saver); + + return; + } + + if (info_result->file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME) + saver->priv->doc_mtime = info_result->file_info->mtime; + + if (info_result->file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) + { + g_free (saver->priv->mime_type); + saver->priv->mime_type = g_strdup (info_result->file_info->mime_type); + } + + remote_save_completed_or_failed (saver); +} + +static gint +async_xfer_ok (GnomeVFSXferProgressInfo *progress_info, + GeditDocumentSaver *saver) +{ + switch (progress_info->phase) + { + case GNOME_VFS_XFER_PHASE_INITIAL: + break; + case GNOME_VFS_XFER_CHECKING_DESTINATION: + { + GnomeVFSFileInfo *orig_info; + GnomeVFSResult res; + + /* we need to retrieve info ourselves too, since xfer + * doesn't allow to access it :( + * If that was not enough we need to do it sync or we are going + * to mess everything up + */ + orig_info = gnome_vfs_file_info_new (); + res = gnome_vfs_get_file_info_uri (saver->priv->vfs_uri, + orig_info, + GNOME_VFS_FILE_INFO_DEFAULT | + GNOME_VFS_FILE_INFO_FOLLOW_LINKS); + + if (res == GNOME_VFS_ERROR_NOT_FOUND) + { + /* ok, we are not overwriting, go on with the xfer */ + break; + } + + if (res != GNOME_VFS_OK) + { + // CHECK: do we want to ignore the error and try to go on anyway? + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + res, + gnome_vfs_result_to_string (res)); + + /* abort xfer */ + return 0; + } + + + /* check if someone else modified the file externally, + * except when "saving as", when saving a new doc (mtime = 0) + * or when the mtime check is explicitely disabled + */ + if (orig_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME) + { + if (saver->priv->doc_mtime > 0 && + orig_info->mtime != saver->priv->doc_mtime && + ((saver->priv->flags & GEDIT_DOCUMENT_SAVE_IGNORE_MTIME) == 0)) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED, + "Externally modified"); + + /* abort xfer */ + return 0; + } + } + + /* store the original file info, so that we can restore permissions */ + // FIXME: what about the case where we are usin "Save as" but overwriting a file... we don't want to restore perms + if (orig_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS) + saver->priv->orig_info = orig_info; + } + break; + case GNOME_VFS_XFER_PHASE_COLLECTING: + case GNOME_VFS_XFER_PHASE_DELETESOURCE: // why do we get this phase?? + break; + case GNOME_VFS_XFER_PHASE_READYTOGO: + saver->priv->size = progress_info->bytes_total; + break; + case GNOME_VFS_XFER_PHASE_OPENSOURCE: + case GNOME_VFS_XFER_PHASE_OPENTARGET: + case GNOME_VFS_XFER_PHASE_COPYING: + case GNOME_VFS_XFER_PHASE_WRITETARGET: + case GNOME_VFS_XFER_PHASE_CLOSETARGET: + if (progress_info->bytes_copied > 0) + saver->priv->bytes_written = MIN (progress_info->total_bytes_copied, + progress_info->bytes_total); + break; + case GNOME_VFS_XFER_PHASE_FILECOMPLETED: + case GNOME_VFS_XFER_PHASE_CLEANUP: + break; + case GNOME_VFS_XFER_PHASE_COMPLETED: + /* Transfer done! + * Restore the permissions if needed and then refetch + * info on our newly written file to get the mime etc */ + { + GList *uri_list = NULL; + + /* Try is not as paranoid as the local version (GID)... it would take + * yet another stat to do it... + */ + if (saver->priv->orig_info != NULL && + (saver->priv->orig_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS)) + { + gnome_vfs_set_file_info_uri (saver->priv->vfs_uri, + saver->priv->orig_info, + GNOME_VFS_SET_FILE_INFO_PERMISSIONS); + + // FIXME: for now is a blind try... do we want to error check? + } + + uri_list = g_list_prepend (uri_list, saver->priv->vfs_uri); + + gnome_vfs_async_get_file_info (&saver->priv->info_handle, + uri_list, + GNOME_VFS_FILE_INFO_DEFAULT | + GNOME_VFS_FILE_INFO_GET_MIME_TYPE | + GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | + GNOME_VFS_FILE_INFO_FOLLOW_LINKS, + GNOME_VFS_PRIORITY_MAX, + remote_get_info_cb, + saver); + g_list_free (uri_list); + } + break; + /* Phases we don't expect to see */ + case GNOME_VFS_XFER_PHASE_SETATTRIBUTES: + case GNOME_VFS_XFER_PHASE_CLOSESOURCE: + case GNOME_VFS_XFER_PHASE_MOVING: + case GNOME_VFS_XFER_PHASE_READSOURCE: + default: + g_return_val_if_reached (0); + } + + /* signal the progress */ + g_signal_emit (saver, + signals[SAVING], + 0, + FALSE, + NULL); + + return 1; +} + +static gint +async_xfer_error (GnomeVFSXferProgressInfo *progress_info, + GeditDocumentSaver *saver) +{ + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + progress_info->vfs_status, + gnome_vfs_result_to_string (progress_info->vfs_status)); + + remote_save_completed_or_failed (saver); + + return GNOME_VFS_XFER_ERROR_ACTION_ABORT; +} + +static gint +async_xfer_progress (GnomeVFSAsyncHandle *handle, + GnomeVFSXferProgressInfo *progress_info, + gpointer data) +{ + GeditDocumentSaver *saver = GEDIT_DOCUMENT_SAVER (data); + + switch (progress_info->status) + { + case GNOME_VFS_XFER_PROGRESS_STATUS_OK: + return async_xfer_ok (progress_info, saver); + case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR: + return async_xfer_error (progress_info, saver); + + /* we should never go in these */ + case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE: + case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE: + default: + g_return_val_if_reached (0); + } +} + +static gboolean +save_remote_file_real (GeditDocumentSaver *saver) +{ + mode_t saved_umask; + gchar *tmp_uri; + GnomeVFSURI *tmp_vfs_uri; + GList *source_uri_list = NULL; + GList *dest_uri_list = NULL; + GnomeVFSResult result; + + /* For remote files we use the following strategy: + * we save to a local temp file and then transfer it + * over to the requested location asyncronously. + * There is no backup of the original remote file. + */ + + /* We set the umask because some (buggy) implementations + * of mkstemp() use permissions 0666 and we want 0600. + */ + saved_umask = umask (0077); + saver->priv->tmpfd = g_file_open_tmp (".gedit-save-XXXXXX", + &saver->priv->tmp_fname, + &saver->priv->error); + umask (saved_umask); + + if (saver->priv->tmpfd == -1) + { + GnomeVFSResult result = gnome_vfs_result_from_errno (); + + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + /* in this case no need to close the tmp file */ + save_completed_or_failed (saver); + + return FALSE; + } + + tmp_uri = g_filename_to_uri (saver->priv->tmp_fname, + NULL, + &saver->priv->error); + if (tmp_uri == NULL) + { + goto error; + } + + tmp_vfs_uri = gnome_vfs_uri_new (tmp_uri); + //needs error checking? + + g_free (tmp_uri); + + source_uri_list = g_list_prepend (source_uri_list, tmp_vfs_uri); + dest_uri_list = g_list_prepend (dest_uri_list, saver->priv->vfs_uri); + + if (!write_document_contents (saver->priv->tmpfd, + GTK_TEXT_BUFFER (saver->priv->document), + saver->priv->encoding, + &saver->priv->error)) + { + goto error; + } + + result = gnome_vfs_async_xfer (&saver->priv->handle, + source_uri_list, + dest_uri_list, + GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_TARGET_DEFAULT_PERMS, // CHECK needs more thinking, follow symlinks etc... options are undocumented :( + GNOME_VFS_XFER_ERROR_MODE_ABORT, /* keep it simple, abort on any error */ + GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE, /* We have already asked confirm (even if it is racy) */ + GNOME_VFS_PRIORITY_DEFAULT, + async_xfer_progress, saver, + NULL, NULL); + + gnome_vfs_uri_unref (tmp_vfs_uri); + g_list_free (source_uri_list); + g_list_free (dest_uri_list); + + if (result != GNOME_VFS_OK) + { + g_set_error (&saver->priv->error, + GEDIT_DOCUMENT_ERROR, + result, + gnome_vfs_result_to_string (result)); + + goto error; + } + + /* No errors: stop the timeout */ + return FALSE; + + error: + remote_save_completed_or_failed (saver); + + /* stop the timeout */ + return FALSE; +} + +static void +save_remote_file (GeditDocumentSaver *saver) +{ + /* saving start */ + g_signal_emit (saver, + signals[SAVING], + 0, + FALSE, + NULL); + + g_timeout_add_full (G_PRIORITY_HIGH, + 0, + (GSourceFunc) save_remote_file_real, + saver, + NULL); +} + +/* ---------- public api ---------- */ + +void +gedit_document_saver_save (GeditDocumentSaver *saver, + const gchar *uri, + const GeditEncoding *encoding, + time_t oldmtime, + GeditDocumentSaveFlags flags) +{ + gchar *local_path; + + g_return_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver)); + g_return_if_fail ((uri != NULL) && (strlen (uri) > 0)); + + // CHECK: + // - sanity check a max len for the uri? + // - check a whitelist of allowed uri types + // report async (in an idle handler) or sync (bool ret) + // async is extra work here, sync is special casing in the caller + + saver->priv->uri = g_strdup (uri); + + /* fetch saving options */ + saver->priv->backup_ext = gedit_prefs_manager_get_backup_extension (); + saver->priv->keep_backup = gedit_prefs_manager_get_create_backup_copy (); + saver->priv->backups_in_curr_dir = TRUE; // TODO configurable backup dir + + if (encoding != NULL) + saver->priv->encoding = encoding; + else + saver->priv->encoding = gedit_encoding_get_utf8 (); + + saver->priv->doc_mtime = oldmtime; + + saver->priv->flags = flags; + + local_path = gnome_vfs_get_local_path_from_uri (uri); + if (local_path != NULL) + { + saver->priv->local_path = local_path; + save_local_file (saver); + } + else + { + saver->priv->vfs_uri = gnome_vfs_uri_new (uri); + save_remote_file (saver); + } +} + +const gchar * +gedit_document_saver_get_uri (GeditDocumentSaver *saver) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), NULL); + + return saver->priv->uri; +} + +const gchar * +gedit_document_saver_get_mime_type (GeditDocumentSaver *saver) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), NULL); + + return saver->priv->mime_type; +} + +time_t +gedit_document_saver_get_mtime (GeditDocumentSaver *saver) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), 0); + + return saver->priv->doc_mtime; +} + +/* Returns 0 if file size is unknown */ +GnomeVFSFileSize +gedit_document_saver_get_file_size (GeditDocumentSaver *saver) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), 0); + + return saver->priv->size; +} + +GnomeVFSFileSize +gedit_document_saver_get_bytes_written (GeditDocumentSaver *saver) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT_SAVER (saver), 0); + + return saver->priv->bytes_written; +} diff --git a/gedit/gedit-document-saver.h b/gedit/gedit-document-saver.h new file mode 100644 index 00000000..155d3f1b --- /dev/null +++ b/gedit/gedit-document-saver.h @@ -0,0 +1,117 @@ +/* + * gedit-document-saver.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_DOCUMENT_SAVER_H__ +#define __GEDIT_DOCUMENT_SAVER_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_DOCUMENT_SAVER (gedit_document_saver_get_type()) +#define GEDIT_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaver)) +#define GEDIT_DOCUMENT_SAVER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaver const)) +#define GEDIT_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaverClass)) +#define GEDIT_IS_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENT_SAVER)) +#define GEDIT_IS_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT_SAVER)) +#define GEDIT_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENT_SAVER, GeditDocumentSaverClass)) + +/* Private structure type */ +typedef struct _GeditDocumentSaverPrivate GeditDocumentSaverPrivate; + +/* + * Main object structure + */ +typedef struct _GeditDocumentSaver GeditDocumentSaver; + +struct _GeditDocumentSaver +{ + GObject object; + + /*< private > */ + GeditDocumentSaverPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditDocumentSaverClass GeditDocumentSaverClass; + +struct _GeditDocumentSaverClass +{ + GObjectClass parent_class; + + void (* saving) (GeditDocumentSaver *saver, + gboolean completed, + const GError *error); +}; + +/* + * Public methods + */ +GType gedit_document_saver_get_type (void) G_GNUC_CONST; + +GeditDocumentSaver *gedit_document_saver_new (GeditDocument *doc); + +/* If enconding == NULL, the encoding will be autodetected */ +void gedit_document_saver_save (GeditDocumentSaver *saver, + const gchar *uri, + const GeditEncoding *encoding, + time_t oldmtime, + GeditDocumentSaveFlags flags); + +#if 0 +void gedit_document_saver_cancel (GeditDocumentSaver *saver); +#endif + +const gchar *gedit_document_saver_get_uri (GeditDocumentSaver *saver); + +/* If backup_uri is NULL no backup will be made */ +const gchar *gedit_document_saver_get_backup_uri (GeditDocumentSaver *saver); +void *gedit_document_saver_set_backup_uri (GeditDocumentSaver *saver, + const gchar *backup_uri); + +const gchar *gedit_document_saver_get_mime_type (GeditDocumentSaver *saver); + +time_t gedit_document_saver_get_mtime (GeditDocumentSaver *saver); + +/* Returns 0 if file size is unknown */ +GnomeVFSFileSize gedit_document_saver_get_file_size (GeditDocumentSaver *saver); + +GnomeVFSFileSize gedit_document_saver_get_bytes_written (GeditDocumentSaver *saver); + + +G_END_DECLS + +#endif /* __GEDIT_DOCUMENT_SAVER_H__ */ diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c index 05a6999e..696eacab 100644 --- a/gedit/gedit-document.c +++ b/gedit/gedit-document.c @@ -1,11 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * 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, 2003, 2004 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 @@ -24,28 +23,22 @@ */ /* - * Modified by the gedit Team, 1998-2004. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H #include #endif -#include -#include -#include #include -#include -#include -#include -#include +#include #include #include -#include -#include #include "gedit-prefs-manager-app.h" #include "gedit-document.h" @@ -54,7 +47,8 @@ #include "gedit-convert.h" #include "gedit-metadata-manager.h" #include "gedit-languages-manager.h" - +#include "gedit-document-loader.h" +#include "gedit-document-saver.h" #include "gedit-marshal.h" #include @@ -77,97 +71,99 @@ PROFILE (static GTimer *timer = NULL); #define GEDIT_MAX_PATH_LEN 2048 #endif +#define GEDIT_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_DOCUMENT, GeditDocumentPrivate)) + +static void gedit_document_set_readonly (GeditDocument *doc, + gboolean readonly); + struct _GeditDocumentPrivate { - gchar *uri; - gint untitled_number; + gint auto_save : 1; + gint readonly : 1; + gint last_save_was_manually : 1; + gint language_set_by_user : 1; + gint is_saving_as : 1; + gint has_selection : 1; + gint stop_cursor_moved_emission : 1; - gchar *uri_for_display; - gchar *short_name_for_display; + gchar *uri; + gint untitled_number; - gchar *encoding; + GnomeVFSURI *vfs_uri; - gchar *mime_type; + const GeditEncoding *encoding; - gchar *last_searched_text; - gchar *last_replace_text; - gboolean last_search_was_case_sensitive; - gboolean last_search_was_entire_word; + gchar *mime_type; - gboolean auto_save; - gint auto_save_interval; + gint auto_save_interval; + guint auto_save_timeout; - guint auto_save_timeout; - gboolean last_save_was_manually; + time_t mtime; - GTimeVal time_of_last_save_or_load; + GTimeVal time_of_last_save_or_load; - gboolean readonly; + guint search_flags; + gchar *search_text; - /* Info needed for implementing async loading */ - EelReadFileHandle *read_handle; - GnomeVFSAsyncHandle *info_handle; + /* Temp data while loading */ + GeditDocumentLoader *loader; + gboolean create; /* Create file if uri points + * to a non existing file */ + const GeditEncoding *requested_encoding; + gint requested_line_pos; - const GeditEncoding *temp_encoding; - gchar *temp_uri; - gulong temp_size; + /* Saving stuff */ + GeditDocumentSaver *saver; }; enum { - NAME_CHANGED, - SAVED, - LOADED, + PROP_0, + + PROP_URI, + PROP_SHORTNAME, + PROP_MIME_TYPE, + PROP_READ_ONLY, + PROP_ENCODING, + PROP_CAN_SEARCH_AGAIN, + PROP_HAS_SELECTION +}; + +enum { + CURSOR_MOVED, LOADING, - READONLY_CHANGED, - CAN_FIND_AGAIN, + LOADED, + SAVING, + SAVED, LAST_SIGNAL }; -static void gedit_document_class_init (GeditDocumentClass *klass); -static void gedit_document_init (GeditDocument *document); -static void gedit_document_finalize (GObject *object); - -static void gedit_document_real_name_changed (GeditDocument *document); -static void gedit_document_real_loaded (GeditDocument *document, - const GError *error); -static void gedit_document_real_saved (GeditDocument *document); -static void gedit_document_real_readonly_changed (GeditDocument *document, - gboolean readonly); -static void gedit_document_real_can_find_again (GeditDocument *document); - -static gboolean gedit_document_save_as_real (GeditDocument *doc, - const gchar *uri, - const GeditEncoding *encoding, - gboolean create_backup_copy, - GError **error); - -static void gedit_document_set_uri (GeditDocument *doc, - const gchar *uri, - const GeditEncoding *encoding, - gboolean enc_autodetected); - -static gboolean gedit_document_auto_save (GeditDocument *doc); - -static GtkTextBufferClass *parent_class = NULL; -static guint document_signals[LAST_SIGNAL] = { 0 }; +static guint document_signals[LAST_SIGNAL] = { 0 }; -static GHashTable *allocated_untitled_numbers = NULL; +G_DEFINE_TYPE(GeditDocument, gedit_document, GTK_TYPE_SOURCE_BUFFER) + +GQuark +gedit_document_error_quark (void) +{ + static GQuark quark; + + if (!quark) + quark = g_quark_from_static_string ("gedit_io_load_error"); + + return quark; +} -static gint gedit_document_get_untitled_number (void); -static void gedit_document_release_untitled_number (gint n); +static GHashTable *allocated_untitled_numbers = NULL; static gint -gedit_document_get_untitled_number (void) +get_untitled_number (void) { gint i = 1; - - gedit_debug (DEBUG_DOCUMENT, ""); if (allocated_untitled_numbers == NULL) allocated_untitled_numbers = g_hash_table_new (NULL, NULL); g_return_val_if_fail (allocated_untitled_numbers != NULL, -1); - + while (TRUE) { if (g_hash_table_lookup (allocated_untitled_numbers, GINT_TO_POINTER (i)) == NULL) @@ -175,92 +171,250 @@ gedit_document_get_untitled_number (void) g_hash_table_insert (allocated_untitled_numbers, GINT_TO_POINTER (i), GINT_TO_POINTER (i)); - + return i; } - + ++i; - } + } } static void -gedit_document_release_untitled_number (gint n) +release_untitled_number (gint n) { - gboolean ret; - g_return_if_fail (allocated_untitled_numbers != NULL); - gedit_debug (DEBUG_DOCUMENT, ""); + g_hash_table_remove (allocated_untitled_numbers, GINT_TO_POINTER (n)); +} + +static void +gedit_document_finalize (GObject *object) +{ + GeditDocument *doc = GEDIT_DOCUMENT (object); + + gedit_debug (DEBUG_DOCUMENT); + + if (doc->priv->auto_save_timeout > 0) + g_source_remove (doc->priv->auto_save_timeout); + + if (doc->priv->untitled_number > 0) + { + g_return_if_fail (doc->priv->uri == NULL); + release_untitled_number (doc->priv->untitled_number); + } + + if (doc->priv->uri != NULL) + { + GtkTextIter iter; + gchar *position; + gchar *lang_id = NULL; + GtkSourceLanguage *lang; + + gtk_text_buffer_get_iter_at_mark ( + GTK_TEXT_BUFFER (doc), + &iter, + gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (doc))); + + position = g_strdup_printf ("%d", + gtk_text_iter_get_offset (&iter)); + + gedit_metadata_manager_set (doc->priv->uri, + "position", + position); + g_free (position); + + if (doc->priv->language_set_by_user) + { + lang = gedit_document_get_language (doc); + + if (lang != NULL) + lang_id = gtk_source_language_get_id (lang); - ret = g_hash_table_remove (allocated_untitled_numbers, GINT_TO_POINTER (n)); - g_return_if_fail (ret); + gedit_metadata_manager_set (doc->priv->uri, + "language", + (lang_id == NULL) ? "_NORMAL_" : lang_id); + g_free (lang_id); + } + } + + g_free (doc->priv->uri); + if (doc->priv->vfs_uri != NULL) + gnome_vfs_uri_unref (doc->priv->vfs_uri); + + g_free (doc->priv->mime_type); + + if (doc->priv->loader) + g_object_unref (doc->priv->loader); + + g_free (doc->priv->search_text); + + G_OBJECT_CLASS (gedit_document_parent_class)->finalize (object); } -GType -gedit_document_get_type (void) +static void +gedit_document_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditDocument *doc = GEDIT_DOCUMENT (object); + + switch (prop_id) + { + case PROP_URI: + g_value_set_string (value, doc->priv->uri); + break; + case PROP_SHORTNAME: + g_value_take_string (value, gedit_document_get_short_name_for_display (doc)); + break; + case PROP_MIME_TYPE: + g_value_set_string (value, doc->priv->mime_type); + break; + case PROP_READ_ONLY: + g_value_set_boolean (value, doc->priv->readonly); + break; + case PROP_ENCODING: + g_value_set_boxed (value, doc->priv->encoding); + break; + case PROP_CAN_SEARCH_AGAIN: + g_value_set_boolean (value, gedit_document_get_can_search_again (doc)); + break; + case PROP_HAS_SELECTION: + g_value_set_boolean (value, doc->priv->has_selection); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +emit_cursor_moved (GeditDocument *doc) { - static GType document_type = 0; - - if (document_type == 0) - { - static const GTypeInfo our_info = - { - sizeof (GeditDocumentClass), - NULL, /* base_init,*/ - NULL, /* base_finalize, */ - (GClassInitFunc) gedit_document_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GeditDocument), - 0, /* n_preallocs */ - (GInstanceInitFunc) gedit_document_init - }; - - document_type = g_type_register_static (GTK_TYPE_SOURCE_BUFFER, - "GeditDocument", - &our_info, - 0); - } - - return document_type; + if (!doc->priv->stop_cursor_moved_emission) + { + g_signal_emit (doc, + document_signals[CURSOR_MOVED], + 0); + } } - static void -gedit_document_class_init (GeditDocumentClass *klass) +gedit_document_mark_set (GtkTextBuffer *buffer, + const GtkTextIter *iter, + GtkTextMark *mark) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditDocument *doc = GEDIT_DOCUMENT (buffer); + + if (GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->mark_set) + GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->mark_set (buffer, + iter, + mark); + + if (mark == gtk_text_buffer_get_insert (buffer) || + mark == gtk_text_buffer_get_selection_bound (buffer)) + { + gboolean has_selection; + + has_selection = gtk_text_buffer_get_selection_bounds (buffer, + NULL, + NULL); + + if (has_selection != doc->priv->has_selection) + { + doc->priv->has_selection = has_selection; + g_object_notify (G_OBJECT (doc), "has-selection"); + } + } - parent_class = g_type_class_peek_parent (klass); + if (mark == gtk_text_buffer_get_insert (buffer)) + { + emit_cursor_moved (doc); + } +} - object_class->finalize = gedit_document_finalize; +static void +gedit_document_changed (GtkTextBuffer *buffer) +{ + emit_cursor_moved (GEDIT_DOCUMENT (buffer)); - klass->name_changed = gedit_document_real_name_changed; - klass->loaded = gedit_document_real_loaded; - klass->saved = gedit_document_real_saved; - klass->readonly_changed = gedit_document_real_readonly_changed; - klass->can_find_again = gedit_document_real_can_find_again; + GTK_TEXT_BUFFER_CLASS (gedit_document_parent_class)->changed (buffer); +} - document_signals[NAME_CHANGED] = - g_signal_new ("name_changed", +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->finalize = gedit_document_finalize; + object_class->get_property = gedit_document_get_property; + + buf_class->mark_set = gedit_document_mark_set; + buf_class->changed = gedit_document_changed; + + g_object_class_install_property (object_class, PROP_URI, + g_param_spec_string ("uri", + "URI", + "The document's URI", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_SHORTNAME, + g_param_spec_string ("shortname", + "Short Name", + "The document's short name", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_MIME_TYPE, + g_param_spec_string ("mime-type", + "MIME Type", + "The document's MIME Type", + "text/plain", + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_READ_ONLY, + g_param_spec_boolean ("read-only", + "Read Only", + "Whether the document is read only or not", + FALSE, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_ENCODING, + g_param_spec_boxed ("encoding", + "Encoding", + "The GeditEncoding used for the document", + GEDIT_TYPE_ENCODING, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_CAN_SEARCH_AGAIN, + g_param_spec_boolean ("can-search-again", + "Can search again", + "Wheter it's possible to search again in the document", + FALSE, + G_PARAM_READABLE)); + + /* This has been properly moved in GtkTextBuffer in gtk 2.10, so when + * we switch to 2.10 we can remove it and part of with gedit_document_mark_set. + */ + g_object_class_install_property (object_class, PROP_HAS_SELECTION, + g_param_spec_boolean ("has-selection", + "Has selection", + "Wheter the document has selected text", + FALSE, + G_PARAM_READABLE)); + + /* This signal is used to update the cursor position is the statusbar, + * it's emitted either when the insert mark is moved explicitely or + * when the buffer changes (insert/delete). + * We prevent the emission of the signal during replace_all to + * improve performance. + */ + document_signals[CURSOR_MOVED] = + g_signal_new ("cursor-moved", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GeditDocumentClass, name_changed), + G_STRUCT_OFFSET (GeditDocumentClass, cursor_moved), NULL, NULL, - gedit_marshal_VOID__VOID, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - document_signals[LOADED] = - g_signal_new ("loaded", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GeditDocumentClass, loaded), - NULL, NULL, - gedit_marshal_VOID__POINTER, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); document_signals[LOADING] = g_signal_new ("loading", @@ -268,2445 +422,1111 @@ gedit_document_class_init (GeditDocumentClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GeditDocumentClass, loading), NULL, NULL, - gedit_marshal_VOID__ULONG_ULONG, + gedit_marshal_VOID__UINT64_UINT64, G_TYPE_NONE, 2, - G_TYPE_ULONG, - G_TYPE_ULONG); + G_TYPE_UINT64, + G_TYPE_UINT64); - - document_signals[SAVED] = - g_signal_new ("saved", + document_signals[LOADED] = + g_signal_new ("loaded", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GeditDocumentClass, saved), + G_STRUCT_OFFSET (GeditDocumentClass, loaded), NULL, NULL, - gedit_marshal_VOID__VOID, + g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, - 0); + 1, + G_TYPE_POINTER); - document_signals[READONLY_CHANGED] = - g_signal_new ("readonly_changed", + document_signals[SAVING] = + g_signal_new ("saving", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GeditDocumentClass, readonly_changed), + G_STRUCT_OFFSET (GeditDocumentClass, saving), NULL, NULL, - gedit_marshal_VOID__BOOLEAN, + gedit_marshal_VOID__UINT64_UINT64, G_TYPE_NONE, - 1, - G_TYPE_BOOLEAN); + 2, + G_TYPE_UINT64, + G_TYPE_UINT64); - document_signals[CAN_FIND_AGAIN] = - g_signal_new ("can_find_again", + document_signals[SAVED] = + g_signal_new ("saved", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GeditDocumentClass, can_find_again), + G_STRUCT_OFFSET (GeditDocumentClass, saved), NULL, NULL, - gedit_marshal_VOID__VOID, + g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, - 0); + 1, + G_TYPE_POINTER); + + g_type_class_add_private (object_class, sizeof(GeditDocumentPrivate)); } -static gchar * -get_uri_shortname_for_display (GnomeVFSURI *uri) +static void +set_language (GeditDocument *doc, + GtkSourceLanguage *lang, + gboolean set_by_user) { - gchar *name; - gboolean validated; + GtkSourceLanguage *old_lang; - validated = FALSE; - name = gnome_vfs_uri_extract_short_name (uri); + gedit_debug (DEBUG_DOCUMENT); - if (name == NULL) - { - name = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD); - } - else if (g_ascii_strcasecmp (uri->method_string, "file") == 0) - { - gchar *text_uri; - gchar *local_file; - text_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD); - local_file = gnome_vfs_get_local_path_from_uri (text_uri); - - if (local_file != NULL) - { - g_free (name); - name = g_filename_display_basename (local_file); - validated = TRUE; - } + old_lang = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (doc)); + + if (old_lang == lang) + return; + + gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (doc), lang); + if (lang != NULL) + gedit_language_init_tag_styles (lang); - g_free (local_file); - g_free (text_uri); - } - else if (!gnome_vfs_uri_has_parent (uri)) + if (lang != NULL) + gtk_source_buffer_set_highlight (GTK_SOURCE_BUFFER (doc), + gedit_prefs_manager_get_enable_syntax_highlighting ()); + else + gtk_source_buffer_set_highlight (GTK_SOURCE_BUFFER (doc), + FALSE); + + if (set_by_user && (doc->priv->uri != NULL)) { - const gchar *method; - - method = uri->method_string; - - if (name == NULL || - strcmp (name, GNOME_VFS_URI_PATH_STR) == 0) - { - g_free (name); - name = g_strdup (method); - } - else + gchar *lang_id = NULL; + + if (lang != NULL) { - gchar *tmp; - - tmp = name; - name = g_strdup_printf ("%s: %s", method, name); - g_free (tmp); + lang_id = gtk_source_language_get_id (lang); + g_return_if_fail (lang_id != NULL); } - } - - if (!validated && !g_utf8_validate (name, -1, NULL)) - { - gchar *utf8_name; - utf8_name = gedit_utils_make_valid_utf8 (name); - g_free (name); - name = utf8_name; - } + gedit_metadata_manager_set (doc->priv->uri, + "language", + (lang_id == NULL) ? "_NORMAL_" : lang_id); - return name; + g_free (lang_id); + } + + doc->priv->language_set_by_user = set_by_user; } static void -update_uri_for_display (GeditDocument *doc) +set_encoding (GeditDocument *doc, + const GeditEncoding *encoding, + gboolean set_by_user) { - gedit_debug (DEBUG_DOCUMENT, ""); + g_return_if_fail (encoding != NULL); - g_free (doc->priv->uri_for_display); - g_free (doc->priv->short_name_for_display); + gedit_debug (DEBUG_DOCUMENT); - if (doc->priv->uri == NULL) - { - doc->priv->uri_for_display = g_strdup_printf (_("%s %d"), _("Unsaved Document"), - doc->priv->untitled_number); - doc->priv->short_name_for_display = g_strdup (doc->priv->uri_for_display); - } - else - { - GnomeVFSURI *vfs_uri; + if (doc->priv->encoding == encoding) + return; - vfs_uri = gnome_vfs_uri_new (doc->priv->uri); + doc->priv->encoding = encoding; - doc->priv->uri_for_display = gnome_vfs_format_uri_for_display (doc->priv->uri); + if (set_by_user) + { + const gchar *charset; - if (vfs_uri == NULL) - doc->priv->short_name_for_display = g_strdup (doc->priv->uri_for_display); - else - { - doc->priv->short_name_for_display = get_uri_shortname_for_display (vfs_uri); + charset = gedit_encoding_get_charset (encoding); - gnome_vfs_uri_unref (vfs_uri); - } + gedit_metadata_manager_set (doc->priv->uri, + "encoding", + charset); } + + g_object_notify (G_OBJECT (doc), "encoding"); } static void -gedit_document_init (GeditDocument *document) +gedit_document_init (GeditDocument *doc) { - const GeditEncoding *enc; - - gedit_debug (DEBUG_DOCUMENT, ""); + gedit_debug (DEBUG_DOCUMENT); - document->priv = g_new0 (GeditDocumentPrivate, 1); - - document->priv->uri = NULL; - document->priv->untitled_number = 0; + doc->priv = GEDIT_DOCUMENT_GET_PRIVATE (doc); - document->priv->mime_type = g_strdup ("text/plain"); + doc->priv->uri = NULL; + doc->priv->vfs_uri = NULL; + doc->priv->untitled_number = get_untitled_number (); - document->priv->readonly = FALSE; + doc->priv->mime_type = g_strdup ("text/plain"); - document->priv->last_save_was_manually = TRUE; + doc->priv->readonly = FALSE; - g_get_current_time (&document->priv->time_of_last_save_or_load); + doc->priv->has_selection = FALSE; + doc->priv->stop_cursor_moved_emission = FALSE; - enc = gedit_encoding_get_utf8 (); - - document->priv->encoding = g_strdup ( - gedit_encoding_get_charset (enc)); + doc->priv->last_save_was_manually = TRUE; + doc->priv->language_set_by_user = FALSE; + + doc->priv->mtime = 0; - gedit_document_set_max_undo_levels (document, - gedit_prefs_manager_get_undo_actions_limit ()); + g_get_current_time (&doc->priv->time_of_last_save_or_load); + + doc->priv->encoding = gedit_encoding_get_utf8 (); + gtk_source_buffer_set_max_undo_levels (GTK_SOURCE_BUFFER (doc), + gedit_prefs_manager_get_undo_actions_limit ()); /* TODO: Set the bracket matching tag style -- Paolo (10 Jan. 2005) */ - gtk_source_buffer_set_check_brackets (GTK_SOURCE_BUFFER (document), + gtk_source_buffer_set_check_brackets (GTK_SOURCE_BUFFER (doc), gedit_prefs_manager_get_bracket_matching ()); - document->priv->auto_save = gedit_prefs_manager_get_auto_save (); - document->priv->auto_save = (document->priv->auto_save != FALSE); + doc->priv->auto_save = gedit_prefs_manager_get_auto_save (); + doc->priv->auto_save = (doc->priv->auto_save != FALSE); + + doc->priv->auto_save_interval = gedit_prefs_manager_get_auto_save_interval (); + if (doc->priv->auto_save_interval <= 0) + doc->priv->auto_save_interval = GPM_DEFAULT_AUTO_SAVE_INTERVAL; +} + +GeditDocument * +gedit_document_new (void) +{ + gedit_debug (DEBUG_DOCUMENT); - document->priv->auto_save_interval = gedit_prefs_manager_get_auto_save_interval (); - if (document->priv->auto_save_interval <= 0) - document->priv->auto_save_interval = GPM_DEFAULT_AUTO_SAVE_INTERVAL; + return GEDIT_DOCUMENT (g_object_new (GEDIT_TYPE_DOCUMENT, NULL)); } +/* If mime type is null, we guess from the filename */ +/* If uri is null, we only set the mime-type */ static void -gedit_document_finalize (GObject *object) +set_uri (GeditDocument *doc, + const gchar *uri, + const gchar *mime_type) { - GeditDocument *document; + gedit_debug (DEBUG_DOCUMENT); - gedit_debug (DEBUG_DOCUMENT, ""); + g_return_if_fail ((uri == NULL) || gedit_utils_is_valid_uri (uri)); - g_return_if_fail (object != NULL); - g_return_if_fail (GEDIT_IS_DOCUMENT (object)); + if (uri != NULL) + { + if (doc->priv->uri == uri) + return; - document = GEDIT_DOCUMENT (object); + g_free (doc->priv->uri); + doc->priv->uri = g_strdup (uri); - g_return_if_fail (document->priv != NULL); + if (doc->priv->vfs_uri != NULL) + gnome_vfs_uri_unref (doc->priv->vfs_uri); - if (document->priv->auto_save_timeout > 0) - g_source_remove (document->priv->auto_save_timeout); + doc->priv->vfs_uri = gnome_vfs_uri_new (uri); + g_return_if_fail (doc->priv->vfs_uri != NULL); - if (document->priv->untitled_number > 0) - { - g_return_if_fail (document->priv->uri == NULL); - gedit_document_release_untitled_number ( - document->priv->untitled_number); + if (doc->priv->untitled_number > 0) + { + release_untitled_number (doc->priv->untitled_number); + doc->priv->untitled_number = 0; + } } - if (document->priv->uri != NULL) + g_return_if_fail (doc->priv->vfs_uri != NULL); + + g_free (doc->priv->mime_type); + if (mime_type != NULL) { - GtkTextIter iter; - gchar *position; - gchar *lang_id = NULL; - GtkSourceLanguage *lang; + doc->priv->mime_type = g_strdup (mime_type); + } + else + { + gchar *base_name; - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (document), - &iter, - gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (document))); + /* Set the mime type using the file extension or "text/plain" + * if no match. */ + base_name = gnome_vfs_uri_extract_short_path_name (doc->priv->vfs_uri); + if (base_name != NULL) + doc->priv->mime_type = g_strdup ("text/plain"); // FIXME +// gnome_vfs_mime_type_from_name_or_default (base_name, +// "text/plain"); + else + doc->priv->mime_type = g_strdup ("text/plain"); - position = g_strdup_printf ("%d", - gtk_text_iter_get_offset (&iter)); + g_free (base_name); + } - gedit_metadata_manager_set (document->priv->uri, - "position", - position); + if (!doc->priv->language_set_by_user) + { + gchar *data; + GtkSourceLanguage *language = NULL; - g_free (position); + data = gedit_metadata_manager_get (doc->priv->uri, "language"); - gedit_metadata_manager_set (document->priv->uri, - "last_searched_text", - document->priv->last_searched_text); - - gedit_metadata_manager_set (document->priv->uri, - "last_replaced_text", - document->priv->last_replace_text); + if (data != NULL) + { + gedit_debug_message (DEBUG_DOCUMENT, "Language: %s", data); - lang = gedit_document_get_language (document); + if (strcmp (data, "_NORMAL_") != 0) + { + language = gedit_languages_manager_get_language_from_id ( + gedit_get_languages_manager (), + data); + } - if (lang != NULL) + g_free (data); + } + else { - lang_id = gtk_source_language_get_id (lang); - g_return_if_fail (lang_id != NULL); + gedit_debug_message (DEBUG_DOCUMENT, "Language Normal"); + + if (strcmp (doc->priv->mime_type, "text/plain") != 0) + { + language = gtk_source_languages_manager_get_language_from_mime_type ( + gedit_get_languages_manager (), + doc->priv->mime_type); + } } - - gedit_metadata_manager_set (document->priv->uri, - "language", - (lang_id == NULL) ? "_NORMAL_" : lang_id); - - g_free (lang_id); - } - g_free (document->priv->uri); - g_free (document->priv->uri_for_display); - g_free (document->priv->short_name_for_display); - g_free (document->priv->mime_type); - g_free (document->priv->last_searched_text); - g_free (document->priv->last_replace_text); - g_free (document->priv->encoding); + set_language (doc, language, FALSE); + } - g_free (document->priv); - document->priv = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); + g_object_notify (G_OBJECT (doc), "uri"); + g_object_notify (G_OBJECT (doc), "shortname"); } -/** - * gedit_document_new: - * - * Creates a new untitled document. - * - * Return value: a new untitled document - **/ -GeditDocument* -gedit_document_new (void) +gchar * +gedit_document_get_uri (GeditDocument *doc) { - GeditDocument *document; - - gedit_debug (DEBUG_DOCUMENT, ""); - - document = GEDIT_DOCUMENT (g_object_new (GEDIT_TYPE_DOCUMENT, NULL)); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL); - g_return_val_if_fail (document->priv != NULL, NULL); - - document->priv->untitled_number = gedit_document_get_untitled_number (); - g_return_val_if_fail (document->priv->untitled_number > 0, NULL); - - return document; + return g_strdup (doc->priv->uri); } -/** - * gedit_document_new_with_uri: - * @uri: the URI of the file that has to be loaded - * @error: return location for error or NULL - * - * Creates a new document. - * - * Return value: a new document - **/ -GeditDocument* -gedit_document_new_with_uri (const gchar *uri, - const GeditEncoding *encoding) +/* Never returns NULL */ +gchar * +gedit_document_get_uri_for_display (GeditDocument *doc) { - GeditDocument *document; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (uri != NULL, NULL); - - document = GEDIT_DOCUMENT (g_object_new (GEDIT_TYPE_DOCUMENT, NULL)); - - g_return_val_if_fail (document->priv != NULL, NULL); - document->priv->uri = g_strdup (uri); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), ""); - gedit_document_load (document, uri, encoding); - - return document; + if (doc->priv->uri == NULL) + return g_strdup_printf (_("Unsaved Document %d"), + doc->priv->untitled_number); + else + return gnome_vfs_format_uri_for_display (doc->priv->uri); } -/** - * gedit_document_set_readonly: - * @document: a #GeditDocument - * @readonly: if TRUE (FALSE) the @document will be set as (not) readonly - * - * Set the value of the readonly flag. - **/ -void -gedit_document_set_readonly (GeditDocument *document, gboolean readonly) +/* move to gedit-utils? */ +static gchar * +get_uri_shortname_for_display (GnomeVFSURI *uri) { - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (document != NULL); - g_return_if_fail (document->priv != NULL); + gchar *name; + gboolean validated; - if (readonly) + validated = FALSE; + name = gnome_vfs_uri_extract_short_name (uri); + + if (name == NULL) { - if (document->priv->auto_save_timeout > 0) - { - gedit_debug (DEBUG_DOCUMENT, "Remove autosave timeout"); + name = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD); + } + else if (g_ascii_strcasecmp (uri->method_string, "file") == 0) + { + gchar *text_uri; + gchar *local_file; + text_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD); + local_file = gnome_vfs_get_local_path_from_uri (text_uri); - g_source_remove (document->priv->auto_save_timeout); - document->priv->auto_save_timeout = 0; + if (local_file != NULL) + { + g_free (name); + name = g_filename_display_basename (local_file); + validated = TRUE; } - } - else + + g_free (local_file); + g_free (text_uri); + } + else if (!gnome_vfs_uri_has_parent (uri)) { - if (document->priv->auto_save && - (document->priv->auto_save_timeout <= 0) && - !gedit_document_is_untitled (document)) + const gchar *method; + + method = uri->method_string; + + if (name == NULL || + strcmp (name, GNOME_VFS_URI_PATH_STR) == 0) + { + g_free (name); + name = g_strdup (method); + } + /* + else { - gedit_debug (DEBUG_DOCUMENT, "Install autosave timeout"); + gchar *tmp; - document->priv->auto_save_timeout = g_timeout_add - (document->priv->auto_save_interval * 1000 * 60, - (GSourceFunc)gedit_document_auto_save, - document); + tmp = name; + name = g_strdup_printf ("%s: %s", method, name); + g_free (tmp); } + */ } - if (document->priv->readonly == readonly) - return; + if (!validated && !g_utf8_validate (name, -1, NULL)) + { + gchar *utf8_name; - document->priv->readonly = readonly; + utf8_name = gedit_utils_make_valid_utf8 (name); + g_free (name); + name = utf8_name; + } - g_signal_emit (G_OBJECT (document), - document_signals[READONLY_CHANGED], - 0, - readonly); + return name; } -/** - * gedit_document_is_readonly: - * @document: a #GeditDocument - * - * Returns TRUE is @document is readonly. - * - * Return value: TRUE if @document is readonly. FALSE otherwise. - **/ -gboolean -gedit_document_is_readonly (GeditDocument *document) +/* Never returns NULL */ +gchar * +gedit_document_get_short_name_for_display (GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (document != NULL, TRUE); - g_return_val_if_fail (document->priv != NULL, TRUE); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), ""); - return document->priv->readonly; + if (doc->priv->uri == NULL) + return g_strdup_printf (_("Unsaved Document %d"), + doc->priv->untitled_number); + else + return get_uri_shortname_for_display (doc->priv->vfs_uri); } -static void -gedit_document_real_name_changed (GeditDocument *document) +/* Never returns NULL */ +gchar * +gedit_document_get_mime_type (GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), "text/plain"); + g_return_val_if_fail (doc->priv->mime_type != NULL, "text/plain"); - g_return_if_fail (document != NULL); + return g_strdup (doc->priv->mime_type); } -static void -gedit_document_real_loaded (GeditDocument *document, const GError *error) +/* Note: do not emit the notify::read-only signal */ +static void +set_readonly (GeditDocument *doc, + gboolean readonly) { - gchar *data; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (document)); - - if (error != NULL) - return; - - g_return_if_fail (document->priv->uri != NULL); - - /* FIXME: commented since it does not work as expected - Paolo */ + gedit_debug (DEBUG_DOCUMENT); - /* - data = gedit_metadata_manager_get (document->priv->uri, - "position"); - if (data != NULL) - { - GtkTextIter iter; - - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (document), - &iter, - atoi (data)); + readonly = (readonly != FALSE); - gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (document), &iter); - - g_free (data); - } - else - */ + if (readonly) { - GtkTextIter iter; - - gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (document), - &iter, - 0); - - gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (document), &iter); + if (doc->priv->auto_save_timeout > 0) + { + g_source_remove (doc->priv->auto_save_timeout); + doc->priv->auto_save_timeout = 0; + } } - - data = gedit_metadata_manager_get (document->priv->uri, - "last_searched_text"); - if (data != NULL) + else { - if (document->priv->last_searched_text == NULL) - gedit_document_set_last_searched_text (document, - data); - - g_free (data); + if (doc->priv->auto_save && + (doc->priv->auto_save_timeout <= 0) && + !gedit_document_is_untitled (doc)) + { +/* doc->priv->auto_save_timeout = g_timeout_add + (doc->priv->auto_save_interval * 1000 * 60, + (GSourceFunc)gedit_document_auto_save, + doc); +*/ + } } - data = gedit_metadata_manager_get (document->priv->uri, - "last_replaced_text"); - if (data != NULL) - { - if (document->priv->last_replace_text == NULL) - gedit_document_set_last_replace_text (document, - data); + if (doc->priv->readonly == readonly) + return; - g_free (data); - } + doc->priv->readonly = readonly; } -static void -gedit_document_real_saved (GeditDocument *document) +static void +gedit_document_set_readonly (GeditDocument *doc, + gboolean readonly) { - gedit_debug (DEBUG_DOCUMENT, ""); + gedit_debug (DEBUG_DOCUMENT); - g_return_if_fail (document != NULL); -} + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); -static void -gedit_document_real_readonly_changed (GeditDocument *document, gboolean readonly) -{ - gedit_debug (DEBUG_DOCUMENT, ""); + set_readonly (doc, readonly); - g_return_if_fail (document != NULL); + g_object_notify (G_OBJECT (doc), "read-only"); } -static void -gedit_document_real_can_find_again (GeditDocument *document) +gboolean +gedit_document_get_readonly (GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE); - g_return_if_fail (document != NULL); + return doc->priv->readonly; } - -gchar* -gedit_document_get_raw_uri (GeditDocument *doc) +static void +reset_temp_loading_data (GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); + /* the loader has been used, throw it away */ + g_object_unref (doc->priv->loader); + doc->priv->loader = NULL; - if (doc->priv->uri == NULL) - return NULL; - else - return g_strdup (doc->priv->uri); + doc->priv->requested_encoding = NULL; + doc->priv->requested_line_pos = 0; } -/* - * Returns a well formatted (ready to display) URI in UTF-8 format - * See: gedit_document_get_raw_uri to have a raw uri (non UTF-8) - */ -gchar* -gedit_document_get_uri (GeditDocument *doc) +static void +document_loader_loaded (GeditDocumentLoader *loader, + const GError *error, + GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), ""); + /* load was successful */ + if (error == NULL) + { + GtkTextIter iter; + const gchar *mime_type; - if (doc->priv->uri_for_display == NULL) - update_uri_for_display (doc); + mime_type = gedit_document_loader_get_mime_type (loader); - g_return_val_if_fail (doc->priv->uri_for_display != NULL, g_strdup ("")); + doc->priv->mtime = gedit_document_loader_get_mtime (loader); - return g_strdup (doc->priv->uri_for_display); -} + g_get_current_time (&doc->priv->time_of_last_save_or_load); -gchar* -gedit_document_get_short_name (GeditDocument *doc) -{ - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), ""); + set_readonly (doc, + gedit_document_loader_get_readonly (loader)); - if (doc->priv->short_name_for_display == NULL) - update_uri_for_display (doc); + set_encoding (doc, + gedit_document_loader_get_encoding (loader), + (doc->priv->requested_encoding != NULL)); + + /* We already set the uri */ + set_uri (doc, NULL, mime_type); - g_return_val_if_fail (doc->priv->short_name_for_display != NULL, g_strdup ("")); - - return g_strdup (doc->priv->short_name_for_display); -} + /* move the cursor at the requested line if any */ + if (doc->priv->requested_line_pos > 0) + { + /* line_pos - 1 because get_iter_at_line counts from 0 */ + gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), + &iter, + doc->priv->requested_line_pos - 1); + } -GQuark -gedit_document_io_error_quark (void) -{ - static GQuark quark; - - if (!quark) - quark = g_quark_from_static_string ("gedit_io_load_error"); + /* else, if enabled, to the position stored in the metadata */ + else if (0) // FIXME: should be a GConf option + { + gchar *pos; + gint offset; - return quark; -} + pos = gedit_metadata_manager_get (doc->priv->uri, + "position"); + offset = pos ? atoi (pos) : 0; + g_free (pos); -static gboolean -gedit_document_auto_save (GeditDocument *doc) -{ - const GeditEncoding *encoding; - gboolean create_backup; - GError *error = NULL; + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), + &iter, + MAX (offset, 0)); + } - gedit_debug (DEBUG_DOCUMENT, ""); + /* otherwise to the top */ + else + { + gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc), + &iter); + } - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail (!gedit_document_is_readonly (doc), FALSE); - g_return_val_if_fail (!gedit_document_is_untitled (doc), FALSE); + gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter); + } - if (!gedit_document_get_modified (doc)) - return TRUE; + /* special case creating a named new doc */ + else if (doc->priv->create && + (error->code == GNOME_VFS_ERROR_NOT_FOUND)) + { + reset_temp_loading_data (doc); + // FIXME: do other stuff?? - encoding = gedit_document_get_encoding (doc); - create_backup = gedit_prefs_manager_get_create_backup_copy (); + g_signal_emit (doc, + document_signals[LOADED], + 0, + NULL); - /* we save a backup just if backups are enabled and if the last - * save was manual. - */ - if (gedit_document_save_as_real (doc, doc->priv->uri, encoding, - doc->priv->last_save_was_manually && create_backup, - &error)) - { - doc->priv->last_save_was_manually = FALSE; - g_get_current_time (&doc->priv->time_of_last_save_or_load); + return; } + + g_signal_emit (doc, + document_signals[LOADED], + 0, + error); + + reset_temp_loading_data (doc); +} - if (error) +static void +document_loader_loading (GeditDocumentLoader *loader, + gboolean completed, + const GError *error, + GeditDocument *doc) +{ + if (completed) { - /* FIXME - Should we actually tell - * the user there was an error? - James */ - g_error_free (error); - return TRUE; + document_loader_loaded (loader, error, doc); } + else + { + GnomeVFSFileSize size; + GnomeVFSFileSize read; + + size = gedit_document_loader_get_file_size (loader); + read = gedit_document_loader_get_bytes_read (loader); - return TRUE; + g_signal_emit (doc, + document_signals[LOADING], + 0, + read, + size); + } } -/* NOTE: thie function frees file_contents */ -static gboolean -update_document_contents (GeditDocument *doc, - const gchar *uri, - const gchar *file_contents, - gint file_size, - const GeditEncoding *encoding, - GError **error) +gboolean +gedit_document_load (GeditDocument *doc, + const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create) { - gboolean enc_autodetected; + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); + g_return_val_if_fail (uri != NULL, FALSE); + g_return_val_if_fail (gedit_utils_is_valid_uri (uri), FALSE); - PROFILE ( - g_message ("Delete previous text %s: %.3f", uri, g_timer_elapsed (timer, NULL)); - ) - - PROFILE ( - g_message ("Deleted: %.3f", g_timer_elapsed (timer, NULL)); - ) + g_return_val_if_fail (doc->priv->loader == NULL, FALSE); - enc_autodetected = (encoding == NULL); + /* create a loader. It will be destroyed when loading is completed */ + doc->priv->loader = gedit_document_loader_new (doc); - if (file_size > 0) - { - GError *conv_error = NULL; - gchar *converted_text; - gint len = -1; + g_signal_connect (doc->priv->loader, + "loading", + G_CALLBACK (document_loader_loading), + doc); - g_return_val_if_fail (file_contents != NULL, FALSE); + doc->priv->create = create; + doc->priv->requested_encoding = encoding; + doc->priv->requested_line_pos = line_pos; - if (encoding == gedit_encoding_get_utf8 ()) - { - if (g_utf8_validate (file_contents, file_size, NULL)) - { - converted_text = (gchar *)file_contents; - len = file_size; - file_contents = NULL; - } - else - { - converted_text = NULL; - conv_error = g_error_new (GEDIT_CONVERT_ERROR, - GEDIT_CONVERT_ERROR_ILLEGAL_SEQUENCE, - "Invalid byte sequence"); - } - } - else - { - converted_text = NULL; - - if (encoding == NULL) - { - const GeditEncoding *enc; - gchar *charset; + set_uri (doc, uri, NULL); - charset = gedit_metadata_manager_get (uri, "encoding"); + return gedit_document_loader_load (doc->priv->loader, + uri, + encoding); +} - if (charset != NULL) - { - enc = gedit_encoding_get_from_charset (charset); +gboolean +gedit_document_load_cancel (GeditDocument *doc) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - if (enc != NULL) - { - converted_text = gedit_convert_to_utf8 (file_contents, - file_size, - &enc, - NULL); + if (doc->priv->loader == NULL) + return FALSE; - if (converted_text != NULL) - encoding = enc; - } + return gedit_document_loader_cancel (doc->priv->loader); +} - g_free (charset); - } - } +static void +document_saver_saving (GeditDocumentSaver *saver, + gboolean completed, + const GError *error, + GeditDocument *doc) +{ + /* FIXME */ + if (error) + g_print ("error saving: %s\n", error->message); - if (converted_text == NULL) - converted_text = gedit_convert_to_utf8 (file_contents, - file_size, - &encoding, - &conv_error); - } - - if (converted_text == NULL) + if (completed) + { + /* save was successful */ + if (error == NULL) { - /* bail out */ - if (conv_error == NULL) - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, - GEDIT_ERROR_INVALID_UTF8_DATA, - _("Invalid UTF-8 data")); - else - g_propagate_error (error, conv_error); - - return FALSE; - } + const gchar *uri; + const gchar *mime_type; - PROFILE ( - g_message ("Text converted: %.3f", g_timer_elapsed (timer, NULL)); - ) + uri = gedit_document_saver_get_uri (saver); + mime_type = gedit_document_saver_get_mime_type (saver); - gedit_document_begin_not_undoable_action (doc); + doc->priv->mtime = gedit_document_saver_get_mtime (saver); - /* Insert text in the buffer */ - gtk_text_buffer_set_text (GTK_TEXT_BUFFER (doc), converted_text, len); + g_get_current_time (&doc->priv->time_of_last_save_or_load); - PROFILE ( - g_message ("Text inserted: %.3f", g_timer_elapsed (timer, NULL)); - ) + gedit_document_set_readonly (doc, FALSE); - if (file_contents != NULL) - { - /* If file_contents == NULL then converted_text is only an alias of - * file_contents and hence it must not be freed */ - g_free (converted_text); + gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), + FALSE); + + set_uri (doc, uri, mime_type); + + set_encoding (doc, + doc->priv->requested_encoding, + TRUE); } - gedit_document_end_not_undoable_action (doc); - - PROFILE ( - g_message ("Text inserted all: %.3f", g_timer_elapsed (timer, NULL)); - ) + g_signal_emit (doc, + document_signals[SAVED], + 0, + error); + /* the saver has been used, throw it away */ + g_object_unref (doc->priv->saver); + doc->priv->saver = NULL; + doc->priv->is_saving_as = FALSE; } else { - if (encoding == NULL) - encoding = gedit_encoding_get_utf8 (); - } - - gedit_document_set_uri (doc, uri, encoding, enc_autodetected); + GnomeVFSFileSize size = 0; + GnomeVFSFileSize written = 0; - gedit_document_set_readonly (doc, gedit_utils_is_uri_read_only (uri)); + size = gedit_document_saver_get_file_size (saver); + written = gedit_document_saver_get_bytes_written (saver); - gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), FALSE); - - g_get_current_time (&doc->priv->time_of_last_save_or_load); - - return TRUE; -} + gedit_debug_message (DEBUG_DOCUMENT, "save progress: %Lu of %Lu", written, size); -static void -reset_temp_data (GeditDocument *doc) -{ - g_free (doc->priv->temp_uri); - - doc->priv->temp_uri = NULL; - doc->priv->temp_encoding = NULL; - doc->priv->temp_size = 0; - - doc->priv->read_handle = NULL; - doc->priv->info_handle = NULL; + g_signal_emit (doc, + document_signals[SAVING], + 0, + written, + size); + } } static void -file_loaded_cb (GnomeVFSResult result, - GnomeVFSFileSize file_size, - gchar *file_contents, - gpointer callback_data) +document_save_real (GeditDocument *doc, + const gchar *uri, + const GeditEncoding *encoding, + time_t mtime, + GeditDocumentSaveFlags flags) { - GError *error = NULL; - gboolean ret; - GeditDocument *doc; + g_return_if_fail (doc->priv->saver == NULL); - gedit_debug (DEBUG_DOCUMENT, ""); + /* create a saver, it will be destroyed once saving is complete */ + doc->priv->saver = gedit_document_saver_new (doc); - doc = GEDIT_DOCUMENT (callback_data); - - /* - g_print ("Loaded URI: %s\n", doc->priv->temp_uri); - g_print ("Final file size: %d\n", (int)file_size); - */ - - PROFILE ( - g_message ("Loaded Document %s: %.3f", doc->priv->temp_uri, g_timer_elapsed (timer, NULL)); - ) + g_signal_connect (doc->priv->saver, + "saving", + G_CALLBACK (document_saver_saving), + doc); - if (result != GNOME_VFS_OK) - { - reset_temp_data (doc); - - g_free (file_contents); + doc->priv->requested_encoding = encoding; - error = g_error_new (GEDIT_DOCUMENT_IO_ERROR, - result, - gnome_vfs_result_to_string (result)); + gedit_document_saver_save (doc->priv->saver, + uri, + encoding, + mtime, + flags); +} - g_signal_emit (G_OBJECT (doc), document_signals[LOADED], 0, error); +void +gedit_document_save (GeditDocument *doc, + GeditDocumentSaveFlags flags) +{ + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + g_return_if_fail (doc->priv->uri != NULL); - g_error_free (error); + document_save_real (doc, + doc->priv->uri, + doc->priv->encoding, + doc->priv->mtime, + flags); +} - return; - } +void +gedit_document_save_as (GeditDocument *doc, + const gchar *uri, + const GeditEncoding *encoding, + GeditDocumentSaveFlags flags) +{ + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + g_return_if_fail (uri != NULL); + g_return_if_fail (encoding != NULL); - ret = update_document_contents (doc, - doc->priv->temp_uri, - file_contents, - file_size, - doc->priv->temp_encoding, - &error); + doc->priv->is_saving_as = TRUE; + + document_save_real (doc, uri, encoding, 0, flags); +} - PROFILE ( - g_message ("Update Document %s: %.3f", doc->priv->uri, g_timer_elapsed (timer, NULL)); - ) - - if (error) - { - g_signal_emit (G_OBJECT (doc), document_signals[LOADED], 0, error); - - g_error_free (error); - } - else - { - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - NULL); - } - - PROFILE ({ - g_message ("Return from signal LAODED %s: %.3f", doc->priv->uri, g_timer_elapsed (timer, NULL)); - g_timer_destroy (timer); - }) - - reset_temp_data (doc); - - g_free (file_contents); -} - -static gboolean -read_more_cb (GnomeVFSFileSize file_size, - const char *file_contents, - gpointer callback_data) -{ - GeditDocument *doc; - - doc = GEDIT_DOCUMENT (callback_data); - - /* - g_print ("Loading URI: %s\n", doc->priv->temp_uri); - g_print ("File size: %ld/%ld\n", (gulong)file_size, doc->priv->temp_size); - */ - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADING], - 0, - (gulong)file_size, - doc->priv->temp_size); - - return TRUE; -} - -static void -get_info_cb (GnomeVFSAsyncHandle *handle, - GList *results, - gpointer callback_data) -{ - GeditDocument *doc; - GnomeVFSGetFileInfoResult *info_result; - - gedit_debug (DEBUG_DOCUMENT, ""); - - /* assert that the list has one and only one item */ - g_return_if_fail (results != NULL && results->next == NULL); - - doc = GEDIT_DOCUMENT (callback_data); - doc->priv->info_handle = NULL; - - info_result = (GnomeVFSGetFileInfoResult *)results->data; - g_return_if_fail (info_result != NULL); - - if (info_result->result != GNOME_VFS_OK) - { - GError *error = NULL; - - gedit_debug (DEBUG_DOCUMENT, "Error reading %s : %s", - doc->priv->temp_uri, - gnome_vfs_result_to_string (info_result->result)); - - reset_temp_data (doc); - - error = g_error_new (GEDIT_DOCUMENT_IO_ERROR, - info_result->result, - gnome_vfs_result_to_string (info_result->result)); - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - error); - - g_error_free (error); - - return; - } - - /* just some extra paranoia, since we passed the follow-symlink flag... */ - g_return_if_fail (info_result->file_info->type != GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK); - - /* if it's not a regular file, error out... */ - if (info_result->file_info->type != GNOME_VFS_FILE_TYPE_REGULAR) - { - GError *error = NULL; - - gedit_debug (DEBUG_DOCUMENT, "File %s is of type: %d", - doc->priv->temp_uri, info_result->file_info->type); - - reset_temp_data (doc); - - error = g_error_new (GEDIT_DOCUMENT_IO_ERROR, - GEDIT_ERROR_NOT_REGULAR_FILE, - "Not a regular file"); - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - error); - - g_error_free (error); - - return; - } - - /* store the mime type */ - g_free (doc->priv->mime_type); - doc->priv->mime_type = info_result->file_info->mime_type ? - g_strdup (info_result->file_info->mime_type) : - g_strdup ("text/plain"); - - if (info_result->file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) - { - doc->priv->temp_size = (gulong)info_result->file_info->size; - } - else - { - doc->priv->temp_size = 0; - } - - PROFILE ( - g_message ("Got Info on Document %s: %.3f", - doc->priv->temp_uri, g_timer_elapsed (timer, NULL)); - ) - - doc->priv->read_handle = eel_read_file_async (doc->priv->temp_uri, - GNOME_VFS_PRIORITY_MAX, - file_loaded_cb, - read_more_cb, - doc); -} - -static gboolean -load_local (GeditDocument *doc) -{ - GError *error = NULL; - GnomeVFSFileInfo *info; - GnomeVFSResult res; - gint file_size; - gchar *file_contents; - gboolean ret; - - PROFILE ( - g_message ("Start loading entire file %s: %.3f", - doc->priv->uri, g_timer_elapsed (timer, NULL)); - ) - - info = gnome_vfs_file_info_new (); - - res = gnome_vfs_get_file_info (doc->priv->temp_uri, - info, - GNOME_VFS_FILE_INFO_DEFAULT | - GNOME_VFS_FILE_INFO_GET_MIME_TYPE | - GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | - GNOME_VFS_FILE_INFO_FOLLOW_LINKS); - - if (res != GNOME_VFS_OK) - { - reset_temp_data (doc); - - gnome_vfs_file_info_unref (info); - - error = g_error_new (GEDIT_DOCUMENT_IO_ERROR, - res, - gnome_vfs_result_to_string (res)); - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - error); - - g_error_free (error); - - return FALSE; - } - - /* just some extra paranoia, since we passed the follow-symlink flag... */ - g_return_val_if_fail (info->type != GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK, FALSE); - - /* if it's not a regular file, error out... */ - if (info->type != GNOME_VFS_FILE_TYPE_REGULAR) - { - GError *error = NULL; - - gedit_debug (DEBUG_DOCUMENT, "File %s is of type: %d", - doc->priv->temp_uri, info->type); - - reset_temp_data (doc); - - error = g_error_new (GEDIT_DOCUMENT_IO_ERROR, - GEDIT_ERROR_NOT_REGULAR_FILE, - "Not a regular file"); - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - error); - - g_error_free (error); - gnome_vfs_file_info_unref (info); - - return FALSE; - } - - /* store the mime type */ - g_free (doc->priv->mime_type); - doc->priv->mime_type = info->mime_type ? - g_strdup (info->mime_type) : - g_strdup ("text/plain"); - - gnome_vfs_file_info_unref (info); - - res = gnome_vfs_read_entire_file (doc->priv->temp_uri, - &file_size, - &file_contents); - - if (res != GNOME_VFS_OK) - { - reset_temp_data (doc); - - g_free (file_contents); - - error = g_error_new (GEDIT_DOCUMENT_IO_ERROR, - res, - gnome_vfs_result_to_string (res)); - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - error); - - g_error_free (error); - - return FALSE; - } - - ret = update_document_contents (doc, - doc->priv->temp_uri, - file_contents, - file_size, - doc->priv->temp_encoding, - &error); - - PROFILE ( - g_message ("Update Document %s: %.3f", doc->priv->uri, g_timer_elapsed (timer, NULL)); - ) - - reset_temp_data (doc); - - if (error) - { - g_signal_emit (G_OBJECT (doc), document_signals[LOADED], 0, error); - - g_error_free (error); - } - else - { - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - NULL); - } - - PROFILE ({ - g_message ("Return from signal LAODED : %.3f", - g_timer_elapsed (timer, NULL)); - g_timer_destroy (timer); - }) - - g_free (file_contents); - - return FALSE; -} - -static gboolean -emit_invalid_uri (GeditDocument *doc) -{ - GError *error = NULL; - GnomeVFSResult res; - - reset_temp_data (doc); - - res = GNOME_VFS_ERROR_INVALID_URI; - - error = g_error_new (GEDIT_DOCUMENT_IO_ERROR, - res, - gnome_vfs_result_to_string (res)); - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADED], - 0, - error); - - g_error_free (error); - - return FALSE; -} - -/** - * gedit_document_load: - * @doc: a GeditDocument - * @uri: the URI of the file that has to be loaded - * - * Read a document from a file - * - * Return value: TRUE if the file is correctly loaded - **/ -void -gedit_document_load (GeditDocument *doc, - const gchar *uri, - const GeditEncoding *encoding) -{ - GnomeVFSURI *u; - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (uri != NULL); - - PROFILE ({ - timer = g_timer_new (); - g_message ("Start loading %s", uri); - }) - - gedit_debug (DEBUG_DOCUMENT, "File to load: %s", uri); - - u = gnome_vfs_uri_new (uri); - if (u == NULL) - { - g_timeout_add_full (G_PRIORITY_HIGH, - 0, - (GSourceFunc)emit_invalid_uri, - doc, - NULL); - - return; - } - - doc->priv->temp_encoding = encoding; - doc->priv->temp_uri = g_strdup (uri); - - if (!eel_vfs_has_capability (doc->priv->temp_uri, EEL_VFS_CAPABILITY_IS_REMOTE_AND_SLOW)) - { - doc->priv->temp_size = 0; - - g_timeout_add_full (G_PRIORITY_HIGH, - 0, - (GSourceFunc)load_local, - doc, - NULL); - - gnome_vfs_uri_unref (u); - } - else - { - GList *uri_list = NULL; - - uri_list = g_list_prepend (uri_list, u); - - gnome_vfs_async_get_file_info (&doc->priv->info_handle, - uri_list, - GNOME_VFS_FILE_INFO_DEFAULT | - GNOME_VFS_FILE_INFO_GET_MIME_TYPE | - GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | - GNOME_VFS_FILE_INFO_FOLLOW_LINKS, - GNOME_VFS_PRIORITY_MAX, - get_info_cb, - doc); - - g_signal_emit (G_OBJECT (doc), - document_signals[LOADING], - 0, - 0, - 0); - - gnome_vfs_uri_unref (u); - - g_list_free (uri_list); - } -} - -gboolean -gedit_document_load_from_stdin (GeditDocument* doc, GError **error) -{ - gchar *stdin_data; - GtkTextIter iter, end; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - - stdin_data = gedit_utils_get_stdin (); - - if (stdin_data != NULL && strlen (stdin_data) > 0) - { - GError *conv_error = NULL; - const GeditEncoding *encoding; - gchar *converted_text; - - if (gedit_encoding_get_current () == gedit_encoding_get_utf8 ()) - { - if (g_utf8_validate (stdin_data, -1, NULL)) - { - converted_text = stdin_data; - stdin_data = NULL; - - encoding = gedit_encoding_get_utf8 (); - } - else - { - converted_text = NULL; - } - } - else - { - encoding = gedit_encoding_get_current (); - - converted_text = gedit_convert_to_utf8 (stdin_data, - -1, - &encoding, - &conv_error); - } - - if (converted_text == NULL) - { - /* bail out */ - if (conv_error == NULL) - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, - GEDIT_ERROR_INVALID_UTF8_DATA, - _("Invalid UTF-8 data")); - else - g_propagate_error (error, conv_error); - - g_free (stdin_data); - - return FALSE; - } - - gedit_document_begin_not_undoable_action (doc); - /* Insert text in the buffer */ - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &iter, 0); - gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &iter, converted_text, -1); - - /* We had a newline in the buffer to begin with. (The buffer always contains - * a newline, so we delete to the end of the buffer to clean up. */ - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end); - gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), &iter, &end); - - /* Place the cursor at the start of the document */ - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &iter, 0); - gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter); - - gedit_document_end_not_undoable_action (doc); - - g_free (converted_text); - } - - if (stdin_data != NULL) - g_free (stdin_data); - - - gedit_document_set_readonly (doc, FALSE); - gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), TRUE); - g_get_current_time (&doc->priv->time_of_last_save_or_load); - - g_signal_emit (G_OBJECT (doc), document_signals [LOADED], 0, NULL); - - return TRUE; -} - -gboolean -gedit_document_is_untouched (const GeditDocument *doc) -{ - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE); - - gedit_debug (DEBUG_DOCUMENT, ""); - - return (doc->priv->uri == NULL) && - (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc))); -} - -static void -gedit_document_set_uri (GeditDocument *doc, - const gchar *uri, - const GeditEncoding *encoding, - gboolean enc_autodetected) -{ - GtkSourceLanguage *language = NULL; - gchar *data; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (uri != NULL); - g_return_if_fail (encoding != NULL); - - if (doc->priv->uri == uri) - return; - - if (doc->priv->uri != NULL) - g_free (doc->priv->uri); - - doc->priv->uri = g_strdup (uri); - - if (doc->priv->untitled_number > 0) - { - gedit_document_release_untitled_number (doc->priv->untitled_number); - doc->priv->untitled_number = 0; - } - - /* Update uri_for_display and short_name_for_display */ - update_uri_for_display (doc); - - data = gedit_metadata_manager_get (uri, "language"); - - if (data != NULL) - { - gedit_debug (DEBUG_DOCUMENT, "Language: %s", data); - - if (strcmp (data, "_NORMAL_") != 0) - language = gedit_languages_manager_get_language_from_id ( - gedit_get_languages_manager (), - data); - - g_free (data); - } - else - { - if (doc->priv->mime_type != NULL) - { - language = gtk_source_languages_manager_get_language_from_mime_type ( - gedit_get_languages_manager (), - doc->priv->mime_type); - } - else - { - /* should never happen */ - g_warning ("gedit document %s has NULL mime_type", uri); - } - } - - gedit_document_set_language (doc, language); - - if (doc->priv->encoding != NULL) - g_free (doc->priv->encoding); - - doc->priv->encoding = g_strdup (gedit_encoding_get_charset (encoding)); - - if (!enc_autodetected) - gedit_metadata_manager_set (doc->priv->uri, - "encoding", - doc->priv->encoding); - - g_signal_emit (G_OBJECT (doc), document_signals[NAME_CHANGED], 0); -} - -gboolean -gedit_document_save (GeditDocument *doc, GError **error) -{ - gboolean create_backup_copy; - const GeditEncoding *encoding; - - gboolean ret; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (doc != NULL, FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); - g_return_val_if_fail (!doc->priv->readonly, FALSE); - g_return_val_if_fail (doc->priv->uri != NULL, FALSE); - - encoding = gedit_document_get_encoding (doc); - g_return_val_if_fail (encoding != NULL, FALSE); - - create_backup_copy = gedit_prefs_manager_get_create_backup_copy (); - - if (doc->priv->auto_save_timeout > 0) - { - g_source_remove (doc->priv->auto_save_timeout); - doc->priv->auto_save_timeout = 0; - } - - ret = gedit_document_save_as_real (doc, - doc->priv->uri, - encoding, - create_backup_copy, - error); - - if (ret) - { - doc->priv->last_save_was_manually = TRUE; - g_get_current_time (&doc->priv->time_of_last_save_or_load); - } - - if (doc->priv->auto_save && (doc->priv->auto_save_timeout <= 0)) - { - doc->priv->auto_save_timeout = - g_timeout_add (doc->priv->auto_save_interval * 1000 * 60, - (GSourceFunc) gedit_document_auto_save, - doc); - } - - return ret; -} - -gboolean -gedit_document_save_as (GeditDocument* doc, const gchar *uri, - const GeditEncoding *encoding, GError **error) -{ - gboolean create_backup; - - gboolean ret = FALSE; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (doc != NULL, FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - - if (encoding == NULL) - encoding = gedit_document_get_encoding (doc); - - create_backup = gedit_prefs_manager_get_create_backup_copy (); - - if (doc->priv->auto_save_timeout > 0) - { - g_source_remove (doc->priv->auto_save_timeout); - doc->priv->auto_save_timeout = 0; - } - - if (gedit_document_save_as_real (doc, uri, encoding, create_backup, error)) - { - gedit_document_set_uri (doc, uri, encoding, FALSE); - gedit_document_set_readonly (doc, FALSE); - - g_get_current_time (&doc->priv->time_of_last_save_or_load); - doc->priv->last_save_was_manually = TRUE; - - ret = TRUE; - } - - if (doc->priv->auto_save && (doc->priv->auto_save_timeout <= 0)) - { - doc->priv->auto_save_timeout = - g_timeout_add (doc->priv->auto_save_interval * 1000 * 60, - (GSourceFunc)gedit_document_auto_save, doc); - } - - return ret; -} - -#define MAX_LINK_LEVEL 256 - -/* Does readlink() recursively until we find a real filename. */ -static char * -follow_symlinks (const gchar *filename, GError **error) -{ - gchar *followed_filename; - gint link_count; - - g_return_val_if_fail (filename != NULL, NULL); - - gedit_debug (DEBUG_DOCUMENT, "Filename: %s", filename); - g_return_val_if_fail (strlen (filename) + 1 <= GEDIT_MAX_PATH_LEN, NULL); - - followed_filename = g_strdup (filename); - link_count = 0; - - while (link_count < MAX_LINK_LEVEL) - { - struct stat st; - - if (lstat (followed_filename, &st) != 0) - /* We could not access the file, so perhaps it does not - * exist. Return this as a real name so that we can - * attempt to create the file. - */ - return followed_filename; - - if (S_ISLNK (st.st_mode)) - { - gint len; - gchar linkname[GEDIT_MAX_PATH_LEN]; - - link_count++; - - len = readlink (followed_filename, linkname, GEDIT_MAX_PATH_LEN - 1); - - if (len == -1) - { - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, errno, - _("Could not read symbolic link information " - "for %s"), followed_filename); - g_free (followed_filename); - return NULL; - } - - linkname[len] = '\0'; - - /* If the linkname is not an absolute path name, append - * it to the directory name of the followed filename. E.g. - * we may have /foo/bar/baz.lnk -> eek.txt, which really - * is /foo/bar/eek.txt. - */ - - if (linkname[0] != G_DIR_SEPARATOR) - { - gchar *slashpos; - gchar *tmp; - - slashpos = strrchr (followed_filename, G_DIR_SEPARATOR); - - if (slashpos) - *slashpos = '\0'; - else - { - tmp = g_strconcat ("./", followed_filename, NULL); - g_free (followed_filename); - followed_filename = tmp; - } - - tmp = g_build_filename (followed_filename, linkname, NULL); - g_free (followed_filename); - followed_filename = tmp; - } - else - { - g_free (followed_filename); - followed_filename = g_strdup (linkname); - } - } else - return followed_filename; - } - - /* Too many symlinks */ - - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, ELOOP, - _("The file has too many symbolic links.")); - - return NULL; -} - -/* FIXME: Remove this function when gnome-vfs will add an equivalent public - function - Paolo (Mar 05, 2004) */ -static gchar * -get_slow_mime_type (const char *text_uri) -{ - GnomeVFSFileInfo *info; - char *mime_type; - GnomeVFSResult result; - - info = gnome_vfs_file_info_new (); - result = gnome_vfs_get_file_info (text_uri, info, - GNOME_VFS_FILE_INFO_GET_MIME_TYPE | - GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE | - GNOME_VFS_FILE_INFO_FOLLOW_LINKS); - if (info->mime_type == NULL || result != GNOME_VFS_OK) { - mime_type = NULL; - } else { - mime_type = g_strdup (info->mime_type); - } - gnome_vfs_file_info_unref (info); - - return mime_type; -} - -/* FIXME: define new ERROR_CODE and remove the error - * strings from here -- Paolo - */ -static gboolean -gedit_document_save_as_real (GeditDocument* doc, const gchar *uri, const GeditEncoding *encoding, - gboolean create_backup_copy, GError **error) +gboolean +gedit_document_insert_file (GeditDocument *doc, + GtkTextIter *iter, + const gchar *uri, + const GeditEncoding *encoding) { - gchar *filename; /* Filename without URI scheme */ - gchar *real_filename; /* Final filename with no symlinks */ - gchar *backup_filename; /* Backup filename, like real_filename.bak */ - gchar *temp_filename; /* Filename for saving */ - gchar *slashpos; - gchar *dirname; - mode_t saved_umask; - struct stat st; - gchar *chars = NULL; - gint fd; - gint retval; - gsize chars_len = 0; - gsize new_len = 0; - gboolean res; - gboolean add_cr; - GtkTextIter start_iter; - GtkTextIter end_iter; - gchar *detected_mime; - ssize_t written; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (doc != NULL, FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - g_return_val_if_fail (encoding != NULL, FALSE); - - retval = FALSE; - - filename = NULL; - real_filename = NULL; - backup_filename = NULL; - temp_filename = NULL; - - /* We don't support non-file:/// stuff */ - - if (!gedit_utils_uri_has_file_scheme (uri)) - { - gchar *error_message; - gchar *scheme_string; - - gchar *temp = gnome_vfs_get_uri_scheme (uri); - scheme_string = gedit_utils_make_valid_utf8 (temp); - g_free (temp); - - if (scheme_string != NULL) - { - error_message = g_strdup_printf ( - _("gedit cannot handle %s: locations in write mode."), - scheme_string); - - g_free (scheme_string); - } - else - error_message = g_strdup_printf ( - _("gedit cannot handle this kind of location in write mode.")); - - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, EROFS, error_message); - g_free (error_message); - return FALSE; - } - - /* Get filename from uri */ - filename = gnome_vfs_get_local_path_from_uri (uri); - - if (!filename) - { - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, 0, - _("Invalid filename.")); - goto out; - } - - /* Get the real filename and file permissions */ - - real_filename = follow_symlinks (filename, error); - - if (!real_filename) - goto out; - - /* Get the directory in which the real filename lives */ - - slashpos = strrchr (real_filename, G_DIR_SEPARATOR); - - if (slashpos) - { - dirname = g_strdup (real_filename); - dirname[slashpos - real_filename + 1] = '\0'; - } - else - dirname = g_strdup ("."); - - /* If there is not an existing file with that name, compute the - * permissions and uid/gid that we will use for the newly-created file. - */ - - if (stat (real_filename, &st) != 0) - { - struct stat dir_st; - int result; - - /* File does not exist? */ - create_backup_copy = FALSE; - - /* Use default permissions */ - saved_umask = umask(0); - st.st_mode = 0666 & ~saved_umask; - umask(saved_umask); - st.st_uid = getuid (); - - result = stat (dirname, &dir_st); - - if (result == 0 && (dir_st.st_mode & S_ISGID)) - st.st_gid = dir_st.st_gid; - else - st.st_gid = getgid (); - } - - /* Save to a temporary file. We set the umask because some (buggy) - * implementations of mkstemp() use permissions 0666 and we want 0600. - */ - - temp_filename = g_build_filename (dirname, ".gedit-save-XXXXXX", NULL); - g_free (dirname); - - saved_umask = umask (0077); - fd = g_mkstemp (temp_filename); /* this modifies temp_filename to the used name */ - umask (saved_umask); - - if (fd == -1) - { - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, errno, " "); - goto out; - } - - gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc), &start_iter, &end_iter); - chars = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), - &start_iter, &end_iter, TRUE); - - chars_len = strlen (chars); - - add_cr = FALSE; - - if (chars_len >= 1) - { - add_cr = (*(chars + chars_len - 1) != '\n'); - } - - if (encoding != gedit_encoding_get_utf8 ()) - { - GError *conv_error = NULL; - gchar* converted_file_contents = NULL; - - converted_file_contents = gedit_convert_from_utf8 (chars, - chars_len, - encoding, - &new_len, - &conv_error); - - if (conv_error != NULL) - { - /* Conversion error */ - g_propagate_error (error, conv_error); - - close (fd); - unlink (temp_filename); - goto out; - } - else - { - g_free (chars); - chars = converted_file_contents; - } - } - else - { - new_len = chars_len; - } - - /* Save the file content */ - written = write (fd, chars, new_len); - res = ((written != -1) && ((gsize)written == new_len)); - - if (res && add_cr) - { - /* Add \n if needed */ - if (encoding != gedit_encoding_get_utf8 ()) - { - gchar* converted_n = NULL; - - converted_n = gedit_convert_from_utf8 ("\n", - -1, - encoding, - &new_len, - NULL); - - if (converted_n == NULL) - { - g_warning ("Cannot add '\\n' at the end of the file."); - } - else - { - written = write (fd, converted_n, new_len); - res = ((written != -1) && ((gsize)written == new_len)); - g_free (converted_n); - } - } - else - { - res = (write (fd, "\n", 1) == 1); - } - } - - if (!res) - { - gchar *msg; - - switch (errno) - { - case ENOSPC: - msg = _("There is not enough disk space to save the file.\n" - "Please free some disk space and try again."); - break; - - case EFBIG: - msg = _("The disk where you are trying to save the file has " - "a limitation on file sizes. Please try saving " - "a smaller file or saving it to a disk that does not " - "have this limitation."); - break; - - default: - msg = " "; - break; - } - - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, errno, msg); - close (fd); - unlink (temp_filename); - goto out; - } - - if (close (fd) != 0) - { - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, errno, " "); - unlink (temp_filename); - goto out; - } - - /* Move the original file to a backup */ - - if (create_backup_copy) - { - gchar *bak_ext; - gint result; - - bak_ext = gedit_prefs_manager_get_backup_extension (); - - backup_filename = g_strconcat (real_filename, - bak_ext, - NULL); - - g_free (bak_ext); - - result = rename (real_filename, backup_filename); - - if (result != 0) - { - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, errno, - _("Could not create a backup file.")); - unlink (temp_filename); - goto out; - } - } - - /* Move the temp file to the original file */ - - if (rename (temp_filename, real_filename) != 0) - { - gint saved_errno; - - saved_errno = errno; - - if (create_backup_copy && rename (backup_filename, real_filename) != 0) - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, errno, - " "); - else - g_set_error (error, GEDIT_DOCUMENT_IO_ERROR, saved_errno, - " "); - - goto out; - } - - /* Restore permissions. There is not much error checking we can do - * here, I'm afraid. The final data is saved anyways. - */ - - chmod (real_filename, st.st_mode); - chown (real_filename, st.st_uid, st.st_gid); - - gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), FALSE); - - /* update the mime type */ - detected_mime = get_slow_mime_type (uri); - g_free (doc->priv->mime_type); - doc->priv->mime_type = detected_mime ? detected_mime : g_strdup ("text/plain"); - - retval = TRUE; - - /* Done */ - - out: - - g_free (chars); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == + GTK_TEXT_BUFFER (doc), FALSE); - g_free (filename); - g_free (real_filename); - g_free (backup_filename); - g_free (temp_filename); + // TODO - return retval; + return FALSE; } -const gchar * -gedit_document_get_mime_type (GeditDocument *doc) +gboolean +gedit_document_is_untouched (GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (doc != NULL, FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); - - g_return_val_if_fail (doc->priv->mime_type != NULL, "text/plain"); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE); - return doc->priv->mime_type; + return (doc->priv->uri == NULL) && + (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc))); } -gboolean -gedit_document_is_untitled (const GeditDocument* doc) +gboolean +gedit_document_is_untitled (GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (doc != NULL, FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), TRUE); return (doc->priv->uri == NULL); } -gboolean -gedit_document_get_modified (const GeditDocument* doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (doc != NULL, FALSE); - - return gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)); -} - gboolean gedit_document_get_deleted (GeditDocument *doc) { - gchar *raw_uri; - gboolean deleted = FALSE; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (doc != NULL, FALSE); - - raw_uri = gedit_document_get_raw_uri (doc); - if (raw_uri) - { - if (gedit_document_is_readonly (doc)) - deleted = FALSE; - else - deleted = !gedit_utils_uri_exists (raw_uri); - } - g_free (raw_uri); - - return deleted; -} - -void -gedit_document_revert (GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (doc != NULL); - g_return_if_fail (!gedit_document_is_untitled (doc)); - - gedit_document_load (doc, doc->priv->uri, gedit_document_get_encoding (doc)); - - return; -} - -void -gedit_document_insert_text (GeditDocument *doc, gint pos, const gchar *text, gint len) -{ - GtkTextIter iter; - - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (pos >= 0); - g_return_if_fail (text != NULL); - g_return_if_fail (g_utf8_validate (text, len, NULL)); - - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &iter, pos); - - gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &iter, text, len); -} - -void -gedit_document_set_max_undo_levels (GeditDocument *doc, gint max_undo_levels) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - - gtk_source_buffer_set_max_undo_levels (GTK_SOURCE_BUFFER (doc), - max_undo_levels); -} - -gboolean -gedit_document_can_undo (const GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - return gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER (doc)); + if (doc->priv->uri == NULL) + return FALSE; + + return !gnome_vfs_uri_exists (doc->priv->vfs_uri); } gboolean -gedit_document_can_redo (const GeditDocument *doc) +_gedit_document_get_has_selection (GeditDocument *doc) { - gedit_debug (DEBUG_DOCUMENT, ""); - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - return gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER (doc)); + return doc->priv->has_selection; } -/** - * A function to determine whether or not the "FindNext/Prev" - * functions are executable +/* + * 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_can_find_again (const GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - - return (doc->priv->last_searched_text != NULL); -} - -void -gedit_document_undo (GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (gedit_document_can_undo (doc)); - - gtk_source_buffer_undo (GTK_SOURCE_BUFFER (doc)); -} - -void -gedit_document_redo (GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (gedit_document_can_redo (doc)); - - gtk_source_buffer_redo (GTK_SOURCE_BUFFER (doc)); -} - -void -gedit_document_begin_not_undoable_action (GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - - gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (doc)); -} - -void -gedit_document_end_not_undoable_action (GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - - gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (doc)); -} - -void -gedit_document_begin_user_action (GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - - gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc)); -} - -void -gedit_document_end_user_action (GeditDocument *doc) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - - gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc)); -} - -/* FIXME: line should be an "int" -- Paolo (Feb. 20, 2005) */ -void -gedit_document_goto_line (GeditDocument* doc, guint line) +gboolean +gedit_document_goto_line (GeditDocument *doc, + gint line) { + gboolean ret = TRUE; guint line_count; GtkTextIter iter; - - gedit_debug (DEBUG_DOCUMENT, ""); - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (doc->priv != NULL); - + gedit_debug (DEBUG_DOCUMENT); + + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); + g_return_val_if_fail (line >= -1, FALSE); + line_count = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (doc)); - + if (line > line_count) + { + ret = FALSE; line = line_count; + } gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line); gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter); + + return ret; } -gchar* -gedit_document_get_last_searched_text (GeditDocument* doc) +void +gedit_document_set_search_text (GeditDocument *doc, + const gchar *text, + guint flags) { - gedit_debug (DEBUG_DOCUMENT, ""); + gchar *converted_text = NULL; + gboolean notify; - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); - - return (doc->priv->last_searched_text != NULL) ? - g_strdup (doc->priv->last_searched_text) : NULL; -} + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + g_return_if_fail ((text == NULL) || (doc->priv->search_text != text)); + g_return_if_fail ((text == NULL) || g_utf8_validate (text, -1, NULL)); -gchar* -gedit_document_get_last_replace_text (GeditDocument* doc) -{ - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); + gedit_debug_message (DEBUG_DOCUMENT, "text = %s", text); - return (doc->priv->last_replace_text != NULL) ? - g_strdup (doc->priv->last_replace_text) : NULL; -} + g_free (doc->priv->search_text); -void -gedit_document_set_last_searched_text (GeditDocument* doc, const gchar *text) -{ - gedit_debug (DEBUG_DOCUMENT, ""); + if (text != NULL && *text != '\0') + { + converted_text = gedit_utils_unescape_search_text (text); + notify = doc->priv->search_text == NULL; - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (doc->priv != NULL); - g_return_if_fail (text != NULL); + doc->priv->search_text = converted_text; + } + else + { + notify = doc->priv->search_text != NULL; + doc->priv->search_text = NULL; + } - if (doc->priv->last_searched_text != NULL) - g_free (doc->priv->last_searched_text); + if (!GEDIT_SEARCH_IS_DONT_SET_FLAGS (flags)) + { + doc->priv->search_flags = flags; + } - doc->priv->last_searched_text = g_strdup (text); + if (notify) + g_object_notify (G_OBJECT (doc), "can-search-again"); } -void -gedit_document_set_last_replace_text (GeditDocument* doc, const gchar *text) +gchar * +gedit_document_get_search_text (GeditDocument *doc, + guint *flags) { - gedit_debug (DEBUG_DOCUMENT, ""); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL); - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (doc->priv != NULL); - g_return_if_fail (text != NULL); + if (flags != NULL) + *flags = doc->priv->search_flags; + + return gedit_utils_escape_search_text (doc->priv->search_text); +} - if (doc->priv->last_replace_text != NULL) - g_free (doc->priv->last_replace_text); +gboolean +gedit_document_get_can_search_again (GeditDocument *doc) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - doc->priv->last_replace_text = g_strdup (text); + return doc->priv->search_text != NULL; } gboolean -gedit_document_find (GeditDocument* doc, const gchar* str, gint flags) +gedit_document_search_forward (GeditDocument *doc, + const GtkTextIter *start, + const GtkTextIter *end, + GtkTextIter *match_start, + GtkTextIter *match_end) { GtkTextIter iter; - gboolean found = FALSE; GtkSourceSearchFlags search_flags; - gchar *converted_str; - gboolean is_first_find = FALSE; - - gedit_debug (DEBUG_DOCUMENT, ""); - + gboolean found = FALSE; + GtkTextIter m_start; + GtkTextIter m_end; + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail (str != NULL, FALSE); - - converted_str = gedit_utils_convert_search_text (str); - g_return_val_if_fail (converted_str != NULL, FALSE); + g_return_val_if_fail ((start == NULL) || + (gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)), FALSE); + g_return_val_if_fail ((end == NULL) || + (gtk_text_iter_get_buffer (end) == GTK_TEXT_BUFFER (doc)), FALSE); - gedit_debug (DEBUG_DOCUMENT, "str: %s", str); - gedit_debug (DEBUG_DOCUMENT, "converted_str: %s", converted_str); - - search_flags = GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_TEXT_ONLY; - - if (!GEDIT_SEARCH_IS_CASE_SENSITIVE (flags)) + if (doc->priv->search_text == NULL) { - search_flags = search_flags | GTK_SOURCE_SEARCH_CASE_INSENSITIVE; + gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == NULL\n"); + return FALSE; } + else + gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == \"%s\"\n", doc->priv->search_text); + + if (start == NULL) + gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc), &iter); + else + iter = *start; + + search_flags = GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_TEXT_ONLY; - if (GEDIT_SEARCH_IS_FROM_CURSOR (flags)) + if (!GEDIT_SEARCH_IS_CASE_SENSITIVE (doc->priv->search_flags)) { - GtkTextIter sel_bound; - - gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), - &iter, - &sel_bound); - - if (!GEDIT_SEARCH_IS_BACKWARDS (flags)) - gtk_text_iter_order (&sel_bound, &iter); - else - gtk_text_iter_order (&iter, &sel_bound); + search_flags = search_flags | GTK_SOURCE_SEARCH_CASE_INSENSITIVE; } - else - { - if (GEDIT_SEARCH_IS_BACKWARDS (flags)) + + while (!found) + { + found = gtk_source_iter_forward_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + end); + + if (found && GEDIT_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) { - /* get an iterator at the end of the document */ - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), - &iter); + found = gtk_text_iter_starts_word (&m_start) && + gtk_text_iter_ends_word (&m_end); + + if (!found) + iter = m_end; } else - { - /* get an iterator at the beginning of the document */ - gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc), - &iter); - } + break; } - if (*converted_str != '\0') - { - GtkTextIter match_start, match_end; - - while (!found) - { - if (GEDIT_SEARCH_IS_BACKWARDS (flags)) - { - /*gtk_text_iter_backward_char (&iter);*/ - - found = gtk_source_iter_backward_search (&iter, - converted_str, search_flags, - &match_start, &match_end, - NULL); - } - else - { - found = gtk_source_iter_forward_search (&iter, - converted_str, search_flags, - &match_start, &match_end, - NULL); - } + if (found && (match_start != NULL)) + *match_start = m_start; + + if (found && (match_end != NULL)) + *match_end = m_end; + + return found; +} + +gboolean +gedit_document_search_backward (GeditDocument *doc, + const GtkTextIter *start, + const GtkTextIter *end, + GtkTextIter *match_start, + GtkTextIter *match_end) +{ + GtkTextIter iter; + GtkSourceSearchFlags search_flags; + gboolean found = FALSE; + GtkTextIter m_start; + GtkTextIter m_end; + + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); + g_return_val_if_fail ((start == NULL) || + (gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)), FALSE); + g_return_val_if_fail ((end == NULL) || + (gtk_text_iter_get_buffer (end) == GTK_TEXT_BUFFER (doc)), FALSE); + + if (doc->priv->search_text == NULL) + { + gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == NULL\n"); + return FALSE; + } + else + gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == \"%s\"\n", doc->priv->search_text); + + if (end == NULL) + gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); + else + iter = *end; + + search_flags = GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_TEXT_ONLY; - if (found && GEDIT_SEARCH_IS_ENTIRE_WORD (flags)) - { - found = gtk_text_iter_starts_word (&match_start) && - gtk_text_iter_ends_word (&match_end); - - if (!found) - { - if (GEDIT_SEARCH_IS_BACKWARDS (flags)) - iter = match_start; - else - iter = match_end; - } - } - else - break; - } + if (!GEDIT_SEARCH_IS_CASE_SENSITIVE (doc->priv->search_flags)) + { + search_flags = search_flags | GTK_SOURCE_SEARCH_CASE_INSENSITIVE; + } - if (found) + while (!found) + { + found = gtk_source_iter_backward_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + start); + + if (found && GEDIT_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) { - gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), - &match_start); + found = gtk_text_iter_starts_word (&m_start) && + gtk_text_iter_ends_word (&m_end); - gtk_text_buffer_move_mark_by_name (GTK_TEXT_BUFFER (doc), - "selection_bound", &match_end); - } - - if (gedit_document_can_find_again (doc)) - { - g_free (doc->priv->last_searched_text); + if (!found) + iter = m_start; } else - { - is_first_find = TRUE; - } - - doc->priv->last_searched_text = g_strdup (str); - doc->priv->last_search_was_case_sensitive = GEDIT_SEARCH_IS_CASE_SENSITIVE (flags); - doc->priv->last_search_was_entire_word = GEDIT_SEARCH_IS_ENTIRE_WORD (flags); - - if (is_first_find) - { - g_signal_emit (G_OBJECT (doc), document_signals[CAN_FIND_AGAIN], 0); - } + break; } - - g_free (converted_str); - - g_signal_emit (G_OBJECT (doc), document_signals[CAN_FIND_AGAIN], 0); - - return found; -} - -static gboolean -gedit_document_find_again (GeditDocument* doc, gint flags) -{ - gchar* last_searched_text; - gboolean found; - gedit_debug (DEBUG_DOCUMENT, ""); - - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail (doc->priv != NULL, FALSE); - - last_searched_text = gedit_document_get_last_searched_text (doc); + if (found && (match_start != NULL)) + *match_start = m_start; - if (last_searched_text == NULL) - return FALSE; + if (found && (match_end != NULL)) + *match_end = m_end; - /* pack bitflag array with previous data */ - GEDIT_SEARCH_SET_CASE_SENSITIVE (flags, doc->priv->last_search_was_case_sensitive); - GEDIT_SEARCH_SET_ENTIRE_WORD (flags, doc->priv->last_search_was_entire_word); - - /* run the search */ - found = gedit_document_find (doc, last_searched_text, flags); - - g_free (last_searched_text); - - return found; -} - -gboolean -gedit_document_find_next (GeditDocument* doc, gint flags) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - GEDIT_SEARCH_SET_BACKWARDS (flags, FALSE); - - /* run the search */ - return gedit_document_find_again (doc, flags); + return found; } -gboolean -gedit_document_find_prev (GeditDocument* doc, gint flags) -{ - gedit_debug (DEBUG_DOCUMENT, ""); - - /* pack bitflag array with the backwards searching operative */ - GEDIT_SEARCH_SET_BACKWARDS (flags, TRUE); - - /* run the search */ - return gedit_document_find_again (doc, flags); -} - -void -gedit_document_replace_selected_text (GeditDocument *doc, const gchar *replace) +gint +gedit_document_replace_all (GeditDocument *doc, + const gchar *find, + const gchar *replace, + guint flags) { GtkTextIter iter; - GtkTextIter sel_bound; - gchar *converted_replace; + GtkTextIter m_start; + GtkTextIter m_end; + GtkSourceSearchFlags search_flags = 0; + gboolean found = TRUE; + gint cont = 0; + gchar *search_text; + gchar *replace_text; + gint replace_text_len; + GtkTextBuffer *buffer; + + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), 0); + g_return_val_if_fail (replace != NULL, 0); + g_return_val_if_fail ((find != NULL) || (doc->priv->search_text != NULL), 0); - gedit_debug (DEBUG_DOCUMENT, ""); + buffer = GTK_TEXT_BUFFER (doc); - g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - g_return_if_fail (replace != NULL); + if (find == NULL) + search_text = g_strdup (doc->priv->search_text); + else + search_text = gedit_utils_unescape_search_text (find); + + replace_text = gedit_utils_unescape_search_text (replace); + + gtk_text_buffer_get_start_iter (buffer, &iter); + + search_flags = GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_TEXT_ONLY; - if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), - &iter, - &sel_bound)) + if (!GEDIT_SEARCH_IS_CASE_SENSITIVE (flags)) { - gedit_debug (DEBUG_DOCUMENT, "There is no selected text"); - - return; + search_flags = search_flags | GTK_SOURCE_SEARCH_CASE_INSENSITIVE; } + + replace_text_len = strlen (replace_text); - converted_replace = gedit_utils_convert_search_text (replace); - - gedit_document_begin_user_action (doc); - - gtk_text_buffer_delete_selection (GTK_TEXT_BUFFER (doc), FALSE, TRUE); - - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), - &iter, - gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (doc))); - - if (*converted_replace != '\0') - gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), - &iter, - converted_replace, strlen (converted_replace)); - - gedit_document_set_last_replace_text (doc, replace); - - gedit_document_end_user_action (doc); - - g_free (converted_replace); -} - -gboolean -gedit_document_replace_all (GeditDocument *doc, - const gchar *find, const gchar *replace, - gint flags) -{ - gboolean cont = 0; + /* disable cursor_moved emission until the end of the + * replace_all so that we don't spend all the time + * updating the position in the statusbar + */ + doc->priv->stop_cursor_moved_emission = TRUE; - gedit_debug (DEBUG_DOCUMENT, ""); + gtk_text_buffer_begin_user_action (buffer); + + do + { + found = gtk_source_iter_forward_search (&iter, + search_text, + search_flags, + &m_start, + &m_end, + NULL); + + if (found && GEDIT_SEARCH_IS_ENTIRE_WORD (flags)) + { + gboolean word; + + word = gtk_text_iter_starts_word (&m_start) && + gtk_text_iter_ends_word (&m_end); + + if (!word) + { + iter = m_end; + continue; + } + } + + if (found) + { + ++cont; + + gtk_text_buffer_delete (buffer, + &m_start, + &m_end); + + gtk_text_buffer_insert (buffer, + &m_start, + replace_text, + replace_text_len); - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail (find != NULL, FALSE); - g_return_val_if_fail (replace != NULL, FALSE); + iter = m_start; + } - gedit_document_begin_user_action (doc); + } while (found); - GEDIT_SEARCH_SET_BACKWARDS (flags, FALSE); - GEDIT_SEARCH_SET_FROM_CURSOR (flags, FALSE); + gtk_text_buffer_end_user_action (buffer); - while (gedit_document_find (doc, find, flags)) - { - gedit_document_replace_selected_text (doc, replace); - - GEDIT_SEARCH_SET_FROM_CURSOR (flags, TRUE); - - ++cont; - } + /* re-enable cursor_moved emission and notify + * the current position + */ + doc->priv->stop_cursor_moved_emission = FALSE; + emit_cursor_moved (doc); - gedit_document_end_user_action (doc); + g_free (search_text); + g_free (replace_text); return cont; -} +} void -gedit_document_set_language (GeditDocument *doc, GtkSourceLanguage *lang) +gedit_document_set_language (GeditDocument *doc, + GtkSourceLanguage *lang) { g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); - if (lang != NULL) - gtk_source_buffer_set_highlight (GTK_SOURCE_BUFFER (doc), - gedit_prefs_manager_get_enable_syntax_highlighting ()); - else - gtk_source_buffer_set_highlight (GTK_SOURCE_BUFFER (doc), FALSE); - - gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (doc), lang); - - if (lang != NULL) - gedit_language_init_tag_styles (lang); - - if (doc->priv->uri != NULL) - { - gchar *lang_id = NULL; - - if (lang != NULL) - { - lang_id = gtk_source_language_get_id (lang); - g_return_if_fail (lang_id != NULL); - } - - gedit_metadata_manager_set (doc->priv->uri, - "language", - (lang_id == NULL) ? "_NORMAL_" : lang_id); - - g_free (lang_id); - } + set_language (doc, lang, TRUE); } GtkSourceLanguage * @@ -2722,94 +1542,54 @@ gedit_document_get_encoding (GeditDocument *doc) { g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL); - return gedit_encoding_get_from_charset (doc->priv->encoding); -} - -glong -gedit_document_get_seconds_since_last_save_or_load (GeditDocument *doc) -{ - GTimeVal current_time; - - g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), -1); - - g_get_current_time(¤t_time); - - return (current_time.tv_sec - doc->priv->time_of_last_save_or_load.tv_sec); + return doc->priv->encoding; } void -gedit_document_enable_auto_save (GeditDocument *doc, gboolean enable) +gedit_document_set_auto_save_enabled (GeditDocument *doc, + gboolean enable) { - gedit_debug (DEBUG_DOCUMENT, ""); + gedit_debug (DEBUG_DOCUMENT); g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); enable = (enable != FALSE); - - if (doc->priv->auto_save == enable) - return; - - doc->priv->auto_save = enable; - - if (doc->priv->auto_save && - (doc->priv->auto_save_timeout <= 0) && - !gedit_document_is_untitled (doc) && - !gedit_document_is_readonly (doc)) - { - gedit_debug (DEBUG_DOCUMENT, "Install autosave timeout"); - - doc->priv->auto_save_timeout = g_timeout_add - (doc->priv->auto_save_interval * 1000 * 60, - (GSourceFunc)gedit_document_auto_save, - doc); - - return; - } - if (!doc->priv->auto_save && (doc->priv->auto_save_timeout > 0)) - { - gedit_debug (DEBUG_DOCUMENT, "Remove autosave timeout"); - - g_source_remove (doc->priv->auto_save_timeout); - doc->priv->auto_save_timeout = 0; - - return; - } - - g_return_if_fail ((!doc->priv->auto_save && (doc->priv->auto_save_timeout <= 0)) || - gedit_document_is_untitled (doc) || gedit_document_is_readonly (doc)); + // TODO + + return; } void -gedit_document_set_auto_save_interval (GeditDocument *doc, gint interval) +gedit_document_set_auto_save_interval (GeditDocument *doc, + gint interval) { - gedit_debug (DEBUG_DOCUMENT, ""); + gedit_debug (DEBUG_DOCUMENT); g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); g_return_if_fail (interval > 0); - if (doc->priv->auto_save_interval == interval) - return; - - doc->priv->auto_save_interval = interval; - - if (!doc->priv->auto_save) - return; + // TODO - if (doc->priv->auto_save_timeout > 0) - { - gedit_debug (DEBUG_DOCUMENT, "Remove autosave timeout"); + return; +} - g_source_remove (doc->priv->auto_save_timeout); - - gedit_debug (DEBUG_DOCUMENT, "Install new autosave timeout"); +glong +_gedit_document_get_seconds_since_last_save_or_load (GeditDocument *doc) +{ + GTimeVal current_time; - g_return_if_fail (!gedit_document_is_untitled (doc)); - g_return_if_fail (!gedit_document_is_readonly (doc)); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), -1); - doc->priv->auto_save_timeout = g_timeout_add - (doc->priv->auto_save_interval * 1000 * 60, - (GSourceFunc)gedit_document_auto_save, - doc); - } + g_get_current_time (¤t_time); + + return (current_time.tv_sec - doc->priv->time_of_last_save_or_load.tv_sec); +} + +gboolean +_gedit_document_is_saving_as (GeditDocument *doc) +{ + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); + + return (doc->priv->is_saving_as); } diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h index b93e0397..cea4451f 100644 --- a/gedit/gedit-document.h +++ b/gedit/gedit-document.h @@ -1,11 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-document.h * 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-2004 Paolo Maggi + * 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 @@ -24,194 +23,232 @@ */ /* - * Modified by the gedit Team, 1998-2004. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ - + #ifndef __GEDIT_DOCUMENT_H__ #define __GEDIT_DOCUMENT_H__ - #include #include -#include +#include #include -#define GEDIT_TYPE_DOCUMENT (gedit_document_get_type ()) -#define GEDIT_DOCUMENT(obj) (GTK_CHECK_CAST ((obj), GEDIT_TYPE_DOCUMENT, GeditDocument)) -#define GEDIT_DOCUMENT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_DOCUMENT, GeditDocumentClass)) -#define GEDIT_IS_DOCUMENT(obj) (GTK_CHECK_TYPE ((obj), GEDIT_TYPE_DOCUMENT)) -#define GEDIT_IS_DOCUMENT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT)) -#define GEDIT_DOCUMENT_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GEDIT_TYPE_DOCUMENT, GeditDocumentClass)) - - -#define GEDIT_SEARCH_ENTIRE_WORD (1 << 0 ) -#define GEDIT_SEARCH_BACKWARDS (1 << 1 ) -#define GEDIT_SEARCH_CASE_SENSITIVE (1 << 2 ) -#define GEDIT_SEARCH_FROM_CURSOR (1 << 3 ) - -#define GEDIT_SEARCH_IS_ENTIRE_WORD(sflags) ((sflags & GEDIT_SEARCH_ENTIRE_WORD) != 0) -#define GEDIT_SEARCH_SET_ENTIRE_WORD(sflags,state) ((state == TRUE) ? \ -(sflags |= GEDIT_SEARCH_ENTIRE_WORD) : (sflags &= ~GEDIT_SEARCH_ENTIRE_WORD)) - -#define GEDIT_SEARCH_IS_BACKWARDS(sflags) ((sflags & GEDIT_SEARCH_BACKWARDS) != 0) -#define GEDIT_SEARCH_SET_BACKWARDS(sflags,state) ((state == TRUE) ? \ -(sflags |= GEDIT_SEARCH_BACKWARDS) : (sflags &= ~GEDIT_SEARCH_BACKWARDS)) - -#define GEDIT_SEARCH_IS_CASE_SENSITIVE(sflags) ((sflags & GEDIT_SEARCH_CASE_SENSITIVE) != 0) -#define GEDIT_SEARCH_SET_CASE_SENSITIVE(sflags,state) ((state == TRUE) ? \ -(sflags |= GEDIT_SEARCH_CASE_SENSITIVE) : (sflags &= ~GEDIT_SEARCH_CASE_SENSITIVE)) - -#define GEDIT_SEARCH_IS_FROM_CURSOR(sflags) ((sflags & GEDIT_SEARCH_FROM_CURSOR) != 0) -#define GEDIT_SEARCH_SET_FROM_CURSOR(sflags,state) ((state == TRUE) ? \ -(sflags |= GEDIT_SEARCH_FROM_CURSOR) : (sflags &= ~GEDIT_SEARCH_FROM_CURSOR)) +G_BEGIN_DECLS +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_DOCUMENT (gedit_document_get_type()) +#define GEDIT_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT, GeditDocument)) +#define GEDIT_DOCUMENT_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENT, GeditDocument const)) +#define GEDIT_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENT, GeditDocumentClass)) +#define GEDIT_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENT)) +#define GEDIT_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENT)) +#define GEDIT_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENT, GeditDocumentClass)) + +typedef enum +{ + GEDIT_SEARCH_DONT_SET_FLAGS = 1 << 0, + GEDIT_SEARCH_ENTIRE_WORD = 1 << 1, + GEDIT_SEARCH_CASE_SENSITIVE = 1 << 2 -typedef struct _GeditDocument GeditDocument; -typedef struct _GeditDocumentClass GeditDocumentClass; +} GeditSearchFlags; +/* Private structure type */ typedef struct _GeditDocumentPrivate GeditDocumentPrivate; +/* + * Main object structure + */ +typedef struct _GeditDocument GeditDocument; + struct _GeditDocument { GtkSourceBuffer buffer; + + /*< private > */ GeditDocumentPrivate *priv; }; +/* + * Class definition + */ +typedef struct _GeditDocumentClass GeditDocumentClass; + struct _GeditDocumentClass { GtkSourceBufferClass parent_class; - /* File name (uri) changed */ - void (* name_changed) (GeditDocument *document); + /* Signals */ // CHECK: ancora da rivedere - /* Connect to the following two signals for loading and reverting */ - /* Document loaded */ - void (* loaded) (GeditDocument *document, - const GError *error); + void (* cursor_moved) (GeditDocument *document); + /* Document load */ void (* loading) (GeditDocument *document, - gulong size, - gulong total_size); + GnomeVFSFileSize size, + GnomeVFSFileSize total_size); - /* Document saved */ - void (* saved) (GeditDocument *document); + void (* loaded) (GeditDocument *document, + const GError *error); - /* Readonly flag changed */ - void (* readonly_changed) (GeditDocument *document, - gboolean readonly); + /* Document save */ + void (* saving) (GeditDocument *document, + GnomeVFSFileSize size, + GnomeVFSFileSize total_size); - /* Find state udpated */ - void (* can_find_again) (GeditDocument *document); + void (* saved) (GeditDocument *document, + const GError *error); }; -#define GEDIT_ERROR_INVALID_UTF8_DATA 1024 -#define GEDIT_ERROR_UNTITLED 1025 -#define GEDIT_ERROR_NOT_REGULAR_FILE 1026 -#define GEDIT_DOCUMENT_IO_ERROR gedit_document_io_error_quark () - -GQuark gedit_document_io_error_quark (void); - -GType gedit_document_get_type (void) G_GNUC_CONST; - -GeditDocument* gedit_document_new (void); -GeditDocument* gedit_document_new_with_uri (const gchar *uri, - const GeditEncoding *encoding); - -void gedit_document_set_readonly (GeditDocument *doc, - gboolean readonly); -gboolean gedit_document_is_readonly (GeditDocument *doc); - -gchar* gedit_document_get_raw_uri (GeditDocument *doc); -gchar* gedit_document_get_uri (GeditDocument *doc); -gchar* gedit_document_get_short_name (GeditDocument *doc); - -const gchar *gedit_document_get_mime_type (GeditDocument *doc); - -void gedit_document_load (GeditDocument *doc, - const gchar *uri, - const GeditEncoding *encoding); - -gboolean gedit_document_load_from_stdin (GeditDocument *doc, - GError **error); - -gboolean gedit_document_is_untouched (const GeditDocument *doc); - -gboolean gedit_document_save (GeditDocument *doc, - GError **error); -gboolean gedit_document_save_as (GeditDocument *doc, - const gchar *uri, - const GeditEncoding *encoding, - GError **error); - -void gedit_document_revert (GeditDocument *doc); - -gboolean gedit_document_is_untitled (const GeditDocument* doc); -gboolean gedit_document_get_modified (const GeditDocument* doc); - -gboolean gedit_document_get_deleted (GeditDocument *doc); - -void gedit_document_insert_text (GeditDocument *doc, - gint pos, - const gchar *text, - gint len); -/* Multi-level Undo/Redo operations */ -void gedit_document_set_max_undo_levels (GeditDocument *doc, - gint max_undo_levels); - -gboolean gedit_document_can_undo (const GeditDocument *doc); -gboolean gedit_document_can_redo (const GeditDocument *doc); -gboolean gedit_document_can_find_again (const GeditDocument *doc); - -void gedit_document_undo (GeditDocument *doc); -void gedit_document_redo (GeditDocument *doc); +typedef enum +{ + /* save file despite external modifications */ + GEDIT_DOCUMENT_SAVE_IGNORE_MTIME = 1 << 0, -void gedit_document_begin_not_undoable_action (GeditDocument *doc); -void gedit_document_end_not_undoable_action (GeditDocument *doc); + /* write the file directly without attempting to backup */ + GEDIT_DOCUMENT_SAVE_IGNORE_BACKUP = 1 << 1 +} GeditDocumentSaveFlags; -void gedit_document_begin_user_action (GeditDocument *doc); -void gedit_document_end_user_action (GeditDocument *doc); -void gedit_document_goto_line (GeditDocument* doc, guint line); +#define GEDIT_DOCUMENT_ERROR gedit_document_error_quark () -gchar* gedit_document_get_last_searched_text (GeditDocument* doc); -gchar* gedit_document_get_last_replace_text (GeditDocument* doc); +enum +{ + /* start at GNOME_VFS_NUM_ERRORS since we use GnomeVFSResult + * for the error codes */ + GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED = GNOME_VFS_NUM_ERRORS, + GEDIT_DOCUMENT_ERROR_NOT_REGULAR_FILE, + GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP, + GEDIT_DOCUMENT_NUM_ERRORS +}; -void gedit_document_set_last_searched_text (GeditDocument* doc, const gchar *text); -void gedit_document_set_last_replace_text (GeditDocument* doc, const gchar *text); +GQuark gedit_document_error_quark (void); + +GType gedit_document_get_type (void) G_GNUC_CONST; + +GeditDocument *gedit_document_new (void); + +gchar *gedit_document_get_uri (GeditDocument *doc); + +gchar *gedit_document_get_uri_for_display + (GeditDocument *doc); +gchar *gedit_document_get_short_name_for_display + (GeditDocument *doc); + +gchar *gedit_document_get_mime_type (GeditDocument *doc); + +gboolean gedit_document_get_readonly (GeditDocument *doc); + +gboolean gedit_document_load (GeditDocument *doc, + const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create); + +gboolean gedit_document_insert_file (GeditDocument *doc, + GtkTextIter *iter, + const gchar *uri, + const GeditEncoding *encoding); + +gboolean gedit_document_load_cancel (GeditDocument *doc); + +void gedit_document_save (GeditDocument *doc, + GeditDocumentSaveFlags flags); + +void gedit_document_save_as (GeditDocument *doc, + const gchar *uri, + const GeditEncoding *encoding, + GeditDocumentSaveFlags flags); + +gboolean gedit_document_is_untouched (GeditDocument *doc); +gboolean gedit_document_is_untitled (GeditDocument *doc); + +gboolean gedit_document_get_deleted (GeditDocument *doc); +/* Ancora da discutere +gboolean gedit_document_get_externally_modified + (GeditDocument *doc); +*/ + +gboolean gedit_document_goto_line (GeditDocument *doc, + gint line); + +void gedit_document_set_search_text (GeditDocument *doc, + const gchar *text, + guint flags); + +gchar *gedit_document_get_search_text (GeditDocument *doc, + guint *flags); + +gboolean gedit_document_get_can_search_again + (GeditDocument *doc); + +gboolean gedit_document_search_forward (GeditDocument *doc, + const GtkTextIter *start, + const GtkTextIter *end, + GtkTextIter *match_start, + GtkTextIter *match_end); + +gboolean gedit_document_search_backward (GeditDocument *doc, + const GtkTextIter *start, + const GtkTextIter *end, + GtkTextIter *match_start, + GtkTextIter *match_end); + +gint gedit_document_replace_all (GeditDocument *doc, + const gchar *find, + const gchar *replace, + guint flags); + +void gedit_document_set_language (GeditDocument *doc, + GtkSourceLanguage *lang); +GtkSourceLanguage + *gedit_document_get_language (GeditDocument *doc); + +const GeditEncoding + *gedit_document_get_encoding (GeditDocument *doc); + +// CHECK: I think this can be private +void gedit_document_set_auto_save_enabled + (GeditDocument *doc, + gboolean enable); +void gedit_document_set_auto_save_interval + (GeditDocument *doc, + gint interval); + +/* + * Non exported functions + */ +gboolean _gedit_document_is_saving_as (GeditDocument *doc); -gboolean gedit_document_find (GeditDocument* doc, const gchar* str, - gint flags); -gboolean gedit_document_find_next (GeditDocument* doc, gint flags); -gboolean gedit_document_find_prev (GeditDocument* doc, gint flags); +// CHECK: va bene un gint? +glong _gedit_document_get_seconds_since_last_save_or_load + (GeditDocument *doc); -void gedit_document_replace_selected_text (GeditDocument *doc, - const gchar *replace); -gboolean gedit_document_replace_all (GeditDocument *doc, - const gchar *find, - const gchar *replace, - gint flags); +/* private because the property will move to gtk */ +gboolean _gedit_document_get_has_selection + (GeditDocument *doc); -void gedit_document_set_language (GeditDocument *doc, - GtkSourceLanguage *lang); -GtkSourceLanguage *gedit_document_get_language (GeditDocument *doc); -const GeditEncoding *gedit_document_get_encoding (GeditDocument *doc); +/* Search macros */ +#define GEDIT_SEARCH_IS_DONT_SET_FLAGS(sflags) ((sflags & GEDIT_SEARCH_DONT_SET_FLAGS) != 0) +#define GEDIT_SEARCH_SET_DONT_SET_FLAGS(sflags,state) ((state == TRUE) ? \ +(sflags |= GEDIT_SEARCH_DONT_SET_FLAGS) : (sflags &= ~GEDIT_SEARCH_DONT_SET_FLAGS)) -glong gedit_document_get_seconds_since_last_save_or_load - (GeditDocument *doc); +#define GEDIT_SEARCH_IS_ENTIRE_WORD(sflags) ((sflags & GEDIT_SEARCH_ENTIRE_WORD) != 0) +#define GEDIT_SEARCH_SET_ENTIRE_WORD(sflags,state) ((state == TRUE) ? \ +(sflags |= GEDIT_SEARCH_ENTIRE_WORD) : (sflags &= ~GEDIT_SEARCH_ENTIRE_WORD)) -void gedit_document_enable_auto_save (GeditDocument *doc, - gboolean enable); -void gedit_document_set_auto_save_interval - (GeditDocument *doc, - gint interval); +#define GEDIT_SEARCH_IS_CASE_SENSITIVE(sflags) ((sflags & GEDIT_SEARCH_CASE_SENSITIVE) != 0) +#define GEDIT_SEARCH_SET_CASE_SENSITIVE(sflags,state) ((state == TRUE) ? \ +(sflags |= GEDIT_SEARCH_CASE_SENSITIVE) : (sflags &= ~GEDIT_SEARCH_CASE_SENSITIVE)) +G_END_DECLS #endif /* __GEDIT_DOCUMENT_H__ */ - - - diff --git a/gedit/gedit-documents-panel.c b/gedit/gedit-documents-panel.c new file mode 100644 index 00000000..2c997091 --- /dev/null +++ b/gedit/gedit-documents-panel.c @@ -0,0 +1,672 @@ +/* + * gedit-documents-panel.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-documents-panel.h" +#include "gedit-utils.h" + +#include + +#define GEDIT_DOCUMENTS_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \ + GEDIT_TYPE_DOCUMENTS_PANEL, \ + GeditDocumentsPanelPrivate)) + +struct _GeditDocumentsPanelPrivate +{ + GeditWindow *window; + + GtkWidget *treeview; + GtkTreeModel *model; +}; + +G_DEFINE_TYPE(GeditDocumentsPanel, gedit_documents_panel, GTK_TYPE_VBOX) + +enum +{ + PROP_0, + PROP_WINDOW, +}; + +#define MAX_DOC_NAME_LENGTH 60 + +static gchar * +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 = gedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH); + + if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc))) + { + if (gedit_document_get_readonly (doc)) + { + tab_name = g_markup_printf_escaped ("%s [%s]", + docname, + _("Read Only")); + } + else + { + tab_name = g_markup_printf_escaped ("%s", + docname); + } + } + else + { + if (gedit_document_get_readonly (doc)) + { + tab_name = g_markup_printf_escaped ("%s [%s]", + docname, + _("Read Only")); + } + else + { + tab_name = g_markup_escape_text (docname, -1); + } + } + + g_free (docname); + g_free (name); + + return tab_name; +} + +static GtkTreeIter +get_iter_from_tab (GeditDocumentsPanel *panel, GeditTab *tab) +{ + gint num; + GtkWidget *nb; + GtkTreeIter iter; + GtkTreePath *path; + + nb = _gedit_window_get_notebook (panel->priv->window); + num = gtk_notebook_page_num (GTK_NOTEBOOK (nb), + GTK_WIDGET (tab)); + + path = gtk_tree_path_new_from_indices (num, -1); + gtk_tree_model_get_iter (panel->priv->model, + &iter, + path); + gtk_tree_path_free (path); + + return iter; +} + +static void +window_active_tab_changed (GeditWindow *window, + GeditTab *tab, + GeditDocumentsPanel *panel) +{ + g_return_if_fail (tab != NULL); + + if (!_gedit_window_is_removing_tabs (window)) + { + GtkTreeIter iter; + GtkTreeSelection *selection; + + iter = get_iter_from_tab (panel, tab); + + if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (panel->priv->model), + &iter)) + { + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (panel->priv->treeview)); + + gtk_tree_selection_select_iter (selection, &iter); + } + } +} + +static void +refresh_list (GeditDocumentsPanel *panel) +{ + /* TODO: refresh the list only if the panel is visible */ + + GList *tabs; + GList *l; + GtkWidget *nb; + GtkListStore *list_store; + GeditTab *active_tab; + + list_store = GTK_LIST_STORE (panel->priv->model); + + gtk_list_store_clear (list_store); + + active_tab = gedit_window_get_active_tab (panel->priv->window); + + nb = _gedit_window_get_notebook (panel->priv->window); + + tabs = gtk_container_get_children (GTK_CONTAINER (nb)); + l = tabs; + + while (l != NULL) + { + GdkPixbuf *pixbuf; + gchar *name; + GtkTreeIter iter; + + name = tab_get_name (GEDIT_TAB (l->data)); + pixbuf = _gedit_tab_get_icon (GEDIT_TAB (l->data)); + + /* Add a new row to the model */ + gtk_list_store_append (list_store, &iter); + gtk_list_store_set (list_store, + &iter, + 0, pixbuf, + 1, name, + 2, l->data, + -1); + + g_free (name); + if (pixbuf != NULL) + g_object_unref (pixbuf); + + if (l->data == active_tab) + { + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (panel->priv->treeview)); + + gtk_tree_selection_select_iter (selection, &iter); + } + + l = g_list_next (l); + } + + g_list_free (tabs); +} + +static void +sync_name_and_icon (GeditTab *tab, + GParamSpec *pspec, + GeditDocumentsPanel *panel) +{ + GdkPixbuf *pixbuf; + gchar *name; + GtkTreeIter iter; + + iter = get_iter_from_tab (panel, tab); + + name = tab_get_name (tab); + pixbuf = _gedit_tab_get_icon (tab); + + gtk_list_store_set (GTK_LIST_STORE (panel->priv->model), + &iter, + 0, pixbuf, + 1, name, + 2, tab, + -1); + + g_free (name); + if (pixbuf != NULL) + g_object_unref (pixbuf); +} + +static void +window_tab_removed (GeditWindow *window, + GeditTab *tab, + GeditDocumentsPanel *panel) +{ + g_signal_handlers_disconnect_by_func (tab, + G_CALLBACK (sync_name_and_icon), + panel); + + if (_gedit_window_is_removing_tabs (window)) + gtk_list_store_clear (GTK_LIST_STORE (panel->priv->model)); + else + refresh_list (panel); +} + +static void +window_tab_added (GeditWindow *window, + GeditTab *tab, + GeditDocumentsPanel *panel) +{ + GtkTreeIter iter; + GtkTreeIter sibling; + GdkPixbuf *pixbuf; + gchar *name; + + g_signal_connect (tab, + "notify::name", + G_CALLBACK (sync_name_and_icon), + panel); + + g_signal_connect (tab, + "notify::state", + G_CALLBACK (sync_name_and_icon), + panel); + + sibling = get_iter_from_tab (panel, tab); + + if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (panel->priv->model), + &sibling)) + { + gtk_list_store_insert_after (GTK_LIST_STORE (panel->priv->model), + &iter, + &sibling); + } + else + { + GtkTreeSelection *selection; + + gtk_list_store_append (GTK_LIST_STORE (panel->priv->model), + &iter); + + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (panel->priv->treeview)); + + gtk_tree_selection_select_iter (selection, &iter); + } + + name = tab_get_name (tab); + pixbuf = _gedit_tab_get_icon (tab); + + gtk_list_store_set (GTK_LIST_STORE (panel->priv->model), + &iter, + 0, pixbuf, + 1, name, + 2, tab, + -1); + + g_free (name); + if (pixbuf != NULL) + g_object_unref (pixbuf); +} + +static void +window_tabs_reordered (GeditWindow *window, + GeditDocumentsPanel *panel) +{ + refresh_list (panel); +} + +static void +set_window (GeditDocumentsPanel *panel, + GeditWindow *window) +{ + g_return_if_fail (panel->priv->window == NULL); + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + panel->priv->window = window; + + g_signal_connect (window, + "tab_added", + G_CALLBACK (window_tab_added), + panel); + g_signal_connect (window, + "tab_removed", + G_CALLBACK (window_tab_removed), + panel); + g_signal_connect (window, + "tabs_reordered", + G_CALLBACK (window_tabs_reordered), + panel); + g_signal_connect (window, + "active_tab_changed", + G_CALLBACK (window_active_tab_changed), + panel); +} + +static void +treeview_cursor_changed (GtkTreeView *view, + GeditDocumentsPanel *panel) +{ + GtkTreeIter iter; + GtkTreeSelection *selection; + gpointer tab; + + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (panel->priv->treeview)); + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + { + gtk_tree_model_get (panel->priv->model, + &iter, + 2, + &tab, + -1); + + if (gedit_window_get_active_tab (panel->priv->window) != tab) + { + gedit_window_set_active_tab (panel->priv->window, + GEDIT_TAB (tab)); + } + } +} + +static void +gedit_documents_panel_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object); + + switch (prop_id) + { + case PROP_WINDOW: + set_window (panel, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_documents_panel_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object); + + switch (prop_id) + { + case PROP_WINDOW: + g_value_set_object (value, + GEDIT_DOCUMENTS_PANEL_GET_PRIVATE (panel)->window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_documents_panel_finalize (GObject *object) +{ + /* GeditDocumentsPanel *tab = GEDIT_DOCUMENTS_PANEL (object); */ + + // TODO: disconnect signal with window + + G_OBJECT_CLASS (gedit_documents_panel_parent_class)->finalize (object); +} + +static void +gedit_documents_panel_class_init (GeditDocumentsPanelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_documents_panel_finalize; + object_class->get_property = gedit_documents_panel_get_property; + object_class->set_property = gedit_documents_panel_set_property; + + g_object_class_install_property (object_class, + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "The GeditWindow this GeditDocumentsPanel is associated with", + GEDIT_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof(GeditDocumentsPanelPrivate)); +} + +static GtkTreePath * +get_current_path (GeditDocumentsPanel *panel) +{ + gint num; + GtkWidget *nb; + GtkTreePath *path; + + nb = _gedit_window_get_notebook (panel->priv->window); + num = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb)); + + path = gtk_tree_path_new_from_indices (num, -1); + + return path; +} + +static void +menu_position (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + GeditDocumentsPanel *panel) +{ + GtkTreePath *path; + GdkRectangle rect; + gint wx, wy; + GtkRequisition requisition; + GtkWidget *w; + + w = panel->priv->treeview; + + path = get_current_path (panel); + + gtk_tree_view_get_cell_area (GTK_TREE_VIEW (w), + path, + NULL, + &rect); + + wx = rect.x; + wy = rect.y; + + gdk_window_get_origin (w->window, x, y); + + gtk_widget_size_request (GTK_WIDGET (menu), &requisition); + + if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL) + { + *x += w->allocation.x + w->allocation.width - requisition.width - 10; + } + else + { + *x += w->allocation.x + 10 ; + } + + wy = MAX (*y + 5, *y + wy + 5); + wy = MIN (wy, *y + w->allocation.height - requisition.height - 5); + + *y = wy; + + *push_in = TRUE; +} + +static gboolean +show_popup_menu (GeditDocumentsPanel *panel, + GdkEventButton *event) +{ + GtkWidget *menu; + + menu = gtk_ui_manager_get_widget (gedit_window_get_ui_manager (panel->priv->window), + "/NotebookPopup"); + g_return_val_if_fail (menu != NULL, FALSE); + + if (event != NULL) + { + gtk_menu_popup (GTK_MENU (menu), + NULL, + NULL, + NULL, + NULL, + event->button, + event->time); + } + else + { + gtk_menu_popup (GTK_MENU (menu), + NULL, + NULL, + (GtkMenuPositionFunc) menu_position, + panel, + 0, + gtk_get_current_event_time ()); + + gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE); + } + + return TRUE; +} + +static gboolean +panel_button_press_event (GtkTreeView *treeview, + GdkEventButton *event, + GeditDocumentsPanel *panel) +{ + if ((GDK_BUTTON_PRESS == event->type) && (3 == event->button)) + { + GtkTreePath* path = NULL; + + if (event->window == gtk_tree_view_get_bin_window (treeview)) + { + /* Change the cursor position */ + if (gtk_tree_view_get_path_at_pos (treeview, + event->x, + event->y, + &path, + NULL, + NULL, + NULL)) + { + + gtk_tree_view_set_cursor (treeview, + path, + NULL, + FALSE); + + gtk_tree_path_free (path); + + /* A row exists at mouse position */ + return show_popup_menu (panel, event); + } + } + } + + return FALSE; +} + +static gboolean +panel_popup_menu (GtkWidget *treeview, + GeditDocumentsPanel *panel) +{ + /* Only respond if the treeview is the actual focus */ + if (gtk_window_get_focus (GTK_WINDOW (panel->priv->window)) == treeview) + { + return show_popup_menu (panel, NULL); + } + + return FALSE; +} + +static void +gedit_documents_panel_init (GeditDocumentsPanel *panel) +{ + GtkWidget *sw; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + GtkTreeSelection *selection; + // GtkWidget *popup_menu; + + panel->priv = GEDIT_DOCUMENTS_PANEL_GET_PRIVATE (panel); + + /* Create the scrolled window */ + sw = gtk_scrolled_window_new (NULL, NULL); + g_return_if_fail (sw != NULL); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), + GTK_SHADOW_IN); + gtk_widget_show (sw); + gtk_box_pack_start (GTK_BOX (panel), sw, TRUE, TRUE, 0); + + /* Create the empty model */ + panel->priv->model = GTK_TREE_MODEL (gtk_list_store_new (3, + GDK_TYPE_PIXBUF, + G_TYPE_STRING, + G_TYPE_POINTER)); + + /* Create the treeview */ + panel->priv->treeview = gtk_tree_view_new_with_model (panel->priv->model); + g_object_unref (G_OBJECT (panel->priv->model)); + gtk_container_add (GTK_CONTAINER (sw), panel->priv->treeview); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (panel->priv->treeview), FALSE); + gtk_widget_show (panel->priv->treeview); + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Documents")); + + cell = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, cell, FALSE); + gtk_tree_view_column_add_attribute (column, cell, "pixbuf", 0); + cell = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "markup", 1); + + gtk_tree_view_append_column (GTK_TREE_VIEW (panel->priv->treeview), + column); + + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (panel->priv->treeview)); + + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + g_signal_connect (panel->priv->treeview, + "cursor_changed", + G_CALLBACK (treeview_cursor_changed), + panel); + g_signal_connect (panel->priv->treeview, + "button-press-event", + G_CALLBACK (panel_button_press_event), + panel); + g_signal_connect (panel->priv->treeview, + "popup-menu", + G_CALLBACK (panel_popup_menu), + panel); +} + +GtkWidget * +gedit_documents_panel_new (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return GTK_WIDGET (g_object_new (GEDIT_TYPE_DOCUMENTS_PANEL, + "window", window, + NULL)); +} diff --git a/gedit/gedit-documents-panel.h b/gedit/gedit-documents-panel.h new file mode 100644 index 00000000..19f2ebc3 --- /dev/null +++ b/gedit/gedit-documents-panel.h @@ -0,0 +1,86 @@ +/* + * gedit-documents-panel.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_DOCUMENTS_PANEL_H__ +#define __GEDIT_DOCUMENTS_PANEL_H__ + +#include + +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_DOCUMENTS_PANEL (gedit_documents_panel_get_type()) +#define GEDIT_DOCUMENTS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENTS_PANEL, GeditDocumentsPanel)) +#define GEDIT_DOCUMENTS_PANEL_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_DOCUMENTS_PANEL, GeditDocumentsPanel const)) +#define GEDIT_DOCUMENTS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_DOCUMENTS_PANEL, GeditDocumentsPanelClass)) +#define GEDIT_IS_DOCUMENTS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_DOCUMENTS_PANEL)) +#define GEDIT_IS_DOCUMENTS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENTS_PANEL)) +#define GEDIT_DOCUMENTS_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_DOCUMENTS_PANEL, GeditDocumentsPanelClass)) + +/* Private structure type */ +typedef struct _GeditDocumentsPanelPrivate GeditDocumentsPanelPrivate; + +/* + * Main object structure + */ +typedef struct _GeditDocumentsPanel GeditDocumentsPanel; + +struct _GeditDocumentsPanel +{ + GtkVBox vbox; + + /*< private > */ + GeditDocumentsPanelPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditDocumentsPanelClass GeditDocumentsPanelClass; + +struct _GeditDocumentsPanelClass +{ + GtkVBoxClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_documents_panel_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_documents_panel_new (GeditWindow *window); + +G_END_DECLS + +#endif /* __GEDIT_DOCUMENTS_PANEL_H__ */ diff --git a/gedit/gedit-encodings-option-menu.c b/gedit/gedit-encodings-option-menu.c index 95b94182..8b78f888 100644 --- a/gedit/gedit-encodings-option-menu.c +++ b/gedit/gedit-encodings-option-menu.c @@ -3,7 +3,7 @@ * gedit-encodings-option-menu.c * This file is part of gedit * - * Copyright (C) 2003 - 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 @@ -22,9 +22,11 @@ */ /* - * Modified by the gedit Team, 2003. See the AUTHORS file for a + * Modified by the gedit Team, 2003-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -34,18 +36,13 @@ #include #include -#include "gedit-encodings-option-menu.h" -#include "gedit-prefs-manager.h" -#include "dialogs/gedit-encodings-dialog.h" +#include +#include +#include #define ENCODING_KEY "Enconding" -static void gedit_encodings_option_menu_class_init (GeditEncodingsOptionMenuClass *klass); -static void gedit_encodings_option_menu_init (GeditEncodingsOptionMenu *menu); -static void gedit_encodings_option_menu_finalize (GObject *object); - -static void update_menu (GeditEncodingsOptionMenu *option_menu); - +static void update_menu (GeditEncodingsOptionMenu *option_menu); /* Properties */ enum { @@ -53,6 +50,10 @@ enum { PROP_SAVE_MODE }; +#define GEDIT_ENCODINGS_OPTION_MENU_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \ + GEDIT_TYPE_ENCODINGS_OPTION_MENU, \ + GeditEncodingsOptionMenuPrivate)) + struct _GeditEncodingsOptionMenuPrivate { gint activated_item; @@ -60,33 +61,8 @@ struct _GeditEncodingsOptionMenuPrivate gboolean save_mode; }; -static GObjectClass *parent_class = NULL; -GType -gedit_encodings_option_menu_get_type (void) -{ - static GType our_type = 0; - - if (our_type == 0) { - static const GTypeInfo our_info = { - sizeof (GeditEncodingsOptionMenuClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gedit_encodings_option_menu_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GeditEncodingsOptionMenu), - 0, /* n_preallocs */ - (GInstanceInitFunc) gedit_encodings_option_menu_init - }; - - our_type = - g_type_register_static (GTK_TYPE_OPTION_MENU, - "GeditEncodingsOptionMenu", &our_info, 0); - } - - return our_type; -} +G_DEFINE_TYPE(GeditEncodingsOptionMenu, gedit_encodings_option_menu, GTK_TYPE_OPTION_MENU) static void gedit_encodings_option_menu_set_property (GObject *object, @@ -99,17 +75,17 @@ gedit_encodings_option_menu_set_property (GObject *object, g_return_if_fail (GEDIT_IS_ENCODINGS_OPTION_MENU (object)); om = GEDIT_ENCODINGS_OPTION_MENU (object); - - switch (prop_id) { - case PROP_SAVE_MODE: - om->priv->save_mode = g_value_get_boolean (value); - - update_menu (om); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + + switch (prop_id) + { + case PROP_SAVE_MODE: + om->priv->save_mode = g_value_get_boolean (value); + + update_menu (om); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } } @@ -122,17 +98,17 @@ gedit_encodings_option_menu_get_property (GObject *object, GeditEncodingsOptionMenu *om; g_return_if_fail (GEDIT_IS_ENCODINGS_OPTION_MENU (object)); - + om = GEDIT_ENCODINGS_OPTION_MENU (object); - switch (prop_id) { - case PROP_SAVE_MODE: - g_value_set_boolean (value, om->priv->save_mode); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + switch (prop_id) + { + case PROP_SAVE_MODE: + g_value_set_boolean (value, om->priv->save_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } } @@ -141,9 +117,6 @@ gedit_encodings_option_menu_class_init (GeditEncodingsOptionMenuClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - parent_class = g_type_class_peek_parent (klass); - object_class->finalize = gedit_encodings_option_menu_finalize; - object_class->set_property = gedit_encodings_option_menu_set_property; object_class->get_property = gedit_encodings_option_menu_get_property; @@ -154,29 +127,71 @@ gedit_encodings_option_menu_class_init (GeditEncodingsOptionMenuClass *klass) ("Save Mode"), FALSE, (G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY))); + G_PARAM_CONSTRUCT))); + + g_type_class_add_private (object_class, sizeof(GeditEncodingsOptionMenuPrivate)); } static void -add_or_remove (GtkMenuItem *menu_item, GeditEncodingsOptionMenu *option_menu) +dialog_response_cb (GtkDialog *dialog, + gint response_id, + GeditEncodingsOptionMenu *option_menu) { + update_menu (option_menu); + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void +add_or_remove (GtkMenuItem *menu_item, + GeditEncodingsOptionMenu *option_menu) +{ if (GTK_IS_RADIO_MENU_ITEM (menu_item)) + { option_menu->priv->activated_item = gtk_option_menu_get_history (GTK_OPTION_MENU (option_menu)); + } else { - + GtkWidget *dialog; + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (option_menu)); - - if (!GTK_WIDGET_TOPLEVEL (toplevel)) + + if (!GTK_WIDGET_TOPLEVEL (toplevel)) toplevel = NULL; gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), option_menu->priv->activated_item); - if (gedit_encodings_dialog_run ((toplevel != NULL) ? GTK_WINDOW (toplevel) : NULL)) - update_menu (option_menu); + dialog = gedit_encodings_dialog_new(); + + if (toplevel != NULL) + { + GtkWindowGroup *wg; + + gtk_window_set_transient_for (GTK_WINDOW (dialog), + GTK_WINDOW (toplevel)); + + wg = GTK_WINDOW (toplevel)->group; + if (wg == NULL) + { + wg = gtk_window_group_new (); + gtk_window_group_add_window (wg, + GTK_WINDOW (toplevel)); + } + + gtk_window_group_add_window (wg, + GTK_WINDOW (dialog)); + } + + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + g_signal_connect (dialog, + "response", + G_CALLBACK (dialog_response_cb), + option_menu); + + gtk_widget_show (dialog); } } @@ -193,12 +208,12 @@ update_menu (GeditEncodingsOptionMenu *option_menu) const GeditEncoding *current_encoding; menu = gtk_menu_new (); - + encodings = list = gedit_prefs_manager_get_shown_in_menu_encodings (); utf8_encoding = gedit_encoding_get_utf8 (); current_encoding = gedit_encoding_get_current (); - + if (!option_menu->priv->save_mode) { menu_item = gtk_radio_menu_item_new_with_label (group, _("Auto Detected")); @@ -211,13 +226,13 @@ update_menu (GeditEncodingsOptionMenu *option_menu) "activate", G_CALLBACK (add_or_remove), option_menu); - + menu_item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); } - + if (current_encoding != utf8_encoding) str = gedit_encoding_to_string (utf8_encoding); else @@ -321,22 +336,7 @@ update_menu (GeditEncodingsOptionMenu *option_menu) static void gedit_encodings_option_menu_init (GeditEncodingsOptionMenu *menu) { - menu->priv = g_new0 (GeditEncodingsOptionMenuPrivate, 1); -} - -static void -gedit_encodings_option_menu_finalize (GObject *object) -{ - GeditEncodingsOptionMenu *menu; - - menu = GEDIT_ENCODINGS_OPTION_MENU (object); - - if (menu->priv != NULL) - { - g_free (menu->priv); - } - - G_OBJECT_CLASS (parent_class)->finalize (object); + menu->priv = GEDIT_ENCODINGS_OPTION_MENU_GET_PRIVATE (menu); } GtkWidget * @@ -355,7 +355,7 @@ gedit_encodings_option_menu_get_selected_encoding (GeditEncodingsOptionMenu *men GtkOptionMenu *option_menu; g_return_val_if_fail (GEDIT_IS_ENCODINGS_OPTION_MENU (menu), NULL); - + option_menu = GTK_OPTION_MENU (menu); g_return_val_if_fail (option_menu != NULL, NULL); @@ -386,7 +386,7 @@ gedit_encodings_option_menu_set_selected_encoding (GeditEncodingsOptionMenu *men gint i; g_return_if_fail (GEDIT_IS_ENCODINGS_OPTION_MENU (menu)); - + option_menu = GTK_OPTION_MENU (menu); g_return_if_fail (option_menu != NULL); @@ -396,7 +396,7 @@ gedit_encodings_option_menu_set_selected_encoding (GeditEncodingsOptionMenu *men { GtkWidget *menu_item; const GeditEncoding *enc; - + menu_item = GTK_WIDGET (list->data); enc = (const GeditEncoding *)g_object_get_data (G_OBJECT (menu_item), @@ -407,7 +407,7 @@ gedit_encodings_option_menu_set_selected_encoding (GeditEncodingsOptionMenu *men gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE); gtk_option_menu_set_history (GTK_OPTION_MENU (menu), i); - + return; } @@ -416,4 +416,3 @@ gedit_encodings_option_menu_set_selected_encoding (GeditEncodingsOptionMenu *men list = g_list_next (list); } } - diff --git a/gedit/gedit-encodings-option-menu.h b/gedit/gedit-encodings-option-menu.h index 593373f7..f563c93b 100644 --- a/gedit/gedit-encodings-option-menu.h +++ b/gedit/gedit-encodings-option-menu.h @@ -3,7 +3,7 @@ * gedit-encodings-option-menu.h * This file is part of gedit * - * Copyright (C) 2003 - 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 @@ -22,16 +22,18 @@ */ /* - * Modified by the gedit Team, 2003. See the AUTHORS file for a + * Modified by the gedit Team, 2003-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_ENCODINGS_OPTION_MENU_H__ #define __GEDIT_ENCODINGS_OPTION_MENU_H__ #include -#include "gedit-encodings.h" +#include G_BEGIN_DECLS diff --git a/gedit/gedit-encodings.c b/gedit/gedit-encodings.c index 616f5c6d..e0839307 100644 --- a/gedit/gedit-encodings.c +++ b/gedit/gedit-encodings.c @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-encodings.c * This file is part of gedit @@ -25,6 +24,8 @@ * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -294,8 +295,7 @@ gedit_encoding_lazy_init (void) /* Translate the names */ encodings[i].name = _(encodings[i].name); - - + ++i; } @@ -441,3 +441,66 @@ gedit_encoding_get_name (const GeditEncoding* enc) return (enc->name == NULL) ? _("Unknown") : enc->name; } +/** + * gedit_encoding_get_type: + * + * Retrieves the GType object which is associated with the + * #GeditEncoding class. + * + * Return value: the GType associated with #GeditEncoding. + **/ +GType +gedit_encoding_get_type (void) +{ + static GType our_type = 0; + + if (!our_type) + our_type = g_boxed_type_register_static ( + "GeditEncoding", + (GBoxedCopyFunc) gedit_encoding_copy, + (GBoxedFreeFunc) gedit_encoding_free); + + return our_type; +} + +/** + * gedit_encoding_copy: + * @enc: a #GeditEncoding. + * + * Makes a copy of the given encoding. + * This function is used by language bindings. + * + * Return value: a new #GeditEncoding. + **/ +GeditEncoding * +gedit_encoding_copy (const GeditEncoding *enc) +{ + GeditEncoding *new_enc; + + g_return_val_if_fail (enc != NULL, NULL); + + new_enc = g_new0 (GeditEncoding, 1); + *new_enc = *enc; + + return new_enc; +} + + +/** + * gedit_encoding_free: + * @enc: a #GeditEncoding. + * + * Frees the resources allocated by the given encoding. + * This function is used by language bindings. + **/ +void +gedit_encoding_free (GeditEncoding *enc) +{ + g_return_if_fail (enc != NULL); + + g_free (enc); +} + + + + diff --git a/gedit/gedit-encodings.h b/gedit/gedit-encodings.h index 85b94e57..b5a368e4 100644 --- a/gedit/gedit-encodings.h +++ b/gedit/gedit-encodings.h @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-encodings.h * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,18 +21,29 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_ENCODINGS_H__ #define __GEDIT_ENCODINGS_H__ #include +#include + +G_BEGIN_DECLS typedef struct _GeditEncoding GeditEncoding; +#define GEDIT_TYPE_ENCODING (gedit_encoding_get_type ()) + +GType gedit_encoding_get_type (void) G_GNUC_CONST; + +GeditEncoding *gedit_encoding_copy (const GeditEncoding *enc); +void gedit_encoding_free (GeditEncoding *enc); const GeditEncoding *gedit_encoding_get_from_charset (const gchar *charset); const GeditEncoding *gedit_encoding_get_from_index (gint index); @@ -46,6 +56,6 @@ const gchar *gedit_encoding_get_charset (const GeditEncoding *enc); const GeditEncoding *gedit_encoding_get_utf8 (void); const GeditEncoding *gedit_encoding_get_current (void); -#endif /* __GEDIT_ENCODINGS_H__ */ - +G_END_DECLS +#endif /* __GEDIT_ENCODINGS_H__ */ diff --git a/gedit/gedit-file-chooser-dialog.c b/gedit/gedit-file-chooser-dialog.c new file mode 100644 index 00000000..76129e0c --- /dev/null +++ b/gedit/gedit-file-chooser-dialog.c @@ -0,0 +1,279 @@ +/* + * gedit-file-chooser-dialog.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +/* TODO: Override set_extra_widget */ +/* TODO: add encoding property */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "gedit-file-chooser-dialog.h" +#include + +#define GEDIT_FILE_CHOOSER_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogPrivate)) + +struct _GeditFileChooserDialogPrivate +{ + GtkWidget *option_menu; +}; + +G_DEFINE_TYPE(GeditFileChooserDialog, gedit_file_chooser_dialog, GTK_TYPE_FILE_CHOOSER_DIALOG) + +static void +gedit_file_chooser_dialog_class_init (GeditFileChooserDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof(GeditFileChooserDialogPrivate)); +} + +static void +create_option_menu (GeditFileChooserDialog *dialog) +{ + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *menu; + + hbox = gtk_hbox_new (FALSE, 6); + + label = gtk_label_new_with_mnemonic (_("C_haracter Coding:")); + menu = gedit_encodings_option_menu_new ( + gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu); + gtk_box_pack_start (GTK_BOX (hbox), + label, + FALSE, + FALSE, + 0); + + gtk_box_pack_end (GTK_BOX (hbox), + menu, + TRUE, + TRUE, + 0); + + gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), + hbox); + gtk_widget_show_all (hbox); + + dialog->priv->option_menu = menu; +} + +static void +action_changed (GeditFileChooserDialog *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->priv->option_menu, + "save_mode", FALSE, + NULL); + gtk_widget_show (dialog->priv->option_menu); + break; + case GTK_FILE_CHOOSER_ACTION_SAVE: + g_object_set (dialog->priv->option_menu, + "save_mode", TRUE, + NULL); + gtk_widget_show (dialog->priv->option_menu); + break; + default: + gtk_widget_hide (dialog->priv->option_menu); + } +} + +static gboolean +all_text_files_filter (const GtkFileFilterInfo *filter_info, + gpointer data) +{ + if (filter_info->mime_type == NULL) + return TRUE; + + if ((strncmp (filter_info->mime_type, "text/", 5) == 0) || + (strcmp (filter_info->mime_type, "application/x-desktop") == 0) || + (strcmp (filter_info->mime_type, "application/x-perl") == 0) || + (strcmp (filter_info->mime_type, "application/x-python") == 0) || + (strcmp (filter_info->mime_type, "application/x-php") == 0)) + { + return TRUE; + } + + return FALSE; +} + +static void +gedit_file_chooser_dialog_init (GeditFileChooserDialog *dialog) +{ + dialog->priv = GEDIT_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog); +} + +static GtkWidget * +gedit_file_chooser_dialog_new_valist (const gchar *title, + GtkWindow *parent, + GtkFileChooserAction action, + const GeditEncoding *encoding, + const gchar *first_button_text, + va_list varargs) +{ + GtkWidget *result; + const char *button_text = first_button_text; + gint response_id; + GtkFileFilter *filter; + + g_return_val_if_fail (parent != NULL, NULL); + + result = g_object_new (GEDIT_TYPE_FILE_CHOOSER_DIALOG, + "title", title, + "file-system-backend", NULL, + "local-only", FALSE, + "action", action, + "select-multiple", action == GTK_FILE_CHOOSER_ACTION_OPEN, + NULL); + + create_option_menu (GEDIT_FILE_CHOOSER_DIALOG (result)); + + g_signal_connect (result, + "notify::action", + G_CALLBACK (action_changed), + NULL); + + if (encoding != NULL) + gedit_encodings_option_menu_set_selected_encoding ( + GEDIT_ENCODINGS_OPTION_MENU (GEDIT_FILE_CHOOSER_DIALOG (result)->priv->option_menu), + encoding); + + /* Filters */ + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter); + + /* Make this filter the default */ + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Text Files")); + gtk_file_filter_add_custom (filter, + GTK_FILE_FILTER_MIME_TYPE, + all_text_files_filter, + NULL, + NULL); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter); + /* TODO: Add filters for all supported languages - Paolo - Feb 21, 2004 */ + + gtk_window_set_transient_for (GTK_WINDOW (result), parent); + gtk_window_set_destroy_with_parent (GTK_WINDOW (result), TRUE); + + while (button_text) + { + response_id = va_arg (varargs, gint); + + gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id); + if ((response_id == GTK_RESPONSE_OK) || + (response_id == GTK_RESPONSE_ACCEPT) || + (response_id == GTK_RESPONSE_YES) || + (response_id == GTK_RESPONSE_APPLY)) + gtk_dialog_set_default_response (GTK_DIALOG (result), response_id); + + button_text = va_arg (varargs, const gchar *); + } + + return result; +} + +/** + * gedit_file_chooser_dialog_new: + * @title: Title of the dialog, or %NULL + * @parent: Transient parent of the dialog, or %NULL + * @action: Open or save mode for the dialog + * @first_button_text: stock ID or text to go in the first button, or %NULL + * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL + * + * Creates a new #GeditFileChooserDialog. This function is analogous to + * gtk_dialog_new_with_buttons(). + * + * Return value: a new #GeditFileChooserDialog + * + **/ +GtkWidget * +gedit_file_chooser_dialog_new (const gchar *title, + GtkWindow *parent, + GtkFileChooserAction action, + const GeditEncoding *encoding, + const gchar *first_button_text, + ...) +{ + GtkWidget *result; + va_list varargs; + + va_start (varargs, first_button_text); + result = gedit_file_chooser_dialog_new_valist (title, parent, action, + encoding, first_button_text, + varargs); + va_end (varargs); + + return result; +} + +void +gedit_file_chooser_dialog_set_encoding (GeditFileChooserDialog *dialog, + const GeditEncoding *encoding) +{ + g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog)); + g_return_if_fail (GEDIT_IS_ENCODINGS_OPTION_MENU (dialog->priv->option_menu)); + + gedit_encodings_option_menu_set_selected_encoding ( + GEDIT_ENCODINGS_OPTION_MENU (dialog->priv->option_menu), + encoding); +} + +const GeditEncoding * +gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog) +{ + g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL); + g_return_val_if_fail (GEDIT_IS_ENCODINGS_OPTION_MENU (dialog->priv->option_menu), NULL); + g_return_val_if_fail ((gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_OPEN || + gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE), NULL); + + return gedit_encodings_option_menu_get_selected_encoding ( + GEDIT_ENCODINGS_OPTION_MENU (dialog->priv->option_menu)); +} diff --git a/gedit/gedit-file-chooser-dialog.h b/gedit/gedit-file-chooser-dialog.h new file mode 100644 index 00000000..c996f48b --- /dev/null +++ b/gedit/gedit-file-chooser-dialog.h @@ -0,0 +1,82 @@ +/* + * gedit-file-chooser-dialog.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_FILE_CHOOSER_DIALOG_H__ +#define __GEDIT_FILE_CHOOSER_DIALOG_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define GEDIT_TYPE_FILE_CHOOSER_DIALOG (gedit_file_chooser_dialog_get_type ()) +#define GEDIT_FILE_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialog)) +#define GEDIT_FILE_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogClass)) +#define GEDIT_IS_FILE_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FILE_CHOOSER_DIALOG)) +#define GEDIT_IS_FILE_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FILE_CHOOSER_DIALOG)) +#define GEDIT_FILE_CHOOSER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogClass)) + +typedef struct _GeditFileChooserDialog GeditFileChooserDialog; +typedef struct _GeditFileChooserDialogClass GeditFileChooserDialogClass; + +typedef struct _GeditFileChooserDialogPrivate GeditFileChooserDialogPrivate; + +struct _GeditFileChooserDialogClass +{ + GtkFileChooserDialogClass parent_class; +}; + +struct _GeditFileChooserDialog +{ + GtkFileChooserDialog parent_instance; + + GeditFileChooserDialogPrivate *priv; +}; + +GType gedit_file_chooser_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_file_chooser_dialog_new (const gchar *title, + GtkWindow *parent, + GtkFileChooserAction action, + const GeditEncoding *encoding, + const gchar *first_button_text, + ...); + +void gedit_file_chooser_dialog_set_encoding (GeditFileChooserDialog *dialog, + const GeditEncoding *encoding); + +const GeditEncoding + *gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog); + + +G_END_DECLS + +#endif /* __GEDIT_FILE_CHOOSER_DIALOG_H__ */ diff --git a/gedit/gedit-help.c b/gedit/gedit-help.c new file mode 100644 index 00000000..44c77f6e --- /dev/null +++ b/gedit/gedit-help.c @@ -0,0 +1,84 @@ +/* + * gedit-help.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-help.h" + +#include +#include +#include + +gboolean +gedit_help_display (GtkWindow *parent, + const gchar *file_name, /* "gedit.xml" if NULL */ + const gchar *link_id) +{ + GError *error = NULL; + gboolean ret; + + g_return_val_if_fail ((parent == NULL) || GTK_IS_WINDOW (parent), FALSE); + + if (file_name == NULL) + file_name = "gedit.xml"; + + ret = gnome_help_display (file_name, + link_id, + &error); + + if (error != NULL) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("There was an error displaying help.")); + + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + error->message); + + g_signal_connect (G_OBJECT (dialog), + "response", + G_CALLBACK (gtk_widget_destroy), + NULL); + + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + + gtk_widget_show (dialog); + + g_error_free (error); + } + + return ret; +} diff --git a/gedit/gedit-help.h b/gedit/gedit-help.h new file mode 100644 index 00000000..8ef6d312 --- /dev/null +++ b/gedit/gedit-help.h @@ -0,0 +1,44 @@ +/* + * gedit-help.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_HELP_H__ +#define __GEDIT_HELP_H__ + +#include + +G_BEGIN_DECLS + +gboolean gedit_help_display (GtkWindow *parent, + const gchar *file_name, /* "gedit.xml" if NULL */ + const gchar *link_id); + +G_END_DECLS + +#endif /* __GEDIT_HELP_H__ */ diff --git a/gedit/gedit-io-error-message-area.c b/gedit/gedit-io-error-message-area.c new file mode 100644 index 00000000..41a7d074 --- /dev/null +++ b/gedit/gedit-io-error-message-area.c @@ -0,0 +1,1302 @@ +/* + * gedit-io-error-message-area.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +/* + * Verbose error reporting for file I/O operations (load, save, revert, create) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include "gedit-utils.h" +#include "gedit-convert.h" +#include "gedit-document.h" +#include "gedit-io-error-message-area.h" +#include "gedit-message-area.h" +#include "gedit-prefs-manager.h" +#include + +#define MAX_URI_IN_DIALOG_LENGTH 50 + +static GtkWidget * +create_unrecoverable_error_message_area (const gchar *primary_text, + const gchar *secondary_text) +{ + GtkWidget *message_area; + GtkWidget *hbox_content; + GtkWidget *image; + GtkWidget *vbox; + gchar *primary_markup; + gchar *secondary_markup; + GtkWidget *primary_label; + GtkWidget *secondary_label; + + message_area = gedit_message_area_new_with_buttons ( + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + NULL); + + hbox_content = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox_content); + + image = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_DIALOG); + gtk_widget_show (image); + gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0); + + primary_markup = g_strdup_printf ("%s", primary_text); + primary_label = gtk_label_new (primary_markup); + g_free (primary_markup); + gtk_widget_show (primary_label); + 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_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5); + GTK_WIDGET_SET_FLAGS (primary_label, GTK_CAN_FOCUS); + gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE); + + if (secondary_text != NULL) + { + secondary_markup = g_strdup_printf ("%s", + secondary_text); + secondary_label = gtk_label_new (secondary_markup); + g_free (secondary_markup); + gtk_widget_show (secondary_label); + gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (secondary_label, GTK_CAN_FOCUS); + 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_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5); + } + + gedit_message_area_set_contents (GEDIT_MESSAGE_AREA (message_area), + hbox_content); + return message_area; +} + +GtkWidget * +gedit_unrecoverable_loading_error_message_area_new (const gchar *uri, + const GError *error) +{ + gchar *error_message = NULL; + gchar *message_details = NULL; + gchar *full_formatted_uri; + gchar *scheme_string; + gchar *uri_for_display; + gchar *temp_uri_for_display; + GtkWidget *message_area; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (error->domain == GEDIT_DOCUMENT_ERROR, NULL); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + switch (error->code) + { + case GNOME_VFS_ERROR_NOT_FOUND: + error_message = g_strdup_printf (_("Could not find the file %s."), + uri_for_display); + message_details = g_strdup (_("Please, check that you typed the " + "location correctly and try again.")); + break; + + case GNOME_VFS_ERROR_CORRUPTED_DATA: + message_details = g_strdup (_("The file contains corrupted data.")); + break; + + case GNOME_VFS_ERROR_NOT_SUPPORTED: + scheme_string = gnome_vfs_get_uri_scheme (uri); + + if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL)) + { + /* Translators: %s is a URI scheme (like for example http, ftp, etc.) */ + message_details = g_strdup_printf (_("gedit cannot handle %s: locations."), + scheme_string); + } + else + { + message_details = g_strdup (_("gedit cannot handle this location.")); + } + + g_free (scheme_string); + break; + + case GNOME_VFS_ERROR_WRONG_FORMAT: + message_details = g_strdup (_("The file contains data in an invalid format.")); + break; + + case GNOME_VFS_ERROR_TOO_BIG: + message_details = g_strdup (_("The file is too big.")); + break; + + case GNOME_VFS_ERROR_INVALID_URI: + 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 GNOME_VFS_ERROR_ACCESS_DENIED: + message_details = g_strdup (_("You do not have the permissions necessary to open the file.")); + break; + + case GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES: + message_details = g_strdup (_("There are too many open files. Please, " + "close some applications and try again.")); + break; + + case GNOME_VFS_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 GNOME_VFS_ERROR_NO_MEMORY: + message_details = g_strdup (_("Not enough available memory to open " + "the file. Please, close some running " + "applications and try again.")); + break; + + case GNOME_VFS_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. + */ + { + GnomeVFSURI *vfs_uri; + + vfs_uri = gnome_vfs_uri_new (uri); + + if (vfs_uri != NULL) + { + const gchar *hn = gnome_vfs_uri_get_host_name (vfs_uri); + + if (hn != NULL) + { + gchar *host_name = gedit_utils_make_valid_utf8 (hn); + + /* Translators: %s is a host name */ + message_details = g_strdup_printf ( + _("Host %s could not be found. " + "Please, check that your proxy settings " + "are correct and try again."), + host_name); + + g_free (host_name); + } + else + { + /* use the same string as INVALID_HOST */ + message_details = g_strdup_printf ( + _("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + } + + gnome_vfs_uri_unref (vfs_uri); + } + else + { + /* use the same string as INVALID_HOST */ + message_details = g_strdup_printf ( + _("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + } + } + break; + + case GNOME_VFS_ERROR_INVALID_HOST_NAME: + message_details = g_strdup_printf (_("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + break; + + case GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS: + message_details = g_strdup (_("Host name was empty. " + "Please, check that your proxy settings " + "are correct and try again.")); + break; + + case GNOME_VFS_ERROR_LOGIN_FAILED: + message_details = g_strdup (_("Attempt to log in failed. " + "Please, check that you typed the location " + "correctly and try again.")); + break; + + case GEDIT_DOCUMENT_ERROR_NOT_REGULAR_FILE: + message_details = g_strdup (_("The file you are trying to open is not a regular file.")); + break; + + case GNOME_VFS_ERROR_GENERIC: + break; + + /* + case GNOME_VFS_ERROR_INTERNAL: + case GNOME_VFS_ERROR_BAD_PARAMETERS: + case GNOME_VFS_ERROR_IO: + case GNOME_VFS_ERROR_BAD_FILE: + case GNOME_VFS_ERROR_NO_SPACE: + case GNOME_VFS_ERROR_READ_ONLY: + case GNOME_VFS_ERROR_NOT_OPEN: + case GNOME_VFS_ERROR_INVALID_OPEN_MODE: + case GNOME_VFS_ERROR_EOF: + case GNOME_VFS_ERROR_NOT_A_DIRECTORY: + case GNOME_VFS_ERROR_IN_PROGRESS: + case GNOME_VFS_ERROR_INTERRUPTED: + case GNOME_VFS_ERROR_FILE_EXISTS: + case GNOME_VFS_ERROR_LOOP: + case GNOME_VFS_ERROR_NOT_PERMITTED: + case GNOME_VFS_ERROR_CANCELLED: + case GNOME_VFS_ERROR_DIRECTORY_BUSY: + case GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY: + case GNOME_VFS_ERROR_TOO_MANY_LINKS: + case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM: + case GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM: + case GNOME_VFS_ERROR_NAME_TOO_LONG: + case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE: + case GNOME_VFS_ERROR_SERVICE_OBSOLETE, + case GNOME_VFS_ERROR_PROTOCOL_ERROR, + case GNOME_VFS_NUM_ERRORS: + */ + + default: + /* We should invent decent error messages for every case we actually experience. */ + g_warning ("Hit unhandled case %d (%s) in %s.", + error->code, gnome_vfs_result_to_string (error->code), G_STRFUNC); + message_details = g_strdup_printf (_("Unexpected error: %s"), + gnome_vfs_result_to_string (error->code)); + break; + } + + if (error_message == NULL) + error_message = g_strdup_printf (_("Could not open the file %s."), + uri_for_display); + + message_area = create_unrecoverable_error_message_area (error_message, + message_details); + + g_free (error_message); + g_free (message_details); + + return message_area; +} + +GtkWidget * +gedit_unrecoverable_reverting_error_message_area_new (const gchar *uri, + const GError *error) +{ + gchar *error_message = NULL; + gchar *message_details = NULL; + gchar *full_formatted_uri; + gchar *scheme_string; + gchar *uri_for_display; + gchar *temp_uri_for_display; + GtkWidget *message_area; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (error->domain == GEDIT_DOCUMENT_ERROR, NULL); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + switch (error->code) + { + case GNOME_VFS_ERROR_NOT_FOUND: + message_details = g_strdup (_("gedit cannot find it. " + "Perhaps, it has recently been deleted.")); + break; + + case GNOME_VFS_ERROR_CORRUPTED_DATA: + message_details = g_strdup (_("The file contains corrupted data.")); + break; + + case GNOME_VFS_ERROR_NOT_SUPPORTED: + scheme_string = gnome_vfs_get_uri_scheme (uri); + + if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL)) + { + message_details = g_strdup_printf (_("gedit cannot handle %s: locations."), + scheme_string); + } + else + { + message_details = g_strdup (_("gedit cannot handle this location.")); + } + + g_free (scheme_string); + break; + + case GNOME_VFS_ERROR_WRONG_FORMAT: + message_details = g_strdup (_("The file contains data in an invalid format.")); + break; + + case GNOME_VFS_ERROR_TOO_BIG: + message_details = g_strdup (_("The file is too big.")); + break; + + case GNOME_VFS_ERROR_ACCESS_DENIED: + message_details = g_strdup (_("You do not have the permissions necessary to open the file.")); + break; + + case GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES: + message_details = g_strdup (_("There are too many open files. Please, " + "close some applications and try again.")); + break; + + case GNOME_VFS_ERROR_IS_DIRECTORY: + message_details = g_strdup_printf (_("%s is a directory."), + uri_for_display); + break; + + case GNOME_VFS_ERROR_NO_MEMORY: + message_details = g_strdup (_("Not enough available memory to open " + "the file. Please, close some running " + "applications and try again.")); + break; + + case GNOME_VFS_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. + */ + { + GnomeVFSURI *vfs_uri; + + vfs_uri = gnome_vfs_uri_new (uri); + + if (vfs_uri != NULL) + { + const gchar *hn = gnome_vfs_uri_get_host_name (vfs_uri); + + if (hn != NULL) + { + gchar *host_name = gedit_utils_make_valid_utf8 (hn); + + /* Translators: %s is a host name */ + message_details = g_strdup_printf ( + _("Host %s could not be found. " + "Please, check that your proxy settings " + "are correct and try again."), + host_name); + + g_free (host_name); + } + else + { + /* use the same string as INVALID_HOST */ + message_details = g_strdup_printf ( + _("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + } + + gnome_vfs_uri_unref (vfs_uri); + } + else + { + /* use the same string as INVALID_HOST */ + message_details = g_strdup_printf ( + _("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + } + } + break; + + case GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS: + message_details = g_strdup (_("Host name was empty. " + "Please, check that your proxy settings " + "are correct and try again.")); + break; + + case GNOME_VFS_ERROR_LOGIN_FAILED: + message_details = g_strdup (_("Attempt to log in failed.")); + break; + + case GEDIT_DOCUMENT_ERROR_NOT_REGULAR_FILE: + message_details = g_strdup_printf (_("%s is not a regular file."), + uri_for_display); + break; + + /* this should never happen, revert should be insensitive */ +//CHECK: we used to have this before new_mdi... is it really useful (see comment above) +/* + case GEDIT_ERROR_UNTITLED: + message_details = g_strdup (_("It is not possible to revert an Untitled document.")); + break; +*/ + case GNOME_VFS_ERROR_GENERIC: + break; + + /* + case GNOME_VFS_ERROR_INVALID_URI: + case GNOME_VFS_ERROR_INVALID_HOST_NAME: + case GNOME_VFS_ERROR_GENERIC: + case GNOME_VFS_ERROR_INTERNAL: + case GNOME_VFS_ERROR_BAD_PARAMETERS: + case GNOME_VFS_ERROR_IO: + case GNOME_VFS_ERROR_BAD_FILE: + case GNOME_VFS_ERROR_NO_SPACE: + case GNOME_VFS_ERROR_READ_ONLY: + case GNOME_VFS_ERROR_NOT_OPEN: + case GNOME_VFS_ERROR_INVALID_OPEN_MODE: + case GNOME_VFS_ERROR_EOF: + case GNOME_VFS_ERROR_NOT_A_DIRECTORY: + case GNOME_VFS_ERROR_IN_PROGRESS: + case GNOME_VFS_ERROR_INTERRUPTED: + case GNOME_VFS_ERROR_FILE_EXISTS: + case GNOME_VFS_ERROR_LOOP: + case GNOME_VFS_ERROR_NOT_PERMITTED: + case GNOME_VFS_ERROR_CANCELLED: + case GNOME_VFS_ERROR_DIRECTORY_BUSY: + case GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY: + case GNOME_VFS_ERROR_TOO_MANY_LINKS: + case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM: + case GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM: + case GNOME_VFS_ERROR_NAME_TOO_LONG: + case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE: + case GNOME_VFS_ERROR_SERVICE_OBSOLETE, + case GNOME_VFS_ERROR_PROTOCOL_ERROR, + case GNOME_VFS_NUM_ERRORS: + case GNOME_VFS_ERROR_IS_DIRECTORY: + */ + + default: + g_warning ("Hit unhandled case %d (%s) in %s.", + error->code, gnome_vfs_result_to_string (error->code), G_STRFUNC); + message_details = g_strdup_printf (_("Unexpected error: %s"), + gnome_vfs_result_to_string (error->code)); + break; + } + + if (error_message == NULL) + error_message = g_strdup_printf (_("Could not revert the file %s."), + uri_for_display); + + message_area = create_unrecoverable_error_message_area (error_message, + message_details); + + g_free (error_message); + g_free (message_details); + + return message_area; +} + +static void +create_option_menu (GtkWidget *message_area, GtkWidget *vbox) +{ + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *menu; + + hbox = gtk_hbox_new (FALSE, 6); + + label = gtk_label_new_with_mnemonic (_("Ch_aracter Coding:")); + gtk_label_set_use_markup (GTK_LABEL (label), TRUE); + menu = gedit_encodings_option_menu_new (TRUE); + g_object_set_data (G_OBJECT (message_area), + "gedit-message-area-encoding-menu", + menu); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu); + gtk_box_pack_start (GTK_BOX (hbox), + label, + FALSE, + FALSE, + 0); + + gtk_box_pack_end (GTK_BOX (hbox), + menu, + TRUE, + TRUE, + 0); + + gtk_widget_show_all (hbox); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); +} + +static GtkWidget * +create_conversion_error_message_area (const gchar *primary_text, + const gchar *secondary_text) +{ + GtkWidget *message_area; + GtkWidget *hbox_content; + GtkWidget *image; + GtkWidget *vbox; + gchar *primary_markup; + gchar *secondary_markup; + GtkWidget *primary_label; + GtkWidget *secondary_label; + + message_area = gedit_message_area_new (); + + gedit_message_area_add_stock_button_with_text (GEDIT_MESSAGE_AREA (message_area), + _("_Retry"), + GTK_STOCK_REDO, + GTK_RESPONSE_OK); + gedit_message_area_add_button (GEDIT_MESSAGE_AREA (message_area), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + + hbox_content = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox_content); + + image = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_DIALOG); + gtk_widget_show (image); + gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0); + + primary_markup = g_strdup_printf ("%s", primary_text); + primary_label = gtk_label_new (primary_markup); + g_free (primary_markup); + gtk_widget_show (primary_label); + 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_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5); + GTK_WIDGET_SET_FLAGS (primary_label, GTK_CAN_FOCUS); + gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE); + + if (secondary_text != NULL) + { + secondary_markup = g_strdup_printf ("%s", + secondary_text); + secondary_label = gtk_label_new (secondary_markup); + g_free (secondary_markup); + gtk_widget_show (secondary_label); + gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (secondary_label, GTK_CAN_FOCUS); + 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_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5); + } + + create_option_menu (message_area, vbox); + + gedit_message_area_set_contents (GEDIT_MESSAGE_AREA (message_area), + hbox_content); + return message_area; +} + +GtkWidget * +gedit_conversion_error_while_loading_message_area_new ( + const gchar *uri, + const GeditEncoding *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 *message_area; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail ((error->domain == G_CONVERT_ERROR) || + (error->domain == GEDIT_CONVERT_ERROR), NULL); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + if (encoding != NULL) + encoding_name = gedit_encoding_to_string (encoding); + else + encoding_name = g_strdup ("UTF-8"); + + if (error->domain == GEDIT_CONVERT_ERROR) + { + g_return_val_if_fail (error->code == GEDIT_CONVERT_ERROR_AUTO_DETECTION_FAILED, NULL); + + error_message = g_strdup_printf (_("Could not open the file %s."), + uri_for_display); + message_details = g_strconcat (_("gedit has not been able to detect " + "the character coding."), "\n", + _("Please check that you are not trying to open a binary file."), "\n", + _("Select a character coding from the menu and try again."), NULL); + } + else + { + + error_message = g_strdup_printf (_("Could not open the file %s using the %s character coding."), + uri_for_display, + encoding_name); + message_details = g_strconcat (_("Please check that you are not trying to open a binary file."), "\n", + _("Select a different character coding from the menu and try again."), NULL); + } + + message_area = create_conversion_error_message_area ( + error_message, + message_details); + + g_free (error_message); + g_free (message_details); + + return message_area; +} + +GtkWidget * +gedit_conversion_error_while_saving_message_area_new ( + const gchar *uri, + const GeditEncoding *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 *message_area; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (error->domain == G_CONVERT_ERROR, NULL); + g_return_val_if_fail (encoding != NULL, NULL); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + encoding_name = gedit_encoding_to_string (encoding); + + error_message = g_strdup_printf (_("Could not save the file %s using the %s character coding."), + uri_for_display, + encoding_name); + message_details = g_strconcat (_("The document contains one or more characters that cannot be encoded " + "using the specified character coding."), "\n", + _("Select a different character coding from the menu and try again."), NULL); + + message_area = create_conversion_error_message_area ( + error_message, + message_details); + + g_free (error_message); + g_free (message_details); + + return message_area; +} + +const GeditEncoding * +gedit_conversion_error_message_area_get_encoding (GtkWidget *message_area) +{ + gpointer menu; + + g_return_val_if_fail (GEDIT_IS_MESSAGE_AREA (message_area), NULL); + + menu = g_object_get_data (G_OBJECT (message_area), + "gedit-message-area-encoding-menu"); + g_return_val_if_fail (menu, NULL); + + return gedit_encodings_option_menu_get_selected_encoding + (GEDIT_ENCODINGS_OPTION_MENU (menu)); +} + +GtkWidget * +gedit_file_already_open_warning_message_area_new (const gchar *uri) +{ + GtkWidget *message_area; + GtkWidget *hbox_content; + GtkWidget *image; + 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; + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + message_area = gedit_message_area_new (); + gedit_message_area_add_button (GEDIT_MESSAGE_AREA (message_area), + _("_Edit Anyway"), + GTK_RESPONSE_YES); + gedit_message_area_add_button (GEDIT_MESSAGE_AREA (message_area), + _("_Don't Edit"), + GTK_RESPONSE_CANCEL); + + hbox_content = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox_content); + + image = gtk_image_new_from_stock ("gtk-dialog-warning", GTK_ICON_SIZE_DIALOG); + gtk_widget_show (image); + gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0); + + // FIXME: try to rephrase in a better way + primary_text = g_strdup_printf (_("The file %s is already open."), 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_widget_show (primary_label); + 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_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5); + GTK_WIDGET_SET_FLAGS (primary_label, GTK_CAN_FOCUS); + gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE); + + secondary_text = _("gedit opened this instance of the file in non-editable way. " + "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_widget_show (secondary_label); + gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (secondary_label, GTK_CAN_FOCUS); + 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_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5); + + gedit_message_area_set_contents (GEDIT_MESSAGE_AREA (message_area), + hbox_content); + return message_area; +} + +GtkWidget * +gedit_externally_modified_saving_error_message_area_new ( + const gchar *uri, + const GError *error) +{ + GtkWidget *message_area; + GtkWidget *hbox_content; + GtkWidget *image; + 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 (uri != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (error->domain == GEDIT_DOCUMENT_ERROR, NULL); + g_return_val_if_fail (error->code == GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED, NULL); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + message_area = gedit_message_area_new (); + gedit_message_area_add_stock_button_with_text (GEDIT_MESSAGE_AREA (message_area), + _("_Save Anyway"), + GTK_STOCK_SAVE, + GTK_RESPONSE_YES); + gedit_message_area_add_button (GEDIT_MESSAGE_AREA (message_area), + _("_Don't Save"), + GTK_RESPONSE_CANCEL); + + hbox_content = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox_content); + + image = gtk_image_new_from_stock ("gtk-dialog-warning", GTK_ICON_SIZE_DIALOG); + gtk_widget_show (image); + gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + 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_widget_show (primary_label); + 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_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5); + GTK_WIDGET_SET_FLAGS (primary_label, GTK_CAN_FOCUS); + 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_widget_show (secondary_label); + gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (secondary_label, GTK_CAN_FOCUS); + 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_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5); + + gedit_message_area_set_contents (GEDIT_MESSAGE_AREA (message_area), + hbox_content); + + return message_area; +} + +GtkWidget * +gedit_no_backup_saving_error_message_area_new (const gchar *uri, + const GError *error) +{ + GtkWidget *message_area; + GtkWidget *hbox_content; + GtkWidget *image; + 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 (uri != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (error->domain == GEDIT_DOCUMENT_ERROR, NULL); + g_return_val_if_fail (error->code == GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP, NULL); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + message_area = gedit_message_area_new (); + gedit_message_area_add_stock_button_with_text (GEDIT_MESSAGE_AREA (message_area), + _("_Save Anyway"), + GTK_STOCK_SAVE, + GTK_RESPONSE_YES); + gedit_message_area_add_button (GEDIT_MESSAGE_AREA (message_area), + _("_Don't Save"), + GTK_RESPONSE_CANCEL); + + hbox_content = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox_content); + + image = gtk_image_new_from_stock ("gtk-dialog-warning", GTK_ICON_SIZE_DIALOG); + gtk_widget_show (image); + gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0); + + // FIXME: review this messages + + if (gedit_prefs_manager_get_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_widget_show (primary_label); + 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_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5); + GTK_WIDGET_SET_FLAGS (primary_label, GTK_CAN_FOCUS); + gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE); + + secondary_text = _("gedit could not backup 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_widget_show (secondary_label); + gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (secondary_label, GTK_CAN_FOCUS); + 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_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5); + + gedit_message_area_set_contents (GEDIT_MESSAGE_AREA (message_area), + hbox_content); + + return message_area; +} + +GtkWidget * +gedit_unrecoverable_saving_error_message_area_new (const gchar *uri, + const GError *error) +{ + gchar *error_message = NULL; + gchar *message_details = NULL; + gchar *full_formatted_uri; + gchar *scheme_string; + gchar *uri_for_display; + gchar *temp_uri_for_display; + GtkWidget *message_area; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (error->domain == GEDIT_DOCUMENT_ERROR, NULL); + + full_formatted_uri = gnome_vfs_format_uri_for_display (uri); + + /* 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_strdup_printf ("%s", temp_uri_for_display); + g_free (temp_uri_for_display); + + switch (error->code) + { + case GNOME_VFS_ERROR_NOT_SUPPORTED: + scheme_string = gnome_vfs_get_uri_scheme (uri); + + if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL)) + { + /* Translators: %s is a URI scheme (like for example http, ftp, etc.) */ + message_details = g_strdup_printf (_("gedit cannot handle %s: locations in write mode. " + "Please, check that you typed the " + "location correctly and try again."), + scheme_string); + } + else + { + message_details = g_strdup (_("gedit cannot handle this location in write mode. " + "Please, check that you typed the " + "location correctly and try again.")); + } + + g_free (scheme_string); + break; + + case GNOME_VFS_ERROR_TOO_BIG: + message_details = g_strdup (_("The disk where you are trying to save the file has " + "a limitation on file sizes. Please try saving " + "a smaller file or saving it to a disk that does not " + "have this limitation.")); + break; + + case GNOME_VFS_ERROR_INVALID_URI: + message_details = g_strdup (_("%s is not a valid location. " + "Please, check that you typed the " + "location correctly and try again.")); + break; + + case GNOME_VFS_ERROR_ACCESS_DENIED: + case GNOME_VFS_ERROR_NOT_PERMITTED: + message_details = g_strdup (_("You do not have the permissions necessary to save the file. " + "Please, check that you typed the " + "location correctly and try again.")); + + break; + + case GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES: + message_details = g_strdup (_("There are too many open files. Please, " + "close some applications and try again.")); + break; + + case GNOME_VFS_ERROR_IS_DIRECTORY: + message_details = g_strdup (_("%s is a directory. " + "Please, check that you typed the " + "location correctly and try again.")); + break; + + case GNOME_VFS_ERROR_NO_MEMORY: + message_details = g_strdup (_("Not enough available memory to save " + "the file. Please, close some running " + "applications and try again.")); + break; + + case GNOME_VFS_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. + */ + { + GnomeVFSURI *vfs_uri; + + vfs_uri = gnome_vfs_uri_new (uri); + + if (vfs_uri != NULL) + { + const gchar *hn = gnome_vfs_uri_get_host_name (vfs_uri); + + if (hn != NULL) + { + gchar *host_name = gedit_utils_make_valid_utf8 (hn); + + /* Translators: %s is a host name */ + message_details = g_strdup_printf ( + _("Host %s could not be found. " + "Please, check that your proxy settings " + "are correct and try again."), + host_name); + + g_free (host_name); + } + else + { + /* use the same string as INVALID_HOST */ + message_details = g_strdup_printf ( + _("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + } + + gnome_vfs_uri_unref (vfs_uri); + } + else + { + /* use the same string as INVALID_HOST */ + message_details = g_strdup_printf ( + _("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + } + } + break; + + case GNOME_VFS_ERROR_INVALID_HOST_NAME: + message_details = g_strdup_printf (_("Host name was invalid. " + "Please, check that you typed the location " + "correctly and try again.")); + break; + + case GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS: + message_details = g_strdup (_("Host name was empty. " + "Please, check that your proxy settings " + "are correct and try again.")); + break; + + case GNOME_VFS_ERROR_LOGIN_FAILED: + message_details = g_strdup (_("Attempt to log in failed. " + "Please, check that you typed the location " + "correctly and try again.")); + break; + + case GNOME_VFS_ERROR_NO_SPACE: + message_details = g_strdup (_("There is not enough disk space to save the file. " + "Please, free some disk space and try again.")); + break; + + case GNOME_VFS_ERROR_READ_ONLY: + case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM: + message_details = g_strdup (_("You are trying to save the file on a read-only disk. " + "Please, check that you typed the location " + "correctly and try again.")); + break; + + case GNOME_VFS_ERROR_FILE_EXISTS: + message_details = g_strdup (_("A file with the same name already exists. " + "Please, use a different name.")); + break; + + case GNOME_VFS_ERROR_NAME_TOO_LONG: + message_details = g_strdup (_("The disk where you are trying to save the file has " + "a limitation on length of the file names. " + "Please, use a shorter name.")); + + case GEDIT_DOCUMENT_ERROR_NOT_REGULAR_FILE: + message_details = g_strdup_printf (_("%s is not a regular file. " + "Please, check that you typed the location " + "correctly and try again."), + uri_for_display); + + case GNOME_VFS_ERROR_GENERIC: + break; + + /* + case GNOME_VFS_ERROR_NOT_FOUND: + case GNOME_VFS_ERROR_CORRUPTED_DATA: + case GNOME_VFS_ERROR_WRONG_FORMAT: + case GNOME_VFS_ERROR_INTERNAL: + case GNOME_VFS_ERROR_BAD_PARAMETERS: + case GNOME_VFS_ERROR_IO: + case GNOME_VFS_ERROR_BAD_FILE: + case GNOME_VFS_ERROR_NOT_OPEN: + case GNOME_VFS_ERROR_INVALID_OPEN_MODE: + case GNOME_VFS_ERROR_EOF: + case GNOME_VFS_ERROR_NOT_A_DIRECTORY: + case GNOME_VFS_ERROR_IN_PROGRESS: + case GNOME_VFS_ERROR_INTERRUPTED: + case GNOME_VFS_ERROR_LOOP: + case GNOME_VFS_ERROR_CANCELLED: + case GNOME_VFS_ERROR_DIRECTORY_BUSY: + case GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY: + case GNOME_VFS_ERROR_TOO_MANY_LINKS: + case GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM: + case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE: + case GNOME_VFS_ERROR_SERVICE_OBSOLETE, + case GNOME_VFS_ERROR_PROTOCOL_ERROR, + case GNOME_VFS_NUM_ERRORS: + */ + + default: + g_warning ("Hit unhandled case %d (%s) in %s.", + error->code, gnome_vfs_result_to_string (error->code), G_STRFUNC); + message_details = g_strdup_printf (_("Unexpected error: %s"), + gnome_vfs_result_to_string (error->code)); + break; + } + + if (error_message == NULL) + error_message = g_strdup_printf (_("Could not save the file %s."), + uri_for_display); + + message_area = create_unrecoverable_error_message_area (error_message, + message_details); + + g_free (error_message); + g_free (message_details); + + return message_area; +} diff --git a/gedit/gedit-io-error-message-area.h b/gedit/gedit-io-error-message-area.h new file mode 100644 index 00000000..dfdce1fc --- /dev/null +++ b/gedit/gedit-io-error-message-area.h @@ -0,0 +1,77 @@ +/* + * gedit-io-error-message-area.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_IO_ERROR_MESSAGE_AREA_H__ +#define __GEDIT_IO_ERROR_MESSAGE_AREA_H__ + +#include + +G_BEGIN_DECLS + +GtkWidget *gedit_unrecoverable_loading_error_message_area_new ( + const gchar *uri, + const GError *error); + +GtkWidget *gedit_unrecoverable_reverting_error_message_area_new ( + const gchar *uri, + const GError *error); + +GtkWidget *gedit_conversion_error_while_loading_message_area_new ( + const gchar *uri, + const GeditEncoding *encoding, + const GError *error); + +GtkWidget *gedit_conversion_error_while_saving_message_area_new ( + const gchar *uri, + const GeditEncoding *encoding, + const GError *error); + +const GeditEncoding + *gedit_conversion_error_message_area_get_encoding ( + GtkWidget *message_area); + +GtkWidget *gedit_file_already_open_warning_message_area_new ( + const gchar *uri); + +GtkWidget *gedit_externally_modified_saving_error_message_area_new ( + const gchar *uri, + const GError *error); + +GtkWidget *gedit_no_backup_saving_error_message_area_new ( + const gchar *uri, + const GError *error); + +GtkWidget *gedit_unrecoverable_saving_error_message_area_new ( + const gchar *uri, + const GError *error); + +G_END_DECLS + +#endif /* __GEDIT_IO_ERROR_MESSAGE_AREA_H__ */ diff --git a/gedit/gedit-languages-manager.c b/gedit/gedit-languages-manager.c index 426ccaa6..0c539069 100644 --- a/gedit/gedit-languages-manager.c +++ b/gedit/gedit-languages-manager.c @@ -3,7 +3,7 @@ * gedit-languages-manager.c * This file is part of gedit * - * Copyright (C) 2003 - 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 @@ -22,9 +22,11 @@ */ /* - * Modified by the gedit Team, 2003. See the AUTHORS file for a + * Modified by the gedit Team, 2003-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ /* FIXME: Monitor gconf keys */ @@ -40,9 +42,9 @@ static GtkSourceLanguagesManager *language_manager = NULL; -static GConfClient *gconf_client = NULL; -static const GSList *languages_list = NULL; -static GSList *languages_list_sorted = NULL; +static GConfClient *gconf_client = NULL; +static const GSList *languages_list = NULL; +static GSList *languages_list_sorted = NULL; GtkSourceLanguagesManager * @@ -207,13 +209,10 @@ string_to_tag_style (const gchar *string) if ((style->strikethrough < 0) || (style->strikethrough > 1)) goto error; - g_strfreev (items); - return style; error: gtk_source_tag_style_free (style); - g_strfreev (items); return NULL; } @@ -358,3 +357,4 @@ gedit_languages_manager_get_available_languages_sorted (GtkSourceLanguagesManage return languages_list_sorted; } + diff --git a/gedit/gedit-languages-manager.h b/gedit/gedit-languages-manager.h index d62bb043..d881687e 100644 --- a/gedit/gedit-languages-manager.h +++ b/gedit/gedit-languages-manager.h @@ -3,7 +3,7 @@ * gedit-languages-manager.h * This file is part of gedit * - * Copyright (C) 2003 - 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 @@ -22,9 +22,11 @@ */ /* - * Modified by the gedit Team, 2003. See the AUTHORS file for a + * Modified by the gedit Team, 2003-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_LANGUAGES_MANAGER_H__ @@ -32,11 +34,13 @@ #include +G_BEGIN_DECLS + GtkSourceLanguagesManager *gedit_get_languages_manager (void); GtkSourceLanguage *gedit_languages_manager_get_language_from_id - (GtkSourceLanguagesManager *lm, - const gchar *lang_id); + (GtkSourceLanguagesManager *lm, + const gchar *lang_id); void gedit_language_set_tag_style (GtkSourceLanguage *language, const gchar *tag_id, @@ -47,4 +51,9 @@ const GSList *gedit_languages_manager_get_available_languages_sorted (GtkSource +const GSList *gedit_languages_manager_get_available_languages_sorted + (GtkSourceLanguagesManager *lm); + +G_END_DECLS + #endif /* __GEDIT_LANGUAGES_MANAGER_H__ */ diff --git a/gedit/gedit-marshal.list b/gedit/gedit-marshal.list index 4d02ae99..79b2f810 100644 --- a/gedit/gedit-marshal.list +++ b/gedit/gedit-marshal.list @@ -1,6 +1,9 @@ BOOLEAN:OBJECT +BOOLEAN:NONE VOID:VOID VOID:BOOLEAN VOID:OBJECT VOID:POINTER -VOID:ULONG,ULONG +VOID:UINT64,UINT64 +VOID:BOOLEAN,POINTER +VOID:BOXED,BOXED diff --git a/gedit/gedit-mdi-child.c b/gedit/gedit-mdi-child.c index a6127284..0a8a4ab1 100644 --- a/gedit/gedit-mdi-child.c +++ b/gedit/gedit-mdi-child.c @@ -182,13 +182,13 @@ gedit_mdi_child_class_init (GeditMDIChildClass *klass) static void gedit_mdi_child_init (GeditMDIChild *child) { - gedit_debug (DEBUG_MDI, "START"); + gedit_debug_message (DEBUG_MDI, "START"); child->priv = g_new0 (GeditMDIChildPrivate, 1); child->priv->closing = FALSE; - gedit_debug (DEBUG_MDI, "END"); + gedit_debug_message (DEBUG_MDI, "END"); } static void @@ -196,7 +196,7 @@ gedit_mdi_child_finalize (GObject *obj) { GeditMDIChild *child; - gedit_debug (DEBUG_MDI, "START"); + gedit_debug_message (DEBUG_MDI, "START"); g_return_if_fail (obj != NULL); @@ -212,7 +212,7 @@ gedit_mdi_child_finalize (GObject *obj) G_OBJECT_CLASS (parent_class)->finalize (obj); - gedit_debug (DEBUG_MDI, "END"); + gedit_debug_message (DEBUG_MDI, "END"); } #define MAX_DOC_NAME_LENGTH 40 @@ -224,7 +224,7 @@ gedit_mdi_child_real_state_changed (GeditMDIChild* child) gchar* docname = NULL; gchar* tab_name = NULL; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (child != NULL); g_return_if_fail (child->document != NULL); @@ -269,7 +269,7 @@ gedit_mdi_child_real_state_changed (GeditMDIChild* child) static void gedit_mdi_child_document_state_changed_handler (GeditDocument *document, GeditMDIChild* child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (child->document == document); g_signal_emit (G_OBJECT (child), mdi_child_signals [STATE_CHANGED], 0); @@ -279,7 +279,7 @@ static void gedit_mdi_child_document_readonly_changed_handler (GeditDocument *document, gboolean readonly, GeditMDIChild* child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (child->document == document); g_signal_emit (G_OBJECT (child), mdi_child_signals [STATE_CHANGED], 0); @@ -289,7 +289,7 @@ static void gedit_mdi_child_document_can_undo_redo_handler (GeditDocument *document, gboolean can, GeditMDIChild* child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (child->document == document); g_signal_emit (G_OBJECT (child), mdi_child_signals [UNDO_REDO_STATE_CHANGED], 0); @@ -298,7 +298,7 @@ gedit_mdi_child_document_can_undo_redo_handler (GeditDocument *document, gboolea static void gedit_mdi_child_document_can_find_again_handler (GeditDocument *document, GeditMDIChild* child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (child->document == document); g_signal_emit (G_OBJECT (child), mdi_child_signals [FIND_STATE_CHANGED], 0); @@ -359,7 +359,7 @@ gedit_mdi_child_new (void) GeditMDIChild *child; gchar* doc_name; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); child = GEDIT_MDI_CHILD (g_object_new (GEDIT_TYPE_MDI_CHILD, NULL)); g_return_val_if_fail (child != NULL, NULL); @@ -373,7 +373,7 @@ gedit_mdi_child_new (void) gedit_mdi_child_connect_signals (child); - gedit_debug (DEBUG_MDI, "END"); + gedit_debug_message (DEBUG_MDI, "END"); g_object_set_data (G_OBJECT (child->document), "mdi-child", child); @@ -386,13 +386,13 @@ gedit_mdi_child_new_with_uri (const gchar *uri, const GeditEncoding *encoding) GeditMDIChild *child; GeditDocument* doc; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); doc = gedit_document_new_with_uri (uri, encoding); if (doc == NULL) { - gedit_debug (DEBUG_MDI, "ERROR"); + gedit_debug_message (DEBUG_MDI, "ERROR"); return NULL; } @@ -406,7 +406,7 @@ gedit_mdi_child_new_with_uri (const gchar *uri, const GeditEncoding *encoding) gedit_mdi_child_connect_signals (child); - gedit_debug (DEBUG_MDI, "END"); + gedit_debug_message (DEBUG_MDI, "END"); g_object_set_data (G_OBJECT (doc), "mdi-child", child); @@ -429,7 +429,7 @@ gedit_mdi_child_create_view (BonoboMDIChild *child) { GeditView *new_view; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (child != NULL, NULL); g_return_val_if_fail (GEDIT_IS_MDI_CHILD (child), NULL); @@ -448,7 +448,7 @@ gedit_mdi_child_get_config_string (BonoboMDIChild *child, gpointer data) { GeditMDIChild *c; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (child != NULL, NULL); g_return_val_if_fail (GEDIT_IS_MDI_CHILD (child), NULL); @@ -464,7 +464,7 @@ gedit_mdi_child_tab_close_clicked (GtkWidget *button, GtkWidget *view) GtkWidget *active_view; gboolean closed; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (GEDIT_IS_VIEW (view)); @@ -488,7 +488,7 @@ gedit_mdi_child_tab_save_clicked (GtkWidget *button, GtkWidget *view) { BonoboMDIChild *child; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (GEDIT_IS_VIEW (view)); @@ -505,7 +505,7 @@ gedit_mdi_child_tab_save_as_clicked (GtkWidget *button, GtkWidget *view) { BonoboMDIChild *child; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (GEDIT_IS_VIEW (view)); @@ -522,7 +522,7 @@ gedit_mdi_child_tab_print_clicked (GtkWidget *button, GtkWidget *view) { GeditDocument *doc; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (GEDIT_IS_VIEW (view)); @@ -537,7 +537,7 @@ gedit_mdi_child_tab_print_clicked (GtkWidget *button, GtkWidget *view) static void gedit_mdi_child_tab_move_window_clicked (GtkWidget *button, GtkWidget *view) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (GEDIT_IS_VIEW (view)); @@ -740,7 +740,7 @@ set_tab_icon (GtkWidget *image, BonoboMDIChild *child) const gchar *mime_type; int icon_size; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (GTK_IS_IMAGE (image), NULL); g_return_val_if_fail (GEDIT_IS_MDI_CHILD (child), NULL); @@ -783,7 +783,7 @@ set_tooltip (GeditTooltips *tooltips, GtkWidget *widget, BonoboMDIChild *child) gchar *encoding; const GeditEncoding *enc; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); uri = gedit_document_get_uri (GEDIT_MDI_CHILD (child)->document); g_return_if_fail (uri != NULL); @@ -840,7 +840,7 @@ gedit_mdi_child_set_label (BonoboMDIChild *child, GtkWidget *view, GtkWidget *o static GeditTooltips *tooltips = NULL; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (child != NULL, NULL); g_return_val_if_fail (GEDIT_IS_MDI_CHILD (child), NULL); @@ -918,7 +918,7 @@ gedit_mdi_child_set_label (BonoboMDIChild *child, GtkWidget *view, GtkWidget *o /* pack the elements */ gtk_box_pack_start (GTK_BOX (event_hbox), image, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (event_hbox), label, TRUE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (event_hbox), label, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (event_box), event_hbox); /* setup the data hierarchy */ diff --git a/gedit/gedit-mdi.c b/gedit/gedit-mdi.c index e1e79f53..d60b08f0 100644 --- a/gedit/gedit-mdi.c +++ b/gedit/gedit-mdi.c @@ -364,7 +364,7 @@ gedit_mdi_add_open_button (GeditMDI *mdi, BonoboUIComponent *ui_component, static void gedit_mdi_init (GeditMDI *mdi) { - gedit_debug (DEBUG_MDI, "START"); + gedit_debug_message (DEBUG_MDI, "START"); bonobo_mdi_construct (BONOBO_MDI (mdi), "gedit-2", @@ -408,7 +408,7 @@ gedit_mdi_init (GeditMDI *mdi) G_CALLBACK (gedit_mdi_app_destroy_handler), NULL); - gedit_debug (DEBUG_MDI, "END"); + gedit_debug_message (DEBUG_MDI, "END"); } static void @@ -416,7 +416,7 @@ gedit_mdi_finalize (GObject *object) { GeditMDI *mdi; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (object != NULL); @@ -442,7 +442,7 @@ gedit_mdi_new (void) { GeditMDI *mdi; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); mdi = GEDIT_MDI (g_object_new (GEDIT_TYPE_MDI, NULL)); g_return_val_if_fail (mdi != NULL, NULL); @@ -479,7 +479,7 @@ gedit_mdi_app_created_handler (BonoboMDI *mdi, BonoboWindow *win) GeditWindowPrefs *prefs; GdkWindowState state; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); ui_component = bonobo_mdi_get_ui_component_from_window (win); g_return_if_fail (ui_component != NULL); @@ -628,7 +628,7 @@ gedit_mdi_app_created_handler (BonoboMDI *mdi, BonoboWindow *win) static void gedit_mdi_app_destroy_handler (BonoboMDI *mdi, BonoboWindow *window) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (window != NULL); g_return_if_fail (BONOBO_IS_WINDOW (window)); @@ -647,7 +647,7 @@ gedit_mdi_view_menu_item_toggled_handler ( gboolean s; GeditWindowPrefs *prefs; - gedit_debug (DEBUG_MDI, "%s toggled to '%s'", path, state); + gedit_debug_message (DEBUG_MDI, "%s toggled to '%s'", path, state); prefs = gedit_window_prefs_get_from_window (win); g_return_if_fail (prefs != NULL); @@ -759,7 +759,7 @@ gedit_mdi_drag_data_received_handler (GtkWidget *widget, GList *p = NULL; GtkWidget *target_window; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); if (info != TARGET_URI_LIST) return; @@ -887,7 +887,7 @@ gedit_mdi_set_app_toolbar_style (BonoboWindow *win) BonoboUIComponent *ui_component; GeditWindowPrefs *prefs = NULL; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (BONOBO_IS_WINDOW (win)); @@ -939,28 +939,28 @@ gedit_mdi_set_app_toolbar_style (BonoboWindow *win) switch (prefs->toolbar_buttons_style) { case GEDIT_TOOLBAR_SYSTEM: - gedit_debug (DEBUG_MDI, "GEDIT: SYSTEM"); + gedit_debug_message (DEBUG_MDI, "GEDIT: SYSTEM"); bonobo_ui_component_set_prop ( ui_component, "/Toolbar", "look", "system", NULL); break; case GEDIT_TOOLBAR_ICONS: - gedit_debug (DEBUG_MDI, "GEDIT: ICONS"); + gedit_debug_message (DEBUG_MDI, "GEDIT: ICONS"); bonobo_ui_component_set_prop ( ui_component, "/Toolbar", "look", "icon", NULL); break; case GEDIT_TOOLBAR_ICONS_AND_TEXT: - gedit_debug (DEBUG_MDI, "GEDIT: ICONS_AND_TEXT"); + gedit_debug_message (DEBUG_MDI, "GEDIT: ICONS_AND_TEXT"); bonobo_ui_component_set_prop ( ui_component, "/Toolbar", "look", "both", NULL); break; case GEDIT_TOOLBAR_ICONS_BOTH_HORIZ: - gedit_debug (DEBUG_MDI, "GEDIT: ICONS_BOTH_HORIZ"); + gedit_debug_message (DEBUG_MDI, "GEDIT: ICONS_BOTH_HORIZ"); bonobo_ui_component_set_prop ( ui_component, "/Toolbar", "look", "both_horiz", NULL); @@ -984,7 +984,7 @@ gedit_mdi_set_app_statusbar_style (BonoboWindow *win) GeditWindowPrefs *prefs = NULL; BonoboUIComponent *ui_component; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (BONOBO_IS_WINDOW (win)); @@ -1013,7 +1013,7 @@ gedit_mdi_set_app_statusbar_style (BonoboWindow *win) static void gedit_mdi_child_state_changed_handler (GeditMDIChild *child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); if (bonobo_mdi_get_active_child (BONOBO_MDI (gedit_mdi)) != BONOBO_MDI_CHILD (child)) return; @@ -1026,7 +1026,7 @@ gedit_mdi_child_state_changed_handler (GeditMDIChild *child) static void gedit_mdi_child_undo_redo_state_changed_handler (GeditMDIChild *child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); if (bonobo_mdi_get_active_child (BONOBO_MDI (gedit_mdi)) != BONOBO_MDI_CHILD (child)) return; @@ -1037,7 +1037,7 @@ gedit_mdi_child_undo_redo_state_changed_handler (GeditMDIChild *child) static void gedit_mdi_child_find_state_changed_handler (GeditMDIChild *child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); if (bonobo_mdi_get_active_child (BONOBO_MDI (gedit_mdi)) != BONOBO_MDI_CHILD (child)) return; @@ -1048,7 +1048,7 @@ gedit_mdi_child_find_state_changed_handler (GeditMDIChild *child) static gint gedit_mdi_add_child_handler (BonoboMDI *mdi, BonoboMDIChild *child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_signal_connect (G_OBJECT (child), "state_changed", G_CALLBACK (gedit_mdi_child_state_changed_handler), @@ -1069,7 +1069,7 @@ gedit_mdi_add_view_handler (BonoboMDI *mdi, GtkWidget *view) GtkTextView *text_view; GtkTargetList *tl; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (view != NULL, TRUE); @@ -1107,7 +1107,7 @@ gedit_mdi_remove_child_handler (BonoboMDI *mdi, BonoboMDIChild *child) GeditDocument *doc; gboolean close = TRUE; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (child != NULL, FALSE); g_return_val_if_fail (GEDIT_MDI_CHILD (child)->document != NULL, FALSE); @@ -1168,7 +1168,7 @@ gedit_mdi_remove_child_handler (BonoboMDI *mdi, BonoboMDIChild *child) gtk_widget_destroy (dlg); - gedit_debug (DEBUG_MDI, "CLOSE: %s", close ? "TRUE" : "FALSE"); + gedit_debug_message (DEBUG_MDI, "CLOSE: %s", close ? "TRUE" : "FALSE"); } return close; @@ -1177,7 +1177,7 @@ gedit_mdi_remove_child_handler (BonoboMDI *mdi, BonoboMDIChild *child) static gboolean gedit_mdi_remove_view_handler (BonoboMDI *mdi, GtkWidget *view) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); return TRUE; } @@ -1190,7 +1190,7 @@ gedit_mdi_can_remove_views (GList *views, BonoboWindow *window) GtkWidget *dlg; gboolean close; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); if (window == NULL) { @@ -1332,7 +1332,7 @@ gedit_mdi_remove_views_handler (BonoboMDI *mdi, BonoboWindow *window) GList *views; gboolean ret; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); if (gedit_mdi_get_state (GEDIT_MDI (mdi)) != GEDIT_STATE_NORMAL) return FALSE; @@ -1352,7 +1352,7 @@ gedit_mdi_remove_all (GeditMDI *mdi) GList *views; gboolean ret; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (GEDIT_IS_MDI (mdi), FALSE); @@ -1408,7 +1408,7 @@ gedit_mdi_set_active_window_title (BonoboMDI *mdi) GtkWidget *active_window; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); active_child = bonobo_mdi_get_active_child (mdi); if (active_child == NULL) @@ -1501,7 +1501,7 @@ gedit_mdi_set_active_window_title (BonoboMDI *mdi) static void gedit_mdi_child_changed_handler (BonoboMDI *mdi, BonoboMDIChild *old_child) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); gedit_mdi_set_active_window_title (mdi); gedit_mdi_update_languages_menu (mdi); @@ -1514,7 +1514,7 @@ void gedit_mdi_view_changed_handler (BonoboMDI *mdi, GtkWidget *old_view) GtkWidget *status; GtkWidget *active_view; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); gedit_mdi_set_active_window_verbs_sensitivity (mdi); @@ -1578,7 +1578,7 @@ gedit_mdi_set_active_window_verbs_sensitivity (BonoboMDI *mdi) GeditDocument* doc = NULL; BonoboUIComponent *ui_component; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); active_window = bonobo_mdi_get_active_window (mdi); @@ -1693,7 +1693,7 @@ gedit_mdi_set_active_window_undo_redo_verbs_sensitivity (BonoboMDI *mdi) GeditDocument* doc = NULL; BonoboUIComponent *ui_component; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); active_window = gedit_get_active_window (); g_return_if_fail (active_window != NULL); @@ -1723,7 +1723,7 @@ gedit_mdi_set_active_window_find_verbs_sensitivity (BonoboMDI *mdi) BonoboUIComponent *ui_component; gboolean sensitive; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); active_window = gedit_get_active_window (); g_return_if_fail (active_window != NULL); @@ -1752,7 +1752,7 @@ EggRecentView * gedit_mdi_get_recent_view_from_window (BonoboWindow *win) { gpointer r; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); r = g_object_get_data (G_OBJECT (win), RECENT_KEY); @@ -1776,7 +1776,7 @@ gedit_mdi_show_output_window_cb (GtkWidget *widget, gpointer user_data) GeditWindowPrefs *prefs; BonoboUIComponent *ui_component; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); bw = BONOBO_WINDOW (user_data); g_return_if_fail (bw != NULL); @@ -1801,7 +1801,7 @@ gedit_mdi_hide_output_window_cb (GtkWidget *widget, gpointer user_data) GeditWindowPrefs *prefs; BonoboUIComponent *ui_component; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); bw = BONOBO_WINDOW (user_data); g_return_if_fail (bw != NULL); @@ -1823,7 +1823,7 @@ GtkWidget * gedit_mdi_get_output_window_from_window (BonoboWindow *win) { gpointer r; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); r = g_object_get_data (G_OBJECT (win), OUTPUT_WINDOW_KEY); @@ -1854,7 +1854,7 @@ gedit_window_prefs_new (void) { GeditWindowPrefs *prefs; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); prefs = g_new0 (GeditWindowPrefs, 1); @@ -1871,7 +1871,7 @@ gedit_window_prefs_new (void) static void gedit_window_prefs_attach_to_window (GeditWindowPrefs *prefs, BonoboWindow *win) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (prefs != NULL); g_return_if_fail (win != NULL); @@ -1888,7 +1888,7 @@ gedit_window_prefs_get_from_window (BonoboWindow *win) { GeditWindowPrefs *prefs; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (win != NULL, NULL); g_return_val_if_fail (BONOBO_IS_WINDOW (win), NULL); @@ -1901,7 +1901,7 @@ gedit_window_prefs_get_from_window (BonoboWindow *win) static void gedit_window_prefs_save (GeditWindowPrefs *prefs) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (prefs != NULL); @@ -2094,7 +2094,7 @@ add_languages_menu (BonoboMDI *mdi, BonoboWindow *win) GSList *sections = NULL; GSList *s; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); gedit_menus_add_menu_item_radio (win, "/menu/View/HighlightMode/", @@ -2209,7 +2209,7 @@ void gedit_mdi_update_languages_menu (BonoboMDI *mdi) BonoboWindow* active_window = NULL; BonoboUIComponent *ui_component; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); active_window = bonobo_mdi_get_active_window (mdi); @@ -2242,7 +2242,7 @@ update_ui_according_to_state (GeditMDI *mdi) GdkCursor *cursor; GList *windows; - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); /* Upate menus and toolbars */ gedit_mdi_set_active_window_verbs_sensitivity (BONOBO_MDI (gedit_mdi)); @@ -2326,7 +2326,7 @@ update_ui_according_to_state (GeditMDI *mdi) GeditState gedit_mdi_get_state (GeditMDI *mdi) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_val_if_fail (GEDIT_IS_MDI (mdi), GEDIT_STATE_NORMAL); @@ -2337,7 +2337,7 @@ void gedit_mdi_set_state (GeditMDI *mdi, GeditState state) { - gedit_debug (DEBUG_MDI, ""); + gedit_debug (DEBUG_MDI); g_return_if_fail (GEDIT_IS_MDI (mdi)); g_return_if_fail ((state == GEDIT_STATE_NORMAL) || diff --git a/gedit/gedit-message-area.c b/gedit/gedit-message-area.c new file mode 100644 index 00000000..58bc1df7 --- /dev/null +++ b/gedit/gedit-message-area.c @@ -0,0 +1,538 @@ +/* + * gedit-message-area.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +/* TODO: Style properties */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "gedit-message-area.h" + +#define GEDIT_MESSAGE_AREA_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_MESSAGE_AREA, GeditMessageAreaPrivate)) + +struct _GeditMessageAreaPrivate +{ + GtkWidget *main_hbox; + + GtkWidget *contents; + GtkWidget *action_area; + + gboolean changing_style; +}; + +typedef struct _ResponseData ResponseData; + +struct _ResponseData +{ + gint response_id; +}; + +enum { + RESPONSE, + CLOSE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE(GeditMessageArea, gedit_message_area, GTK_TYPE_HBOX) + + + +static void +gedit_message_area_finalize (GObject *object) +{ + /* + GeditMessageArea *message_area = GEDIT_MESSAGE_AREA (object); + */ + + G_OBJECT_CLASS (gedit_message_area_parent_class)->finalize (object); +} + +static ResponseData * +get_response_data (GtkWidget *widget, + gboolean create) +{ + ResponseData *ad = g_object_get_data (G_OBJECT (widget), + "gedit-message-area-response-data"); + + if (ad == NULL && create) + { + ad = g_new (ResponseData, 1); + + g_object_set_data_full (G_OBJECT (widget), + "gedit-message-area-response-data", + ad, + g_free); + } + + return ad; +} + +static GtkWidget * +find_button (GeditMessageArea *message_area, + gint response_id) +{ + GList *children, *tmp_list; + GtkWidget *child = NULL; + + children = gtk_container_get_children ( + GTK_CONTAINER (message_area->priv->action_area)); + + for (tmp_list = children; tmp_list; tmp_list = tmp_list->next) + { + ResponseData *rd = get_response_data (tmp_list->data, FALSE); + + if (rd && rd->response_id == response_id) + { + child = tmp_list->data; + break; + } + } + + g_list_free (children); + + return child; +} + +static void +gedit_message_area_close (GeditMessageArea *message_area) +{ + if (!find_button (message_area, GTK_RESPONSE_CANCEL)) + return; + + /* emit response signal */ + gedit_message_area_response (GEDIT_MESSAGE_AREA (message_area), + GTK_RESPONSE_CANCEL); +} + +static gboolean +paint_message_area (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) +{ + gtk_paint_flat_box (widget->style, + widget->window, + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, + NULL, + widget, + "tooltip", + widget->allocation.x + 1, + widget->allocation.y + 1, + widget->allocation.width - 2, + widget->allocation.height - 2); + + return FALSE; +} + +static void +style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + GtkTooltips *tooltips; + GtkStyle *style; + + GeditMessageArea *message_area = GEDIT_MESSAGE_AREA (widget); + + if (message_area->priv->changing_style) + return; + + g_print ("style-set\n"); + + tooltips = gtk_tooltips_new (); + g_object_ref (G_OBJECT (tooltips)); + gtk_object_sink (GTK_OBJECT (tooltips)); + + gtk_tooltips_force_window (tooltips); + gtk_widget_ensure_style (tooltips->tip_window); + style = gtk_widget_get_style (tooltips->tip_window); + + message_area->priv->changing_style = TRUE; + gtk_widget_set_style (GTK_WIDGET (widget), style); + message_area->priv->changing_style = FALSE; + + g_object_unref (tooltips); +} + +static void +gedit_message_area_class_init (GeditMessageAreaClass *klass) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkBindingSet *binding_set; + + object_class = G_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + object_class->finalize = gedit_message_area_finalize; + + widget_class->style_set = style_set; + + klass->close = gedit_message_area_close; + + g_type_class_add_private (object_class, sizeof(GeditMessageAreaPrivate)); + + signals[RESPONSE] = g_signal_new ("response", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GeditMessageAreaClass, response), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[CLOSE] = g_signal_new ("close", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GeditMessageAreaClass, close), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + binding_set = gtk_binding_set_by_class (klass); + + gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "close", 0); +} + +static void +gedit_message_area_init (GeditMessageArea *message_area) +{ + message_area->priv = GEDIT_MESSAGE_AREA_GET_PRIVATE (message_area); + + message_area->priv->main_hbox = gtk_hbox_new (FALSE, 16); /* FIXME: use style properties */ + gtk_widget_show (message_area->priv->main_hbox); + gtk_container_set_border_width (GTK_CONTAINER (message_area->priv->main_hbox), + 8); /* FIXME: use style properties */ + + message_area->priv->action_area = gtk_vbox_new (TRUE, 10); /* FIXME: use style properties */ + gtk_widget_show (message_area->priv->action_area); + gtk_box_pack_end (GTK_BOX (message_area->priv->main_hbox), + message_area->priv->action_area, + FALSE, + TRUE, + 0); + + gtk_box_pack_start (GTK_BOX (message_area), + message_area->priv->main_hbox, + TRUE, + TRUE, + 0); + + /* CHECK: do we really need it? */ + gtk_widget_set_name (GTK_WIDGET (message_area), "gtk-tooltips"); + + g_signal_connect (message_area, + "expose_event", + G_CALLBACK (paint_message_area), + NULL); +} + +static gint +get_response_for_widget (GeditMessageArea *message_area, + GtkWidget *widget) +{ + ResponseData *rd; + + rd = get_response_data (widget, FALSE); + if (!rd) + return GTK_RESPONSE_NONE; + else + return rd->response_id; +} + +static void +action_widget_activated (GtkWidget *widget, GeditMessageArea *message_area) +{ + gint response_id; + + response_id = get_response_for_widget (message_area, widget); + + gedit_message_area_response (message_area, response_id); +} + +void +gedit_message_area_add_action_widget (GeditMessageArea *message_area, + GtkWidget *child, + gint response_id) +{ + ResponseData *ad; + guint signal_id; + + g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area)); + g_return_if_fail (GTK_IS_WIDGET (child)); + + ad = get_response_data (child, TRUE); + + ad->response_id = response_id; + + if (GTK_IS_BUTTON (child)) + signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON); + else + signal_id = GTK_WIDGET_GET_CLASS (child)->activate_signal; + + if (signal_id) + { + GClosure *closure; + + closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated), + G_OBJECT (message_area)); + + g_signal_connect_closure_by_id (child, + signal_id, + 0, + closure, + FALSE); + } + else + g_warning ("Only 'activatable' widgets can be packed into the action area of a GeditMessageArea"); + + if (response_id != GTK_RESPONSE_HELP) + gtk_box_pack_start (GTK_BOX (message_area->priv->action_area), + child, + FALSE, + FALSE, + 0); + else + gtk_box_pack_end (GTK_BOX (message_area->priv->action_area), + child, + FALSE, + FALSE, + 0); +} + +void +gedit_message_area_set_contents (GeditMessageArea *message_area, + GtkWidget *contents) +{ + g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area)); + g_return_if_fail (GTK_IS_WIDGET (contents)); + + message_area->priv->contents = contents; + gtk_box_pack_start (GTK_BOX (message_area->priv->main_hbox), + message_area->priv->contents, + TRUE, + TRUE, + 0); +} + +GtkWidget* +gedit_message_area_add_button (GeditMessageArea *message_area, + const gchar *button_text, + gint response_id) +{ + GtkWidget *button; + + g_return_val_if_fail (GEDIT_IS_MESSAGE_AREA (message_area), NULL); + g_return_val_if_fail (button_text != NULL, NULL); + + button = gtk_button_new_from_stock (button_text); + + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + + gtk_widget_show (button); + + gedit_message_area_add_action_widget (message_area, + button, + response_id); + + return button; +} + +static void +add_buttons_valist (GeditMessageArea *message_area, + const gchar *first_button_text, + va_list args) +{ + const gchar* text; + gint response_id; + + g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area)); + + if (first_button_text == NULL) + return; + + text = first_button_text; + response_id = va_arg (args, gint); + + while (text != NULL) + { + gedit_message_area_add_button (message_area, + text, + response_id); + + text = va_arg (args, gchar*); + if (text == NULL) + break; + + response_id = va_arg (args, int); + } +} + +void +gedit_message_area_add_buttons (GeditMessageArea *message_area, + const gchar *first_button_text, + ...) +{ + va_list args; + + va_start (args, first_button_text); + + add_buttons_valist (message_area, + first_button_text, + args); + + va_end (args); +} + +GtkWidget * +gedit_message_area_new (void) +{ + return g_object_new (GEDIT_TYPE_MESSAGE_AREA, NULL); +} + +GtkWidget * +gedit_message_area_new_with_buttons (const gchar *first_button_text, + ...) +{ + GeditMessageArea *message_area; + va_list args; + + message_area = GEDIT_MESSAGE_AREA (gedit_message_area_new ()); + + va_start (args, first_button_text); + + add_buttons_valist (message_area, + first_button_text, + args); + + va_end (args); + + return GTK_WIDGET (message_area); +} + +void +gedit_message_area_set_response_sensitive (GeditMessageArea *message_area, + gint response_id, + gboolean setting) +{ + GList *children; + GList *tmp_list; + + g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area)); + + children = gtk_container_get_children (GTK_CONTAINER (message_area->priv->action_area)); + + tmp_list = children; + while (tmp_list != NULL) + { + GtkWidget *widget = tmp_list->data; + ResponseData *rd = get_response_data (widget, FALSE); + + if (rd && rd->response_id == response_id) + gtk_widget_set_sensitive (widget, setting); + + tmp_list = g_list_next (tmp_list); + } + + g_list_free (children); +} + +void +gedit_message_area_set_default_response (GeditMessageArea *message_area, + gint response_id) +{ + GList *children; + GList *tmp_list; + + g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area)); + + children = gtk_container_get_children (GTK_CONTAINER (message_area->priv->action_area)); + + tmp_list = children; + while (tmp_list != NULL) + { + GtkWidget *widget = tmp_list->data; + ResponseData *rd = get_response_data (widget, FALSE); + + if (rd && rd->response_id == response_id) + gtk_widget_grab_default (widget); + + tmp_list = g_list_next (tmp_list); + } + + g_list_free (children); +} + +void +gedit_message_area_response (GeditMessageArea *message_area, + gint response_id) +{ + g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area)); + + g_signal_emit (message_area, + signals[RESPONSE], + 0, + response_id); +} + +GtkWidget * +gedit_message_area_add_stock_button_with_text (GeditMessageArea *message_area, + const gchar *text, + const gchar *stock_id, + gint response_id) +{ + GtkWidget *button; + + g_return_val_if_fail (GEDIT_IS_MESSAGE_AREA (message_area), NULL); + g_return_val_if_fail (text != NULL, NULL); + g_return_val_if_fail (stock_id != NULL, NULL); + + button = gtk_button_new_with_mnemonic (text); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_stock (stock_id, + GTK_ICON_SIZE_BUTTON)); + + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + + gtk_widget_show (button); + + gedit_message_area_add_action_widget (message_area, + button, + response_id); + + return button; +} + diff --git a/gedit/gedit-message-area.h b/gedit/gedit-message-area.h new file mode 100644 index 00000000..cf7cd30e --- /dev/null +++ b/gedit/gedit-message-area.h @@ -0,0 +1,130 @@ +/* + * gedit-message-area.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_MESSAGE_AREA_H__ +#define __GEDIT_MESSAGE_AREA_H__ + +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_MESSAGE_AREA (gedit_message_area_get_type()) +#define GEDIT_MESSAGE_AREA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_MESSAGE_AREA, GeditMessageArea)) +#define GEDIT_MESSAGE_AREA_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_MESSAGE_AREA, GeditMessageArea const)) +#define GEDIT_MESSAGE_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_MESSAGE_AREA, GeditMessageAreaClass)) +#define GEDIT_IS_MESSAGE_AREA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_MESSAGE_AREA)) +#define GEDIT_IS_MESSAGE_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE_AREA)) +#define GEDIT_MESSAGE_AREA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_MESSAGE_AREA, GeditMessageAreaClass)) + +/* Private structure type */ +typedef struct _GeditMessageAreaPrivate GeditMessageAreaPrivate; + +/* + * Main object structure + */ +typedef struct _GeditMessageArea GeditMessageArea; + +struct _GeditMessageArea +{ + GtkHBox parent; + + /*< private > */ + GeditMessageAreaPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditMessageAreaClass GeditMessageAreaClass; + +struct _GeditMessageAreaClass +{ + GtkHBoxClass parent_class; + + /* Signals */ + void (* response) (GeditMessageArea *message_area, gint response_id); + + /* Keybinding signals */ + void (* close) (GeditMessageArea *message_area); + + /* Padding for future expansion */ + void (*_gedit_reserved1) (void); + void (*_gedit_reserved2) (void); +}; + +/* + * Public methods + */ +GType gedit_message_area_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_message_area_new (void); + +GtkWidget *gedit_message_area_new_with_buttons (const gchar *first_button_text, + ...); + +void gedit_message_area_set_contents (GeditMessageArea *message_area, + GtkWidget *contents); + +void gedit_message_area_add_action_widget (GeditMessageArea *message_area, + GtkWidget *child, + gint response_id); + +GtkWidget *gedit_message_area_add_button (GeditMessageArea *message_area, + const gchar *button_text, + gint response_id); + +GtkWidget *gedit_message_area_add_stock_button_with_text + (GeditMessageArea *message_area, + const gchar *text, + const gchar *stock_id, + gint response_id); + +void gedit_message_area_add_buttons (GeditMessageArea *message_area, + const gchar *first_button_text, + ...); + +void gedit_message_area_set_response_sensitive + (GeditMessageArea *message_area, + gint response_id, + gboolean setting); +void gedit_message_area_set_default_response + (GeditMessageArea *message_area, + gint response_id); + +/* Emit response signal */ +void gedit_message_area_response (GeditMessageArea *message_area, + gint response_id); + +G_END_DECLS + +#endif /* __GEDIT_MESSAGE_AREA_H__ */ diff --git a/gedit/gedit-metadata-manager.c b/gedit/gedit-metadata-manager.c index b937007e..f3f069f3 100644 --- a/gedit/gedit-metadata-manager.c +++ b/gedit/gedit-metadata-manager.c @@ -82,7 +82,7 @@ item_free (gpointer data) g_return_if_fail (data != NULL); - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); item = (Item *)data; @@ -95,7 +95,7 @@ item_free (gpointer data) static gboolean gedit_metadata_manager_init (void) { - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); if (gedit_metadata_manager != NULL) return TRUE; @@ -125,7 +125,7 @@ gedit_metadata_manager_init (void) void gedit_metadata_manager_shutdown (void) { - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); if (gedit_metadata_manager == NULL) return; @@ -149,7 +149,7 @@ parseItem (xmlDocPtr doc, xmlNodePtr cur) xmlChar *uri; xmlChar *atime; - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0) return; @@ -215,7 +215,7 @@ load_values () xmlNodePtr cur; gchar *file_name; - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); g_return_val_if_fail (gedit_metadata_manager != NULL, FALSE); g_return_val_if_fail (gedit_metadata_manager->values_loaded == FALSE, FALSE); @@ -279,7 +279,7 @@ gedit_metadata_manager_get (const gchar *uri, Item *item; gchar *value; - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (key != NULL, NULL); @@ -323,7 +323,7 @@ gedit_metadata_manager_set (const gchar *uri, { Item *item; - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); g_return_if_fail (uri != NULL); g_return_if_fail (key != NULL); @@ -376,7 +376,7 @@ save_values (const gchar *key, const gchar *value, xmlNodePtr parent) { xmlNodePtr xml_node; - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); g_return_if_fail (key != NULL); @@ -388,7 +388,7 @@ save_values (const gchar *key, const gchar *value, xmlNodePtr parent) xmlSetProp (xml_node, "key", key); xmlSetProp (xml_node, "value", value); - gedit_debug (DEBUG_METADATA, "entry: %s = %s", key, value); + gedit_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value); } static void @@ -398,7 +398,7 @@ save_item (const gchar *key, const gpointer *data, xmlNodePtr parent) const Item *item = (const Item *)data; gchar *atime; - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); g_return_if_fail (key != NULL); @@ -409,13 +409,13 @@ save_item (const gchar *key, const gpointer *data, xmlNodePtr parent) xmlSetProp (xml_node, "uri", key); - gedit_debug (DEBUG_METADATA, "uri: %s", key); + gedit_debug_message (DEBUG_METADATA, "uri: %s", key); /* FIXME: is the cast right? - Paolo */ atime = g_strdup_printf ("%d", (int)item->atime); xmlSetProp (xml_node, "atime", atime); - gedit_debug (DEBUG_METADATA, "atime: %s", atime); + gedit_debug_message (DEBUG_METADATA, "atime: %s", atime); g_free (atime); @@ -472,7 +472,7 @@ gedit_metadata_manager_save (gpointer data) xmlNodePtr root; gchar *file_name; - gedit_debug (DEBUG_METADATA, ""); + gedit_debug (DEBUG_METADATA); if (!gedit_metadata_manager->modified) return TRUE; @@ -501,8 +501,8 @@ gedit_metadata_manager_save (gpointer data) gedit_metadata_manager->modified = FALSE; - gedit_debug (DEBUG_METADATA, "DONE"); - + gedit_debug_message (DEBUG_METADATA, "DONE"); + return TRUE; } diff --git a/gedit/gedit-module.c b/gedit/gedit-module.c new file mode 100644 index 00000000..35cc60f1 --- /dev/null +++ b/gedit/gedit-module.c @@ -0,0 +1,220 @@ +/* + * gedit-module.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* This is a modified version of ephy-module.c from Epiphany source code. + * Here the original copyright assignment: + * + * Copyright (C) 2003 Marco Pesenti Gritti + * Copyright (C) 2003, 2004 Christian Persch + * + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#include "config.h" + +#include "gedit-module.h" +#include "gedit-debug.h" + +#include + +typedef struct _GeditModuleClass GeditModuleClass; + +struct _GeditModuleClass +{ + GTypeModuleClass parent_class; +}; + +struct _GeditModule +{ + GTypeModule parent_instance; + + GModule *library; + + gchar *path; + GType type; +}; + +typedef GType (*GeditModuleRegisterFunc) (GTypeModule *); + +static void gedit_module_init (GeditModule *action); +static void gedit_module_class_init (GeditModuleClass *class); + +static GObjectClass *parent_class = NULL; + +GType +gedit_module_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) + { + static const GTypeInfo type_info = + { + sizeof (GeditModuleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gedit_module_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (GeditModule), + 0, /* n_preallocs */ + (GInstanceInitFunc) gedit_module_init, + }; + + type = g_type_register_static (G_TYPE_TYPE_MODULE, + "GeditModule", + &type_info, 0); + } + + return type; +} + +static gboolean +gedit_module_load (GTypeModule *gmodule) +{ + GeditModule *module = GEDIT_MODULE (gmodule); + GeditModuleRegisterFunc register_func; + + gedit_debug_message (DEBUG_PLUGINS, "Loading %s", module->path); + + module->library = g_module_open (module->path, 0); + + if (module->library == NULL) + { + g_warning (g_module_error()); + + return FALSE; + } + + /* extract symbols from the lib */ + if (!g_module_symbol (module->library, "register_gedit_plugin", + (void *) ®ister_func)) + { + g_warning (g_module_error()); + g_module_close (module->library); + + return FALSE; + } + + g_assert (register_func); + + module->type = register_func (gmodule); + + if (module->type == 0) + { + g_warning ("Invalid gedit plugin contained by module %s", module->path); + return FALSE; + } + + return TRUE; +} + +static void +gedit_module_unload (GTypeModule *gmodule) +{ + GeditModule *module = GEDIT_MODULE (gmodule); + + gedit_debug_message (DEBUG_PLUGINS, "Unloading %s", module->path); + + g_module_close (module->library); + + module->library = NULL; + module->type = 0; +} + +const gchar * +gedit_module_get_path (GeditModule *module) +{ + g_return_val_if_fail (GEDIT_IS_MODULE (module), NULL); + + return module->path; +} + +GObject * +gedit_module_new_object (GeditModule *module) +{ + gedit_debug_message (DEBUG_PLUGINS, "Creating object of type %s", g_type_name (module->type)); + + if (module->type == 0) + { + return NULL; + } + + return g_object_new (module->type, NULL); +} + +static void +gedit_module_init (GeditModule *module) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditModule %p initialising", module); +} + +static void +gedit_module_finalize (GObject *object) +{ + GeditModule *module = GEDIT_MODULE (object); + + gedit_debug_message (DEBUG_PLUGINS, "GeditModule %p finalising", module); + + g_free (module->path); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gedit_module_class_init (GeditModuleClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class); + + parent_class = (GObjectClass *) g_type_class_peek_parent (class); + + object_class->finalize = gedit_module_finalize; + + module_class->load = gedit_module_load; + module_class->unload = gedit_module_unload; +} + +GeditModule * +gedit_module_new (const gchar *path) +{ + GeditModule *result; + + if (path == NULL || path[0] == '\0') + { + return NULL; + } + + result = g_object_new (GEDIT_TYPE_MODULE, NULL); + + g_type_module_set_name (G_TYPE_MODULE (result), path); + result->path = g_strdup (path); + + return result; +} diff --git a/gedit/gedit-module.h b/gedit/gedit-module.h new file mode 100644 index 00000000..f0a32546 --- /dev/null +++ b/gedit/gedit-module.h @@ -0,0 +1,65 @@ +/* + * gedit-module.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* This is a modified version of gedit-module.h from Epiphany source code. + * Here the original copyright assignment: + * + * Copyright (C) 2003 Marco Pesenti Gritti + * Copyright (C) 2003, 2004 Christian Persch + * + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef GEDIT_MODULE_H +#define GEDIT_MODULE_H + +#include + +G_BEGIN_DECLS + +#define GEDIT_TYPE_MODULE (gedit_module_get_type ()) +#define GEDIT_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MODULE, GeditModule)) +#define GEDIT_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MODULE, GeditModuleClass)) +#define GEDIT_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MODULE)) +#define GEDIT_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), GEDIT_TYPE_MODULE)) +#define GEDIT_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_MODULE, GeditModuleClass)) + +typedef struct _GeditModule GeditModule; + +GType gedit_module_get_type (void) G_GNUC_CONST;; + +GeditModule *gedit_module_new (const gchar *path); + +const gchar *gedit_module_get_path (GeditModule *module); + +GObject *gedit_module_new_object (GeditModule *module); + +G_END_DECLS + +#endif diff --git a/gedit/gedit-notebook.c b/gedit/gedit-notebook.c new file mode 100644 index 00000000..b6a3720a --- /dev/null +++ b/gedit/gedit-notebook.c @@ -0,0 +1,1100 @@ +/* + * gedit-notebook.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + */ + +/* This file is a modified version of the epiphany file ephy-notebook.c + * Here the relevant copyright: + * + * Copyright (C) 2002 Christophe Fergeau + * Copyright (C) 2003 Marco Pesenti Gritti + * Copyright (C) 2003, 2004 Christian Persch + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gedit-notebook.h" +#include "gedit-marshal.h" +#include "gedit-window.h" +#include "gedit-tooltips.h" +#include "gedit-spinner.h" + +#define AFTER_ALL_TABS -1 +#define NOT_IN_APP_WINDOWS -2 + +#define GEDIT_NOTEBOOK_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_NOTEBOOK, GeditNotebookPrivate)) + +struct _GeditNotebookPrivate +{ + GList *focused_pages; + GeditTooltips *title_tips; + gulong motion_notify_handler_id; + gint x_start; + gint y_start; + gint drag_in_progress : 1; + gint always_show_tabs : 1; + gint close_buttons_sensitive : 1; + gint tab_drag_and_drop_enabled : 1; +}; + +G_DEFINE_TYPE(GeditNotebook, gedit_notebook, GTK_TYPE_NOTEBOOK) + +static void gedit_notebook_finalize (GObject *object); + +static void move_current_tab_to_another_notebook (GeditNotebook *src, + GeditNotebook *dest, + GdkEventMotion *event, + gint dest_position); + +/* Local variables */ +static GdkCursor *cursor = NULL; + +/* Signals */ +enum +{ + TAB_ADDED, + TAB_REMOVED, + TABS_REORDERED, + TAB_DETACHED, + TAB_CLOSE_REQUEST, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +gedit_notebook_class_init (GeditNotebookClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_notebook_finalize; + + signals[TAB_ADDED] = + g_signal_new ("tab_added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeditNotebookClass, tab_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GEDIT_TYPE_TAB); + signals[TAB_REMOVED] = + g_signal_new ("tab_removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeditNotebookClass, tab_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GEDIT_TYPE_TAB); + signals[TAB_DETACHED] = + g_signal_new ("tab_detached", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeditNotebookClass, tab_detached), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GEDIT_TYPE_TAB); + signals[TABS_REORDERED] = + g_signal_new ("tabs_reordered", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeditNotebookClass, tabs_reordered), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[TAB_CLOSE_REQUEST] = + g_signal_new ("tab-close-request", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GeditNotebookClass, tab_close_request), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GEDIT_TYPE_TAB); + + g_type_class_add_private (object_class, sizeof(GeditNotebookPrivate)); +} + +static GeditNotebook * +find_notebook_at_pointer (gint abs_x, gint abs_y) +{ + GdkWindow *win_at_pointer; + GdkWindow *toplevel_win; + gpointer toplevel = NULL; + gint x, y; + + /* FIXME multi-head */ + win_at_pointer = gdk_window_at_pointer (&x, &y); + if (win_at_pointer == NULL) + { + /* We are outside all windows of the same application */ + return NULL; + } + + toplevel_win = gdk_window_get_toplevel (win_at_pointer); + + /* get the GtkWidget which owns the toplevel GdkWindow */ + gdk_window_get_user_data (toplevel_win, &toplevel); + + /* toplevel should be an GeditWindow */ + if ((toplevel != NULL) && + GEDIT_IS_WINDOW (toplevel)) + { + return GEDIT_NOTEBOOK (_gedit_window_get_notebook + (GEDIT_WINDOW (toplevel))); + } + + /* We are outside all windows containing a notebook */ + return NULL; +} + +static gboolean +is_in_notebook_window (GeditNotebook *notebook, + gint abs_x, + gint abs_y) +{ + GeditNotebook *nb_at_pointer; + + g_return_val_if_fail (notebook != NULL, FALSE); + + nb_at_pointer = find_notebook_at_pointer (abs_x, abs_y); + + return (nb_at_pointer == notebook); +} + +static gint +find_tab_num_at_pos (GeditNotebook *notebook, + gint abs_x, + gint abs_y) +{ + GtkPositionType tab_pos; + int page_num = 0; + GtkNotebook *nb = GTK_NOTEBOOK (notebook); + GtkWidget *page; + + tab_pos = gtk_notebook_get_tab_pos (GTK_NOTEBOOK (notebook)); + + if (GTK_NOTEBOOK (notebook)->first_tab == NULL) + { + return AFTER_ALL_TABS; + } + + /* For some reason unfullscreen + quick click can + cause a wrong click event to be reported to the tab */ + if (!is_in_notebook_window (notebook, abs_x, abs_y)) + { + return NOT_IN_APP_WINDOWS; + } + + while ((page = gtk_notebook_get_nth_page (nb, page_num)) != NULL) + { + GtkWidget *tab; + gint max_x, max_y; + gint x_root, y_root; + + tab = gtk_notebook_get_tab_label (nb, page); + g_return_val_if_fail (tab != NULL, AFTER_ALL_TABS); + + if (!GTK_WIDGET_MAPPED (GTK_WIDGET (tab))) + { + ++page_num; + continue; + } + + gdk_window_get_origin (GDK_WINDOW (tab->window), + &x_root, &y_root); + + max_x = x_root + tab->allocation.x + tab->allocation.width; + max_y = y_root + tab->allocation.y + tab->allocation.height; + + if (((tab_pos == GTK_POS_TOP) || + (tab_pos == GTK_POS_BOTTOM)) && + (abs_x <= max_x)) + { + return page_num; + } + else if (((tab_pos == GTK_POS_LEFT) || + (tab_pos == GTK_POS_RIGHT)) && + (abs_y <= max_y)) + { + return page_num; + } + + ++page_num; + } + + return AFTER_ALL_TABS; +} + +static gint +find_notebook_and_tab_at_pos (gint abs_x, + gint abs_y, + GeditNotebook **notebook, + gint *page_num) +{ + *notebook = find_notebook_at_pointer (abs_x, abs_y); + if (*notebook == NULL) + { + return NOT_IN_APP_WINDOWS; + } + + *page_num = find_tab_num_at_pos (*notebook, abs_x, abs_y); + + if (*page_num < 0) + { + return *page_num; + } + else + { + return 0; + } +} + +/* If dest_position is greater than or equal to the number of tabs + of the destination nootebook or negative, tab will be moved to the + end of the tabs. */ +void +gedit_notebook_move_tab (GeditNotebook *src, + GeditNotebook *dest, + GeditTab *tab, + gint dest_position) +{ + g_return_if_fail (GEDIT_IS_NOTEBOOK (src)); + g_return_if_fail (GEDIT_IS_NOTEBOOK (dest)); + g_return_if_fail (src != dest); + g_return_if_fail (GEDIT_IS_TAB (tab)); + + /* make sure the tab isn't destroyed while we move it */ + g_object_ref (tab); + gedit_notebook_remove_tab (src, tab); + gedit_notebook_add_tab (dest, tab, dest_position, TRUE); + g_object_unref (tab); +} + +/* If dest_position is greater than or equal to the number of tabs + of the destination nootebook or negative, tab will be moved to the + end of the tabs. */ +void +gedit_notebook_reorder_tab (GeditNotebook *src, + GeditTab *tab, + gint dest_position) +{ + g_return_if_fail (GEDIT_IS_NOTEBOOK (src)); + g_return_if_fail (GEDIT_IS_TAB (tab)); + + gtk_notebook_reorder_child (GTK_NOTEBOOK (src), + GTK_WIDGET (tab), + dest_position); + + if (!src->priv->drag_in_progress) + { + g_signal_emit (G_OBJECT (src), + signals[TABS_REORDERED], + 0); + } +} + +static void +drag_start (GeditNotebook *notebook, + guint32 time) +{ + notebook->priv->drag_in_progress = TRUE; + + /* get a new cursor, if necessary */ + /* FIXME multi-head */ + if (cursor == NULL) + cursor = gdk_cursor_new (GDK_FLEUR); + + /* grab the pointer */ + gtk_grab_add (GTK_WIDGET (notebook)); + + /* FIXME multi-head */ + if (!gdk_pointer_is_grabbed ()) + { + gdk_pointer_grab (GTK_WIDGET (notebook)->window, + FALSE, + GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, + NULL, + cursor, + time); + } +} + +static void +drag_stop (GeditNotebook *notebook) +{ + if (notebook->priv->drag_in_progress) + { + g_signal_emit (G_OBJECT (notebook), + signals[TABS_REORDERED], + 0); + } + + notebook->priv->drag_in_progress = FALSE; + if (notebook->priv->motion_notify_handler_id != 0) + { + g_signal_handler_disconnect (G_OBJECT (notebook), + notebook->priv->motion_notify_handler_id); + notebook->priv->motion_notify_handler_id = 0; + } +} + +/* This function is only called during dnd, we don't need to emit TABS_REORDERED + * here, instead we do it on drag_stop + */ +static void +move_current_tab (GeditNotebook *notebook, + gint dest_position) +{ + gint cur_page_num; + + cur_page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)); + + if (dest_position != cur_page_num) + { + GtkWidget *cur_tab; + + cur_tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), + cur_page_num); + + gedit_notebook_reorder_tab (GEDIT_NOTEBOOK (notebook), + GEDIT_TAB (cur_tab), + dest_position); + } +} + +static gboolean +motion_notify_cb (GeditNotebook *notebook, + GdkEventMotion *event, + gpointer data) +{ + GeditNotebook *dest; + gint page_num; + gint result; + + if (notebook->priv->drag_in_progress == FALSE) + { + if (notebook->priv->tab_drag_and_drop_enabled == FALSE) + return FALSE; + + if (gtk_drag_check_threshold (GTK_WIDGET (notebook), + notebook->priv->x_start, + notebook->priv->y_start, + event->x_root, + event->y_root)) + { + drag_start (notebook, event->time); + return TRUE; + } + + return FALSE; + } + + result = find_notebook_and_tab_at_pos ((gint)event->x_root, + (gint)event->y_root, + &dest, + &page_num); + + if (result != NOT_IN_APP_WINDOWS) + { + if (dest != notebook) + { + move_current_tab_to_another_notebook (notebook, + dest, + event, + page_num); + } + else + { + g_return_val_if_fail (page_num >= -1, FALSE); + move_current_tab (notebook, page_num); + } + } + + return FALSE; +} + +static void +move_current_tab_to_another_notebook (GeditNotebook *src, + GeditNotebook *dest, + GdkEventMotion *event, + gint dest_position) +{ + GeditTab *tab; + gint cur_page; + + /* This is getting tricky, the tab was dragged in a notebook + * in another window of the same app, we move the tab + * to that new notebook, and let this notebook handle the + * drag + */ + g_return_if_fail (GEDIT_IS_NOTEBOOK (dest)); + g_return_if_fail (dest != src); + + cur_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (src)); + tab = GEDIT_TAB (gtk_notebook_get_nth_page (GTK_NOTEBOOK (src), + cur_page)); + + /* stop drag in origin window */ + /* ungrab the pointer if it's grabbed */ + drag_stop (src); + if (gdk_pointer_is_grabbed ()) + { + gdk_pointer_ungrab (event->time); + } + gtk_grab_remove (GTK_WIDGET (src)); + + gedit_notebook_move_tab (src, dest, tab, dest_position); + + /* start drag handling in dest notebook */ + dest->priv->motion_notify_handler_id = + g_signal_connect (G_OBJECT (dest), + "motion-notify-event", + G_CALLBACK (motion_notify_cb), + NULL); + + drag_start (dest, event->time); +} + +static gboolean +button_release_cb (GeditNotebook *notebook, + GdkEventButton *event, + gpointer data) +{ + if (notebook->priv->drag_in_progress) + { + gint cur_page_num; + GtkWidget *cur_page; + + cur_page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)); + cur_page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), + cur_page_num); + + /* CHECK: I don't follow the code here -- Paolo */ + if (!is_in_notebook_window (notebook, event->x_root, event->y_root) && + (gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) > 1)) + { + /* Tab was detached */ + g_signal_emit (G_OBJECT (notebook), + signals[TAB_DETACHED], + 0, + cur_page); + } + + /* ungrab the pointer if it's grabbed */ + if (gdk_pointer_is_grabbed ()) + { + gdk_pointer_ungrab (event->time); + } + gtk_grab_remove (GTK_WIDGET (notebook)); + } + + /* This must be called even if a drag isn't happening */ + drag_stop (notebook); + + return FALSE; +} + +static gboolean +button_press_cb (GeditNotebook *notebook, + GdkEventButton *event, + gpointer data) +{ + gint tab_clicked; + + if (notebook->priv->drag_in_progress) + return TRUE; + + tab_clicked = find_tab_num_at_pos (notebook, + event->x_root, + event->y_root); + + if ((event->button == 1) && + (event->type == GDK_BUTTON_PRESS) && + (tab_clicked >= 0)) + { + notebook->priv->x_start = event->x_root; + notebook->priv->y_start = event->y_root; + + notebook->priv->motion_notify_handler_id = + g_signal_connect (G_OBJECT (notebook), + "motion-notify-event", + G_CALLBACK (motion_notify_cb), + NULL); + } + else if ((event->type == GDK_BUTTON_PRESS) && + (event->button == 3)) + { + if (tab_clicked == -1) + { + // CHECK: do we really need it? + + /* consume event, so that we don't pop up the context menu when + * the mouse if not over a tab label + */ + return TRUE; + } + else + { + /* Switch to the page the mouse is over, but don't consume the event */ + gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), + tab_clicked); + } + } + + return FALSE; +} + +GtkWidget * +gedit_notebook_new (void) +{ + return GTK_WIDGET (g_object_new (GEDIT_TYPE_NOTEBOOK, NULL)); +} + +static void +gedit_notebook_switch_page_cb (GtkNotebook *notebook, + GtkNotebookPage *page, + guint page_num, + gpointer data) +{ + GeditNotebook *nb = GEDIT_NOTEBOOK (notebook); + GtkWidget *child; + GeditView *view; + + child = gtk_notebook_get_nth_page (notebook, page_num); + + /* Remove the old page, we dont want to grow unnecessarily + * the list */ + if (nb->priv->focused_pages) + { + nb->priv->focused_pages = + g_list_remove (nb->priv->focused_pages, child); + } + + nb->priv->focused_pages = g_list_append (nb->priv->focused_pages, + child); + + /* give focus to the view */ + view = gedit_tab_get_view (GEDIT_TAB (child)); + gtk_widget_grab_focus (GTK_WIDGET (view)); +} + +/* + * update_tabs_visibility: Hide tabs if there is only one tab + * and the pref is not set. + */ +static void +update_tabs_visibility (GeditNotebook *nb, + gboolean before_inserting) +{ + gboolean show_tabs; + guint num; + + num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)); + + if (before_inserting) num++; + + show_tabs = (nb->priv->always_show_tabs || num > 1); + + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (nb), show_tabs); +} + +static void +gedit_notebook_init (GeditNotebook *notebook) +{ + notebook->priv = GEDIT_NOTEBOOK_GET_PRIVATE (notebook); + + notebook->priv->close_buttons_sensitive = TRUE; + notebook->priv->tab_drag_and_drop_enabled = TRUE; + + gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE); + + notebook->priv->title_tips = gedit_tooltips_new (); + g_object_ref (G_OBJECT (notebook->priv->title_tips)); + gtk_object_sink (GTK_OBJECT (notebook->priv->title_tips)); + + notebook->priv->always_show_tabs = TRUE; + + g_signal_connect (notebook, + "button-press-event", + (GCallback)button_press_cb, + NULL); + g_signal_connect (notebook, + "button-release-event", + (GCallback)button_release_cb, + NULL); + gtk_widget_add_events (GTK_WIDGET (notebook), + GDK_BUTTON1_MOTION_MASK); + + g_signal_connect_after (G_OBJECT (notebook), + "switch_page", + G_CALLBACK (gedit_notebook_switch_page_cb), + NULL); +} + +static void +gedit_notebook_finalize (GObject *object) +{ + GeditNotebook *notebook = GEDIT_NOTEBOOK (object); + + if (notebook->priv->focused_pages) + g_list_free (notebook->priv->focused_pages); + + g_object_unref (notebook->priv->title_tips); + + G_OBJECT_CLASS (gedit_notebook_parent_class)->finalize (object); +} + +static void +sync_name (GeditTab *tab, GParamSpec *pspec, GtkWidget *hbox) +{ + GeditNotebook *nb; + GtkWidget *label; + GtkWidget *ebox; + GtkWidget *button; + GtkWidget *spinner; + GeditTooltips *tips; + gchar *str; + GtkImage *icon; + GeditTabState state; + + tips = GEDIT_TOOLTIPS (g_object_get_data (G_OBJECT (hbox), "tooltips")); + label = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "label")); + ebox = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "label-ebox")); + icon = GTK_IMAGE (g_object_get_data (G_OBJECT (hbox), "icon")); + button = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "close-button")); + spinner = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "spinner")); + + nb = GEDIT_NOTEBOOK (gtk_widget_get_parent (GTK_WIDGET (tab))); + + g_return_if_fail ((tips != NULL) && + (label != NULL) && + (ebox != NULL) && + (button != NULL) && + (icon != NULL) && + (spinner != NULL) && + (nb != NULL)); + + str = _gedit_tab_get_name (tab); + g_return_if_fail (str != NULL); + + gtk_label_set_text (GTK_LABEL (label), str); + g_free (str); + + str = _gedit_tab_get_tooltips (tab); + g_return_if_fail (str != NULL); + + gedit_tooltips_set_tip (tips, ebox, str, NULL); + g_free (str); + + state = gedit_tab_get_state (tab); + + gtk_widget_set_sensitive (button, + nb->priv->close_buttons_sensitive && + (state != GEDIT_TAB_STATE_CLOSING) && + (state != GEDIT_TAB_STATE_SAVING) && + (state != GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW) && + (state != GEDIT_TAB_STATE_SAVING_ERROR)); + + if ((state == GEDIT_TAB_STATE_LOADING) || + (state == GEDIT_TAB_STATE_SAVING) || + (state == GEDIT_TAB_STATE_REVERTING)) + { + gtk_widget_hide (GTK_WIDGET (icon)); + + gtk_widget_show (spinner); + gedit_spinner_start (GEDIT_SPINNER (spinner)); + } + else + { + GdkPixbuf *pixbuf; + + pixbuf = _gedit_tab_get_icon (tab); + gtk_image_set_from_pixbuf (icon, pixbuf); + + if (pixbuf != NULL) + g_object_unref (pixbuf); + + gtk_widget_show (GTK_WIDGET (icon)); + + gtk_widget_hide (spinner); + gedit_spinner_stop (GEDIT_SPINNER (spinner)); + } +} + +static void +close_button_clicked_cb (GtkWidget *widget, + GtkWidget *tab) +{ + GeditNotebook *notebook; + + notebook = GEDIT_NOTEBOOK (gtk_widget_get_parent (tab)); + g_signal_emit (notebook, signals[TAB_CLOSE_REQUEST], 0, tab); +} + +static GtkWidget * +build_tab_label (GeditNotebook *nb, + GeditTab *tab) +{ + GtkWidget *hbox, *label_hbox, *label_ebox; + GtkWidget *label, *dummy_label; + GtkWidget *close_button; + GtkSettings *settings; + gint w, h; + GtkWidget *image; + GtkWidget *spinner; + GtkWidget *icon; + + hbox = gtk_hbox_new (FALSE, 0); + + label_ebox = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (label_ebox), FALSE); + gtk_box_pack_start (GTK_BOX (hbox), label_ebox, TRUE, TRUE, 0); + + label_hbox = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (label_ebox), label_hbox); + + /* setup close button */ + close_button = gtk_button_new (); + gtk_button_set_relief (GTK_BUTTON (close_button), + GTK_RELIEF_NONE); + /* don't allow focus on the close button */ + gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE); + + /* fetch the size of an icon */ + settings = gtk_widget_get_settings (GTK_WIDGET (tab)); + gtk_icon_size_lookup_for_settings (settings, + GTK_ICON_SIZE_MENU, + &w, &h); + image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + gtk_widget_set_size_request (close_button, w + 2, h + 2); + gtk_container_add (GTK_CONTAINER (close_button), image); + gtk_box_pack_start (GTK_BOX (hbox), close_button, FALSE, FALSE, 0); + + gedit_tooltips_set_tip (nb->priv->title_tips, close_button, + _("Close document"), NULL); + + g_signal_connect (G_OBJECT (close_button), "clicked", + G_CALLBACK (close_button_clicked_cb), + tab); + + /* setup spinner */ + spinner = gedit_spinner_new (); + gedit_spinner_set_size (GEDIT_SPINNER (spinner), GTK_ICON_SIZE_MENU); + gtk_box_pack_start (GTK_BOX (label_hbox), spinner, FALSE, FALSE, 0); + + /* setup site icon, empty by default */ + icon = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (label_hbox), icon, FALSE, FALSE, 0); + + /* setup label */ + label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_misc_set_padding (GTK_MISC (label), 2, 0); + gtk_box_pack_start (GTK_BOX (label_hbox), label, FALSE, FALSE, 0); + + dummy_label = gtk_label_new (""); + gtk_box_pack_start (GTK_BOX (label_hbox), dummy_label, TRUE, TRUE, 0); + + gtk_widget_show (hbox); + gtk_widget_show (label_ebox); + gtk_widget_show (label_hbox); + gtk_widget_show (label); + gtk_widget_show (dummy_label); + gtk_widget_show (image); + gtk_widget_show (close_button); + gtk_widget_show (icon); + + g_object_set_data (G_OBJECT (hbox), "label", label); + g_object_set_data (G_OBJECT (hbox), "label-ebox", label_ebox); + g_object_set_data (G_OBJECT (hbox), "spinner", spinner); + g_object_set_data (G_OBJECT (hbox), "icon", icon); + g_object_set_data (G_OBJECT (hbox), "close-button", close_button); + g_object_set_data (G_OBJECT (tab), "close-button", close_button); + g_object_set_data (G_OBJECT (hbox), "tooltips", nb->priv->title_tips); + + return hbox; +} + +void +gedit_notebook_set_always_show_tabs (GeditNotebook *nb, + gboolean show_tabs) +{ + g_return_if_fail (GEDIT_IS_NOTEBOOK (nb)); + + nb->priv->always_show_tabs = (show_tabs != FALSE); + + update_tabs_visibility (nb, FALSE); +} + +void +gedit_notebook_add_tab (GeditNotebook *nb, + GeditTab *tab, + gint position, + gboolean jump_to) +{ + GtkWidget *label; + + g_return_if_fail (GEDIT_IS_NOTEBOOK (nb)); + g_return_if_fail (GEDIT_IS_TAB (tab)); + + label = build_tab_label (nb, tab); + + update_tabs_visibility (nb, TRUE); + + gtk_notebook_insert_page (GTK_NOTEBOOK (nb), + GTK_WIDGET (tab), + label, + position); + + sync_name (tab, NULL, label); + + g_signal_connect_object (tab, + "notify::name", + G_CALLBACK (sync_name), + label, + 0); + g_signal_connect_object (tab, + "notify::state", + G_CALLBACK (sync_name), + label, + 0); + + g_signal_emit (G_OBJECT (nb), signals[TAB_ADDED], 0, tab); + + /* The signal handler may have reordered the tabs */ + position = gtk_notebook_page_num (GTK_NOTEBOOK (nb), + GTK_WIDGET (tab)); + + if (jump_to) + { + GeditView *view; + + gtk_notebook_set_current_page (GTK_NOTEBOOK (nb), position); + g_object_set_data (G_OBJECT (tab), + "jump_to", + GINT_TO_POINTER (jump_to)); + view = gedit_tab_get_view (tab); + + gtk_widget_grab_focus (GTK_WIDGET (view)); + } +} + +static void +smart_tab_switching_on_closure (GeditNotebook *nb, + GeditTab *tab) +{ + gboolean jump_to; + + jump_to = GPOINTER_TO_INT (g_object_get_data + (G_OBJECT (tab), "jump_to")); + + if (!jump_to || !nb->priv->focused_pages) + { + gtk_notebook_next_page (GTK_NOTEBOOK (nb)); + } + else + { + GList *l; + GtkWidget *child; + int page_num; + + /* activate the last focused tab */ + l = g_list_last (nb->priv->focused_pages); + child = GTK_WIDGET (l->data); + page_num = gtk_notebook_page_num (GTK_NOTEBOOK (nb), + child); + gtk_notebook_set_current_page (GTK_NOTEBOOK (nb), + page_num); + } +} + +static void +remove_tab (GeditTab *tab, + GeditNotebook *nb) +{ + GtkWidget *label, *ebox; + gint position; + + position = gtk_notebook_page_num (GTK_NOTEBOOK (nb), GTK_WIDGET (tab)); + + label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb), GTK_WIDGET (tab)); + ebox = GTK_WIDGET (g_object_get_data (G_OBJECT (label), "label-ebox")); + gedit_tooltips_set_tip (GEDIT_TOOLTIPS (nb->priv->title_tips), + ebox, + NULL, + NULL); + + g_signal_handlers_disconnect_by_func (tab, + G_CALLBACK (sync_name), + label); + + /** + * we ref the tab so that it's still alive while the tabs_removed + * signal is processed. + */ + g_object_ref (tab); + + gtk_notebook_remove_page (GTK_NOTEBOOK (nb), position); + + update_tabs_visibility (nb, FALSE); + + g_signal_emit (G_OBJECT (nb), signals[TAB_REMOVED], 0, tab); + + g_object_unref (tab); +} + +void +gedit_notebook_remove_tab (GeditNotebook *nb, + GeditTab *tab) +{ + gint position, curr; + + g_return_if_fail (GEDIT_IS_NOTEBOOK (nb)); + g_return_if_fail (GEDIT_IS_TAB (tab)); + + /* Remove the page from the focused pages list */ + nb->priv->focused_pages = g_list_remove (nb->priv->focused_pages, + tab); + + position = gtk_notebook_page_num (GTK_NOTEBOOK (nb), GTK_WIDGET (tab)); + curr = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb)); + + if (position == curr) + { + smart_tab_switching_on_closure (nb, tab); + } + + remove_tab (tab, nb); +} + +void +gedit_notebook_remove_all_tabs (GeditNotebook *nb) +{ + g_return_if_fail (GEDIT_IS_NOTEBOOK (nb)); + + g_list_free (nb->priv->focused_pages); + nb->priv->focused_pages = NULL; + + gtk_container_foreach (GTK_CONTAINER (nb), + (GtkCallback)remove_tab, + nb); +} + +static void +set_close_buttons_sensitivity (GeditTab *tab, + GeditNotebook *nb) +{ + GtkWidget *button; + GeditTabState state; + + button = GTK_WIDGET (g_object_get_data (G_OBJECT (tab), + "close-button")); + g_return_if_fail (button != NULL); + + state = gedit_tab_get_state (tab); + + gtk_widget_set_sensitive (button, + nb->priv->close_buttons_sensitive && + (state != GEDIT_TAB_STATE_CLOSING) && + (state != GEDIT_TAB_STATE_SAVING) && + (state != GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW) && + (state != GEDIT_TAB_STATE_SAVING_ERROR)); +} + +void +gedit_notebook_set_close_buttons_sensitive (GeditNotebook *nb, + gboolean sensitive) +{ + g_return_if_fail (GEDIT_IS_NOTEBOOK (nb)); + + sensitive = (sensitive != FALSE); + + if (sensitive == nb->priv->close_buttons_sensitive) + return; + + nb->priv->close_buttons_sensitive = sensitive; + + gtk_container_foreach (GTK_CONTAINER (nb), + (GtkCallback)set_close_buttons_sensitivity, + nb); +} + +gboolean +gedit_notebook_get_close_buttons_sensitive (GeditNotebook *nb) +{ + g_return_val_if_fail (GEDIT_IS_NOTEBOOK (nb), TRUE); + + return nb->priv->close_buttons_sensitive; +} + +void +gedit_notebook_set_tab_drag_and_drop_enabled (GeditNotebook *nb, + gboolean enable) +{ + g_return_if_fail (GEDIT_IS_NOTEBOOK (nb)); + + enable = (enable != FALSE); + + if (enable == nb->priv->tab_drag_and_drop_enabled) + return; + + nb->priv->tab_drag_and_drop_enabled = enable; +} + +gboolean +gedit_notebook_get_tab_drag_and_drop_enabled (GeditNotebook *nb) +{ + g_return_val_if_fail (GEDIT_IS_NOTEBOOK (nb), TRUE); + + return nb->priv->tab_drag_and_drop_enabled; +} + diff --git a/gedit/gedit-notebook.h b/gedit/gedit-notebook.h new file mode 100644 index 00000000..6451cc82 --- /dev/null +++ b/gedit/gedit-notebook.h @@ -0,0 +1,143 @@ +/* + * gedit-notebook.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + */ + +/* This file is a modified version of the epiphany file ephy-notebook.h + * Here the relevant copyright: + * + * Copyright (C) 2002 Christophe Fergeau + * Copyright (C) 2003 Marco Pesenti Gritti + * Copyright (C) 2003, 2004 Christian Persch + * + */ + +#ifndef GEDIT_NOTEBOOK_H +#define GEDIT_NOTEBOOK_H + +#include + +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_NOTEBOOK (gedit_notebook_get_type ()) +#define GEDIT_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_NOTEBOOK, GeditNotebook)) +#define GEDIT_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_NOTEBOOK, GeditNotebookClass)) +#define GEDIT_IS_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_NOTEBOOK)) +#define GEDIT_IS_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_NOTEBOOK)) +#define GEDIT_NOTEBOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_NOTEBOOK, GeditNotebookClass)) + +/* Private structure type */ +typedef struct _GeditNotebookPrivate GeditNotebookPrivate; + +/* + * Main object structure + */ +typedef struct _GeditNotebook GeditNotebook; + +struct _GeditNotebook +{ + GtkNotebook notebook; + + /*< private >*/ + GeditNotebookPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditNotebookClass GeditNotebookClass; + +struct _GeditNotebookClass +{ + GtkNotebookClass parent_class; + + /* Signals */ + void (* tab_added) (GeditNotebook *notebook, + GeditTab *tab); + void (* tab_removed) (GeditNotebook *notebook, + GeditTab *tab); + void (* tab_detached) (GeditNotebook *notebook, + GeditTab *tab); + void (* tabs_reordered) (GeditNotebook *notebook); + void (* tab_close_request) + (GeditNotebook *notebook, + GeditTab *tab); +}; + +/* + * Public methods + */ +GType gedit_notebook_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_notebook_new (void); + +void gedit_notebook_add_tab (GeditNotebook *nb, + GeditTab *tab, + gint position, + gboolean jump_to); + +void gedit_notebook_remove_tab (GeditNotebook *nb, + GeditTab *tab); + +void gedit_notebook_remove_all_tabs (GeditNotebook *nb); + +void gedit_notebook_reorder_tab (GeditNotebook *src, + GeditTab *tab, + gint dest_position); + +void gedit_notebook_move_tab (GeditNotebook *src, + GeditNotebook *dest, + GeditTab *tab, + gint dest_position); + +/* FIXME: do we really need this function ? */ +void gedit_notebook_set_always_show_tabs + (GeditNotebook *nb, + gboolean show_tabs); + +void gedit_notebook_set_close_buttons_sensitive + (GeditNotebook *nb, + gboolean sensitive); + +gboolean gedit_notebook_get_close_buttons_sensitive + (GeditNotebook *nb); + +void gedit_notebook_set_tab_drag_and_drop_enabled + (GeditNotebook *nb, + gboolean enable); + +gboolean gedit_notebook_get_tab_drag_and_drop_enabled + (GeditNotebook *nb); + +G_END_DECLS + +#endif /* GEDIT_NOTEBOOK_H */ diff --git a/gedit/gedit-output-window.c b/gedit/gedit-output-window.c index 085ad250..6d52a9ac 100644 --- a/gedit/gedit-output-window.c +++ b/gedit/gedit-output-window.c @@ -525,10 +525,7 @@ gedit_output_window_finalize (GObject *object) g_object_unref (ow->priv->tooltips); - if (ow->priv != NULL) - { - g_free (ow->priv); - } + g_free (ow->priv); G_OBJECT_CLASS (parent_class)->finalize (object); } diff --git a/gedit/gedit-panel.c b/gedit/gedit-panel.c new file mode 100644 index 00000000..60e835d5 --- /dev/null +++ b/gedit/gedit-panel.c @@ -0,0 +1,703 @@ +/* + * gedit-panel.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#include "gedit-panel.h" + +#include +#include +#include +#include + +#include "gedit-window.h" +#include "gedit-debug.h" + +#define PANEL_ITEM_KEY "GeditPanelItemKey" + +#define GEDIT_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PANEL, GeditPanelPrivate)) + +struct _GeditPanelPrivate +{ + /* Title bar */ + GtkWidget *close_button; + GtkWidget *title_image; + GtkWidget *title_label; + + /* Notebook */ + GtkWidget *notebook; + + GtkTooltips *tooltips; +}; + +typedef struct _GeditPanelItem GeditPanelItem; + +struct _GeditPanelItem +{ + gchar *name; + GtkWidget *icon; +}; + +/* Signals */ +enum { + CLOSE, + FOCUS_DOCUMENT, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE(GeditPanel, gedit_panel, GTK_TYPE_VBOX) + +static void +gedit_panel_finalize (GObject *obj) +{ + GeditPanel *panel = GEDIT_PANEL (obj); + + g_object_unref (panel->priv->tooltips); + + if (G_OBJECT_CLASS (gedit_panel_parent_class)->finalize) + (*G_OBJECT_CLASS (gedit_panel_parent_class)->finalize) (obj); +} + +static void +gedit_panel_close (GeditPanel *panel) +{ + gtk_widget_hide (GTK_WIDGET (panel)); +} + +static void +gedit_panel_focus_document (GeditPanel *panel) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel)); + if (GTK_WIDGET_TOPLEVEL (toplevel) && GEDIT_IS_WINDOW (toplevel)) + { + GeditView *view; + + view = gedit_window_get_active_view (GEDIT_WINDOW (toplevel)); + if (view != NULL) + gtk_widget_grab_focus (GTK_WIDGET (view)); + } +} + +static void +gedit_panel_grab_focus (GtkWidget *w) +{ + gint n; + GtkWidget *tab; + GeditPanel *panel = GEDIT_PANEL (w); + + n = gtk_notebook_get_current_page (GTK_NOTEBOOK (panel->priv->notebook)); + if (n == -1) + return; + + tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (panel->priv->notebook), + n); + g_return_if_fail (tab != NULL); + + gtk_widget_grab_focus (tab); +} + +static void +gedit_panel_class_init (GeditPanelClass *klass) +{ + GtkBindingSet *binding_set; + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GeditPanelPrivate)); + + g_object_class->finalize = gedit_panel_finalize; + + widget_class->grab_focus = gedit_panel_grab_focus; + + klass->close = gedit_panel_close; + klass->focus_document = gedit_panel_focus_document; + + signals[CLOSE] = g_signal_new ("close", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GeditPanelClass, close), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[FOCUS_DOCUMENT] = g_signal_new ("focus_document", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GeditPanelClass, focus_document), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + binding_set = gtk_binding_set_by_class (klass); + + gtk_binding_entry_add_signal (binding_set, + GDK_Escape, + 0, + "close", + 0); + gtk_binding_entry_add_signal (binding_set, + GDK_Return, + GDK_CONTROL_MASK, + "focus_document", + 0); +} + +#define TAB_WIDTH_N_CHARS 10 + +static void +tab_label_style_set_cb (GtkWidget *label, + GtkStyle *previous_style, + GtkWidget *hbox) +{ + gint h, w; + + gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (label), + GTK_ICON_SIZE_MENU, &w, &h); + + if (GTK_WIDGET_VISIBLE (label)) + { + PangoFontMetrics *metrics; + PangoContext *context; + gint char_width, len; + const gchar *str; + + context = gtk_widget_get_pango_context (label); + metrics = pango_context_get_metrics (context, + label->style->font_desc, + pango_context_get_language (context)); + + char_width = pango_font_metrics_get_approximate_digit_width (metrics); + pango_font_metrics_unref (metrics); + + str = gtk_label_get_text (GTK_LABEL (label)); + len = g_utf8_strlen (str, -1); + + gtk_widget_set_size_request + (hbox, MIN (TAB_WIDTH_N_CHARS, len) * PANGO_PIXELS(char_width) + w, -1); + } + else + { + gtk_widget_set_size_request (hbox, w, -1); + } +} + +/* This is ugly, since it supports only known + * storage types of GtkImage, otherwise fall back + * to the empty icon. + * See http://bugzilla.gnome.org/show_bug.cgi?id=317520. + */ +static void +set_gtk_image_from_gtk_image (GtkImage *image, + GtkImage *source) +{ + switch (gtk_image_get_storage_type (source)) + { + case GTK_IMAGE_EMPTY: + gtk_image_clear (image); + break; + case GTK_IMAGE_PIXMAP: + { + GdkPixmap *pm; + GdkBitmap *bm; + + gtk_image_get_pixmap (source, &pm, &bm); + gtk_image_set_from_pixmap (image, pm, bm); + } + break; + case GTK_IMAGE_IMAGE: + { + GdkImage *i; + GdkBitmap *bm; + + gtk_image_get_image (source, &i, &bm); + gtk_image_set_from_image (image, i, bm); + } + break; + case GTK_IMAGE_PIXBUF: + { + GdkPixbuf *pb; + + pb = gtk_image_get_pixbuf (source); + gtk_image_set_from_pixbuf (image, pb); + } + break; + case GTK_IMAGE_STOCK: + { + gchar *s_id; + GtkIconSize s; + + gtk_image_get_stock (source, &s_id, &s); + gtk_image_set_from_stock (image, s_id, s); + } + break; + case GTK_IMAGE_ICON_SET: + { + GtkIconSet *is; + GtkIconSize s; + + gtk_image_get_icon_set (source, &is, &s); + gtk_image_set_from_icon_set (image, is, s); + } + break; + case GTK_IMAGE_ANIMATION: + { + GdkPixbufAnimation *a; + + a = gtk_image_get_animation (source); + gtk_image_set_from_animation (image, a); + } + break; + case GTK_IMAGE_ICON_NAME: + { + const gchar *n; + GtkIconSize s; + + gtk_image_get_icon_name (source, &n, &s); + gtk_image_set_from_icon_name (image, n, s); + } + break; + default: + gtk_image_set_from_stock (image, + GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + } +} + +static void +sync_title (GeditPanel *panel, + GeditPanelItem *item) +{ + if (item != NULL) + { + gtk_label_set_text (GTK_LABEL (panel->priv->title_label), + item->name); + + set_gtk_image_from_gtk_image (GTK_IMAGE (panel->priv->title_image), + GTK_IMAGE (item->icon)); + } + else + { + gtk_label_set_text (GTK_LABEL (panel->priv->title_label), + _("Empty")); + + gtk_image_set_from_stock (GTK_IMAGE (panel->priv->title_image), + GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + } +} + +static void +notebook_page_changed (GtkNotebook *notebook, + GtkNotebookPage *page, + guint page_num, + GeditPanel *panel) +{ + GtkWidget *item; + GeditPanelItem *data; + gint i; + gint pages; + + item = gtk_notebook_get_nth_page (notebook, page_num); + g_return_if_fail (item != NULL); + + data = (GeditPanelItem *)g_object_get_data (G_OBJECT (item), + PANEL_ITEM_KEY); + g_return_if_fail (data != NULL); + + sync_title (panel, data); + + pages = gtk_notebook_get_n_pages (notebook); + for (i = 0; i < pages; ++i) + { + GtkWidget *p; + GtkWidget *label; + GtkWidget *hbox; + + p = gtk_notebook_get_nth_page (notebook, i); + + label = GTK_WIDGET (g_object_get_data (G_OBJECT (p), "label")); + + if (p != item) + gtk_widget_hide (label); + else + gtk_widget_show (label); + + hbox = GTK_WIDGET (g_object_get_data (G_OBJECT (p), "hbox")); + + tab_label_style_set_cb (label, NULL, hbox); + } +} + +static void +panel_show (GeditPanel *panel, + gpointer user_data) +{ + gint page; + GtkNotebook *nb; + + nb = GTK_NOTEBOOK (panel->priv->notebook); + + page = gtk_notebook_get_current_page (nb); + + if (page != -1) + notebook_page_changed (nb, NULL, page, panel); +} + +static void +close_button_clicked_cb (GtkWidget *widget, + GtkWidget *panel) +{ + gtk_widget_hide (panel); +} + +static void +gedit_panel_init (GeditPanel *panel) +{ + GtkWidget *title_hbox; + GtkWidget *icon_name_hbox; + GtkWidget *image; + GtkWidget *dummy_label; + GtkSettings *settings; + gint w, h; + + panel->priv = GEDIT_PANEL_GET_PRIVATE (panel); + g_return_if_fail (panel->priv != NULL); + + panel->priv->tooltips = gtk_tooltips_new (); + g_object_ref (G_OBJECT (panel->priv->tooltips)); + gtk_object_sink (GTK_OBJECT (panel->priv->tooltips)); + + /* Create title hbox */ + title_hbox = gtk_hbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (title_hbox), + 6); + + gtk_box_pack_start (GTK_BOX (panel), title_hbox, FALSE, FALSE, 0); + + icon_name_hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (title_hbox), + icon_name_hbox, + TRUE, + TRUE, + 0); + + panel->priv->title_image = + gtk_image_new_from_stock (GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + + gtk_box_pack_start (GTK_BOX (icon_name_hbox), + panel->priv->title_image, + FALSE, + FALSE, + 0); + + dummy_label = gtk_label_new (" "); + + gtk_box_pack_start (GTK_BOX (icon_name_hbox), + dummy_label, + FALSE, + FALSE, + 0); + + panel->priv->title_label = gtk_label_new (_("Empty")); + + /* FIXME: elipsize */ + + gtk_box_pack_start (GTK_BOX (icon_name_hbox), + panel->priv->title_label, + FALSE, + FALSE, + 0); + + panel->priv->close_button = gtk_button_new (); + gtk_button_set_relief (GTK_BUTTON (panel->priv->close_button), + GTK_RELIEF_NONE); + /* fetch the size of an icon */ + settings = gtk_widget_get_settings (GTK_WIDGET (panel)); + gtk_icon_size_lookup_for_settings (settings, + GTK_ICON_SIZE_MENU, + &w, &h); + image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + gtk_widget_set_size_request (panel->priv->close_button, w + 2, h + 2); + gtk_container_add (GTK_CONTAINER (panel->priv->close_button), image); + gtk_button_set_focus_on_click (GTK_BUTTON (panel->priv->close_button), + FALSE); + + gtk_box_pack_start (GTK_BOX (title_hbox), + panel->priv->close_button, + FALSE, + FALSE, + 0); + + gtk_tooltips_set_tip (panel->priv->tooltips, + panel->priv->close_button, + _("Hide panel"), + NULL); + + g_signal_connect (G_OBJECT (panel->priv->close_button), + "clicked", + G_CALLBACK (close_button_clicked_cb), + panel); + + gtk_widget_show_all (GTK_WIDGET (title_hbox)); + + /* Create the notebook */ + panel->priv->notebook = gtk_notebook_new (); + gtk_box_pack_start (GTK_BOX (panel), + panel->priv->notebook, + TRUE, + TRUE, + 0); + gtk_notebook_set_tab_pos (GTK_NOTEBOOK (panel->priv->notebook), + GTK_POS_BOTTOM); + gtk_notebook_set_scrollable (GTK_NOTEBOOK (panel->priv->notebook), + TRUE); + gtk_notebook_popup_enable (GTK_NOTEBOOK (panel->priv->notebook)); + + gtk_widget_show (GTK_WIDGET (panel->priv->notebook)); + + g_signal_connect (panel->priv->notebook, + "switch-page", + G_CALLBACK (notebook_page_changed), + panel); + + g_signal_connect (panel, + "show", + G_CALLBACK (panel_show), + NULL); +} + +GtkWidget * +gedit_panel_new (void) +{ + return GTK_WIDGET (g_object_new (GEDIT_TYPE_PANEL, NULL)); +} + +static GtkWidget * +build_tab_label (GeditPanel *panel, + GtkWidget *item, + const gchar *name, + GtkWidget *icon) +{ + GtkWidget *hbox, *label_hbox, *label_ebox; + GtkWidget *label; + + /* set hbox spacing and label padding (see below) so that there's an + * equal amount of space around the label */ + hbox = gtk_hbox_new (FALSE, 4); + + label_ebox = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (label_ebox), FALSE); + gtk_box_pack_start (GTK_BOX (hbox), label_ebox, TRUE, TRUE, 0); + + label_hbox = gtk_hbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (label_ebox), label_hbox); + + /* setup icon */ + gtk_box_pack_start (GTK_BOX (label_hbox), icon, FALSE, FALSE, 0); + + /* setup label */ + label = gtk_label_new (name); + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_misc_set_padding (GTK_MISC (label), 0, 0); + gtk_box_pack_start (GTK_BOX (label_hbox), label, TRUE, TRUE, 0); + + /* Set minimal size */ + g_signal_connect (label, "style-set", + G_CALLBACK (tab_label_style_set_cb), hbox); + + gtk_tooltips_set_tip (panel->priv->tooltips, + label_ebox, + name, + NULL); + + gtk_widget_show_all (hbox); + gtk_widget_hide (label); + + g_object_set_data (G_OBJECT (item), "label", label); + g_object_set_data (G_OBJECT (item), "hbox", hbox); + g_object_set_data (G_OBJECT (item), "label-ebox", label_ebox); + + return hbox; +} + +void +gedit_panel_add_item (GeditPanel *panel, + GtkWidget *item, + const gchar *name, + GtkWidget *image) +{ + GeditPanelItem *data; + GtkWidget *tab_label; + GtkWidget *menu_label; + + g_return_if_fail (GEDIT_IS_PANEL (panel)); + g_return_if_fail (GTK_IS_WIDGET (item)); + g_return_if_fail (name != NULL); + g_return_if_fail (image == NULL || GTK_IS_IMAGE (image)); + + data = g_new (GeditPanelItem, 1); + + data->name = g_strdup (name); + + if (image == NULL) + { + /* default to empty */ + data->icon = gtk_image_new_from_stock (GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + } + else + { + data->icon = image; + } + + g_object_set_data (G_OBJECT (item), + PANEL_ITEM_KEY, + data); + + tab_label = build_tab_label (panel, item, data->name, data->icon); + + menu_label = gtk_label_new (name); + gtk_misc_set_alignment (GTK_MISC (menu_label), 0.0, 0.5); + + if (!GTK_WIDGET_VISIBLE (item)) + gtk_widget_show (item); + + gtk_notebook_append_page_menu (GTK_NOTEBOOK (panel->priv->notebook), + item, + tab_label, + menu_label); +} + +void +gedit_panel_add_item_with_stock_icon (GeditPanel *panel, + GtkWidget *item, + const gchar *name, + const gchar *stock_id) +{ + GtkWidget *icon = NULL; + + if (stock_id != NULL) + { + icon = gtk_image_new_from_stock (stock_id, + GTK_ICON_SIZE_MENU); + } + + gedit_panel_add_item (panel, item, name, icon); +} + +gboolean +gedit_panel_remove_item (GeditPanel *panel, + GtkWidget *item) +{ + GeditPanelItem *data; + gint page_num; + GtkWidget *ebox; + + g_return_val_if_fail (GEDIT_IS_PANEL (panel), FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE); + + page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook), + item); + + if (page_num == -1) + return FALSE; + + data = (GeditPanelItem *)g_object_get_data (G_OBJECT (item), + PANEL_ITEM_KEY); + g_return_val_if_fail (data != NULL, FALSE); + + g_free (data->name); + g_free (data); + + g_object_set_data (G_OBJECT (item), + PANEL_ITEM_KEY, + NULL); + + ebox = g_object_get_data (G_OBJECT (item), "label-ebox"); + gtk_tooltips_set_tip (GTK_TOOLTIPS (panel->priv->tooltips), + ebox, + NULL, + NULL); + + gtk_notebook_remove_page (GTK_NOTEBOOK (panel->priv->notebook), + page_num); + + /* if we removed all the pages, reset the title */ + if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->priv->notebook)) == 0) + { + sync_title (panel, NULL); + } + + return TRUE; +} + +gboolean +gedit_panel_activate_item (GeditPanel *panel, + GtkWidget *item) +{ + gint page_num; + + g_return_val_if_fail (GEDIT_IS_PANEL (panel), FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE); + + page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook), + item); + + if (page_num == -1) + return FALSE; + + gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->priv->notebook), + page_num); + + return TRUE; +} + +gboolean +gedit_panel_item_is_active (GeditPanel *panel, + GtkWidget *item) +{ + gint cur_page; + gint page_num; + + g_return_val_if_fail (GEDIT_IS_PANEL (panel), FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE); + + page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook), + item); + + if (page_num == -1) + return FALSE; + + cur_page = gtk_notebook_get_current_page ( + GTK_NOTEBOOK (panel->priv->notebook)); + + return (page_num == cur_page); +} + diff --git a/gedit/gedit-panel.h b/gedit/gedit-panel.h new file mode 100644 index 00000000..2c811cc1 --- /dev/null +++ b/gedit/gedit-panel.h @@ -0,0 +1,107 @@ +/* + * gedit-panel.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_PANEL_H__ +#define __GEDIT_PANEL_H__ + +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_PANEL (gedit_panel_get_type()) +#define GEDIT_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PANEL, GeditPanel)) +#define GEDIT_PANEL_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PANEL, GeditPanel const)) +#define GEDIT_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PANEL, GeditPanelClass)) +#define GEDIT_IS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PANEL)) +#define GEDIT_IS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PANEL)) +#define GEDIT_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PANEL, GeditPanelClass)) + +/* Private structure type */ +typedef struct _GeditPanelPrivate GeditPanelPrivate; + +/* + * Main object structure + */ +typedef struct _GeditPanel GeditPanel; + +struct _GeditPanel +{ + GtkVBox vbox; + + /*< private > */ + GeditPanelPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditPanelClass GeditPanelClass; + +struct _GeditPanelClass +{ + GtkVBoxClass parent_class; + + /* Keybinding signals */ + void (* close) (GeditPanel *panel); + void (* focus_document) (GeditPanel *panel); +}; + +/* + * Public methods + */ +GType gedit_panel_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_panel_new (void); + +void gedit_panel_add_item (GeditPanel *panel, + GtkWidget *item, + const gchar *name, + GtkWidget *image); + +void gedit_panel_add_item_with_stock_icon (GeditPanel *panel, + GtkWidget *item, + const gchar *name, + const gchar *stock_id); + +gboolean gedit_panel_remove_item (GeditPanel *panel, + GtkWidget *item); + +gboolean gedit_panel_activate_item (GeditPanel *panel, + GtkWidget *item); + +gboolean gedit_panel_item_is_active (GeditPanel *panel, + GtkWidget *item); + +G_END_DECLS + +#endif /* __GEDIT_PANEL_H__ */ diff --git a/gedit/gedit-plugin-manager.c b/gedit/gedit-plugin-manager.c new file mode 100644 index 00000000..f6825655 --- /dev/null +++ b/gedit/gedit-plugin-manager.c @@ -0,0 +1,579 @@ +/* + * gedit-plugin-manager.c + * This file is part of gedit + * + * Copyright (C) 2002 Paolo Maggi and James Willcox + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include + +#include "gedit-plugin-manager.h" +#include "gedit-utils.h" +#include "gedit-plugins-engine.h" +#include "gedit-plugin.h" +#include "gedit-debug.h" + +enum +{ + ACTIVE_COLUMN, + NAME_COLUMN, + N_COLUMNS +}; + +#define PLUGIN_MANAGER_NAME_TITLE _("Plugin") +#define PLUGIN_MANAGER_ACTIVE_TITLE _("Enabled") + +#define GEDIT_PLUGIN_MANAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerPrivate)) + +struct _GeditPluginManagerPrivate +{ + GtkWidget *tree; + + GtkWidget *about_button; + GtkWidget *configure_button; + + const GList *plugins; + + GtkWidget *about; +}; + +G_DEFINE_TYPE(GeditPluginManager, gedit_plugin_manager, GTK_TYPE_VBOX) + +static GeditPluginInfo *plugin_manager_get_selected_plugin (GeditPluginManager *pm); +static void plugin_manager_toggle_active (GtkTreeIter *iter, GtkTreeModel *model); +static void plugin_manager_toggle_all (GeditPluginManager *pm); + +static void +gedit_plugin_manager_class_init (GeditPluginManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (GeditPluginManagerPrivate)); +} + +static void +about_button_cb (GtkWidget *button, + GeditPluginManager *pm) +{ + GeditPluginInfo *info; + GdkPixbuf *pixbuf = NULL; + + gedit_debug (DEBUG_PLUGINS); + + info = plugin_manager_get_selected_plugin (pm); + + g_return_if_fail (info != NULL); + + pixbuf = gdk_pixbuf_new_from_file (GNOME_ICONDIR "/gedit-plugin-manager.png", NULL); + + /* if there is another about dialog already open destroy it */ + if (pm->priv->about) + gtk_widget_destroy (pm->priv->about); + + pm->priv->about = g_object_new (GTK_TYPE_ABOUT_DIALOG, + "name", gedit_plugins_engine_get_plugin_name (info), + "copyright", gedit_plugins_engine_get_plugin_copyright (info), + "authors", gedit_plugins_engine_get_plugin_authors (info), + "comments", gedit_plugins_engine_get_plugin_description (info), + "website", gedit_plugins_engine_get_plugin_website (info), + "logo", pixbuf, + NULL); + + gtk_window_set_destroy_with_parent (GTK_WINDOW (pm->priv->about), + TRUE); + + g_signal_connect (pm->priv->about, + "response", + G_CALLBACK (gtk_widget_destroy), + NULL); + g_signal_connect (pm->priv->about, + "destroy", + G_CALLBACK (gtk_widget_destroyed), + &pm->priv->about); + + gtk_window_set_transient_for (GTK_WINDOW (pm->priv->about), + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET(pm)))); + gtk_widget_show (pm->priv->about); + + if (pixbuf != NULL) + g_object_unref (pixbuf); +} + +static void +configure_button_cb (GtkWidget *button, + GeditPluginManager *pm) +{ + GeditPluginInfo *info; + GtkWindow *toplevel; + + gedit_debug (DEBUG_PLUGINS); + + info = plugin_manager_get_selected_plugin (pm); + + g_return_if_fail (info != NULL); + + gedit_debug_message (DEBUG_PLUGINS, "Configuring: %s\n", + gedit_plugins_engine_get_plugin_name (info)); + + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET(pm))); + + gedit_plugins_engine_configure_plugin (info, toplevel); + + gedit_debug_message (DEBUG_PLUGINS, "Done"); +} + +static void +plugin_manager_view_cell_cb (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer data) +{ + GeditPluginInfo *info; +// const gchar *title; + + g_return_if_fail (tree_model != NULL); + g_return_if_fail (tree_column != NULL); + + gtk_tree_model_get (tree_model, iter, NAME_COLUMN, &info, -1); + + if (info == NULL) + return; + +// title = gtk_tree_view_column_get_title (tree_column); + + /* FIXME: this string comparison stuff sucks. is there a better way? */ +// if (!strcmp (title, PLUGIN_MANAGER_NAME_TITLE)) + g_object_set (G_OBJECT (cell), + "text", + gedit_plugins_engine_get_plugin_name (info), + NULL); +} + +static void +active_toggled_cb (GtkCellRendererToggle *cell, + gchar *path_str, + GeditPluginManager *pm) +{ + GtkTreeIter iter; + GtkTreePath *path; + GtkTreeModel *model; + + gedit_debug (DEBUG_PLUGINS); + + path = gtk_tree_path_new_from_string (path_str); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); + g_return_if_fail (model != NULL); + + gtk_tree_model_get_iter (model, &iter, path); + + if (&iter != NULL) + plugin_manager_toggle_active (&iter, model); + + gtk_tree_path_free (path); +} + +static void +cursor_changed_cb (GtkTreeView *view, + gpointer data) +{ + GeditPluginManager *pm = data; + GeditPluginInfo *info; + + gedit_debug (DEBUG_PLUGINS); + + info = plugin_manager_get_selected_plugin (pm); + + gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->about_button), + info != NULL); + gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button), + (info != NULL) && + gedit_plugins_engine_plugin_is_configurable (info)); +} + +static void +row_activated_cb (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer data) +{ + GeditPluginManager *pm = data; + GtkTreeIter iter; + GtkTreeModel *model; + + gedit_debug (DEBUG_PLUGINS); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); + + g_return_if_fail (model != NULL); + + gtk_tree_model_get_iter (model, &iter, path); + + g_return_if_fail (&iter != NULL); + + plugin_manager_toggle_active (&iter, model); +} + +static void +column_clicked_cb (GtkTreeViewColumn *tree_column, + gpointer data) +{ + GeditPluginManager *pm = data; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (pm != NULL); + + plugin_manager_toggle_all (pm); +} + +static void +plugin_manager_populate_lists (GeditPluginManager *pm) +{ + const GList *plugins; + GtkListStore *model; + GtkTreeIter iter; + + gedit_debug (DEBUG_PLUGINS); + + plugins = pm->priv->plugins; + + model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree))); + + while (plugins) + { + GeditPluginInfo *info; + info = (GeditPluginInfo *)plugins->data; + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, + ACTIVE_COLUMN, gedit_plugins_engine_plugin_is_active (info), + NAME_COLUMN, info, + -1); + + plugins = plugins->next; + } + + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) + { + GtkTreeSelection *selection; + GeditPluginInfo* info; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree)); + g_return_if_fail (selection != NULL); + + gtk_tree_selection_select_iter (selection, &iter); + + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, + NAME_COLUMN, &info, -1); + + gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button), + gedit_plugins_engine_plugin_is_configurable (info)); + } +} + +static void +plugin_manager_set_active (GtkTreeIter *iter, + GtkTreeModel *model, + gboolean active) +{ + GeditPluginInfo *info; + + gedit_debug (DEBUG_PLUGINS); + + gtk_tree_model_get (model, iter, NAME_COLUMN, &info, -1); + + g_return_if_fail (info != NULL); + + if (active) + { + /* activate the plugin */ + if (!gedit_plugins_engine_activate_plugin (info)) { + gedit_debug_message (DEBUG_PLUGINS, "Could not activate %s.\n", + gedit_plugins_engine_get_plugin_name (info)); + active ^= 1; + } + } + else + { + /* deactivate the plugin */ + if (!gedit_plugins_engine_deactivate_plugin (info)) { + gedit_debug_message (DEBUG_PLUGINS, "Could not deactivate %s.\n", + gedit_plugins_engine_get_plugin_name (info)); + + active ^= 1; + } + } + + /* set new value */ + gtk_list_store_set (GTK_LIST_STORE (model), + iter, + ACTIVE_COLUMN, + gedit_plugins_engine_plugin_is_active (info), + -1); +} + +static void +plugin_manager_toggle_active (GtkTreeIter *iter, + GtkTreeModel *model) +{ + gboolean active; + + gedit_debug (DEBUG_PLUGINS); + + gtk_tree_model_get (model, iter, ACTIVE_COLUMN, &active, -1); + + active ^= 1; + + plugin_manager_set_active (iter, model, active); +} + +static GeditPluginInfo * +plugin_manager_get_selected_plugin (GeditPluginManager *pm) +{ + GeditPluginInfo *info = NULL; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreeSelection *selection; + + gedit_debug (DEBUG_PLUGINS); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); + g_return_val_if_fail (model != NULL, NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree)); + g_return_val_if_fail (selection != NULL, NULL); + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + { + gtk_tree_model_get (model, &iter, NAME_COLUMN, &info, -1); + } + + return info; +} + +static void +plugin_manager_toggle_all (GeditPluginManager *pm) +{ + GtkTreeModel *model; + GtkTreeIter iter; + static gboolean active; + + gedit_debug (DEBUG_PLUGINS); + + active ^= 1; + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); + + g_return_if_fail (model != NULL); + + gtk_tree_model_get_iter_first (model, &iter); + + do { + plugin_manager_set_active (&iter, model, active); + } + while (gtk_tree_model_iter_next (model, &iter)); +} + +/* Callback used as the interactive search comparison function */ +static gboolean +name_search_cb (GtkTreeModel *model, + gint column, + const gchar *key, + GtkTreeIter *iter, + gpointer data) +{ + GeditPluginInfo *info; + gchar *normalized_string; + gchar *normalized_key; + gchar *case_normalized_string; + gchar *case_normalized_key; + gint key_len; + gboolean retval; + + gtk_tree_model_get (model, iter, NAME_COLUMN, &info, -1); + if (!info) + return FALSE; + + normalized_string = g_utf8_normalize (gedit_plugins_engine_get_plugin_name (info), -1, G_NORMALIZE_ALL); + normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL); + case_normalized_string = g_utf8_casefold (normalized_string, -1); + case_normalized_key = g_utf8_casefold (normalized_key, -1); + + key_len = strlen (case_normalized_key); + + /* Oddly enough, this callback must return whether to stop the search + * because we found a match, not whether we actually matched. + */ + retval = (strncmp (case_normalized_key, case_normalized_string, key_len) != 0); + + g_free (normalized_key); + g_free (normalized_string); + g_free (case_normalized_key); + g_free (case_normalized_string); + + return retval; +} + +static void +plugin_manager_construct_tree (GeditPluginManager *pm) +{ + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + GtkListStore *model; + + gedit_debug (DEBUG_PLUGINS); + + model = gtk_list_store_new (N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_POINTER); + + gtk_tree_view_set_model (GTK_TREE_VIEW (pm->priv->tree), GTK_TREE_MODEL (model)); + g_object_unref (model); + + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pm->priv->tree), TRUE); + gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (pm->priv->tree), TRUE); + + /* first column */ + cell = gtk_cell_renderer_toggle_new (); + g_signal_connect (cell, + "toggled", + G_CALLBACK (active_toggled_cb), + pm); + column = gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_ACTIVE_TITLE, + cell, + "active", + ACTIVE_COLUMN, + NULL); + gtk_tree_view_column_set_clickable (column, TRUE); + gtk_tree_view_column_set_resizable (column, TRUE); + g_signal_connect (column, "clicked", G_CALLBACK (column_clicked_cb), pm); + gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column); + + /* second column */ + cell = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_NAME_TITLE, cell, NULL); + gtk_tree_view_column_set_resizable (column, TRUE); + gtk_tree_view_column_set_cell_data_func (column, cell, plugin_manager_view_cell_cb, + pm, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column); + + /* Enable search for our non-string column */ + gtk_tree_view_set_search_column (GTK_TREE_VIEW (pm->priv->tree), NAME_COLUMN); + gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (pm->priv->tree), + name_search_cb, + NULL, + NULL); + + g_signal_connect (pm->priv->tree, + "cursor_changed", + G_CALLBACK (cursor_changed_cb), + pm); + g_signal_connect (pm->priv->tree, + "row_activated", + G_CALLBACK (row_activated_cb), + pm); + + gtk_widget_show (pm->priv->tree); +} + +static void +gedit_plugin_manager_init (GeditPluginManager *pm) +{ + GtkWidget *viewport; + GtkWidget *hbuttonbox; + + gedit_debug (DEBUG_PLUGINS); + + pm->priv = GEDIT_PLUGIN_MANAGER_GET_PRIVATE (pm); + + gtk_box_set_spacing (GTK_BOX (pm), 6); + + viewport = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (viewport), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (viewport), + GTK_SHADOW_IN); + + gtk_box_pack_start (GTK_BOX (pm), viewport, TRUE, TRUE, 0); + + pm->priv->tree = gtk_tree_view_new (); + gtk_container_add (GTK_CONTAINER (viewport), pm->priv->tree); + + hbuttonbox = gtk_hbutton_box_new (); + gtk_box_pack_start (GTK_BOX (pm), hbuttonbox, FALSE, FALSE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (hbuttonbox), 8); + + pm->priv->about_button = gedit_gtk_button_new_with_stock_icon (_("_About Plugin"), + GTK_STOCK_ABOUT); + gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->about_button); + + pm->priv->configure_button = gedit_gtk_button_new_with_stock_icon (_("C_onfigure Plugin"), + GTK_STOCK_PREFERENCES); + gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->configure_button); + + /* setup a window of a sane size. */ + gtk_widget_set_size_request (GTK_WIDGET (viewport), 270, 100); + + g_signal_connect (pm->priv->about_button, + "clicked", + G_CALLBACK (about_button_cb), + pm); + g_signal_connect (pm->priv->configure_button, + "clicked", + G_CALLBACK (configure_button_cb), + pm); + + plugin_manager_construct_tree (pm); + + /* get the list of available plugins (or installed) */ + pm->priv->plugins = gedit_plugins_engine_get_plugins_list (); + + if (pm->priv->plugins != NULL) + { + plugin_manager_populate_lists (pm); + } + else + { + gtk_widget_set_sensitive (pm->priv->about_button, FALSE); + gtk_widget_set_sensitive (pm->priv->configure_button, FALSE); + } +} + +GtkWidget *gedit_plugin_manager_new (void) +{ + return g_object_new (GEDIT_TYPE_PLUGIN_MANAGER,0); +} diff --git a/gedit/gedit-plugin-manager.h b/gedit/gedit-plugin-manager.h new file mode 100644 index 00000000..0e2e29f4 --- /dev/null +++ b/gedit/gedit-plugin-manager.h @@ -0,0 +1,85 @@ +/* + * gedit-plugin-manager.h + * This file is part of gedit + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_PLUGIN_MANAGER_H__ +#define __GEDIT_PLUGIN_MANAGER_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_PLUGIN_MANAGER (gedit_plugin_manager_get_type()) +#define GEDIT_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManager)) +#define GEDIT_PLUGIN_MANAGER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManager const)) +#define GEDIT_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerClass)) +#define GEDIT_IS_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PLUGIN_MANAGER)) +#define GEDIT_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN_MANAGER)) +#define GEDIT_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerClass)) + +/* Private structure type */ +typedef struct _GeditPluginManagerPrivate GeditPluginManagerPrivate; + +/* + * Main object structure + */ +typedef struct _GeditPluginManager GeditPluginManager; + +struct _GeditPluginManager +{ + GtkVBox vbox; + + /*< private > */ + GeditPluginManagerPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditPluginManagerClass GeditPluginManagerClass; + +struct _GeditPluginManagerClass +{ + GtkVBoxClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_plugin_manager_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_plugin_manager_new (void); + +G_END_DECLS + +#endif /* __GEDIT_PLUGIN_MANAGER_H__ */ diff --git a/gedit/gedit-plugin.c b/gedit/gedit-plugin.c index 2cbc1eee..b9984191 100644 --- a/gedit/gedit-plugin.c +++ b/gedit/gedit-plugin.c @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-plugin.h * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,9 +21,11 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -32,19 +33,80 @@ #endif #include "gedit-plugin.h" -#include "dialogs/gedit-dialogs.h" -gchar* -gedit_plugin_locate_program (const gchar *program_name, - const gchar *plugin_name, - GtkWindow *parent, - const gchar *gconf_key, - const gchar *help_id) +G_DEFINE_TYPE(GeditPlugin, gedit_plugin, G_TYPE_OBJECT) + +static void +dummy (GeditPlugin *plugin, GeditWindow *window) +{ + /* Empty */ +} + +static GtkWidget * +create_configure_dialog (GeditPlugin *plugin) +{ + return NULL; +} + +static void +gedit_plugin_class_init (GeditPluginClass *klass) +{ + klass->activate = dummy; + klass->deactivate = dummy; + klass->update_ui = dummy; + + klass->create_configure_dialog = create_configure_dialog; +} + +static void +gedit_plugin_init (GeditPlugin *plugin) +{ + /* Empty */ +} + +void +gedit_plugin_activate (GeditPlugin *plugin, + GeditWindow *window) { - return gedit_plugin_program_location_dialog (program_name, - plugin_name, - parent, - gconf_key, - help_id); + g_return_if_fail (GEDIT_IS_PLUGIN (plugin)); + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + GEDIT_PLUGIN_GET_CLASS (plugin)->activate (plugin, window); } +void +gedit_plugin_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + g_return_if_fail (GEDIT_IS_PLUGIN (plugin)); + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + GEDIT_PLUGIN_GET_CLASS (plugin)->deactivate (plugin, window); +} + +void +gedit_plugin_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + g_return_if_fail (GEDIT_IS_PLUGIN (plugin)); + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + GEDIT_PLUGIN_GET_CLASS (plugin)->update_ui (plugin, window); +} + +gboolean +gedit_plugin_is_configurable (GeditPlugin *plugin) +{ + g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), FALSE); + + return (GEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog != + create_configure_dialog); +} + +GtkWidget * +gedit_plugin_create_configure_dialog (GeditPlugin *plugin) +{ + g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), NULL); + + return GEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog (plugin); +} diff --git a/gedit/gedit-plugin.h b/gedit/gedit-plugin.h index 8ad74c99..d2fafa62 100644 --- a/gedit/gedit-plugin.h +++ b/gedit/gedit-plugin.h @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-plugin.h * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,59 +21,149 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_PLUGIN_H__ #define __GEDIT_PLUGIN_H__ -#include -#include -#include +#include -typedef enum -{ - PLUGIN_OK, - PLUGIN_ERROR, - PLUGIN_DEAD -} GeditPluginState; +#include + +/* TODO: add a .h file that includes all the .h files normally needed to + * develop a plugin */ + +G_BEGIN_DECLS +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_PLUGIN (gedit_plugin_get_type()) +#define GEDIT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN, GeditPlugin)) +#define GEDIT_PLUGIN_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN, GeditPlugin const)) +#define GEDIT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PLUGIN, GeditPluginClass)) +#define GEDIT_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PLUGIN)) +#define GEDIT_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN)) +#define GEDIT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PLUGIN, GeditPluginClass)) + +/* + * Main object structure + */ typedef struct _GeditPlugin GeditPlugin; -struct _GeditPlugin +struct _GeditPlugin { - gchar *file; - - gchar *location; - GModule *handle; - - /* The following fields are compulsory */ - gchar *name; - gchar *desc; - gchar *author; - gchar *copyright; - - /* The following fields are compulsory */ - GeditPluginState (*init) (GeditPlugin *p); - GeditPluginState (*activate) (GeditPlugin *p); - GeditPluginState (*deactivate) (GeditPlugin *p); - - /* The following fields are optional */ - GeditPluginState (*configure) (GeditPlugin *p, GtkWidget *parent); - GeditPluginState (*update_ui) (GeditPlugin *p, BonoboWindow *w); - GeditPluginState (*destroy) (GeditPlugin *p); - - /* Eventually filled in by the plugin */ - gpointer private_data; -}; + GObject parent; +}; + +/* + * Class definition + */ +typedef struct _GeditPluginClass GeditPluginClass; + +struct _GeditPluginClass +{ + GObjectClass parent_class; + + /* Virtual public methods */ -gchar* gedit_plugin_locate_program (const gchar *program_name, - const gchar *plugin_name, - GtkWindow *parent, - const gchar *gconf_key, - const gchar *help_id); + void (*activate) (GeditPlugin *plugin, + GeditWindow *window); + void (*deactivate) (GeditPlugin *plugin, + GeditWindow *window); + + void (*update_ui) (GeditPlugin *plugin, + GeditWindow *window); + + GtkWidget *(*create_configure_dialog) + (GeditPlugin *plugin); + + /* Padding for future expansion */ + void (*_gedit_reserved1) (void); + void (*_gedit_reserved2) (void); + void (*_gedit_reserved3) (void); + void (*_gedit_reserved4) (void); +}; + +/* + * Public methods + */ +GType gedit_plugin_get_type (void) G_GNUC_CONST; + +void gedit_plugin_activate (GeditPlugin *plugin, + GeditWindow *window); +void gedit_plugin_deactivate (GeditPlugin *plugin, + GeditWindow *window); + +void gedit_plugin_update_ui (GeditPlugin *plugin, + GeditWindow *window); + +gboolean gedit_plugin_is_configurable (GeditPlugin *plugin); +GtkWidget *gedit_plugin_create_configure_dialog + (GeditPlugin *plugin); + +/* + * Utility macro used to register plugins + * + * use: GEDIT_PLUGIN_REGISTER_TYPE(GeditSamplePlugin, gedit_sample_plugin) + */ + +#define GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name) \ + \ +static GType plugin_name##_type = 0; \ + \ +GType \ +plugin_name##_get_type (void) \ +{ \ + return plugin_name##_type; \ +} \ + \ +static void plugin_name##_init (PluginName *self); \ +static void plugin_name##_class_init (PluginName##Class *klass); \ +static gpointer plugin_name##_parent_class = NULL; \ +static void plugin_name##_class_intern_init (gpointer klass) \ +{ \ + plugin_name##_parent_class = g_type_class_peek_parent (klass); \ + plugin_name##_class_init ((PluginName##Class *) klass); \ +} \ + \ +G_MODULE_EXPORT GType \ +register_gedit_plugin (GTypeModule *module) \ +{ \ + static const GTypeInfo our_info = \ + { \ + sizeof (PluginName##Class), \ + NULL, /* base_init */ \ + NULL, /* base_finalize */ \ + (GClassInitFunc) plugin_name##_class_intern_init, \ + NULL, \ + NULL, /* class_data */ \ + sizeof (PluginName), \ + 0, /* n_preallocs */ \ + (GInstanceInitFunc) plugin_name##_init \ + }; \ + \ + gedit_debug_message (DEBUG_PLUGINS, "Registering " #PluginName); \ + \ + /* Initialise the i18n stuff */ \ + bindtextdomain (GETTEXT_PACKAGE, GEDIT_LOCALEDIR); \ + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); \ + \ + plugin_name##_type = g_type_module_register_type (module, \ + GEDIT_TYPE_PLUGIN, \ + #PluginName, \ + &our_info, \ + 0); \ + return plugin_name##_type; \ +} + + +G_END_DECLS #endif /* __GEDIT_PLUGIN_H__ */ diff --git a/gedit/gedit-plugins-engine.c b/gedit/gedit-plugins-engine.c index e8ee423a..2d61058c 100644 --- a/gedit/gedit-plugins-engine.c +++ b/gedit/gedit-plugins-engine.c @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-plugins-engine.c * This file is part of gedit * - * Copyright (C) 2002-2004 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 @@ -22,9 +21,11 @@ */ /* - * Modified by the gedit Team, 2002-2004. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -39,22 +40,51 @@ #include #include "gedit-plugins-engine.h" +#include "gedit-plugin.h" #include "gedit-debug.h" +#include "gedit-app.h" + +#include "gedit-module.h" +#ifdef ENABLE_PYTHON +#include "gedit-python-module.h" +#endif -#define USER_GEDIT_PLUGINS_LOCATION ".gedit-2/plugins/" +#define USER_GEDIT_PLUGINS_LOCATION "gedit/plugins/" #define GEDIT_PLUGINS_ENGINE_BASE_KEY "/apps/gedit-2/plugins" #define GEDIT_PLUGINS_ENGINE_KEY GEDIT_PLUGINS_ENGINE_BASE_KEY "/active-plugins" -#define SOEXT ("." G_MODULE_SUFFIX) -#define SOEXT_LEN (strlen (SOEXT)) #define PLUGIN_EXT ".gedit-plugin" +typedef enum +{ + GEDIT_PLUGIN_LOADER_C, + GEDIT_PLUGIN_LOADER_PY, +} GeditPluginLang; + +struct _GeditPluginInfo +{ + gchar *file; + + gchar *location; + GeditPluginLang lang; + GTypeModule *module; + + gchar *name; + gchar *desc; + gchar **authors; + gchar *copyright; + gchar *website; + + GeditPlugin *plugin; + + gboolean active; +}; -static void gedit_plugins_engine_active_plugins_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); +static void gedit_plugins_engine_active_plugins_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); static GList *gedit_plugins_list = NULL; @@ -62,19 +92,19 @@ static GConfClient *gedit_plugins_engine_gconf_client = NULL; GSList *active_plugins = NULL; -static GeditPlugin * +static GeditPluginInfo * gedit_plugins_engine_load (const gchar *file) { - GeditPlugin *plugin; + GeditPluginInfo *info; GKeyFile *plugin_file = NULL; gchar *str; g_return_val_if_fail (file != NULL, NULL); - gedit_debug (DEBUG_PLUGINS, "Loading plugin: %s", file); + gedit_debug_message (DEBUG_PLUGINS, "Loading plugin: %s", file); - plugin = g_new0 (GeditPlugin, 1); - plugin->file = g_strdup (file); + info = g_new0 (GeditPluginInfo, 1); + info->file = g_strdup (file); plugin_file = g_key_file_new (); if (!g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL)) @@ -83,20 +113,61 @@ gedit_plugins_engine_load (const gchar *file) goto error; } + if (!g_key_file_has_key (plugin_file, + "Gedit Plugin", + "IAge", + NULL)) + { + gedit_debug_message (DEBUG_PLUGINS, + "IAge key does not exist in file: %s", file); + goto error; + } + + /* Check IAge=2 */ + if (g_key_file_get_integer (plugin_file, + "Gedit Plugin", + "IAge", + NULL) != 2) + { + gedit_debug_message (DEBUG_PLUGINS, + "Wrong IAge in file: %s", file); + goto error; + } + /* Get Location */ str = g_key_file_get_string (plugin_file, "Gedit Plugin", - "Location", + "Module", NULL); if (str) { - plugin->location = str; + info->location = str; } else { - g_warning ("Could not find 'Location' in %s", file); + g_warning ("Could not find 'Module' in %s", file); + goto error; + } + + /* Get the loader for this plugin */ + str = g_key_file_get_string (plugin_file, + "Gedit Plugin", + "Loader", + NULL); + if (str && strcmp(str, "python") == 0) + { + info->lang = GEDIT_PLUGIN_LOADER_PY; +#ifndef ENABLE_PYTHON + g_warning ("Cannot load python extension '%s', gedit was not " + "compiled with python support", file); goto error; +#endif } + else + { + info->lang = GEDIT_PLUGIN_LOADER_C; + } + g_free (str); /* Get Name */ str = g_key_file_get_locale_string (plugin_file, @@ -104,9 +175,7 @@ gedit_plugins_engine_load (const gchar *file) "Name", NULL, NULL); if (str) - { - plugin->name = str; - } + info->name = str; else { g_warning ("Could not find 'Name' in %s", file); @@ -119,57 +188,50 @@ gedit_plugins_engine_load (const gchar *file) "Description", NULL, NULL); if (str) - { - plugin->desc = str; - } + info->desc = str; else - { - g_warning ("Could not find 'Description' in %s", file); - goto error; - } + gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Description' in %s", file); + - /* Get Author */ + /* Get Authors */ + info->authors = g_key_file_get_string_list (plugin_file, + "Gedit Plugin", + "Authors", + NULL, + NULL); + if (info->authors == NULL) + gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Authors' in %s", file); + + + /* Get Copyright */ str = g_key_file_get_string (plugin_file, "Gedit Plugin", - "Author", + "Copyright", NULL); if (str) - { - plugin->author = str; - } + info->copyright = str; else - { - g_warning ("Could not find 'Author' in %s", file); - goto error; - } + gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Copyright' in %s", file); /* Get Copyright */ str = g_key_file_get_string (plugin_file, "Gedit Plugin", - "Copyright", + "Website", NULL); if (str) - { - plugin->copyright = str; - } + info->website = str; else - { - g_warning ("Could not find 'Copyright' in %s", file); - goto error; - } - + gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Website' in %s", file); + g_key_file_free (plugin_file); - - return plugin; + + return info; error: - g_free (plugin->file); - g_free (plugin->location); - g_free (plugin->name); - g_free (plugin->desc); - g_free (plugin->author); - g_free (plugin->copyright); - g_free (plugin); + g_free (info->file); + g_free (info->location); + g_free (info->name); + g_free (info); g_key_file_free (plugin_file); return NULL; @@ -184,12 +246,12 @@ gedit_plugins_engine_load_dir (const gchar *dir) g_return_if_fail (gedit_plugins_engine_gconf_client != NULL); - gedit_debug (DEBUG_PLUGINS, "DIR: %s", dir); + gedit_debug_message (DEBUG_PLUGINS, "DIR: %s", dir); d = g_dir_open (dir, 0, &error); if (!d) { - gedit_debug (DEBUG_PLUGINS, "%s", error->message); + g_warning (error->message); g_error_free (error); return; } @@ -199,35 +261,24 @@ gedit_plugins_engine_load_dir (const gchar *dir) if (g_str_has_suffix (dirent, PLUGIN_EXT)) { gchar *plugin_file; - GeditPlugin *plugin; GeditPluginInfo *info; - gboolean to_be_activated; - + plugin_file = g_build_filename (dir, dirent, NULL); - plugin = gedit_plugins_engine_load (plugin_file); + info = gedit_plugins_engine_load (plugin_file); g_free (plugin_file); - if (plugin == NULL) + if (info == NULL) continue; - info = g_new0 (GeditPluginInfo, 1); - info->plugin = plugin; - - to_be_activated = (g_slist_find_custom (active_plugins, - plugin->location, - (GCompareFunc)strcmp) != NULL); - /* Actually, the plugin will be activated when reactivate_all - * will be called for the first time. - * */ - if (to_be_activated) - info->state = GEDIT_PLUGIN_ACTIVATED; - else - info->state = GEDIT_PLUGIN_DEACTIVATED; + * will be called for the first time. */ + info->active = (g_slist_find_custom (active_plugins, + info->location, + (GCompareFunc)strcmp) != NULL); gedit_plugins_list = g_list_prepend (gedit_plugins_list, info); - gedit_debug (DEBUG_PLUGINS, "Plugin %s loaded", plugin->name); + gedit_debug_message (DEBUG_PLUGINS, "Plugin %s loaded", info->name); } } @@ -239,17 +290,15 @@ gedit_plugins_engine_load_dir (const gchar *dir) static void gedit_plugins_engine_load_all (void) { - gchar const *home = g_get_home_dir (); + gchar *pdir; - /* load user's plugins */ - if (home != NULL) - { - gchar *pdir; + pdir = gnome_util_home_file (USER_GEDIT_PLUGINS_LOCATION); - pdir = gnome_util_prepend_user_home (USER_GEDIT_PLUGINS_LOCATION); + /* load user's plugins */ + if (g_file_test (pdir, G_FILE_TEST_IS_DIR)) gedit_plugins_engine_load_dir (pdir); - g_free (pdir); - } + + g_free (pdir); /* load system plugins */ gedit_plugins_engine_load_dir (GEDIT_PLUGINDIR "/"); @@ -258,10 +307,15 @@ gedit_plugins_engine_load_all (void) gboolean gedit_plugins_engine_init (void) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); + + g_return_val_if_fail (gedit_plugins_list == NULL, FALSE); if (!g_module_supported ()) + { + g_warning ("gedit is not able to initialize the plugins engine."); return FALSE; + } gedit_plugins_engine_gconf_client = gconf_client_get_default (); g_return_val_if_fail (gedit_plugins_engine_gconf_client != NULL, FALSE); @@ -292,7 +346,7 @@ gedit_plugins_engine_shutdown (void) { GList *pl; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); g_return_if_fail (gedit_plugins_engine_gconf_client != NULL); @@ -300,32 +354,24 @@ gedit_plugins_engine_shutdown (void) { GeditPluginInfo *info = (GeditPluginInfo*)pl->data; - if (info->plugin->destroy != NULL) + if (info->plugin != NULL) { - gint r; - gedit_debug (DEBUG_PLUGINS, "Destroy plugin %s", info->plugin->name); + gedit_debug_message (DEBUG_PLUGINS, "Unref plugin %s", info->name); - r = info->plugin->destroy (info->plugin); + g_object_unref (info->plugin); - if (r != PLUGIN_OK) - { - g_warning ("Error, impossible to destroy plugin '%s'", - info->plugin->name); - } + /* info->module must not be unref since it is not possible to finalize + * a type module */ } - if (info->plugin->handle != NULL) - g_module_close (info->plugin->handle); - - g_free (info->plugin->file); - g_free (info->plugin->location); - g_free (info->plugin->name); - g_free (info->plugin->desc); - g_free (info->plugin->author); - g_free (info->plugin->copyright); - - g_free (info->plugin); - + g_free (info->file); + g_free (info->location); + g_free (info->name); + g_free (info->desc); + g_free (info->website); + g_free (info->copyright); + g_strfreev (info->authors); + g_free (info); } @@ -344,184 +390,141 @@ gedit_plugins_engine_shutdown (void) const GList * gedit_plugins_engine_get_plugins_list (void) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); return gedit_plugins_list; } -static GeditPluginInfo * -gedit_plugins_engine_find_plugin_info (GeditPlugin *plugin) -{ - GList *pl; - - gedit_debug (DEBUG_PLUGINS, ""); - - for (pl = gedit_plugins_list; pl; pl = pl->next) - { - GeditPluginInfo *info = (GeditPluginInfo*)pl->data; - - if (info->plugin == plugin) - return info; - } - - return NULL; -} - static gboolean -load_plugin_module (GeditPlugin *plugin) +load_plugin_module (GeditPluginInfo *info) { gchar *path; gchar *dirname; - gint res; - - g_return_val_if_fail (plugin != NULL, FALSE); - g_return_val_if_fail (plugin->file != NULL, FALSE); - g_return_val_if_fail (plugin->location != NULL, FALSE); - dirname = g_path_get_dirname (plugin->file); - g_return_val_if_fail (dirname != NULL, FALSE); - - path = g_module_build_path (dirname, plugin->location); - g_free (dirname); - g_return_val_if_fail (path != NULL, FALSE); - - plugin->handle = g_module_open (path, G_MODULE_BIND_LAZY); - g_free (path); + gedit_debug (DEBUG_PLUGINS); - if (plugin->handle == NULL) - { - g_warning ("Error, unable to open module file '%s'\n", - g_module_error ()); - - return FALSE; - } + g_return_val_if_fail (info != NULL, FALSE); + g_return_val_if_fail (info->file != NULL, FALSE); + g_return_val_if_fail (info->location != NULL, FALSE); + g_return_val_if_fail (info->plugin == NULL, FALSE); - /* Load "init" symbol */ - if (!g_module_symbol (plugin->handle, "init", - (gpointer*)&plugin->init)) + switch (info->lang) { - g_warning ("Error, plugin '%s' does not contain init function.", - plugin->name); + case GEDIT_PLUGIN_LOADER_C: + dirname = g_path_get_dirname (info->file); + g_return_val_if_fail (dirname != NULL, FALSE); - goto error_2; + path = g_module_build_path (dirname, info->location); + g_free (dirname); + g_return_val_if_fail (path != NULL, FALSE); + + info->module = G_TYPE_MODULE (gedit_module_new (path)); + g_free (path); + break; +#ifdef ENABLE_PYTHON + case GEDIT_PLUGIN_LOADER_PY: + { + gchar *dir = g_path_get_dirname (info->file); + + info->module = G_TYPE_MODULE ( + gedit_python_module_new (dir, info->location)); + + g_free (dir); + break; + } +#endif } - /* Load "activate" symbol */ - if (!g_module_symbol (plugin->handle, "activate", - (gpointer*)&plugin->activate)) + + if (g_type_module_use (info->module) == FALSE) { - g_warning ("Error, plugin '%s' does not contain activate function.", - plugin->name); + switch (info->lang) + { + case GEDIT_PLUGIN_LOADER_C: + g_warning ("Could not load plugin file at %s\n", + gedit_module_get_path (GEDIT_MODULE (info->module))); + break; + case GEDIT_PLUGIN_LOADER_PY: + g_warning ("Could not load python module %s\n", info->location); + break; + } + + g_object_unref (G_OBJECT (info->module)); + info->module = NULL; - goto error_2; + return FALSE; } - - /* Load "deactivate" symbol */ - if (!g_module_symbol (plugin->handle, "deactivate", - (gpointer*)&plugin->deactivate)) + + switch (info->lang) { - g_warning ("Error, plugin '%s' does not contain deactivate function.", - plugin->name); - - goto error_2; + case GEDIT_PLUGIN_LOADER_C: + info->plugin = GEDIT_PLUGIN (gedit_module_new_object (GEDIT_MODULE (info->module))); + break; +#ifdef ENABLE_PYTHON + case GEDIT_PLUGIN_LOADER_PY: + info->plugin = GEDIT_PLUGIN (gedit_python_module_new_object (GEDIT_PYTHON_MODULE (info->module))); + break; +#endif } - - /* Load "configure" symbol */ - if (!g_module_symbol (plugin->handle, "configure", - (gpointer*)&plugin->configure)) - plugin->configure = NULL; - - /* Load "update_ui" symbol */ - if (!g_module_symbol (plugin->handle, "update_ui", - (gpointer*)&plugin->update_ui)) - plugin->update_ui = NULL; - - /* Load "destroy" symbol */ - if (!g_module_symbol (plugin->handle, "destroy", - (gpointer*)&plugin->destroy)) - plugin->destroy = NULL; - /* Initialize plugin */ - res = plugin->init (plugin); - if (res != PLUGIN_OK) - { - g_warning ("Error, impossible to initialize plugin '%s'", - plugin->name); - - goto error_2; - } + g_type_module_unuse (info->module); - return TRUE; - -error_2: - g_module_close (plugin->handle); - - plugin->handle = NULL; + gedit_debug_message (DEBUG_PLUGINS, "End"); - plugin->init = NULL; - plugin->activate = NULL; - plugin->deactivate = NULL; - - plugin->update_ui = NULL; - plugin->destroy = NULL; - plugin->configure = NULL; - - return FALSE; + return TRUE; } static gboolean -gedit_plugins_engine_activate_plugin_real (GeditPlugin *plugin) +gedit_plugins_engine_activate_plugin_real (GeditPluginInfo *info) { gboolean res = TRUE; - gint r = PLUGIN_OK; - if (plugin->handle == NULL) - res = load_plugin_module (plugin); + if (info->plugin == NULL) + res = load_plugin_module (info); if (res) - r = plugin->activate (plugin); - - if (!res || (r != PLUGIN_OK)) { - g_warning ("Error, impossible to activate plugin '%s'", - plugin->name); - - return FALSE; + const GList *wins = gedit_app_get_windows (gedit_app_get_default ()); + while (wins != NULL) + { + gedit_plugin_activate (info->plugin, + GEDIT_WINDOW (wins->data)); + + wins = g_list_next (wins); + } } + else + g_warning ("Error, impossible to activate plugin '%s'", + info->name); - return TRUE; + return res; } gboolean -gedit_plugins_engine_activate_plugin (GeditPlugin *plugin) +gedit_plugins_engine_activate_plugin (GeditPluginInfo *info) { - GeditPluginInfo *info; - - gedit_debug (DEBUG_PLUGINS, ""); - - g_return_val_if_fail (plugin != NULL, FALSE); + gedit_debug (DEBUG_PLUGINS); - info = gedit_plugins_engine_find_plugin_info (plugin); g_return_val_if_fail (info != NULL, FALSE); - if (info->state == GEDIT_PLUGIN_ACTIVATED) + if (info->active) return TRUE; - if (gedit_plugins_engine_activate_plugin_real (plugin)) + if (gedit_plugins_engine_activate_plugin_real (info)) { gboolean res; GSList *list; /* Update plugin state */ - info->state = GEDIT_PLUGIN_ACTIVATED; + info->active = TRUE; /* I want to be really sure :) */ list = active_plugins; while (list != NULL) { - if (strcmp (plugin->location, (gchar *)list->data) == 0) + if (strcmp (info->location, (gchar *)list->data) == 0) { - g_warning ("Plugin %s is already activated.", plugin->location); + g_warning ("Plugin %s is already active.", info->location); return TRUE; } @@ -529,7 +532,7 @@ gedit_plugins_engine_activate_plugin (GeditPlugin *plugin) } active_plugins = g_slist_insert_sorted (active_plugins, - g_strdup (plugin->location), + g_strdup (info->location), (GCompareFunc)strcmp); res = gconf_client_set_list (gedit_plugins_engine_gconf_client, @@ -547,161 +550,175 @@ gedit_plugins_engine_activate_plugin (GeditPlugin *plugin) return FALSE; } -static gboolean -gedit_plugins_engine_deactivate_plugin_real (GeditPlugin *plugin) +static void +gedit_plugins_engine_deactivate_plugin_real (GeditPluginInfo *info) { - gint res; + const GList *wins = gedit_app_get_windows (gedit_app_get_default ()); - res = plugin->deactivate (plugin); - - if (res != PLUGIN_OK) + while (wins != NULL) { - g_warning ("Error, impossible to deactivate plugin '%s'", - plugin->name); - - return FALSE; + gedit_plugin_deactivate (info->plugin, + GEDIT_WINDOW (wins->data)); + + wins = g_list_next (wins); } - - return TRUE; } gboolean -gedit_plugins_engine_deactivate_plugin (GeditPlugin *plugin) +gedit_plugins_engine_deactivate_plugin (GeditPluginInfo *info) { - GeditPluginInfo *info; - - gedit_debug (DEBUG_PLUGINS, ""); - - g_return_val_if_fail (plugin != NULL, FALSE); + gboolean res; + GSList *list; + + gedit_debug (DEBUG_PLUGINS); - info = gedit_plugins_engine_find_plugin_info (plugin); g_return_val_if_fail (info != NULL, FALSE); - if (info->state == GEDIT_PLUGIN_DEACTIVATED) + if (!info->active) return TRUE; - if (gedit_plugins_engine_deactivate_plugin_real (plugin)) - { - gboolean res; - GSList *list; - - /* Update plugin state */ - info->state = GEDIT_PLUGIN_DEACTIVATED; + gedit_plugins_engine_deactivate_plugin_real (info); - list = active_plugins; - res = (list == NULL); + /* Update plugin state */ + info->active = FALSE; - while (list != NULL) - { - if (strcmp (plugin->location, (gchar *)list->data) == 0) - { - g_free (list->data); - active_plugins = g_slist_delete_link (active_plugins, list); - list = NULL; - res = TRUE; - } - else - list = g_slist_next (list); - } + list = active_plugins; + res = (list == NULL); - if (!res) + while (list != NULL) + { + if (strcmp (info->location, (gchar *)list->data) == 0) { - g_warning ("Plugin %s is already deactivated.", plugin->location); - return TRUE; + g_free (list->data); + active_plugins = g_slist_delete_link (active_plugins, list); + list = NULL; + res = TRUE; } + else + list = g_slist_next (list); + } - res = gconf_client_set_list (gedit_plugins_engine_gconf_client, - GEDIT_PLUGINS_ENGINE_KEY, - GCONF_VALUE_STRING, - active_plugins, - NULL); - - if (!res) - g_warning ("Error saving the list of active plugins."); - + if (!res) + { + g_warning ("Plugin %s is already deactivated.", info->location); return TRUE; } - return FALSE; + res = gconf_client_set_list (gedit_plugins_engine_gconf_client, + GEDIT_PLUGINS_ENGINE_KEY, + GCONF_VALUE_STRING, + active_plugins, + NULL); + + if (!res) + g_warning ("Error saving the list of active plugins."); + + return TRUE; +} + +gboolean +gedit_plugins_engine_plugin_is_active (GeditPluginInfo *info) +{ + g_return_val_if_fail (info != NULL, FALSE); + + return info->active; } static void -gedit_plugins_engine_reactivate_all (void) +reactivate_all (GeditWindow *window) { GList *pl; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); for (pl = gedit_plugins_list; pl; pl = pl->next) { + gboolean res = TRUE; + GeditPluginInfo *info = (GeditPluginInfo*)pl->data; - if (info->state == GEDIT_PLUGIN_ACTIVATED) + if ((info->plugin == NULL) && info->active) + res = load_plugin_module (info); + + if (info->active && res) { - if (!gedit_plugins_engine_activate_plugin_real (info->plugin)) - info->state = GEDIT_PLUGIN_DEACTIVATED; + gedit_plugin_activate (info->plugin, + window); } } + + gedit_debug_message (DEBUG_PLUGINS, "End"); } void -gedit_plugins_engine_update_plugins_ui (BonoboWindow* window, gboolean new_window) +gedit_plugins_engine_update_plugins_ui (GeditWindow *window, + gboolean new_window) { GList *pl; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); - g_return_if_fail (window != NULL); - g_return_if_fail (BONOBO_IS_WINDOW (window)); + g_return_if_fail (GEDIT_IS_WINDOW (window)); if (new_window) - gedit_plugins_engine_reactivate_all (); + reactivate_all (window); /* updated ui of all the plugins that implement update_ui */ for (pl = gedit_plugins_list; pl; pl = pl->next) { - gint r; GeditPluginInfo *info = (GeditPluginInfo*)pl->data; - if ((info->state != GEDIT_PLUGIN_ACTIVATED) || - (info->plugin->update_ui == NULL)) + if (!info->active) continue; - - gedit_debug (DEBUG_PLUGINS, "Updating UI of %s", info->plugin->name); - - r = info->plugin->update_ui (info->plugin, window); - if (r != PLUGIN_OK) - { - g_warning ("Error, impossible to update ui of the plugin '%s'", - info->plugin->name); - } + + gedit_debug_message (DEBUG_PLUGINS, "Updating UI of %s", info->name); + + gedit_plugin_update_ui (info->plugin, window); } } gboolean -gedit_plugins_engine_is_a_configurable_plugin (GeditPlugin *plugin) +gedit_plugins_engine_plugin_is_configurable (GeditPluginInfo *info) { - GeditPluginInfo *info; + gedit_debug (DEBUG_PLUGINS); - gedit_debug (DEBUG_PLUGINS, ""); - - g_return_val_if_fail (plugin != NULL, FALSE); - - info = gedit_plugins_engine_find_plugin_info (plugin); g_return_val_if_fail (info != NULL, FALSE); - return (plugin->configure != NULL) && (info->state == GEDIT_PLUGIN_ACTIVATED); + if ((info->plugin == NULL) || !info->active) + return FALSE; + + return gedit_plugin_is_configurable (info->plugin); } -gboolean -gedit_plugins_engine_configure_plugin (GeditPlugin *plugin, GtkWidget* parent) +void +gedit_plugins_engine_configure_plugin (GeditPluginInfo *info, + GtkWindow *parent) { - gedit_debug (DEBUG_PLUGINS, ""); + GtkWidget *conf_dlg; + + GtkWindowGroup *wg; + + gedit_debug (DEBUG_PLUGINS); - g_return_val_if_fail (plugin != NULL, FALSE); - g_return_val_if_fail (plugin->configure != NULL, FALSE); + g_return_if_fail (info != NULL); - return (plugin->configure (plugin, parent) == PLUGIN_OK); + conf_dlg = gedit_plugin_create_configure_dialog (info->plugin); + g_return_if_fail (conf_dlg != NULL); + gtk_window_set_transient_for (GTK_WINDOW (conf_dlg), + parent); + + wg = parent->group; + if (wg == NULL) + { + wg = gtk_window_group_new (); + gtk_window_group_add_window (wg, parent); + } + + gtk_window_group_add_window (wg, + GTK_WINDOW (conf_dlg)); + + gtk_window_set_modal (GTK_WINDOW (conf_dlg), TRUE); + gtk_widget_show (conf_dlg); } static void @@ -713,15 +730,16 @@ gedit_plugins_engine_active_plugins_changed (GConfClient *client, GList *pl; gboolean to_activate; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); - if (!((entry->value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (entry->value) == GCONF_VALUE_STRING))) + if (!((entry->value->type == GCONF_VALUE_LIST) && + (gconf_value_get_list_type (entry->value) == GCONF_VALUE_STRING))) { - g_warning ("You may have a corrupted gconf key: %s", GEDIT_PLUGINS_ENGINE_KEY); + g_warning ("The gconf key '%s' mat be corrupted", GEDIT_PLUGINS_ENGINE_KEY); return; } @@ -735,25 +753,67 @@ gedit_plugins_engine_active_plugins_changed (GConfClient *client, GeditPluginInfo *info = (GeditPluginInfo*)pl->data; to_activate = (g_slist_find_custom (active_plugins, - info->plugin->location, + info->location, (GCompareFunc)strcmp) != NULL); - if ((info->state == GEDIT_PLUGIN_DEACTIVATED) && to_activate) + if (!info->active && to_activate) { /* Activate plugin */ - if (gedit_plugins_engine_activate_plugin_real (info->plugin)) + if (gedit_plugins_engine_activate_plugin_real (info)) /* Update plugin state */ - info->state = GEDIT_PLUGIN_ACTIVATED; + info->active = TRUE; } else { - if ((info->state == GEDIT_PLUGIN_ACTIVATED) && !to_activate) + if (info->active && !to_activate) { - if (gedit_plugins_engine_deactivate_plugin_real (info->plugin)) - /* Update plugin state */ - info->state = GEDIT_PLUGIN_DEACTIVATED; + gedit_plugins_engine_deactivate_plugin_real (info); + + /* Update plugin state */ + info->active = FALSE; } } } } +const gchar * +gedit_plugins_engine_get_plugin_name (GeditPluginInfo *info) +{ + g_return_val_if_fail (info != NULL, NULL); + + return info->name; +} + +const gchar * +gedit_plugins_engine_get_plugin_description (GeditPluginInfo *info) +{ + g_return_val_if_fail (info != NULL, NULL); + + return info->desc; +} + +const gchar ** +gedit_plugins_engine_get_plugin_authors (GeditPluginInfo *info) +{ + g_return_val_if_fail (info != NULL, (const gchar **)NULL); + + return (const gchar **)info->authors; +} + +const gchar * +gedit_plugins_engine_get_plugin_website (GeditPluginInfo *info) +{ + g_return_val_if_fail (info != NULL, NULL); + + return info->website; +} + +const gchar * +gedit_plugins_engine_get_plugin_copyright (GeditPluginInfo *info) +{ + g_return_val_if_fail (info != NULL, NULL); + + return info->copyright; +} + + diff --git a/gedit/gedit-plugins-engine.h b/gedit/gedit-plugins-engine.h index bd392f3f..0abdced9 100644 --- a/gedit/gedit-plugins-engine.h +++ b/gedit/gedit-plugins-engine.h @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-plugins-engine.h * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,46 +21,53 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_PLUGINS_ENGINE_H__ #define __GEDIT_PLUGINS_ENGINE_H__ -#include +#include +#include typedef struct _GeditPluginInfo GeditPluginInfo; -typedef enum { - GEDIT_PLUGIN_ACTIVATED, - GEDIT_PLUGIN_DEACTIVATED -} GeditPluginActivationState; - -struct _GeditPluginInfo -{ - GeditPlugin *plugin; - GeditPluginActivationState state; -}; - gboolean gedit_plugins_engine_init (void); void gedit_plugins_engine_shutdown (void); const GList *gedit_plugins_engine_get_plugins_list (void); -gboolean gedit_plugins_engine_activate_plugin (GeditPlugin *plugin); -gboolean gedit_plugins_engine_deactivate_plugin (GeditPlugin *plugin); -gboolean gedit_plugins_engine_configure_plugin (GeditPlugin *plugin, GtkWidget* parent); +gboolean gedit_plugins_engine_activate_plugin (GeditPluginInfo *info); +gboolean gedit_plugins_engine_deactivate_plugin (GeditPluginInfo *info); +gboolean gedit_plugins_engine_plugin_is_active (GeditPluginInfo *info); +gboolean gedit_plugins_engine_plugin_is_configurable + (GeditPluginInfo *info); +void gedit_plugins_engine_configure_plugin (GeditPluginInfo *info, + GtkWindow *parent); /* * new_window == TRUE if this function is called because a new top window * has been created */ -void gedit_plugins_engine_update_plugins_ui (BonoboWindow *window, gboolean new_window); +void gedit_plugins_engine_update_plugins_ui (GeditWindow *window, + gboolean new_window); + + +const gchar *gedit_plugins_engine_get_plugin_name (GeditPluginInfo *info); +const gchar *gedit_plugins_engine_get_plugin_description + (GeditPluginInfo *info); -gboolean gedit_plugins_engine_is_a_configurable_plugin (GeditPlugin *plugin); +const gchar **gedit_plugins_engine_get_plugin_authors + (GeditPluginInfo *info); +const gchar *gedit_plugins_engine_get_plugin_website + (GeditPluginInfo *info); +const gchar *gedit_plugins_engine_get_plugin_copyright + (GeditPluginInfo *info); #endif /* __GEDIT_PLUGINS_ENGINE_H__ */ diff --git a/gedit/gedit-prefs-manager-app.c b/gedit/gedit-prefs-manager-app.c index 516cf4b5..f85b15c0 100644 --- a/gedit/gedit-prefs-manager-app.c +++ b/gedit/gedit-prefs-manager-app.c @@ -3,7 +3,7 @@ * gedit-prefs-manager.c * This file is part of gedit * - * Copyright (C) 2002-2003 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 @@ -24,7 +24,9 @@ /* * Modified by the gedit Team, 2002-2003. See the AUTHORS file for a * list of people on the gedit Team. - * See the ChangeLog files for a list of changes. + * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -38,75 +40,87 @@ #include "gedit-prefs-manager.h" #include "gedit-prefs-manager-private.h" #include "gedit-prefs-manager-app.h" +#include "gedit-app.h" #include "gedit-debug.h" #include "gedit-view.h" -#include "gedit-mdi.h" +#include "gedit-window.h" #include "gedit-recent.h" -#include "gedit2.h" -#include - -static void gedit_prefs_manager_editor_font_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); - -static void gedit_prefs_manager_editor_colors_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_tabs_size_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_wrap_mode_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_line_numbers_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_auto_indent_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_undo_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_right_margin_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_hl_current_line_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_bracket_matching_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_syntax_hl_enable_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_max_recents_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); -static void gedit_prefs_manager_auto_save_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); + +static void gedit_prefs_manager_editor_font_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_editor_colors_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_tabs_size_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_wrap_mode_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_line_numbers_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_auto_indent_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_undo_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_right_margin_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_hl_current_line_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_bracket_matching_changed(GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_syntax_hl_enable_changed(GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_max_recents_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + +static void gedit_prefs_manager_auto_save_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); + static gint window_state = -1; static gint window_height = -1; static gint window_width = -1; - +static gint side_panel_size = -1; +static gint bottom_panel_size = -1; gboolean gedit_prefs_manager_app_init (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (gedit_prefs_manager == NULL, FALSE); @@ -134,12 +148,12 @@ gedit_prefs_manager_app_init (void) GPM_TABS_DIR, gedit_prefs_manager_tabs_size_changed, NULL, NULL, NULL); - + gconf_client_notify_add (gedit_prefs_manager->gconf_client, GPM_WRAP_MODE_DIR, gedit_prefs_manager_wrap_mode_changed, NULL, NULL, NULL); - + gconf_client_notify_add (gedit_prefs_manager->gconf_client, GPM_LINE_NUMBERS_DIR, gedit_prefs_manager_line_numbers_changed, @@ -193,16 +207,16 @@ gedit_prefs_manager_app_init (void) void gedit_prefs_manager_app_shutdown () { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); gedit_prefs_manager_shutdown (); gnome_config_sync (); } - /* Window state */ -gint gedit_prefs_manager_get_window_state (void) +gint +gedit_prefs_manager_get_window_state (void) { if (window_state == -1) window_state = gnome_config_get_int (GPM_WINDOW_STATE "=" GPM_DEFAULT_WINDOW_STATE_STR); @@ -213,7 +227,7 @@ gint gedit_prefs_manager_get_window_state (void) void gedit_prefs_manager_set_window_state (gint ws) { - g_return_if_fail (ws != -1); + g_return_if_fail (ws > -1); window_state = ws; gnome_config_set_int (GPM_WINDOW_STATE, ws); @@ -235,16 +249,16 @@ gedit_prefs_manager_get_window_height (void) return window_height; } - gint gedit_prefs_manager_get_default_window_height (void) { return GPM_DEFAULT_WINDOW_HEIGHT; } -void gedit_prefs_manager_set_window_height (gint wh) +void +gedit_prefs_manager_set_window_height (gint wh) { - g_return_if_fail (wh != -1); + g_return_if_fail (wh > -1); window_height = wh; gnome_config_set_int (GPM_WINDOW_HEIGHT, wh); @@ -275,7 +289,7 @@ gedit_prefs_manager_get_default_window_width (void) void gedit_prefs_manager_set_window_width (gint ww) { - g_return_if_fail (ww != -1); + g_return_if_fail (ww > -1); window_width = ww; gnome_config_set_int (GPM_WINDOW_WIDTH, ww); @@ -287,38 +301,87 @@ gedit_prefs_manager_window_width_can_set (void) return TRUE; } -void -gedit_prefs_manager_save_window_size_and_state (BonoboWindow *window) +/* Side panel size */ +gint +gedit_prefs_manager_get_side_panel_size (void) { - const BonoboMDIWindowInfo *window_info; + if (side_panel_size == -1) + side_panel_size = gnome_config_get_int (GPM_SIDE_PANEL_SIZE "=" GPM_DEFAULT_SIDE_PANEL_SIZE_STR); - gedit_debug (DEBUG_PREFS, ""); - - g_return_if_fail (window != NULL); - g_return_if_fail (BONOBO_IS_WINDOW (window)); + return side_panel_size; +} - window_info = bonobo_mdi_get_window_info (window); - g_return_if_fail (window_info != NULL); +gint +gedit_prefs_manager_get_default_side_panel_size (void) +{ + return GPM_DEFAULT_SIDE_PANEL_SIZE; +} + +void +gedit_prefs_manager_set_side_panel_size (gint ps) +{ + g_return_if_fail (ps > -1); - if (gedit_prefs_manager_window_height_can_set ()) - gedit_prefs_manager_set_window_height (window_info->height); + if (side_panel_size == ps) + return; + + side_panel_size = ps; + gnome_config_set_int (GPM_SIDE_PANEL_SIZE, ps); +} + +gboolean +gedit_prefs_manager_side_panel_size_can_set (void) +{ + return TRUE; +} + +/* Bottom panel size */ +gint +gedit_prefs_manager_get_bottom_panel_size (void) +{ + if (bottom_panel_size == -1) + bottom_panel_size = gnome_config_get_int (GPM_BOTTOM_PANEL_SIZE "=" GPM_DEFAULT_BOTTOM_PANEL_SIZE_STR); - if (gedit_prefs_manager_window_width_can_set ()) - gedit_prefs_manager_set_window_width (window_info->width); + return bottom_panel_size; +} - if (gedit_prefs_manager_window_state_can_set ()) - gedit_prefs_manager_set_window_state (window_info->state); +gint +gedit_prefs_manager_get_default_bottom_panel_size (void) +{ + return GPM_DEFAULT_BOTTOM_PANEL_SIZE; +} + +void +gedit_prefs_manager_set_bottom_panel_size (gint ps) +{ + g_return_if_fail (ps > -1); + + if (bottom_panel_size == ps) + return; + + bottom_panel_size = ps; + gnome_config_set_int (GPM_BOTTOM_PANEL_SIZE, ps); +} + +gboolean +gedit_prefs_manager_bottom_panel_size_can_set (void) +{ + return TRUE; } static void gedit_prefs_manager_editor_font_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - GList *children; + GList *views; + GList *l; gchar *font = NULL; gboolean def = TRUE; - - gedit_debug (DEBUG_PREFS, ""); + gint ts; + + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -344,81 +407,76 @@ gedit_prefs_manager_editor_font_changed (GConfClient *client, } else return; - + if ((font == NULL) && !def) font = gedit_prefs_manager_get_editor_font (); - - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); - while (children != NULL) - { - gint ts; - - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + ts = gedit_prefs_manager_get_tabs_size (); - ts = gedit_prefs_manager_get_tabs_size (); - while (views != NULL) - { - GeditView *v = GEDIT_VIEW (views->data); - - gedit_view_set_font (v, def, font); - gedit_view_set_tab_size (v, ts); + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; - views = views->next; - } - - children = children->next; + while (l != NULL) + { + gedit_view_set_font (GEDIT_VIEW (l->data), + def, + font); + gtk_source_view_set_tabs_width (GTK_SOURCE_VIEW (l->data), + ts); + + l = l->next; } - if (font != NULL) - g_free (font); + g_list_free (views); + g_free (font); } - static void -set_colors (gboolean def, GdkColor* backgroud, GdkColor* text, - GdkColor* selection, GdkColor* sel_text) +set_colors (gboolean def, + GdkColor *backgroud, + GdkColor *text, + GdkColor *selection, + GdkColor *sel_text) { - GList *children; + GList *views; + GList *l; - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; - while (children != NULL) + while (l != NULL) { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); - - while (views != NULL) - { - GeditView *v = GEDIT_VIEW (views->data); - - gedit_view_set_colors (v, - def, - backgroud, - text, - selection, - sel_text); - views = views->next; - } - - children = children->next; + gedit_view_set_colors (GEDIT_VIEW (l->data), + def, + backgroud, + text, + selection, + sel_text); + + l = l->next; } + + g_list_free (views); } static void gedit_prefs_manager_editor_colors_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) -{ - gboolean def = TRUE; + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) +{ gchar *str_color; GdkColor color; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); if (strcmp (entry->key, GPM_USE_DEFAULT_COLORS) == 0) { + gboolean def = TRUE; + if (entry->value->type == GCONF_VALUE_BOOL) def = gconf_value_get_bool (entry->value); else @@ -445,6 +503,12 @@ gedit_prefs_manager_editor_colors_changed (GConfClient *client, return; } + if (gedit_prefs_manager_get_use_default_colors ()) + { + set_colors (TRUE, NULL, NULL, NULL, NULL); + return; + } + if (strcmp (entry->key, GPM_BACKGROUND_COLOR) == 0) { if (entry->value->type == GCONF_VALUE_STRING) @@ -452,12 +516,10 @@ gedit_prefs_manager_editor_colors_changed (GConfClient *client, else str_color = g_strdup (GPM_DEFAULT_BACKGROUND_COLOR); - def = gedit_prefs_manager_get_use_default_colors (); - gdk_color_parse (str_color, &color); g_free (str_color); - set_colors (def, &color, NULL, NULL, NULL); + set_colors (FALSE, &color, NULL, NULL, NULL); return; } @@ -469,12 +531,10 @@ gedit_prefs_manager_editor_colors_changed (GConfClient *client, else str_color = g_strdup (GPM_DEFAULT_TEXT_COLOR); - def = gedit_prefs_manager_get_use_default_colors (); - gdk_color_parse (str_color, &color); g_free (str_color); - set_colors (def, NULL, &color, NULL, NULL); + set_colors (FALSE, NULL, &color, NULL, NULL); return; } @@ -486,12 +546,10 @@ gedit_prefs_manager_editor_colors_changed (GConfClient *client, else str_color = g_strdup (GPM_DEFAULT_SELECTION_COLOR); - def = gedit_prefs_manager_get_use_default_colors (); - gdk_color_parse (str_color, &color); g_free (str_color); - set_colors (def, NULL, NULL, &color, NULL); + set_colors (FALSE, NULL, NULL, &color, NULL); return; } @@ -503,12 +561,10 @@ gedit_prefs_manager_editor_colors_changed (GConfClient *client, else str_color = g_strdup (GPM_DEFAULT_SELECTED_TEXT_COLOR); - def = gedit_prefs_manager_get_use_default_colors (); - gdk_color_parse (str_color, &color); g_free (str_color); - set_colors (def, NULL, NULL, NULL, &color); + set_colors (FALSE, NULL, NULL, NULL, &color); return; } @@ -516,10 +572,11 @@ gedit_prefs_manager_editor_colors_changed (GConfClient *client, static void gedit_prefs_manager_tabs_size_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -527,7 +584,8 @@ gedit_prefs_manager_tabs_size_changed (GConfClient *client, if (strcmp (entry->key, GPM_TABS_SIZE) == 0) { gint tabs_size; - GList *children; + GList *views; + GList *l; if (entry->value->type == GCONF_VALUE_INT) tabs_size = gconf_value_get_int (entry->value); @@ -536,55 +594,44 @@ gedit_prefs_manager_tabs_size_changed (GConfClient *client, tabs_size = CLAMP (tabs_size, 1, 24); - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; - while (children != NULL) + while (l != NULL) { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + gtk_source_view_set_tabs_width (GTK_SOURCE_VIEW (l->data), + tabs_size); - while (views != NULL) - { - GeditView *v = GEDIT_VIEW (views->data); - - gedit_view_set_tab_size (v, tabs_size); - - views = views->next; - } - - children = children->next; + l = l->next; } + g_list_free (views); } else if (strcmp (entry->key, GPM_INSERT_SPACES) == 0) { gboolean enable; - - GList *children; + GList *views; + GList *l; if (entry->value->type == GCONF_VALUE_BOOL) enable = gconf_value_get_bool (entry->value); else enable = GPM_DEFAULT_INSERT_SPACES; - - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); - while (children != NULL) + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; + + while (l != NULL) { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + gtk_source_view_set_insert_spaces_instead_of_tabs ( + GTK_SOURCE_VIEW (l->data), + enable); - while (views != NULL) - { - GeditView *v = GEDIT_VIEW (views->data); - - gedit_view_set_insert_spaces_instead_of_tabs (v, enable); - - views = views->next; - } - - children = children->next; + l = l->next; } - } + g_list_free (views); + } } static GtkWrapMode @@ -609,9 +656,11 @@ get_wrap_mode_from_string (const gchar* str) static void gedit_prefs_manager_wrap_mode_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -619,41 +668,37 @@ gedit_prefs_manager_wrap_mode_changed (GConfClient *client, if (strcmp (entry->key, GPM_WRAP_MODE) == 0) { GtkWrapMode wrap_mode; - - GList *children; - + GList *views; + GList *l; + if (entry->value->type == GCONF_VALUE_STRING) wrap_mode = get_wrap_mode_from_string (gconf_value_get_string (entry->value)); else wrap_mode = get_wrap_mode_from_string (GPM_DEFAULT_WRAP_MODE); - - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); - while (children != NULL) + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; + + while (l != NULL) { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (l->data), + wrap_mode); - while (views != NULL) - { - GeditView *v = GEDIT_VIEW (views->data); - - gedit_view_set_wrap_mode (v, wrap_mode); - - views = views->next; - } - - children = children->next; + l = l->next; } - } + g_list_free (views); + } } static void gedit_prefs_manager_line_numbers_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -661,39 +706,36 @@ gedit_prefs_manager_line_numbers_changed (GConfClient *client, if (strcmp (entry->key, GPM_DISPLAY_LINE_NUMBERS) == 0) { gboolean dln; - - GList *children; - + GList *views; + GList *l; + if (entry->value->type == GCONF_VALUE_BOOL) dln = gconf_value_get_bool (entry->value); else dln = GPM_DEFAULT_DISPLAY_LINE_NUMBERS; - - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); - while (children != NULL) + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; + + while (l != NULL) { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW (l->data), + dln); - while (views != NULL) - { - GeditView *v = GEDIT_VIEW (views->data); - - gedit_view_show_line_numbers (v, dln); - - views = views->next; - } - - children = children->next; + l = l->next; } + + g_list_free (views); } } static void gedit_prefs_manager_hl_current_line_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -701,80 +743,73 @@ gedit_prefs_manager_hl_current_line_changed (GConfClient *client, if (strcmp (entry->key, GPM_HIGHLIGHT_CURRENT_LINE) == 0) { gboolean hl; - - GList *children; + GList *views; + GList *l; if (entry->value->type == GCONF_VALUE_BOOL) hl = gconf_value_get_bool (entry->value); else hl = GPM_DEFAULT_HIGHLIGHT_CURRENT_LINE; - - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); - while (children != NULL) + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; + + while (l != NULL) { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + gtk_source_view_set_highlight_current_line (GTK_SOURCE_VIEW (l->data), + hl); - while (views != NULL) - { - GtkSourceView *v = GTK_SOURCE_VIEW ( - gedit_view_get_gtk_text_view (GEDIT_VIEW (views->data))); - - gtk_source_view_set_highlight_current_line (v, hl); - - views = views->next; - } - - children = children->next; + l = l->next; } + + g_list_free (views); } } - static void gedit_prefs_manager_bracket_matching_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); if (strcmp (entry->key, GPM_BRACKET_MATCHING) == 0) { + gboolean enable; GList *docs; GList *l; - gboolean enable; if (entry->value->type == GCONF_VALUE_BOOL) enable = gconf_value_get_bool (entry->value); else enable = GPM_DEFAULT_BRACKET_MATCHING; - docs = gedit_get_open_documents (); - + docs = gedit_app_get_documents (gedit_app_get_default ()); l = docs; + while (l != NULL) { - g_return_if_fail (GTK_IS_SOURCE_BUFFER (l->data)); - gtk_source_buffer_set_check_brackets (GTK_SOURCE_BUFFER (l->data), enable); - - l = g_list_next (l); + l = l->next; } g_list_free (docs); } - } static void gedit_prefs_manager_auto_indent_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -782,40 +817,36 @@ gedit_prefs_manager_auto_indent_changed (GConfClient *client, if (strcmp (entry->key, GPM_AUTO_INDENT) == 0) { gboolean enable; - - GList *children; - + GList *views; + GList *l; + if (entry->value->type == GCONF_VALUE_BOOL) enable = gconf_value_get_bool (entry->value); else enable = GPM_DEFAULT_AUTO_INDENT; - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); - - while (children != NULL) - { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; - while (views != NULL) - { - GeditView *v = GEDIT_VIEW (views->data); - - gedit_view_set_auto_indent (v, enable); + while (l != NULL) + { + gtk_source_view_set_auto_indent (GTK_SOURCE_VIEW (l->data), + enable); - views = views->next; - } - - children = children->next; + l = l->next; } + + g_list_free (views); } } static void gedit_prefs_manager_undo_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -825,7 +856,7 @@ gedit_prefs_manager_undo_changed (GConfClient *client, gint ul; GList *docs; GList *l; - + if (entry->value->type == GCONF_VALUE_INT) ul = gconf_value_get_int (entry->value); else @@ -833,15 +864,15 @@ gedit_prefs_manager_undo_changed (GConfClient *client, ul = CLAMP (ul, -1, 250); - docs = gedit_get_open_documents (); + docs = gedit_app_get_documents (gedit_app_get_default ()); l = docs; + while (l != NULL) { - GeditDocument *d = GEDIT_DOCUMENT (l->data); + gtk_source_buffer_set_max_undo_levels (GTK_SOURCE_BUFFER (l->data), + ul); - gedit_document_set_max_undo_levels (d, ul); - - l = g_list_next (l); + l = l->next; } g_list_free (docs); @@ -850,10 +881,11 @@ gedit_prefs_manager_undo_changed (GConfClient *client, static void gedit_prefs_manager_right_margin_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -861,95 +893,81 @@ gedit_prefs_manager_right_margin_changed (GConfClient *client, if (strcmp (entry->key, GPM_RIGHT_MARGIN_POSITION) == 0) { gint pos; - GList *children; - + GList *views; + GList *l; + if (entry->value->type == GCONF_VALUE_INT) pos = gconf_value_get_int (entry->value); else pos = GPM_DEFAULT_RIGHT_MARGIN_POSITION; - + pos = CLAMP (pos, 1, 160); - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; - while (children != NULL) + while (l != NULL) { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + gtk_source_view_set_margin (GTK_SOURCE_VIEW (l->data), + pos); - while (views != NULL) - { - GeditView *v; - GtkSourceView *sv; - - v = GEDIT_VIEW (views->data); - sv = GTK_SOURCE_VIEW (gedit_view_get_gtk_text_view (v)); - - gtk_source_view_set_margin (sv, pos); - - views = views->next; - } - - children = children->next; + l = l->next; } + g_list_free (views); } else if (strcmp (entry->key, GPM_DISPLAY_RIGHT_MARGIN) == 0) { gboolean display; - - GList *children; - + GList *views; + GList *l; + if (entry->value->type == GCONF_VALUE_BOOL) display = gconf_value_get_bool (entry->value); else display = GPM_DEFAULT_DISPLAY_RIGHT_MARGIN; - - children = bonobo_mdi_get_children (BONOBO_MDI (gedit_mdi)); - while (children != NULL) - { - GList *views = bonobo_mdi_child_get_views (BONOBO_MDI_CHILD (children->data)); + views = gedit_app_get_views (gedit_app_get_default ()); + l = views; - while (views != NULL) - { - GeditView *v; - GtkSourceView *sv; - - v = GEDIT_VIEW (views->data); - sv = GTK_SOURCE_VIEW (gedit_view_get_gtk_text_view (v)); + while (l != NULL) + { + gtk_source_view_set_show_margin (GTK_SOURCE_VIEW (l->data), + display); - gtk_source_view_set_show_margin (sv, display); - - views = views->next; - } - - children = children->next; + l = l->next; } + + g_list_free (views); } } -static void +static void gedit_prefs_manager_syntax_hl_enable_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); if (strcmp (entry->key, GPM_SYNTAX_HL_ENABLE) == 0) { + gboolean enable; GList *docs; GList *l; - gboolean enable; + const GList *windows; if (entry->value->type == GCONF_VALUE_BOOL) enable = gconf_value_get_bool (entry->value); else enable = GPM_DEFAULT_SYNTAX_HL_ENABLE; - docs = gedit_get_open_documents (); + docs = gedit_app_get_documents (gedit_app_get_default ()); l = docs; + while (l != NULL) { g_return_if_fail (GTK_IS_SOURCE_BUFFER (l->data)); @@ -957,37 +975,37 @@ gedit_prefs_manager_syntax_hl_enable_changed (GConfClient *client, gtk_source_buffer_set_highlight (GTK_SOURCE_BUFFER (l->data), enable); - l = g_list_next (l); + l = l->next; } g_list_free (docs); /* update the sensitivity of the Higlight Mode menu item */ - l = gedit_get_top_windows (); - while (l != NULL) + windows = gedit_app_get_windows (gedit_app_get_default ()); + while (windows != NULL) { - BonoboUIComponent *ui_component; + GtkUIManager *ui; + GtkAction *a; + + ui = gedit_window_get_ui_manager (GEDIT_WINDOW (windows->data)); - g_return_if_fail (BONOBO_IS_WINDOW (l->data)); + a = gtk_ui_manager_get_action (ui, + "/MenuBar/ViewMenu/ViewHighlightModeMenu"); - ui_component = bonobo_mdi_get_ui_component_from_window (l->data); - if (enable) - bonobo_ui_component_set_prop (ui_component, "/menu/View/HighlightMode", - "sensitive", "1", NULL); - else - bonobo_ui_component_set_prop (ui_component, "/menu/View/HighlightMode", - "sensitive", "0", NULL); + gtk_action_set_sensitive (a, enable); - l = g_list_next (l); + windows = g_list_next (windows); } } } static void gedit_prefs_manager_max_recents_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -1015,12 +1033,14 @@ gedit_prefs_manager_max_recents_changed (GConfClient *client, static void gedit_prefs_manager_auto_save_changed (GConfClient *client, - guint cnxn_id, GConfEntry *entry, gpointer user_data) + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { GList *docs; GList *l; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (entry->key != NULL); g_return_if_fail (entry->value != NULL); @@ -1034,16 +1054,16 @@ gedit_prefs_manager_auto_save_changed (GConfClient *client, else auto_save = GPM_DEFAULT_AUTO_SAVE; - docs = gedit_get_open_documents (); + docs = gedit_app_get_documents (gedit_app_get_default ()); l = docs; while (l != NULL) { GeditDocument *doc = GEDIT_DOCUMENT (l->data); - gedit_document_enable_auto_save (doc, auto_save); + gedit_document_set_auto_save_enabled (doc, auto_save); - l = g_list_next (l); + l = l->next; } g_list_free (docs); @@ -1062,16 +1082,16 @@ gedit_prefs_manager_auto_save_changed (GConfClient *client, else auto_save_interval = GPM_DEFAULT_AUTO_SAVE_INTERVAL; - docs = gedit_get_open_documents (); + docs = gedit_app_get_documents (gedit_app_get_default ()); l = docs; - + while (l != NULL) { GeditDocument *doc = GEDIT_DOCUMENT (l->data); gedit_document_set_auto_save_interval (doc, auto_save_interval); - l = g_list_next (l); + l = l->next; } g_list_free (docs); diff --git a/gedit/gedit-prefs-manager-app.h b/gedit/gedit-prefs-manager-app.h index ff6e0376..a065fbc5 100644 --- a/gedit/gedit-prefs-manager-app.h +++ b/gedit/gedit-prefs-manager-app.h @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-prefs-manager-app.h * This file is part of gedit * - * Copyright (C) 2002-2003 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 @@ -22,9 +21,12 @@ */ /* - * Modified by the gedit Team, 2002-2003. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ + * */ #ifndef __GEDIT_PREFS_MANAGER_APP_H__ @@ -32,7 +34,6 @@ #include #include -#include /** LIFE CYCLE MANAGEMENT FUNCTIONS **/ @@ -59,6 +60,16 @@ gint gedit_prefs_manager_get_default_window_width (void); void gedit_prefs_manager_set_window_width (gint ww); gboolean gedit_prefs_manager_window_width_can_set (void); -void gedit_prefs_manager_save_window_size_and_state (BonoboWindow *window); +/* Side panel size */ +gint gedit_prefs_manager_get_side_panel_size (void); +gint gedit_prefs_manager_get_default_side_panel_size(void); +void gedit_prefs_manager_set_side_panel_size (gint ps); +gboolean gedit_prefs_manager_side_panel_size_can_set (void); + +/* Bottom panel size */ +gint gedit_prefs_manager_get_bottom_panel_size (void); +gint gedit_prefs_manager_get_default_bottom_panel_size(void); +void gedit_prefs_manager_set_bottom_panel_size (gint ps); +gboolean gedit_prefs_manager_bottom_panel_size_can_set (void); #endif /* __GEDIT_PREFS_MANAGER_APP_H__ */ diff --git a/gedit/gedit-prefs-manager.c b/gedit/gedit-prefs-manager.c index 4af56a04..cf5461c5 100644 --- a/gedit/gedit-prefs-manager.c +++ b/gedit/gedit-prefs-manager.c @@ -45,7 +45,7 @@ #define DEFINE_BOOL_PREF(name, key, def) gboolean \ gedit_prefs_manager_get_ ## name (void) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ return gedit_prefs_manager_get_bool (key, \ (def)); \ @@ -54,7 +54,7 @@ gedit_prefs_manager_get_ ## name (void) \ void \ gedit_prefs_manager_set_ ## name (gboolean v) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ gedit_prefs_manager_set_bool (key, \ v); \ @@ -63,7 +63,7 @@ gedit_prefs_manager_set_ ## name (gboolean v) \ gboolean \ gedit_prefs_manager_ ## name ## _can_set (void) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ return gedit_prefs_manager_key_is_writable (key);\ } @@ -73,7 +73,7 @@ gedit_prefs_manager_ ## name ## _can_set (void) \ #define DEFINE_INT_PREF(name, key, def) gint \ gedit_prefs_manager_get_ ## name (void) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ return gedit_prefs_manager_get_int (key, \ (def)); \ @@ -82,7 +82,7 @@ gedit_prefs_manager_get_ ## name (void) \ void \ gedit_prefs_manager_set_ ## name (gint v) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ gedit_prefs_manager_set_int (key, \ v); \ @@ -91,7 +91,7 @@ gedit_prefs_manager_set_ ## name (gint v) \ gboolean \ gedit_prefs_manager_ ## name ## _can_set (void) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ return gedit_prefs_manager_key_is_writable (key);\ } @@ -101,7 +101,7 @@ gedit_prefs_manager_ ## name ## _can_set (void) \ #define DEFINE_STRING_PREF(name, key, def) gchar* \ gedit_prefs_manager_get_ ## name (void) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ return gedit_prefs_manager_get_string (key, \ def); \ @@ -110,7 +110,7 @@ gedit_prefs_manager_get_ ## name (void) \ void \ gedit_prefs_manager_set_ ## name (const gchar* v) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ gedit_prefs_manager_set_string (key, \ v); \ @@ -119,7 +119,7 @@ gedit_prefs_manager_set_ ## name (const gchar* v) \ gboolean \ gedit_prefs_manager_ ## name ## _can_set (void) \ { \ - gedit_debug (DEBUG_PREFS, ""); \ + gedit_debug (DEBUG_PREFS); \ \ return gedit_prefs_manager_key_is_writable (key);\ } @@ -163,7 +163,7 @@ gboolean gconf_client_set_color (GConfClient* client, gboolean gedit_prefs_manager_init (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); if (gedit_prefs_manager == NULL) { @@ -194,7 +194,7 @@ gedit_prefs_manager_init (void) void gedit_prefs_manager_shutdown () { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (gedit_prefs_manager != NULL); @@ -205,7 +205,7 @@ gedit_prefs_manager_shutdown () static gboolean gedit_prefs_manager_get_bool (const gchar* key, gboolean def) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (gedit_prefs_manager != NULL, def); g_return_val_if_fail (gedit_prefs_manager->gconf_client != NULL, def); @@ -219,7 +219,7 @@ gedit_prefs_manager_get_bool (const gchar* key, gboolean def) static gint gedit_prefs_manager_get_int (const gchar* key, gint def) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (gedit_prefs_manager != NULL, def); g_return_val_if_fail (gedit_prefs_manager->gconf_client != NULL, def); @@ -233,7 +233,7 @@ gedit_prefs_manager_get_int (const gchar* key, gint def) static gchar * gedit_prefs_manager_get_string (const gchar* key, const gchar* def) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (gedit_prefs_manager != NULL, def ? g_strdup (def) : NULL); @@ -249,7 +249,7 @@ gedit_prefs_manager_get_string (const gchar* key, const gchar* def) static void gedit_prefs_manager_set_bool (const gchar* key, gboolean value) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (gedit_prefs_manager != NULL); g_return_if_fail (gedit_prefs_manager->gconf_client != NULL); @@ -262,7 +262,7 @@ gedit_prefs_manager_set_bool (const gchar* key, gboolean value) static void gedit_prefs_manager_set_int (const gchar* key, gint value) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (gedit_prefs_manager != NULL); g_return_if_fail (gedit_prefs_manager->gconf_client != NULL); @@ -275,7 +275,7 @@ gedit_prefs_manager_set_int (const gchar* key, gint value) static void gedit_prefs_manager_set_string (const gchar* key, const gchar* value) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (value != NULL); @@ -290,7 +290,7 @@ gedit_prefs_manager_set_string (const gchar* key, const gchar* value) static gboolean gedit_prefs_manager_key_is_writable (const gchar* key) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (gedit_prefs_manager != NULL, FALSE); g_return_val_if_fail (gedit_prefs_manager->gconf_client != NULL, FALSE); @@ -301,7 +301,7 @@ gedit_prefs_manager_key_is_writable (const gchar* key) static gchar* gdk_color_to_string (GdkColor color) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return g_strdup_printf ("#%04x%04x%04x", color.red, @@ -316,7 +316,7 @@ gconf_client_get_color_with_default (GConfClient* client, const gchar* key, gchar *str_color = NULL; GdkColor color = {0, }; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (client != NULL, color); g_return_val_if_fail (GCONF_IS_CLIENT (client), color); @@ -343,7 +343,7 @@ gconf_client_set_color (GConfClient* client, const gchar* key, gchar *str_color = NULL; gboolean res; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (GCONF_IS_CLIENT (client), FALSE); @@ -366,7 +366,7 @@ gedit_prefs_manager_get_color (const gchar* key, const gchar* def) { GdkColor color = {0, }; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); if (def != NULL) gdk_color_parse (def, &color); @@ -383,7 +383,7 @@ gedit_prefs_manager_get_color (const gchar* key, const gchar* def) static void gedit_prefs_manager_set_color (const gchar* key, GdkColor value) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_if_fail (gedit_prefs_manager != NULL); g_return_if_fail (gedit_prefs_manager->gconf_client != NULL); @@ -415,7 +415,7 @@ DEFINE_BOOL_PREF (use_default_colors, GdkColor gedit_prefs_manager_get_background_color (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_get_color (GPM_BACKGROUND_COLOR, GPM_DEFAULT_BACKGROUND_COLOR); @@ -424,7 +424,7 @@ gedit_prefs_manager_get_background_color (void) void gedit_prefs_manager_set_background_color (GdkColor color) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); gedit_prefs_manager_set_color (GPM_BACKGROUND_COLOR, color); @@ -433,7 +433,7 @@ gedit_prefs_manager_set_background_color (GdkColor color) gboolean gedit_prefs_manager_background_color_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_BACKGROUND_COLOR); } @@ -442,7 +442,7 @@ gedit_prefs_manager_background_color_can_set (void) GdkColor gedit_prefs_manager_get_text_color (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_get_color (GPM_TEXT_COLOR, GPM_DEFAULT_TEXT_COLOR); @@ -451,7 +451,7 @@ gedit_prefs_manager_get_text_color (void) void gedit_prefs_manager_set_text_color (GdkColor color) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); gedit_prefs_manager_set_color (GPM_TEXT_COLOR, color); @@ -460,7 +460,7 @@ gedit_prefs_manager_set_text_color (GdkColor color) gboolean gedit_prefs_manager_text_color_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_TEXT_COLOR); } @@ -469,7 +469,7 @@ gedit_prefs_manager_text_color_can_set (void) GdkColor gedit_prefs_manager_get_selected_text_color (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_get_color (GPM_SELECTED_TEXT_COLOR, GPM_DEFAULT_SELECTED_TEXT_COLOR); @@ -478,7 +478,7 @@ gedit_prefs_manager_get_selected_text_color (void) void gedit_prefs_manager_set_selected_text_color (GdkColor color) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); gedit_prefs_manager_set_color (GPM_SELECTED_TEXT_COLOR, color); @@ -487,7 +487,7 @@ gedit_prefs_manager_set_selected_text_color (GdkColor color) gboolean gedit_prefs_manager_selected_text_color_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_SELECTED_TEXT_COLOR); } @@ -496,7 +496,7 @@ gedit_prefs_manager_selected_text_color_can_set (void) GdkColor gedit_prefs_manager_get_selection_color (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_get_color (GPM_SELECTION_COLOR, GPM_DEFAULT_SELECTION_COLOR); @@ -505,7 +505,7 @@ gedit_prefs_manager_get_selection_color (void) void gedit_prefs_manager_set_selection_color (GdkColor color) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); gedit_prefs_manager_set_color (GPM_SELECTION_COLOR, color); @@ -514,7 +514,7 @@ gedit_prefs_manager_set_selection_color (GdkColor color) gboolean gedit_prefs_manager_selection_color_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_SELECTION_COLOR); } @@ -529,7 +529,7 @@ DEFINE_BOOL_PREF (create_backup_copy, gchar * gedit_prefs_manager_get_backup_extension (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_get_string (GPM_BACKUP_COPY_EXTENSION, GPM_DEFAULT_BACKUP_COPY_EXTENSION); @@ -578,7 +578,7 @@ gedit_prefs_manager_get_wrap_mode (void) gchar *str; GtkWrapMode res; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); str = gedit_prefs_manager_get_string (GPM_WRAP_MODE, GPM_DEFAULT_WRAP_MODE); @@ -595,7 +595,7 @@ gedit_prefs_manager_set_wrap_mode (GtkWrapMode wp) { const gchar * str; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); switch (wp) { @@ -618,7 +618,7 @@ gedit_prefs_manager_set_wrap_mode (GtkWrapMode wp) gboolean gedit_prefs_manager_wrap_mode_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_WRAP_MODE); } @@ -657,7 +657,7 @@ gedit_prefs_manager_get_toolbar_buttons_style (void) gchar *str; GeditToolbarSetting res; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); str = gedit_prefs_manager_get_string (GPM_TOOLBAR_BUTTONS_STYLE, GPM_DEFAULT_TOOLBAR_BUTTONS_STYLE); @@ -688,7 +688,7 @@ gedit_prefs_manager_set_toolbar_buttons_style (GeditToolbarSetting tbs) { const gchar * str; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); switch (tbs) { @@ -715,7 +715,7 @@ gedit_prefs_manager_set_toolbar_buttons_style (GeditToolbarSetting tbs) gboolean gedit_prefs_manager_toolbar_buttons_style_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_TOOLBAR_BUTTONS_STYLE); @@ -725,6 +725,16 @@ gedit_prefs_manager_toolbar_buttons_style_can_set (void) DEFINE_BOOL_PREF (statusbar_visible, GPM_STATUSBAR_VISIBLE, GPM_DEFAULT_STATUSBAR_VISIBLE) + +/* Side Pane visiblity */ +DEFINE_BOOL_PREF (side_pane_visible, + GPM_SIDE_PANE_VISIBLE, + GPM_DEFAULT_SIDE_PANE_VISIBLE) + +/* Bottom Panel visiblity */ +DEFINE_BOOL_PREF (bottom_panel_visible, + GPM_BOTTOM_PANEL_VISIBLE, + GPM_DEFAULT_BOTTOM_PANEL_VISIBLE) /* Print syntax highlighting */ DEFINE_BOOL_PREF (print_syntax_hl, @@ -744,7 +754,7 @@ gedit_prefs_manager_get_print_wrap_mode (void) gchar *str; GtkWrapMode res; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); str = gedit_prefs_manager_get_string (GPM_PRINT_WRAP_MODE, GPM_DEFAULT_PRINT_WRAP_MODE); @@ -769,7 +779,7 @@ gedit_prefs_manager_set_print_wrap_mode (GtkWrapMode pwp) { const gchar * str; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); switch (pwp) { @@ -792,7 +802,7 @@ gedit_prefs_manager_set_print_wrap_mode (GtkWrapMode pwp) gboolean gedit_prefs_manager_print_wrap_mode_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_PRINT_WRAP_MODE); } @@ -1014,7 +1024,7 @@ gedit_prefs_manager_get_default_print_font_numbers (void) gint gedit_prefs_manager_get_max_recents (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_get_int (GPM_MAX_RECENTS, GPM_DEFAULT_MAX_RECENTS); @@ -1043,7 +1053,7 @@ gedit_prefs_manager_get_auto_detected_encodings (void) { GSList *strings; GSList *res = NULL; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (gedit_prefs_manager != NULL, NULL); g_return_val_if_fail (gedit_prefs_manager->gconf_client != NULL, NULL); @@ -1102,7 +1112,7 @@ gedit_prefs_manager_get_auto_detected_encodings (void) res = g_slist_reverse (res); } - gedit_debug (DEBUG_PREFS, "Done"); + gedit_debug_message (DEBUG_PREFS, "Done"); return res; } @@ -1112,7 +1122,7 @@ gedit_prefs_manager_get_shown_in_menu_encodings (void) { GSList *strings; GSList *res = NULL; - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); g_return_val_if_fail (gedit_prefs_manager != NULL, NULL); g_return_val_if_fail (gedit_prefs_manager->gconf_client != NULL, NULL); @@ -1195,7 +1205,7 @@ gedit_prefs_manager_set_shown_in_menu_encodings (const GSList *encs) gboolean gedit_prefs_manager_shown_in_menu_encodings_can_set (void) { - gedit_debug (DEBUG_PREFS, ""); + gedit_debug (DEBUG_PREFS); return gedit_prefs_manager_key_is_writable (GPM_SHOWN_IN_MENU_ENCODINGS); @@ -1227,6 +1237,44 @@ DEFINE_BOOL_PREF (enable_syntax_highlighting, GPM_DEFAULT_SYNTAX_HL_ENABLE) +GSList * +gedit_prefs_manager_get_writable_vfs_schemes (void) +{ + GSList *strings; + + gedit_debug (DEBUG_PREFS); + + g_return_val_if_fail (gedit_prefs_manager != NULL, NULL); + g_return_val_if_fail (gedit_prefs_manager->gconf_client != NULL, NULL); + + strings = gconf_client_get_list (gedit_prefs_manager->gconf_client, + GPM_WRITABLE_VFS_SCHEMES, + GCONF_VALUE_STRING, + NULL); + + if (strings == NULL) + { + gint i = 0; + const gchar* s[] = GPM_DEFAULT_WRITABLE_VFS_SCHEMES; + + while (s[i] != NULL) + { + strings = g_slist_prepend (strings, g_strdup (s[i])); + + ++i; + } + + strings = g_slist_reverse (strings); + } + + /* The 'file' scheme is writable by default. */ + strings = g_slist_prepend (strings, g_strdup ("file")); + + gedit_debug_message (DEBUG_PREFS, "Done"); + + return strings; +} + /* The following functions are taken from gconf-client.c * and partially modified. * The licensing terms on these is: diff --git a/gedit/gedit-prefs-manager.h b/gedit/gedit-prefs-manager.h index 52032501..44d0bb35 100644 --- a/gedit/gedit-prefs-manager.h +++ b/gedit/gedit-prefs-manager.h @@ -92,6 +92,12 @@ #define GPM_STATUSBAR_DIR GPM_PREFS_DIR "/ui/statusbar" #define GPM_STATUSBAR_VISIBLE GPM_STATUSBAR_DIR "/statusbar_visible" +#define GPM_SIDE_PANE_DIR GPM_PREFS_DIR "/ui/side_pane" +#define GPM_SIDE_PANE_VISIBLE GPM_SIDE_PANE_DIR "/side_pane_visible" + +#define GPM_BOTTOM_PANEL_DIR GPM_PREFS_DIR "/ui/bottom_panel" +#define GPM_BOTTOM_PANEL_VISIBLE GPM_BOTTOM_PANEL_DIR "/bottom_panel_visible" + #define GPM_RECENTS_DIR GPM_PREFS_DIR "/ui/recents" #define GPM_MAX_RECENTS GPM_RECENTS_DIR "/max_recents" @@ -114,6 +120,8 @@ #define GPM_WINDOW_STATE GPM_WINDOW_DIR "/state" #define GPM_WINDOW_WIDTH GPM_WINDOW_DIR "/width" #define GPM_WINDOW_HEIGHT GPM_WINDOW_DIR "/height" +#define GPM_SIDE_PANEL_SIZE GPM_WINDOW_DIR "/side_panel_size" +#define GPM_BOTTOM_PANEL_SIZE GPM_WINDOW_DIR "/bottom_panel_size" /* Encodings */ #define GPM_ENCODINGS_DIR GPM_PREFS_DIR "/encodings" @@ -124,6 +132,9 @@ #define GPM_SYNTAX_HL_DIR GPM_PREFS_DIR "/syntax_highlighting" #define GPM_SYNTAX_HL_ENABLE GPM_SYNTAX_HL_DIR "/enable" +/* White list of writable gnome-vfs methods */ +#define GPM_WRITABLE_VFS_SCHEMES GPM_SAVE_DIR "/writable_vfs_schemes" + /* Fallback default values. Keep in sync with gedit.schemas */ #define GPM_DEFAULT_USE_DEFAULT_FONT 0 /* FALSE */ @@ -159,6 +170,8 @@ #define GPM_DEFAULT_TOOLBAR_SHOW_TOOLTIPS 1 /* TRUE */ #define GPM_DEFAULT_STATUSBAR_VISIBLE 1 /* TRUE */ +#define GPM_DEFAULT_SIDE_PANE_VISIBLE 0 /* FALSE */ +#define GPM_DEFAULT_BOTTOM_PANEL_VISIBLE 0 /* FALSE */ #define GPM_DEFAULT_PRINT_SYNTAX 1 /* TRUE */ #define GPM_DEFAULT_PRINT_HEADER 1 /* TRUE */ @@ -179,6 +192,12 @@ #define GPM_DEFAULT_WINDOW_WIDTH_STR "650" #define GPM_DEFAULT_WINDOW_HEIGHT_STR "500" +#define GPM_DEFAULT_SIDE_PANEL_SIZE 200 +#define GPM_DEFAULT_BOTTOM_PANEL_SIZE 140 + +#define GPM_DEFAULT_SIDE_PANEL_SIZE_STR "200" +#define GPM_DEFAULT_BOTTOM_PANEL_SIZE_STR "140" + #define GPM_DEFAULT_HIGHLIGHT_CURRENT_LINE 1 /* TRUE */ #define GPM_DEFAULT_BRACKET_MATCHING 0 /* FALSE */ @@ -188,6 +207,8 @@ #define GPM_DEFAULT_SYNTAX_HL_ENABLE 1 /* TRUE */ +#define GPM_DEFAULT_WRITABLE_VFS_SCHEMES {"ssh", "sftp", "smb", "dav", "davs", NULL} + typedef enum { GEDIT_TOOLBAR_SYSTEM = 0, GEDIT_TOOLBAR_ICONS, @@ -304,6 +325,15 @@ gboolean gedit_prefs_manager_get_statusbar_visible (void); void gedit_prefs_manager_set_statusbar_visible (gboolean sv); gboolean gedit_prefs_manager_statusbar_visible_can_set (void); +/* Side pane visible */ +gboolean gedit_prefs_manager_get_side_pane_visible (void); +void gedit_prefs_manager_set_side_pane_visible (gboolean tv); +gboolean gedit_prefs_manager_side_pane_visible_can_set (void); + +/* Bottom panel visible */ +gboolean gedit_prefs_manager_get_bottom_panel_visible (void); +void gedit_prefs_manager_set_bottom_panel_visible (gboolean tv); +gboolean gedit_prefs_manager_bottom_panel_visible_can_set(void); /* Print syntax highlighting */ gboolean gedit_prefs_manager_get_print_syntax_hl (void); void gedit_prefs_manager_set_print_syntax_hl (gboolean ps); @@ -379,6 +409,9 @@ gboolean gedit_prefs_manager_get_enable_syntax_highlighting (void); void gedit_prefs_manager_set_enable_syntax_highlighting (gboolean esh); gboolean gedit_prefs_manager_enable_syntax_highlighting_can_set (void); +/* Writable VFS schemes */ +GSList *gedit_prefs_manager_get_writable_vfs_schemes (void); + #endif /* __GEDIT_PREFS_MANAGER_H__ */ diff --git a/gedit/gedit-print-job-preview.c b/gedit/gedit-print-job-preview.c new file mode 100644 index 00000000..56ed4be7 --- /dev/null +++ b/gedit/gedit-print-job-preview.c @@ -0,0 +1,1252 @@ +/* + * gedit-print-job-preview.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +/* This is a modified version of the file gnome-print-job-preview.f file + * of the library libgnomeprintui. Here the original copyright assignment. + */ + +/* + * Copyright (C) 2000-2002 Ximian Inc. + * + * Authors: Michael Zucchi + * Miguel de Icaza (miguel@gnu.org) + * Lauris Kaplinski + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +/* FIXME */ +#define WE_ARE_LIBGNOMEPRINT_INTERNALS +#include + +#include "gedit-print-job-preview.h" + +#define GPMP_ZOOM_IN_FACTOR M_SQRT2 +#define GPMP_ZOOM_OUT_FACTOR M_SQRT1_2 +#define GPMP_ZOOM_MIN 0.0625 +#define GPMP_ZOOM_MAX 16.0 + +#define GPMP_A4_WIDTH (210.0 * 72.0 / 25.4) +#define GPMP_A4_HEIGHT (297.0 * 72.0 / 2.54) + +#define GPP_COLOR_RGBA(color, ALPHA) \ + ((guint32) (ALPHA | \ + (((color).red / 256) << 24) | \ + (((color).green / 256) << 16) | \ + (((color).blue / 256) << 8))) + +#define GEDIT_PRINT_JOB_PREVIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PRINT_JOB_PREVIEW, GeditPrintJobPreviewPrivate)) + +struct _GeditPrintJobPreviewPrivate +{ + /* Navigation and zoom buttons */ + GtkWidget *bpn, *bpp; + GtkWidget *bz1, *bzf, *bzi, *bzo; + /* Zoom factor */ + gdouble zoom; + + /* Physical area dimensions */ + gdouble paw, pah; + /* Calculated Physical Area -> Layout */ + gdouble pa2ly[6]; + + /* State */ + guint dragging : 1; + gint anchorx, anchory; + gint offsetx, offsety; + + /* Our GnomePrintJob */ + GnomePrintJob *job; + /* Our GnomePrintPreview */ + GnomePrintContext *preview; + + GtkWidget *page_entry; + GtkWidget *scrolled_window; + GtkWidget *last; + GnomeCanvas *canvas; + GnomeCanvasItem *page; + + gint current_page; + gint pagecount; + + /* Strict theme compliance [#96802] */ + gboolean theme_compliance; + + /* Number of pages displayed together */ + gulong nx, ny; + gint update_func_id; + + GPtrArray *page_array; +}; + +enum { + PROP_0, + PROP_NX, + PROP_NY +}; + +G_DEFINE_TYPE(GeditPrintJobPreview, gedit_print_job_preview, GTK_TYPE_VBOX); + +static void gpmp_parse_layout (GeditPrintJobPreview *pmp); +static void gedit_print_job_preview_update (GeditPrintJobPreview *pmp); +static void gedit_print_job_preview_set_nx_and_ny (GeditPrintJobPreview *pmp, + gulong nx, gulong ny); + +static gint +goto_page (GeditPrintJobPreview *mp, gint page) +{ + guchar c[32]; + + g_return_val_if_fail (mp != NULL, GNOME_PRINT_ERROR_BADVALUE); + + g_return_val_if_fail ((mp->priv->pagecount == 0) || + (page < mp->priv->pagecount), + GNOME_PRINT_ERROR_BADVALUE); + + g_snprintf (c, 32, "%d", page + 1); + gtk_entry_set_text (GTK_ENTRY (mp->priv->page_entry), c); + + gtk_widget_set_sensitive (mp->priv->bpp, (page > 0) && + (mp->priv->pagecount > 1)); + gtk_widget_set_sensitive (mp->priv->bpn, (page != (mp->priv->pagecount - 1)) && + (mp->priv->pagecount > 1)); + + if (page != mp->priv->current_page) { + mp->priv->current_page = page; + if (mp->priv->pagecount > 0) + gedit_print_job_preview_update (mp); + } + + return GNOME_PRINT_OK; +} + +static gint +change_page_cmd (GtkEntry *entry, GeditPrintJobPreview *pmp) +{ + const gchar *text; + gint page; + + text = gtk_entry_get_text (entry); + + page = CLAMP (atoi (text), 1, pmp->priv->pagecount) - 1; + + gtk_widget_grab_focus (GTK_WIDGET (pmp->priv->canvas)); + + return goto_page (pmp, page); +} + +/* + * Padding in points around the simulated page + */ + +#define PAGE_PAD 6 +#define CLOSE_ENOUGH(a,b) (fabs (a - b) < 1e-6) + +static void +gpmp_zoom (GeditPrintJobPreview *mp, gdouble factor) +{ + gdouble zoom, xdpi, ydpi; + int w, h, w_mm, h_mm; + GdkScreen *screen; + + if (factor <= 0.) { + gint width = GTK_WIDGET (mp->priv->canvas)->allocation.width; + gint height = GTK_WIDGET (mp->priv->canvas)->allocation.height; + gdouble zoomx = width / ((mp->priv->paw + PAGE_PAD * 2) * mp->priv->nx + PAGE_PAD * 2); + gdouble zoomy = height / ((mp->priv->pah + PAGE_PAD * 2) * mp->priv->ny + PAGE_PAD * 2); + + zoom = MIN (zoomx, zoomy); + } else + zoom = mp->priv->zoom * factor; + + mp->priv->zoom = CLAMP (zoom, GPMP_ZOOM_MIN, GPMP_ZOOM_MAX); + + gtk_widget_set_sensitive (mp->priv->bz1, (!CLOSE_ENOUGH (mp->priv->zoom, 1.0))); + gtk_widget_set_sensitive (mp->priv->bzi, (!CLOSE_ENOUGH (mp->priv->zoom, GPMP_ZOOM_MAX))); + gtk_widget_set_sensitive (mp->priv->bzo, (!CLOSE_ENOUGH (mp->priv->zoom, GPMP_ZOOM_MIN))); + + screen = gtk_widget_get_screen (GTK_WIDGET (mp->priv->canvas)), +#if 0 + /* there is no per monitor physical size info available for now */ + n = gdk_screen_get_n_monitors (screen); + for (i = 0; i < n; i++) { + gdk_screen_get_monitor_geometry (screen, i, &monitor); + if (x >= monitor.x && x <= monitor.x + monitor.width && + y >= monitor.y && y <= monitor.y + monitor.height) { + break; + } + } +#endif + /* + * From xdpyinfo.c: + * + * there are 2.54 centimeters to an inch; so there are 25.4 millimeters. + * + * dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch)) + * = N pixels / (M inch / 25.4) + * = N * 25.4 pixels / M inch + */ + w_mm = gdk_screen_get_width_mm (screen); + xdpi = -1.; + if (w_mm > 0) { + w = gdk_screen_get_width (screen); + xdpi = (w * 25.4) / (gdouble) w_mm; + } + if (xdpi < 30. || 600. < xdpi) { + g_warning ("Invalid the x-resolution for the screen, assuming 96dpi"); + xdpi = 96.; + } + + h_mm = gdk_screen_get_height_mm (screen); + ydpi = -1.; + if (h_mm > 0) { + h = gdk_screen_get_height (screen); + ydpi = (h * 25.4) / (gdouble) h_mm; + } + if (ydpi < 30. || 600. < ydpi) { + g_warning ("Invalid the y-resolution for the screen, assuming 96dpi"); + ydpi = 96.; + } + + gnome_canvas_set_pixels_per_unit (mp->priv->canvas, mp->priv->zoom * (xdpi + ydpi) / (72. * 2.)); +} + +/* Button press handler for the print preview canvas */ + +static gint +preview_canvas_button_press (GtkWidget *widget, GdkEventButton *event, GeditPrintJobPreview *mp) +{ + gint retval; + + retval = FALSE; + + if (event->button == 1) { + GdkCursor *cursor; + GdkDisplay *display = gtk_widget_get_display (widget); + + mp->priv->dragging = TRUE; + + gnome_canvas_get_scroll_offsets (GNOME_CANVAS (widget), &mp->priv->offsetx, &mp->priv->offsety); + + mp->priv->anchorx = event->x - mp->priv->offsetx; + mp->priv->anchory = event->y - mp->priv->offsety; + + cursor = gdk_cursor_new_for_display (display, GDK_FLEUR); + gdk_pointer_grab (widget->window, FALSE, + (GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_RELEASE_MASK), + NULL, cursor, event->time); + gdk_cursor_unref (cursor); + + retval = TRUE; + } + + return retval; +} + +/* Motion notify handler for the print preview canvas */ + +static gint +preview_canvas_motion (GtkWidget *widget, GdkEventMotion *event, GeditPrintJobPreview *mp) +{ + GdkModifierType mod; + gint retval; + + retval = FALSE; + + if (mp->priv->dragging) { + gint x, y, dx, dy; + + if (event->is_hint) { + gdk_window_get_pointer (widget->window, &x, &y, &mod); + } else { + x = event->x; + y = event->y; + } + + dx = mp->priv->anchorx - x; + dy = mp->priv->anchory - y; + + gnome_canvas_scroll_to ( mp->priv->canvas, mp->priv->offsetx + dx, mp->priv->offsety + dy); + + /* Get new anchor and offset */ + mp->priv->anchorx = event->x; + mp->priv->anchory = event->y; + gnome_canvas_get_scroll_offsets (GNOME_CANVAS (widget), &mp->priv->offsetx, &mp->priv->offsety); + + retval = TRUE; + } + + return retval; +} + +/* Button release handler for the print preview canvas */ + +static gint +preview_canvas_button_release (GtkWidget *widget, GdkEventButton *event, GeditPrintJobPreview *mp) +{ + gint retval; + + retval = TRUE; + + if (event->button == 1) { + mp->priv->dragging = FALSE; + gdk_display_pointer_ungrab (gtk_widget_get_display (widget), + event->time); + retval = TRUE; + } + + return retval; +} + +static void +preview_close_cmd (gpointer unused, GeditPrintJobPreview *mp) +{ + gtk_widget_destroy (GTK_WIDGET (mp)); +} + +static void +preview_next_page_cmd (void *unused, GeditPrintJobPreview *pmp) +{ + GdkEvent *event; + + event = gtk_get_current_event (); + + if (event->button.state & GDK_SHIFT_MASK) + goto_page (pmp, pmp->priv->pagecount - 1); + else + goto_page (pmp, MIN (pmp->priv->current_page + pmp->priv->nx * pmp->priv->ny, + pmp->priv->pagecount - 1)); + + gdk_event_free (event); +} + +static void +preview_prev_page_cmd (void *unused, GeditPrintJobPreview *pmp) +{ + GdkEvent *event; + + event = gtk_get_current_event (); + + if (event->button.state & GDK_SHIFT_MASK) + goto_page (pmp, 0); + else + goto_page (pmp, + MAX ((gint) (pmp->priv->current_page - pmp->priv->nx * pmp->priv->ny), 0)); + + gdk_event_free (event); +} + +static void +gpmp_zoom_in_cmd (GtkToggleButton *t, GeditPrintJobPreview *pmp) +{ + gpmp_zoom (pmp, GPMP_ZOOM_IN_FACTOR); +} + +static void +gpmp_zoom_out_cmd (GtkToggleButton *t, GeditPrintJobPreview *pmp) +{ + gpmp_zoom (pmp, GPMP_ZOOM_OUT_FACTOR); +} + +static void +preview_zoom_fit_cmd (GeditPrintJobPreview *mp) +{ + gpmp_zoom (mp, -1.); +} + +static void +preview_zoom_100_cmd (GeditPrintJobPreview *mp) +{ + gpmp_zoom (mp, 1. / mp->priv->zoom); /* cheesy way to force 100% */ +} + +static gint +preview_canvas_key (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + GeditPrintJobPreview *pmp; + gint x,y; + gint height, width; + gint domove = 0; + + pmp = (GeditPrintJobPreview *) data; + + gnome_canvas_get_scroll_offsets (pmp->priv->canvas, &x, &y); + height = GTK_WIDGET (pmp->priv->canvas)->allocation.height; + width = GTK_WIDGET (pmp->priv->canvas)->allocation.width; + + switch (event->keyval) { + case '1': + preview_zoom_100_cmd (pmp); + break; + case '+': + case '=': + case GDK_KP_Add: + gpmp_zoom_in_cmd (NULL, pmp); + break; + case '-': + case '_': + case GDK_KP_Subtract: + gpmp_zoom_out_cmd (NULL, pmp); + break; + case GDK_KP_Right: + case GDK_Right: + if (event->state & GDK_SHIFT_MASK) + x += width; + else + x += 10; + domove = 1; + break; + case GDK_KP_Left: + case GDK_Left: + if (event->state & GDK_SHIFT_MASK) + x -= width; + else + x -= 10; + domove = 1; + break; + case GDK_KP_Up: + case GDK_Up: + if (event->state & GDK_SHIFT_MASK) + goto page_up; + y -= 10; + domove = 1; + break; + case GDK_KP_Down: + case GDK_Down: + if (event->state & GDK_SHIFT_MASK) + goto page_down; + y += 10; + domove = 1; + break; + case GDK_KP_Page_Up: + case GDK_Page_Up: + case GDK_Delete: + case GDK_KP_Delete: + case GDK_BackSpace: + page_up: + if (y <= 0) { + if (pmp->priv->current_page > 0) { + goto_page (pmp, pmp->priv->current_page - 1); + y = GTK_LAYOUT (pmp->priv->canvas)->height - height; + } + } else { + y -= height; + } + domove = 1; + break; + case GDK_KP_Page_Down: + case GDK_Page_Down: + case ' ': + page_down: + if (y >= GTK_LAYOUT (pmp->priv->canvas)->height - height) { + if (pmp->priv->current_page < pmp->priv->pagecount - 1) { + goto_page (pmp, pmp->priv->current_page + 1); + y = 0; + } + } else { + y += height; + } + domove = 1; + break; + case GDK_KP_Home: + case GDK_Home: + goto_page (pmp, 0); + y = 0; + domove = 1; + break; + case GDK_KP_End: + case GDK_End: + goto_page (pmp, pmp->priv->pagecount - 1); + y = 0; + domove = 1; + break; + case GDK_Escape: + gtk_widget_destroy (GTK_WIDGET (pmp)); + return TRUE; + /* break skipped */ + case 'c': + if (event->state & GDK_MOD1_MASK) + { + gtk_widget_destroy (GTK_WIDGET (pmp)); + return TRUE; + } + break; + case 'p': + if (event->state & GDK_MOD1_MASK) + { + gtk_widget_grab_focus (GTK_WIDGET (pmp->priv->page_entry)); + return TRUE; + } + break; + default: + return FALSE; + } + + if (domove) + gnome_canvas_scroll_to (pmp->priv->canvas, x, y); + + g_signal_stop_emission (G_OBJECT (widget), g_signal_lookup ("key_press_event", G_OBJECT_TYPE (widget)), 0); + + return TRUE; +} + +static void +canvas_style_changed_cb (GtkWidget *canvas, GtkStyle *ps, GeditPrintJobPreview *mp) +{ + GtkStyle *style; + gint32 border_color; + gint32 page_color; + guint i; + GnomeCanvasItem *page; + + style = gtk_widget_get_style (GTK_WIDGET (canvas)); + if (mp->priv->theme_compliance) { + page_color = GPP_COLOR_RGBA (style->base [GTK_STATE_NORMAL], + 0xff); + border_color = GPP_COLOR_RGBA (style->text [GTK_STATE_NORMAL], + 0xff); + } + else { + page_color = GPP_COLOR_RGBA (style->white, 0xff); + border_color = GPP_COLOR_RGBA (style->black, 0xff); + } + + for (i = 0; i < mp->priv->page_array->len; i++) { + page = g_object_get_data (mp->priv->page_array->pdata[i], "page"); + gnome_canvas_item_set (page, + "fill_color_rgba", page_color, + "outline_color_rgba", border_color, + NULL); + } + + gedit_print_job_preview_update (mp); +} + +static void +entry_insert_text_cb (GtkEditable *editable, const gchar *text, gint length, gint *position) +{ + gunichar c; + const gchar *p; + const gchar *end; + + p = text; + end = text + length; + + while (p != end) { + const gchar *next; + next = g_utf8_next_char (p); + + c = g_utf8_get_char (p); + + if (!g_unichar_isdigit (c)) { + g_signal_stop_emission_by_name (editable, "insert_text"); + break; + } + + p = next; + } +} + +static gboolean +entry_focus_out_event_cb (GtkWidget *widget, GdkEventFocus *event, GeditPrintJobPreview *pjp) +{ + const gchar *text; + gint page; + + text = gtk_entry_get_text (GTK_ENTRY(widget)); + page = atoi (text) - 1; + + /* Reset the page number only if really needed */ + if (page != pjp->priv->current_page) { + gchar *str; + + str = g_strdup_printf ("%d", pjp->priv->current_page + 1); + gtk_entry_set_text (GTK_ENTRY (widget), str); + g_free (str); + } + + return FALSE; +} + +static void +create_preview_canvas (GeditPrintJobPreview *mp) +{ + AtkObject *atko; + + mp->priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (mp->priv->scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + gtk_widget_push_colormap (gdk_screen_get_rgb_colormap ( + gtk_widget_get_screen (mp->priv->scrolled_window))); + mp->priv->canvas = GNOME_CANVAS (gnome_canvas_new_aa ()); + gnome_canvas_set_center_scroll_region (mp->priv->canvas, FALSE); + gtk_widget_pop_colormap (); + atko = gtk_widget_get_accessible (GTK_WIDGET (mp->priv->canvas)); + atk_object_set_name (atko, _("Page Preview")); + atk_object_set_description (atko, _("The preview of a page in the document to be printed")); + + g_signal_connect (G_OBJECT (mp->priv->canvas), "button_press_event", + (GCallback) preview_canvas_button_press, mp); + g_signal_connect (G_OBJECT (mp->priv->canvas), "button_release_event", + (GCallback) preview_canvas_button_release, mp); + g_signal_connect (G_OBJECT (mp->priv->canvas), "motion_notify_event", + (GCallback) preview_canvas_motion, mp); + g_signal_connect (G_OBJECT (mp->priv->canvas), "key_press_event", + (GCallback) preview_canvas_key, mp); + + gtk_container_add (GTK_CONTAINER (mp->priv->scrolled_window), GTK_WIDGET (mp->priv->canvas)); + + g_signal_connect (G_OBJECT (mp->priv->canvas), "style_set", + G_CALLBACK (canvas_style_changed_cb), mp); + + gtk_box_pack_end (GTK_BOX (mp), mp->priv->scrolled_window, TRUE, TRUE, 0); + + gtk_widget_show_all (GTK_WIDGET (mp->priv->scrolled_window)); + gtk_widget_grab_focus (GTK_WIDGET (mp->priv->canvas)); +} + +static void +on_1x1_clicked (GtkMenuItem *i, GeditPrintJobPreview *mp) +{ + gedit_print_job_preview_set_nx_and_ny (mp, 1, 1); +} + +static void +on_1x2_clicked (GtkMenuItem *i, GeditPrintJobPreview *mp) +{ + gedit_print_job_preview_set_nx_and_ny (mp, 2, 1); +} + +static void +on_2x1_clicked (GtkMenuItem *i, GeditPrintJobPreview *mp) +{ + gedit_print_job_preview_set_nx_and_ny (mp, 1, 2); +} + +static void +on_2x2_clicked (GtkMenuItem *i, GeditPrintJobPreview *mp) +{ + gedit_print_job_preview_set_nx_and_ny (mp, 2, 2); +} + + +#if 0 +static void +on_other_clicked (GtkMenuItem *i, GeditPrintJobPreview *mp) +{ + +} +#endif + +static void +gpmp_multi_cmd (GtkWidget *w, GeditPrintJobPreview *mp) +{ + GtkWidget *m, *i; + + m = gtk_menu_new (); + gtk_widget_show (m); + g_signal_connect (m, "selection_done", G_CALLBACK (gtk_widget_destroy), + m); + + i = gtk_menu_item_new_with_label ("1x1"); + gtk_widget_show (i); + gtk_menu_attach (GTK_MENU (m), i, 0, 1, 0, 1); + g_signal_connect (i, "activate", G_CALLBACK (on_1x1_clicked), mp); + + i = gtk_menu_item_new_with_label ("2x1"); + gtk_widget_show (i); + gtk_menu_attach (GTK_MENU (m), i, 0, 1, 1, 2); + g_signal_connect (i, "activate", G_CALLBACK (on_2x1_clicked), mp); + + i = gtk_menu_item_new_with_label ("1x2"); + gtk_widget_show (i); + gtk_menu_attach (GTK_MENU (m), i, 1, 2, 0, 1); + g_signal_connect (i, "activate", G_CALLBACK (on_1x2_clicked), mp); + + i = gtk_menu_item_new_with_label ("2x2"); + gtk_widget_show (i); + gtk_menu_attach (GTK_MENU (m), i, 1, 2, 1, 2); + g_signal_connect (i, "activate", G_CALLBACK (on_2x2_clicked), mp); + +#if 0 + i = gtk_menu_item_new_with_label (_("Other")); + gtk_widget_show (i); + gtk_menu_attach (GTK_MENU (m), i, 0, 2, 2, 3); + gtk_widget_set_sensitive (i, FALSE); + g_signal_connect (i, "activate", G_CALLBACK (on_other_clicked), mp); +#endif + + gtk_menu_popup (GTK_MENU (m), NULL, NULL, NULL, mp, 0, + GDK_CURRENT_TIME); +} + +static void +create_toplevel (GeditPrintJobPreview *mp) +{ + GtkWidget *tb; + GtkToolItem *i; + AtkObject *atko; + GtkWidget *status; + + tb = gtk_toolbar_new (); + gtk_toolbar_set_style (GTK_TOOLBAR (tb), GTK_TOOLBAR_BOTH_HORIZ); + gtk_widget_show (tb); + gtk_box_pack_start (GTK_BOX (mp), tb, FALSE, FALSE, 0); + + i = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (i), "P_revious Page"); + mp->priv->bpp = GTK_WIDGET(i); + gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (i), TRUE); + + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Show the previous page"), ""); + g_signal_connect (i, "clicked", + G_CALLBACK (preview_prev_page_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD); + mp->priv->bpn = GTK_WIDGET (i); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (i), "_Next Page"); + gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (i), TRUE); + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Show the next page"), ""); + g_signal_connect (i, "clicked", + G_CALLBACK (preview_next_page_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_separator_tool_item_new (); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + status = gtk_hbox_new (FALSE, 4); + mp->priv->page_entry = gtk_entry_new (); + gtk_entry_set_width_chars (GTK_ENTRY (mp->priv->page_entry), 3); + gtk_entry_set_max_length (GTK_ENTRY (mp->priv->page_entry), 6); + gtk_tooltips_set_tip (GTK_TOOLBAR (tb)->tooltips, + mp->priv->page_entry, + _("Current page (Alt+P)"), + NULL); + + g_signal_connect (G_OBJECT (mp->priv->page_entry), "activate", + G_CALLBACK (change_page_cmd), mp); + g_signal_connect (G_OBJECT (mp->priv->page_entry), "insert_text", + G_CALLBACK (entry_insert_text_cb), NULL); + g_signal_connect (G_OBJECT (mp->priv->page_entry), "focus_out_event", + G_CALLBACK (entry_focus_out_event_cb), mp); + + gtk_box_pack_start (GTK_BOX (status), mp->priv->page_entry, FALSE, FALSE, 0); + /* gtk_label_set_mnemonic_widget ((GtkLabel *) l, mp->priv->page_entry); */ + + /* We are displaying 'XXX of XXX'. */ + gtk_box_pack_start (GTK_BOX (status), gtk_label_new (_("of")), + FALSE, FALSE, 0); + + mp->priv->last = gtk_label_new (""); + gtk_box_pack_start (GTK_BOX (status), mp->priv->last, FALSE, FALSE, 0); + atko = gtk_widget_get_accessible (mp->priv->last); + atk_object_set_name (atko, _("Page total")); + atk_object_set_description (atko, _("The total number of pages in the document")); + + gtk_widget_show_all (status); + + i = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (i), status); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_separator_tool_item_new (); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_tool_button_new_from_stock (GTK_STOCK_DND_MULTIPLE); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (i), "_Show Multiple Pages"); + gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (i), TRUE); + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Show multiple pages"), ""); + g_signal_connect (i, "clicked", G_CALLBACK (gpmp_multi_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_separator_tool_item_new (); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_100); + mp->priv->bz1 = GTK_WIDGET (i); + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Zoom 1:1"), ""); + g_signal_connect_swapped (i, "clicked", + G_CALLBACK (preview_zoom_100_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + i = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_FIT); + mp->priv->bzf = GTK_WIDGET (i); + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Zoom to fit the whole page"), ""); + g_signal_connect_swapped (i, "clicked", + G_CALLBACK (preview_zoom_fit_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_IN); + mp->priv->bzi = GTK_WIDGET (i); + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Zoom the page in"), ""); + g_signal_connect (i, "clicked", + G_CALLBACK (gpmp_zoom_in_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + i = gtk_tool_button_new_from_stock (GTK_STOCK_ZOOM_OUT); + mp->priv->bzo = GTK_WIDGET (i); + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Zoom the page out"), ""); + g_signal_connect (i, "clicked", + G_CALLBACK (gpmp_zoom_out_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_separator_tool_item_new (); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); + + i = gtk_tool_button_new (NULL, "_Close Preview"); + gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (i), TRUE); + gtk_tool_item_set_is_important (i, TRUE); + gtk_tool_item_set_tooltip (i, GTK_TOOLBAR (tb)->tooltips, + _("Close print preview"), ""); + g_signal_connect (i, "clicked", + G_CALLBACK (preview_close_cmd), mp); + gtk_widget_show (GTK_WIDGET (i)); + gtk_toolbar_insert (GTK_TOOLBAR (tb), i, -1); +} + +static void +gedit_print_job_preview_destroy (GtkObject *object) +{ + GeditPrintJobPreview *pmp = GEDIT_PRINT_JOB_PREVIEW (object); + + if (pmp->priv->page_array != NULL) { + g_ptr_array_free (pmp->priv->page_array, TRUE); + pmp->priv->page_array = NULL; + } + + if (pmp->priv->job != NULL) { + g_object_unref (G_OBJECT (pmp->priv->job)); + pmp->priv->job = NULL; + } + + if (pmp->priv->update_func_id) { + g_source_remove (pmp->priv->update_func_id); + pmp->priv->update_func_id = 0; + } + + if (GTK_OBJECT_CLASS (gedit_print_job_preview_parent_class)->destroy) + (* GTK_OBJECT_CLASS (gedit_print_job_preview_parent_class)->destroy) (object); +} + +static void +gedit_print_job_preview_finalize (GObject *object) +{ + if (G_OBJECT_CLASS (gedit_print_job_preview_parent_class)->finalize) + (* G_OBJECT_CLASS (gedit_print_job_preview_parent_class)->finalize) (object); +} + +static gboolean +update_func (gpointer data) +{ + GeditPrintJobPreview *pmp = GEDIT_PRINT_JOB_PREVIEW (data); + + gedit_print_job_preview_update (pmp); + pmp->priv->update_func_id = 0; + + return FALSE; +} + +static void +gedit_print_job_preview_set_nx_and_ny (GeditPrintJobPreview *pmp, + gulong nx, gulong ny) +{ + GPtrArray *a; + GnomeCanvasItem *group, *item; + guint i, col, row; + + g_return_if_fail (GEDIT_IS_PRINT_JOB_PREVIEW (pmp)); + g_return_if_fail (nx > 0); + g_return_if_fail (ny > 0); + + pmp->priv->nx = nx; + pmp->priv->ny = ny; + + /* Remove unnecessary pages */ + a = pmp->priv->page_array; + while (pmp->priv->page_array->len > MIN (nx * ny, pmp->priv->pagecount)) { + gtk_object_destroy (GTK_OBJECT (a->pdata[a->len - 1])); + g_ptr_array_remove_index (a, a->len - 1); + } + + /* Create pages if needed */ + if (pmp->priv->page_array->len < MIN (nx * ny, pmp->priv->pagecount)) { + gdouble transform[6]; + + transform[0] = 1.; transform[1] = 0.; + transform[2] = 0.; transform[3] = -1.; + transform[4] = 0.; transform[5] = pmp->priv->pah; + art_affine_multiply (transform, pmp->priv->pa2ly, transform); + + while (pmp->priv->page_array->len < MIN (nx * ny, pmp->priv->pagecount)) { + GnomePrintPreview *preview; + + group = gnome_canvas_item_new ( + gnome_canvas_root (pmp->priv->canvas), + GNOME_TYPE_CANVAS_GROUP, "x", 0., "y", 0., NULL); + g_ptr_array_add (a, group); + item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (group), + GNOME_TYPE_CANVAS_RECT, "x1", 0.0, "y1", 0.0, + "x2", (gdouble) pmp->priv->paw, "y2", (gdouble) pmp->priv->pah, + "fill_color", "white", "outline_color", "black", + "width_pixels", 1, NULL); + gnome_canvas_item_lower_to_bottom (item); + g_object_set_data (G_OBJECT (group), "page", item); + item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (group), + GNOME_TYPE_CANVAS_RECT, "x1", 3.0, "y1", 3.0, + "x2", (gdouble) pmp->priv->paw + 3, + "y2", (gdouble) pmp->priv->pah + 3, + "fill_color", "black", NULL); + gnome_canvas_item_lower_to_bottom (item); + + /* Create the group that holds the preview. */ + item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (group), + GNOME_TYPE_CANVAS_GROUP, + "x", 0., "y", 0., NULL); + gnome_canvas_item_affine_absolute (item, transform); + preview = g_object_new (GNOME_TYPE_PRINT_PREVIEW, + "group", item, + "theme_compliance", pmp->priv->theme_compliance, + NULL); + /* CHECK: changing this I have fixed a crash, but I'm not sure + * of the fix since I may have included a mem leak */ + /* + g_object_set_data_full (G_OBJECT (group), "preview", preview, + (GDestroyNotify) g_object_unref); + */ + g_object_set_data (G_OBJECT (group), "preview", preview); + } + } + + /* Position the pages */ + for (i = 0; i < a->len; i++) { + col = i % pmp->priv->nx; + row = i / pmp->priv->nx; + g_object_set (a->pdata[i], + "x", (gdouble) col * (pmp->priv->paw + PAGE_PAD * 2), + "y", (gdouble) row * (pmp->priv->pah + PAGE_PAD * 2), NULL); + } + + preview_zoom_fit_cmd (pmp); + + if (!pmp->priv->update_func_id) + pmp->priv->update_func_id = g_idle_add_full ( + G_PRIORITY_DEFAULT_IDLE, update_func, pmp, NULL); +} + +static void +gedit_print_job_preview_update (GeditPrintJobPreview *pmp) +{ + guint col, row, i, page; + GPtrArray *a; + + g_return_if_fail (GEDIT_IS_PRINT_JOB_PREVIEW (pmp)); + + a = pmp->priv->page_array; + + /* Show something on the pages */ + for (i = 0; i < a->len; i++) { + GnomeCanvasItem *group = a->pdata[i]; + GnomePrintPreview *preview = g_object_get_data ( + G_OBJECT (group), "preview"); + + col = i % pmp->priv->nx; + row = i / pmp->priv->nx; + page = (guint) (pmp->priv->current_page / (pmp->priv->nx * pmp->priv->ny)) + * (pmp->priv->nx * pmp->priv->ny) + i; + + /* Do we need to show this page? */ + if (page < pmp->priv->pagecount) + gnome_canvas_item_show (group); + else { + gnome_canvas_item_hide (group); + continue; + } + gnome_print_job_render_page (pmp->priv->job, + GNOME_PRINT_CONTEXT (preview), page, TRUE); + } + + gnome_canvas_set_scroll_region (pmp->priv->canvas, + 0 - PAGE_PAD, 0 - PAGE_PAD, + (pmp->priv->paw + PAGE_PAD * 2) * pmp->priv->nx + PAGE_PAD, + (pmp->priv->pah + PAGE_PAD * 2) * pmp->priv->ny + PAGE_PAD); +} + +static void +gedit_print_job_preview_get_property (GObject *object, guint n, GValue *v, GParamSpec *pspec) +{ + GeditPrintJobPreview *pmp = GEDIT_PRINT_JOB_PREVIEW (object); + + switch (n) { + case PROP_NX: + g_value_set_ulong (v, pmp->priv->nx); + break; + case PROP_NY: + g_value_set_ulong (v, pmp->priv->ny); + break; + default: + break; + } +} + +static void +gedit_print_job_preview_set_property (GObject *object, guint n, + const GValue *v, GParamSpec *pspec) +{ + GeditPrintJobPreview *pmp = GEDIT_PRINT_JOB_PREVIEW (object); + + switch (n) { + case PROP_NX: + gedit_print_job_preview_set_nx_and_ny (pmp, + g_value_get_ulong (v), pmp->priv->ny); + break; + case PROP_NY: + gedit_print_job_preview_set_nx_and_ny (pmp, + pmp->priv->nx, g_value_get_ulong (v)); + break; + default: + break; + } +} + +static void +grab_focus (GtkWidget *w) +{ + GeditPrintJobPreview *pmp; + + pmp = GEDIT_PRINT_JOB_PREVIEW (w); + + gtk_widget_grab_focus (GTK_WIDGET (pmp->priv->canvas)); +} + +static void +gedit_print_job_preview_class_init (GeditPrintJobPreviewClass *klass) +{ + GtkObjectClass *object_class; + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class = (GtkObjectClass *) klass; + + object_class->destroy = gedit_print_job_preview_destroy; + + widget_class->grab_focus = grab_focus; + + gobject_class->finalize = gedit_print_job_preview_finalize; + gobject_class->set_property = gedit_print_job_preview_set_property; + gobject_class->get_property = gedit_print_job_preview_get_property; + + g_object_class_install_property (gobject_class, PROP_NX, + g_param_spec_ulong ("nx", _("Number of pages horizontally"), + _("Number of pages horizontally"), 1, 0xffff, 1, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_NY, + g_param_spec_ulong ("ny", _("Number of pages vertically"), + _("Number of pages vertically"), 1, 0xffff, 1, + G_PARAM_READWRITE)); + + g_type_class_add_private(klass, sizeof(GeditPrintJobPreviewPrivate)); +} + +static void +gedit_print_job_preview_init (GeditPrintJobPreview *mp) +{ + const gchar *env_theme_variable; + + mp->priv = GEDIT_PRINT_JOB_PREVIEW_GET_PRIVATE(mp); + mp->priv->current_page = -1; + + mp->priv->theme_compliance = FALSE; + env_theme_variable = g_getenv("GP_PREVIEW_STRICT_THEME"); + if (env_theme_variable && env_theme_variable [0]) + mp->priv->theme_compliance = TRUE; + + mp->priv->zoom = 1.0; + + mp->priv->nx = mp->priv->ny = 1; + mp->priv->page_array = g_ptr_array_new (); +} + +static void +realized (GtkWidget *widget, GeditPrintJobPreview *gpmp) +{ + preview_zoom_100_cmd (gpmp); +} + +GtkWidget * +gedit_print_job_preview_new (GnomePrintJob *gpm) +{ + GeditPrintJobPreview *gpmp; + gchar *text; + + g_return_val_if_fail (gpm != NULL, NULL); + g_return_val_if_fail (GNOME_IS_PRINT_JOB (gpm), NULL); + + gpmp = g_object_new (GEDIT_TYPE_PRINT_JOB_PREVIEW, NULL); + + gpmp->priv->job = gpm; + g_object_ref (G_OBJECT (gpm)); + + gpmp_parse_layout (gpmp); + create_toplevel (gpmp); + create_preview_canvas (gpmp); + + /* this zooms to fit, once we know how big the window actually is */ + g_signal_connect_after (gpmp->priv->canvas, "realize", + (GCallback) realized, gpmp); + + gpmp->priv->pagecount = gnome_print_job_get_pages (gpm); + goto_page (gpmp, 0); + + if (gpmp->priv->pagecount == 0) { + gpmp->priv->pagecount = 1; + text = g_strdup_printf ("%d " + "" + "%s", + 1, + _("No visible output was created.")); + } else + text = g_strdup_printf ("%d", gpmp->priv->pagecount); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (gpmp->priv->last), text); + g_free (text); + + on_1x1_clicked (NULL, gpmp); + return (GtkWidget *) gpmp; +} + +#ifdef GPMP_VERBOSE +#define PRINT_2(s,a,b) g_print ("GPMP %s %g %g\n", s, (a), (b)) +#define PRINT_DRECT(s,a) g_print ("GPMP %s %g %g %g %g\n", (s), (a)->x0, (a)->y0, (a)->x1, (a)->y1) +#define PRINT_AFFINE(s,a) g_print ("GPMP %s %g %g %g %g %g %g\n", (s), *(a), *((a) + 1), *((a) + 2), *((a) + 3), *((a) + 4), *((a) + 5)) +#else +#define PRINT_2(s,a,b) +#define PRINT_DRECT(s,a) +#define PRINT_AFFINE(s,a) +#endif + +static void +gpmp_parse_layout (GeditPrintJobPreview *mp) +{ + GnomePrintConfig *config; + GnomePrintLayoutData *lyd; + + /* Calculate layout-compensated page dimensions */ + mp->priv->paw = GPMP_A4_WIDTH; + mp->priv->pah = GPMP_A4_HEIGHT; + art_affine_identity (mp->priv->pa2ly); + config = gnome_print_job_get_config (mp->priv->job); + lyd = gnome_print_config_get_layout_data (config, NULL, NULL, NULL, NULL); + gnome_print_config_unref (config); + if (lyd) { + GnomePrintLayout *ly; + ly = gnome_print_layout_new_from_data (lyd); + if (ly) { + gdouble pp2lyI[6], pa2pp[6]; + gdouble expansion; + ArtDRect pp, ap, tp; + /* Find paper -> layout transformation */ + art_affine_invert (pp2lyI, ly->LYP[0].matrix); + PRINT_AFFINE ("pp2ly:", &pp2lyI[0]); + /* Find out, what the page dimensions should be */ + expansion = art_affine_expansion (pp2lyI); + if (expansion > 1e-6) { + /* Normalize */ + pp2lyI[0] /= expansion; + pp2lyI[1] /= expansion; + pp2lyI[2] /= expansion; + pp2lyI[3] /= expansion; + pp2lyI[4] = 0.0; + pp2lyI[5] = 0.0; + PRINT_AFFINE ("pp2lyI:", &pp2lyI[0]); + /* Find page dimensions relative to layout */ + pp.x0 = 0.0; + pp.y0 = 0.0; + pp.x1 = lyd->pw; + pp.y1 = lyd->ph; + art_drect_affine_transform (&tp, &pp, pp2lyI); + /* Compensate with expansion */ + mp->priv->paw = tp.x1 - tp.x0; + mp->priv->pah = tp.y1 - tp.y0; + PRINT_2 ("Width & Height", mp->priv->paw, mp->priv->pah); + } + /* Now compensate with feed orientation */ + art_affine_invert (pa2pp, ly->PP2PA); + PRINT_AFFINE ("pa2pp:", &pa2pp[0]); + art_affine_multiply (mp->priv->pa2ly, pa2pp, pp2lyI); + PRINT_AFFINE ("pa2ly:", &mp->priv->pa2ly[0]); + /* Finally we need translation factors */ + /* Page box in normalized layout */ + pp.x0 = 0.0; + pp.y0 = 0.0; + pp.x1 = lyd->pw; + pp.y1 = lyd->ph; + art_drect_affine_transform (&ap, &pp, ly->PP2PA); + art_drect_affine_transform (&tp, &ap, mp->priv->pa2ly); + PRINT_DRECT ("RRR:", &tp); + mp->priv->pa2ly[4] -= tp.x0; + mp->priv->pa2ly[5] -= tp.y0; + PRINT_AFFINE ("pa2ly:", &mp->priv->pa2ly[0]); + /* Now, if job does PA2LY LY2PA concat it ends with scaled identity */ + gnome_print_layout_free (ly); + } + gnome_print_layout_data_free (lyd); + } +} diff --git a/gedit/gedit-print-job-preview.h b/gedit/gedit-print-job-preview.h new file mode 100644 index 00000000..0d59e9fd --- /dev/null +++ b/gedit/gedit-print-job-preview.h @@ -0,0 +1,81 @@ +/* + * gedit-print-job-preview.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +/* This is a modified version of the file gnome-print-job-preview.f file + * of the library libgnomeprintui. Here the original copyright assignment. + */ + +/* + * Copyright (C) 2000-2002 Ximian Inc. + * + * Authors: Michael Zucchi + * Miguel de Icaza (miguel@gnu.org) + */ + +#ifndef __GEDIT_PRINT_MASTER_PREVIEW_H__ +#define __GEDIT_PRINT_MASTER_PREVIEW_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GEDIT_TYPE_PRINT_JOB_PREVIEW (gedit_print_job_preview_get_type ()) +#define GEDIT_PRINT_JOB_PREVIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_PRINT_JOB_PREVIEW, GeditPrintJobPreview)) +#define GEDIT_PRINT_JOB_PREVIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GEDIT_TYPE_PRINT_JOB_PREVIEW, GeditPrintJobPreviewClass)) +#define GEDIT_IS_PRINT_JOB_PREVIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_PRINT_JOB_PREVIEW)) +#define GEDIT_IS_PRINT_JOB_PREVIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_PRINT_JOB_PREVIEW)) +#define GEDIT_PRINT_JOB_PREVIEW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_PRINT_JOB_PREVIEW, GeditPrintJobPreviewClass)) + +typedef struct _GeditPrintJobPreview GeditPrintJobPreview; +typedef struct _GeditPrintJobPreviewClass GeditPrintJobPreviewClass; +typedef struct _GeditPrintJobPreviewPrivate GeditPrintJobPreviewPrivate; + +struct _GeditPrintJobPreview +{ + GtkVBox vbox; + + GeditPrintJobPreviewPrivate *priv; +}; + +struct _GeditPrintJobPreviewClass +{ + GtkVBoxClass parent_class; +}; + +GType gedit_print_job_preview_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_print_job_preview_new (GnomePrintJob *gpm); + +G_END_DECLS + +#endif /* __GEDIT_PRINT_MASTER_PREVIEW_H__ */ + diff --git a/gedit/gedit-print.c b/gedit/gedit-print.c index a9887f48..91d3d78e 100644 --- a/gedit/gedit-print.c +++ b/gedit/gedit-print.c @@ -1,10 +1,9 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-print.c * This file is part of gedit * - * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi - * Copyright (C) 2002 Paolo Maggi + * 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 @@ -23,87 +22,51 @@ */ /* - * Modified by the gedit Team, 1998-2002. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H #include #endif +#include +#include + #include #include #include #include #include /* For strlen */ -#include -#include -#include -#include -#include - -#include "gedit2.h" #include "gedit-print.h" #include "gedit-debug.h" #include "gedit-utils.h" -#include "gedit-document.h" #include "gedit-prefs-manager-app.h" +#include "gedit-tab.h" #define GEDIT_PRINT_CONFIG_FILE "gedit-print-config" -enum -{ - PREVIEW_NO, - PREVIEW, - PREVIEW_FROM_DIALOG -}; - -typedef struct _GeditPrintJobInfo GeditPrintJobInfo; +G_DEFINE_TYPE(GeditPrintJob, gedit_print_job, GTK_TYPE_SOURCE_PRINT_JOB) -struct _GeditPrintJobInfo +static void +gedit_print_job_class_init (GeditPrintJobClass *klass) { - GeditDocument *doc; - - GtkSourcePrintJob *pjob; - - gint preview; - - gint range_type; - - gint first_line_to_print; - gint last_line_to_print; - - /* Popup dialog */ - GtkWidget *dialog; - GtkWidget *label; - GtkWidget *progressbar; - - GtkWindow *parent; -}; - -static GeditPrintJobInfo* gedit_print_job_info_new (GeditDocument *doc); -static void gedit_print_job_info_destroy (GeditPrintJobInfo *pji, - gboolean save_config); -static void gedit_print_real (GeditPrintJobInfo *pji, - GtkTextIter *start, - GtkTextIter *end, - GtkWindow *parent); -static void gedit_print_preview_real (GeditPrintJobInfo *pji, - GtkTextIter *start, - GtkTextIter *end, - GtkWindow *parent); + /* Empty */ +} static GnomePrintConfig * -load_gedit_print_config_from_file () +load_print_config_from_file () { gchar *file_name; gboolean res; gchar *contents; GnomePrintConfig *gedit_print_config; - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); file_name = gnome_util_home_file (GEDIT_PRINT_CONFIG_FILE); @@ -122,7 +85,7 @@ load_gedit_print_config_from_file () } static void -save_gedit_print_config_to_file (GnomePrintConfig *gedit_print_config) +save_print_config_to_file (GnomePrintConfig *gedit_print_config) { gint fd; gchar *str; @@ -131,7 +94,7 @@ save_gedit_print_config_to_file (GnomePrintConfig *gedit_print_config) gchar *file_name; gboolean res; - gedit_debug (DEBUG_PRINT, ""); + gedit_debug (DEBUG_PRINT); g_return_if_fail (gedit_print_config != NULL); @@ -168,340 +131,81 @@ save_gedit_print_config_to_file (GnomePrintConfig *gedit_print_config) g_free (str); } +#define GEDIT_PRINT_CONFIG "gedit-print-config-key" static void -gedit_print_job_info_destroy (GeditPrintJobInfo *pji, gboolean save_config) -{ - GnomePrintConfig *config = NULL; - - gedit_debug (DEBUG_PRINT, ""); - - g_return_if_fail (pji != NULL); - - if (pji->pjob != NULL) - config = gtk_source_print_job_get_config (pji->pjob); - - if (config != NULL) - { - if (save_config) - save_gedit_print_config_to_file (config); - } - - if (pji->pjob != NULL) - g_object_unref (pji->pjob); - - g_free (pji); -} - -static GtkWidget * -get_print_dialog (GeditPrintJobInfo *pji) +buffer_set (GeditPrintJob *job, GParamSpec *pspec, gpointer d) { - GtkWidget *dialog; - gint selection_flag; - gint lines; + GtkSourceBuffer *buffer; + GtkSourcePrintJob *pjob; + gpointer data; GnomePrintConfig *config; - - gedit_debug (DEBUG_PRINT, ""); - - g_return_val_if_fail (pji != NULL, NULL); - if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (pji->doc), NULL, NULL)) - selection_flag = GNOME_PRINT_RANGE_SELECTION_UNSENSITIVE; - else - selection_flag = GNOME_PRINT_RANGE_SELECTION; + gedit_debug (DEBUG_PRINT); - g_return_val_if_fail(pji->pjob != NULL, NULL); - config = gtk_source_print_job_get_config (pji->pjob); + pjob = GTK_SOURCE_PRINT_JOB (job); - dialog = g_object_new (GNOME_TYPE_PRINT_DIALOG, "print_config", config, NULL); + buffer = gtk_source_print_job_get_buffer (pjob); - gnome_print_dialog_construct (GNOME_PRINT_DIALOG (dialog), - _("Print"), - GNOME_PRINT_DIALOG_RANGE | GNOME_PRINT_DIALOG_COPIES); - - lines = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (pji->doc)); - - gnome_print_dialog_construct_range_page ( GNOME_PRINT_DIALOG (dialog), - GNOME_PRINT_RANGE_ALL | - GNOME_PRINT_RANGE_RANGE | - selection_flag, - 1, lines, "A", _("Lines")); - - gtk_window_set_transient_for (GTK_WINDOW (dialog), - GTK_WINDOW (gedit_get_active_window ())); - - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); - - return dialog; -} - -static void -gedit_print_dialog_response (GtkWidget *dialog, int response, GeditPrintJobInfo *pji) -{ - GtkTextIter start, end; - gint line_start, line_end; - - pji->range_type = gnome_print_dialog_get_range (GNOME_PRINT_DIALOG (dialog)); - gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (pji->doc), &start, &end); - - switch (pji->range_type) - { - case GNOME_PRINT_RANGE_ALL: - break; + data = g_object_get_data (G_OBJECT (buffer), + GEDIT_PRINT_CONFIG); - case GNOME_PRINT_RANGE_SELECTION: - gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (pji->doc), - &start, &end); - break; - - case GNOME_PRINT_RANGE_RANGE: - gnome_print_dialog_get_range_page (GNOME_PRINT_DIALOG (dialog), - &line_start, &line_end); - - gtk_text_iter_set_line (&start, line_start - 1); - gtk_text_iter_set_line (&end, line_end - 1); - gtk_text_iter_forward_to_line_end (&end); - break; - - default: - g_return_if_reached (); - } - - switch (response) - { - case GNOME_PRINT_DIALOG_RESPONSE_PRINT: - gedit_debug (DEBUG_PRINT, "Print button pressed."); - pji->preview = PREVIEW_NO; - gedit_print_real (pji, &start, &end, - GTK_WINDOW (gedit_get_active_window ())); - gtk_widget_destroy (dialog); - break; - - case GNOME_PRINT_DIALOG_RESPONSE_PREVIEW: - gedit_debug (DEBUG_PRINT, "Preview button pressed."); - pji->preview = PREVIEW_FROM_DIALOG; - gedit_print_preview_real (pji, &start, &end, GTK_WINDOW (dialog)); - break; - - default: - gtk_widget_destroy (dialog); - gedit_print_job_info_destroy (pji, FALSE); - } -} - -static void -show_printing_dialog (GeditPrintJobInfo *pji, GtkWindow *parent) -{ - GtkWidget *window; - GtkWidget *frame; - GtkWidget *hbox; - GtkWidget *image; - GtkWidget *vbox; - GtkWidget *label; - GtkWidget *progressbar; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_modal (GTK_WINDOW (window), TRUE); - gtk_window_set_resizable (GTK_WINDOW (window), FALSE); - gtk_window_set_destroy_with_parent (GTK_WINDOW (window), TRUE); - gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ON_PARENT); + if (data == NULL) + { + config = load_print_config_from_file (); + g_return_if_fail (config != NULL); - gtk_window_set_decorated (GTK_WINDOW (window), FALSE); - gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE); - gtk_window_set_skip_pager_hint (GTK_WINDOW (window), TRUE); - - gtk_window_set_transient_for (GTK_WINDOW (window), parent); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_container_add (GTK_CONTAINER (window), frame); - - hbox = gtk_hbox_new (FALSE, 12); - gtk_container_add (GTK_CONTAINER (frame), hbox); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 12); - - image = gtk_image_new_from_stock ("gtk-print", GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); - - vbox = gtk_vbox_new (FALSE, 12); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Preparing pages...")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - progressbar = gtk_progress_bar_new (); - gtk_box_pack_start (GTK_BOX (vbox), progressbar, FALSE, FALSE, 0); - - pji->dialog = window; - pji->label = label; - pji->progressbar = progressbar; - - gtk_widget_show_all (pji->dialog); - - /* Update UI */ - while (gtk_events_pending ()) - gtk_main_iteration (); -} - -static void -page_cb (GtkSourcePrintJob *job, GeditPrintJobInfo *pji) -{ - gchar *str; - gint page_num = gtk_source_print_job_get_page (pji->pjob); - gint total = gtk_source_print_job_get_page_count (pji->pjob); - - if (pji->preview != PREVIEW_NO) - str = g_strdup_printf (_("Rendering page %d of %d..."), page_num, total); - else - str = g_strdup_printf (_("Printing page %d of %d..."), page_num, total); - - gtk_label_set_label (GTK_LABEL (pji->label), str); - g_free (str); - - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pji->progressbar), - 1.0 * page_num / total); - - /* Update UI */ - while (gtk_events_pending ()) - gtk_main_iteration (); - -} - -static void -preview_finished_cb (GtkSourcePrintJob *job, GeditPrintJobInfo *pji) -{ - GnomePrintJob *gjob; - GtkWidget *preview = NULL; - - gjob = gtk_source_print_job_get_print_job (job); - - preview = gnome_print_job_preview_new (gjob, _("Print preview")); - if (pji->parent != NULL) - { - gtk_window_set_transient_for (GTK_WINDOW (preview), pji->parent); - gtk_window_set_modal (GTK_WINDOW (preview), TRUE); + g_object_set_data_full (G_OBJECT (buffer), + GEDIT_PRINT_CONFIG, + config, + (GDestroyNotify)gnome_print_config_unref); } - - g_object_unref (gjob); - - gtk_widget_destroy (pji->dialog); - - if (pji->preview == PREVIEW) - gedit_print_job_info_destroy (pji, FALSE); else { - g_signal_handlers_disconnect_by_func (pji->pjob, (GCallback) page_cb, pji); - g_signal_handlers_disconnect_by_func (pji->pjob, (GCallback) preview_finished_cb, pji); + config = GNOME_PRINT_CONFIG (data); } - - gtk_widget_show (preview); -} - -static void -print_finished_cb (GtkSourcePrintJob *job, GeditPrintJobInfo *pji) -{ - GnomePrintJob *gjob; - - gjob = gtk_source_print_job_get_print_job (job); - - gnome_print_job_print (gjob); - - g_object_unref (gjob); - gtk_widget_destroy (pji->dialog); - - gedit_print_job_info_destroy (pji, TRUE); -} + gnome_print_config_set_int (config, GNOME_PRINT_KEY_NUM_COPIES, 1); + gnome_print_config_set_boolean (config, GNOME_PRINT_KEY_COLLATE, FALSE); -void -gedit_print (GeditDocument *doc) -{ - GeditPrintJobInfo *pji; - GtkWidget *dialog; + gtk_source_print_job_set_config (pjob, config); - gedit_debug (DEBUG_PRINT, ""); + gtk_source_print_job_set_highlight (pjob, + gtk_source_buffer_get_highlight (buffer) && + gedit_prefs_manager_get_print_syntax_hl ()); - g_return_if_fail (doc != NULL); - - pji = gedit_print_job_info_new (doc); - pji->preview = PREVIEW_NO; - - dialog = get_print_dialog (pji); - - g_signal_connect (dialog, "response", - G_CALLBACK (gedit_print_dialog_response), - pji); - - gtk_widget_show (dialog); -} - -static void -gedit_print_preview_real (GeditPrintJobInfo *pji, - GtkTextIter *start, - GtkTextIter *end, - GtkWindow *parent) -{ - show_printing_dialog (pji, parent); - - pji->parent = parent; - - g_signal_connect (pji->pjob, "begin_page", (GCallback) page_cb, pji); - g_signal_connect (pji->pjob, "finished", (GCallback) preview_finished_cb, pji); - - if (!gtk_source_print_job_print_range_async (pji->pjob, start, end)) - { - /* FIXME */ - g_warning ("Async print failed"); - gtk_widget_destroy (pji->dialog); - } -} - -static void -gedit_print_real (GeditPrintJobInfo *pji, - GtkTextIter *start, - GtkTextIter *end, - GtkWindow *parent) -{ - show_printing_dialog (pji, parent); - - g_signal_connect (pji->pjob, "begin_page", (GCallback) page_cb, pji); - g_signal_connect (pji->pjob, "finished", (GCallback) print_finished_cb, pji); - - if (!gtk_source_print_job_print_range_async (pji->pjob, start, end)) + if (gedit_prefs_manager_get_print_header ()) { - /* FIXME */ - g_warning ("Async print failed"); - gtk_widget_destroy (pji->dialog); - } -} + gchar *doc_name; + gchar *name_to_display; + gchar *left; -void -gedit_print_preview (GeditDocument *doc) -{ - GeditPrintJobInfo *pji; - GtkTextIter start, end; + doc_name = gedit_document_get_uri_for_display (GEDIT_DOCUMENT (buffer)); + name_to_display = gedit_utils_str_middle_truncate (doc_name, 60); - gedit_debug (DEBUG_PRINT, ""); - - g_return_if_fail (doc != NULL); + left = g_strdup_printf (_("File: %s"), name_to_display); - pji = gedit_print_job_info_new (doc); + /* Translators: %N is the current page number, %Q is the total + * number of pages (ex. Page 2 of 10) + */ + gtk_source_print_job_set_header_format (pjob, + left, + NULL, + _("Page %N of %Q"), + TRUE); - gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (pji->doc), &start, &end); + gtk_source_print_job_set_print_header (pjob, TRUE); - pji->preview = PREVIEW; - gedit_print_preview_real (pji, &start, &end, GTK_WINDOW (gedit_get_active_window ())); + g_free (doc_name); + g_free (name_to_display); + g_free (left); + } } -static GeditPrintJobInfo * -gedit_print_job_info_new (GeditDocument* doc) -{ +static void +gedit_print_job_init (GeditPrintJob *job) +{ GtkSourcePrintJob *pjob; - GnomePrintConfig *config; - GeditPrintJobInfo *pji; gchar *print_font_body; gchar *print_font_header; @@ -511,25 +215,10 @@ gedit_print_job_info_new (GeditDocument* doc) PangoFontDescription *print_font_header_desc; PangoFontDescription *print_font_numbers_desc; - gedit_debug (DEBUG_PRINT, ""); - - g_return_val_if_fail (doc != NULL, NULL); - - config = load_gedit_print_config_from_file (); - g_return_val_if_fail (config != NULL, NULL); - - gnome_print_config_set_int (config, GNOME_PRINT_KEY_NUM_COPIES, 1); - gnome_print_config_set_boolean (config, GNOME_PRINT_KEY_COLLATE, FALSE); - - pjob = gtk_source_print_job_new_with_buffer (config, - GTK_SOURCE_BUFFER (doc)); - - gnome_print_config_unref (config); - - gtk_source_print_job_set_highlight (pjob, - gtk_source_buffer_get_highlight (GTK_SOURCE_BUFFER (doc)) && - gedit_prefs_manager_get_print_syntax_hl ()); + gedit_debug (DEBUG_PRINT); + pjob = GTK_SOURCE_PRINT_JOB (job); + gtk_source_print_job_set_print_numbers (pjob, gedit_prefs_manager_get_print_line_numbers ()); @@ -539,32 +228,7 @@ gedit_print_job_info_new (GeditDocument* doc) gtk_source_print_job_set_tabs_width (pjob, gedit_prefs_manager_get_tabs_size ()); - if (gedit_prefs_manager_get_print_header ()) - { - gchar *doc_name; - gchar *name_to_display; - gchar *left; - - doc_name = gedit_document_get_uri (doc); - name_to_display = gedit_utils_str_middle_truncate (doc_name, 60); - - left = g_strdup_printf (_("File: %s"), name_to_display); - - /* Translators: %N is the current page number, %Q is the total - * number of pages (ex. Page 2 of 10) - */ - gtk_source_print_job_set_header_format (pjob, - left, NULL, _("Page %N of %Q"), TRUE); - - gtk_source_print_job_set_print_header (pjob, TRUE); - - g_free (doc_name); - g_free (name_to_display); - g_free (left); - } - else - gtk_source_print_job_set_print_header (pjob, FALSE); - + gtk_source_print_job_set_print_header (pjob, FALSE); gtk_source_print_job_set_print_footer (pjob, FALSE); print_font_body = gedit_prefs_manager_get_print_font_body (); @@ -590,15 +254,89 @@ gedit_print_job_info_new (GeditDocument* doc) pango_font_description_free (print_font_body_desc); pango_font_description_free (print_font_header_desc); pango_font_description_free (print_font_numbers_desc); + + g_signal_connect (job, + "notify::buffer", + G_CALLBACK (buffer_set), + NULL); +} - pji = g_new0 (GeditPrintJobInfo, 1); - - pji->pjob = pjob; +GeditPrintJob * +gedit_print_job_new (GeditDocument *doc) +{ + GeditPrintJob *job; + + job = GEDIT_PRINT_JOB (g_object_new (GEDIT_TYPE_PRINT_JOB, + "buffer", doc, + NULL)); - pji->doc = doc; - pji->preview = PREVIEW_NO; - pji->range_type = GNOME_PRINT_RANGE_ALL; + return job; +} - return pji; +void +gedit_print_job_save_config (GeditPrintJob *job) +{ + GnomePrintConfig *config; + + g_return_if_fail (GEDIT_IS_PRINT_JOB (job)); + + config = gtk_source_print_job_get_config (GTK_SOURCE_PRINT_JOB (job)); + + save_print_config_to_file (config); } +GtkWidget * +gedit_print_dialog_new (GeditPrintJob *job) +{ + GtkWidget *dialog; + gint selection_flag; + gint lines; + GnomePrintConfig *config; + GtkSourceBuffer *buffer; + GeditTab *tab; + GeditTabState tab_state; + + gedit_debug (DEBUG_PRINT); + + g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), NULL); + + buffer = gtk_source_print_job_get_buffer (GTK_SOURCE_PRINT_JOB (job)); + g_return_val_if_fail (buffer != NULL, NULL); + + if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (buffer), NULL, NULL)) + selection_flag = GNOME_PRINT_RANGE_SELECTION_UNSENSITIVE; + else + selection_flag = GNOME_PRINT_RANGE_SELECTION; + + config = gtk_source_print_job_get_config (GTK_SOURCE_PRINT_JOB (job)); + + dialog = g_object_new (GNOME_TYPE_PRINT_DIALOG, "print_config", config, NULL); + + gnome_print_dialog_construct (GNOME_PRINT_DIALOG (dialog), + _("Print"), + GNOME_PRINT_DIALOG_RANGE | GNOME_PRINT_DIALOG_COPIES); + + lines = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (buffer)); + + gnome_print_dialog_construct_range_page (GNOME_PRINT_DIALOG (dialog), + GNOME_PRINT_RANGE_ALL | + GNOME_PRINT_RANGE_RANGE | + selection_flag, + 1, lines, "A", _("Lines")); + + /* Disable the print preview button of the gnome print dialog if + * the state of the active tab is print_previewing or + * showing_print_preview + */ + tab = gedit_tab_get_from_document (GEDIT_DOCUMENT (buffer)); + tab_state = gedit_tab_get_state (tab); + if ((tab_state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW) || + (tab_state == GEDIT_TAB_STATE_PRINT_PREVIEWING)) + { + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GNOME_PRINT_DIALOG_RESPONSE_PREVIEW, + FALSE); + } + + return dialog; +} diff --git a/gedit/gedit-print.h b/gedit/gedit-print.h index 1be52a5c..8c82dd81 100644 --- a/gedit/gedit-print.h +++ b/gedit/gedit-print.h @@ -1,9 +1,9 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-print.h * This file is part of gedit * - * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi + * 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 @@ -22,17 +22,67 @@ */ /* - * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_PRINT_H__ #define __GEDIT_PRINT_H__ #include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_PRINT_JOB (gedit_print_job_get_type()) +#define GEDIT_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PRINT_JOB, GeditPrintJob)) +#define GEDIT_PRINT_JOB_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PRINT_JOB, GeditPrintJob const)) +#define GEDIT_PRINT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PRINT_JOB, GeditPrintJobClass)) +#define GEDIT_IS_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PRINT_JOB)) +#define GEDIT_IS_PRINT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PRINT_JOB)) +#define GEDIT_PRINT_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PRINT_JOB, GeditPrintJobClass)) + +/* + * Main object structure + */ +typedef struct _GeditPrintJob GeditPrintJob; + +struct _GeditPrintJob +{ + GtkSourcePrintJob parent; +}; + +/* + * Class definition + */ +typedef struct _GeditPrintJobClass GeditPrintJobClass; + +struct _GeditPrintJobClass +{ + GtkSourcePrintJobClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_print_job_get_type (void) G_GNUC_CONST; + +GeditPrintJob *gedit_print_job_new (GeditDocument *doc); + +void gedit_print_job_save_config (GeditPrintJob *job); + + +/* GeditPrintDialog (it is a GnomePrintDialog) */ + +GtkWidget *gedit_print_dialog_new (GeditPrintJob *job); -void gedit_print (GeditDocument* doc); -void gedit_print_preview (GeditDocument* doc); +G_END_DECLS #endif /* __GEDIT_PRINT_H__ */ diff --git a/gedit/gedit-progress-message-area.c b/gedit/gedit-progress-message-area.c new file mode 100644 index 00000000..769a8cf7 --- /dev/null +++ b/gedit/gedit-progress-message-area.c @@ -0,0 +1,242 @@ +/* + * gedit-progress-message-area.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + + /* TODO: add properties */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "gedit-progress-message-area.h" + +enum { + PROP_0, + PROP_HAS_CANCEL_BUTTON +}; + + +#define GEDIT_PROGRESS_MESSAGE_AREA_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PROGRESS_MESSAGE_AREA, GeditProgressMessageAreaPrivate)) + +struct _GeditProgressMessageAreaPrivate +{ + GtkWidget *image; + GtkWidget *label; + GtkWidget *progress; +}; + +G_DEFINE_TYPE(GeditProgressMessageArea, gedit_progress_message_area, GEDIT_TYPE_MESSAGE_AREA) + +static void +gedit_progress_message_area_set_has_cancel_button (GeditProgressMessageArea *area, + gboolean has_button) +{ + if (has_button) + gedit_message_area_add_button (GEDIT_MESSAGE_AREA (area), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + + g_object_notify (G_OBJECT (area), "has-cancel-button"); +} + +static void +gedit_progress_message_area_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeditProgressMessageArea *area; + + area = GEDIT_PROGRESS_MESSAGE_AREA (object); + + switch (prop_id) + { + case PROP_HAS_CANCEL_BUTTON: + gedit_progress_message_area_set_has_cancel_button (area, + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_progress_message_area_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditProgressMessageArea *area; + + area = GEDIT_PROGRESS_MESSAGE_AREA (object); + + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_progress_message_area_class_init (GeditProgressMessageAreaClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gedit_progress_message_area_set_property; + gobject_class->get_property = gedit_progress_message_area_get_property; + + g_object_class_install_property (gobject_class, + PROP_HAS_CANCEL_BUTTON, + g_param_spec_boolean ("has-cancel-button", + "Has Cancel Button", + "If the message area has a cancel button", + TRUE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (gobject_class, sizeof(GeditProgressMessageAreaPrivate)); +} + +static void +gedit_progress_message_area_init (GeditProgressMessageArea *area) +{ + GtkWidget *vbox; + GtkWidget *hbox; + + area->priv = GEDIT_PROGRESS_MESSAGE_AREA_GET_PRIVATE (area); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + + hbox = gtk_hbox_new (FALSE, 4); + gtk_widget_show (hbox); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + area->priv->image = gtk_image_new_from_icon_name (GTK_STOCK_MISSING_IMAGE, + GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_show (area->priv->image); + gtk_misc_set_alignment (GTK_MISC (area->priv->image), 0.5, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), area->priv->image, FALSE, FALSE, 4); + + area->priv->label = gtk_label_new (""); + gtk_widget_show (area->priv->label); + gtk_box_pack_start (GTK_BOX (hbox), area->priv->label, TRUE, TRUE, 0); + gtk_label_set_use_markup (GTK_LABEL (area->priv->label), TRUE); + gtk_misc_set_alignment (GTK_MISC (area->priv->label), 0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (area->priv->label), + PANGO_ELLIPSIZE_END); + + area->priv->progress = gtk_progress_bar_new (); + gtk_widget_show (area->priv->progress); + gtk_box_pack_start (GTK_BOX (vbox), area->priv->progress, TRUE, FALSE, 0); + gtk_widget_set_size_request (area->priv->progress, -1, 15); + + gedit_message_area_set_contents (GEDIT_MESSAGE_AREA (area), + vbox); +} + +GtkWidget * +gedit_progress_message_area_new (const gchar *stock_id, + const gchar *markup, + gboolean has_cancel) +{ + GeditProgressMessageArea *area; + + g_return_val_if_fail (stock_id != NULL, NULL); + g_return_val_if_fail (markup != NULL, NULL); + + area = GEDIT_PROGRESS_MESSAGE_AREA (g_object_new (GEDIT_TYPE_PROGRESS_MESSAGE_AREA, + "has-cancel-button", has_cancel, + NULL)); + + gedit_progress_message_area_set_stock_image (area, + stock_id); + + gedit_progress_message_area_set_markup (area, + markup); + + return GTK_WIDGET (area); +} + +void +gedit_progress_message_area_set_stock_image (GeditProgressMessageArea *area, + const gchar *stock_id) +{ + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (area)); + g_return_if_fail (stock_id != NULL); + + gtk_image_set_from_stock (GTK_IMAGE (area->priv->image), + stock_id, + GTK_ICON_SIZE_SMALL_TOOLBAR); +} + +void +gedit_progress_message_area_set_markup (GeditProgressMessageArea *area, + const gchar *markup) +{ + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (area)); + g_return_if_fail (markup != NULL); + + gtk_label_set_markup (GTK_LABEL (area->priv->label), + markup); +} + +void +gedit_progress_message_area_set_text (GeditProgressMessageArea *area, + const gchar *text) +{ + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (area)); + g_return_if_fail (text != NULL); + + gtk_label_set_text (GTK_LABEL (area->priv->label), + text); +} + +void +gedit_progress_message_area_set_fraction (GeditProgressMessageArea *area, + gdouble fraction) +{ + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (area)); + + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (area->priv->progress), + fraction); +} + +void +gedit_progress_message_area_pulse (GeditProgressMessageArea *area) +{ + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (area)); + + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (area->priv->progress)); +} diff --git a/gedit/gedit-progress-message-area.h b/gedit/gedit-progress-message-area.h new file mode 100644 index 00000000..380da221 --- /dev/null +++ b/gedit/gedit-progress-message-area.h @@ -0,0 +1,101 @@ +/* + * gedit-progress-message-area.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_PROGRESS_MESSAGE_AREA_H__ +#define __GEDIT_PROGRESS_MESSAGE_AREA_H__ + +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_PROGRESS_MESSAGE_AREA (gedit_progress_message_area_get_type()) +#define GEDIT_PROGRESS_MESSAGE_AREA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PROGRESS_MESSAGE_AREA, GeditProgressMessageArea)) +#define GEDIT_PROGRESS_MESSAGE_AREA_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PROGRESS_MESSAGE_AREA, GeditProgressMessageArea const)) +#define GEDIT_PROGRESS_MESSAGE_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PROGRESS_MESSAGE_AREA, GeditProgressMessageAreaClass)) +#define GEDIT_IS_PROGRESS_MESSAGE_AREA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PROGRESS_MESSAGE_AREA)) +#define GEDIT_IS_PROGRESS_MESSAGE_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PROGRESS_MESSAGE_AREA)) +#define GEDIT_PROGRESS_MESSAGE_AREA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PROGRESS_MESSAGE_AREA, GeditProgressMessageAreaClass)) + +/* Private structure type */ +typedef struct _GeditProgressMessageAreaPrivate GeditProgressMessageAreaPrivate; + +/* + * Main object structure + */ +typedef struct _GeditProgressMessageArea GeditProgressMessageArea; + +struct _GeditProgressMessageArea +{ + GeditMessageArea parent; + + /*< private > */ + GeditProgressMessageAreaPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditProgressMessageAreaClass GeditProgressMessageAreaClass; + +struct _GeditProgressMessageAreaClass +{ + GeditMessageAreaClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_progress_message_area_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_progress_message_area_new (const gchar *stock_id, + const gchar *markup, + gboolean has_cancel); + +void gedit_progress_message_area_set_stock_image (GeditProgressMessageArea *area, + const gchar *stock_id); + +void gedit_progress_message_area_set_markup (GeditProgressMessageArea *area, + const gchar *markup); + +void gedit_progress_message_area_set_text (GeditProgressMessageArea *area, + const gchar *text); + +void gedit_progress_message_area_set_fraction (GeditProgressMessageArea *area, + gdouble fraction); + +void gedit_progress_message_area_pulse (GeditProgressMessageArea *area); + + +G_END_DECLS + +#endif /* __GEDIT_PROGRESS_MESSAGE_AREA_H__ */ diff --git a/gedit/gedit-python-module.c b/gedit/gedit-python-module.c new file mode 100644 index 00000000..6c68e506 --- /dev/null +++ b/gedit/gedit-python-module.c @@ -0,0 +1,304 @@ +/* + * gedit-python-module.c + * This file is part of gedit + * + * Copyright (C) 2005 Raphael Slinckx + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "gedit-python-module.h" +#include "gedit-python-plugin.h" +#include "gedit-debug.h" + +#define GEDIT_PYTHON_MODULE_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PYTHON_MODULE, GeditPythonModulePrivate)) + +struct _GeditPythonModulePrivate +{ + gchar *module; + gchar *path; + GType type; +}; + +enum +{ + PROP_0, + PROP_PATH, + PROP_MODULE +}; + +/* Exported by pygedit module */ +void pygedit_register_classes (PyObject *d); +void pygedit_add_constants (PyObject *module, const gchar *strip_prefix); +extern PyMethodDef pygedit_functions[]; + +/* We retreive this to check for correct class hierarchy */ +static PyTypeObject *PyGeditPlugin_Type; + +G_DEFINE_TYPE (GeditPythonModule, gedit_python_module, G_TYPE_TYPE_MODULE); + +static void +gedit_python_module_init_python () +{ + PyObject *pygtk, *mdict, *require, *path; + PyObject *sys_path, *gedit, *gtk, *pygtk_version, *pygtk_required_version; + char *argv[] = { "gedit", NULL }; + + if (Py_IsInitialized ()) + { + g_warning ("Python Should only be initted once, since it's in class_init"); + g_return_if_reached (); + } + + Py_Initialize (); + PySys_SetArgv (1, argv); + + /* pygtk.require("2.0") */ + pygtk = PyImport_ImportModule ("pygtk"); + mdict = PyModule_GetDict (pygtk); + require = PyDict_GetItemString (mdict, "require"); + PyObject_CallObject (require, Py_BuildValue ("(S)", PyString_FromString ("2.0"))); + + /* import gobject */ + init_pygobject (); + + /* import gtk */ + init_pygtk (); + + /* gtk.pygtk_version < (2, 4, 0) */ + gtk = PyImport_ImportModule ("gtk"); + mdict = PyModule_GetDict (gtk); + pygtk_version = PyDict_GetItemString (mdict, "pygtk_version"); + pygtk_required_version = Py_BuildValue ("(iii)", 2, 4, 0); + if (PyObject_Compare (pygtk_version, pygtk_required_version) == -1) + { + g_warning("PyGTK %s required, but %s found.", + PyString_AsString (PyObject_Repr (pygtk_required_version)), + PyString_AsString (PyObject_Repr (pygtk_version))); + Py_DECREF (pygtk_required_version); + return; + } + Py_DECREF (pygtk_required_version); + + /* sys.path.insert(0, ...) for system-wide plugins */ + sys_path = PySys_GetObject ("path"); + path = PyString_FromString (GEDIT_PLUGINDIR "/"); + PyList_Insert (sys_path, 0, path); + Py_DECREF(path); + + /* import gedit */ + gedit = Py_InitModule ("gedit", pygedit_functions); + mdict = PyModule_GetDict (gedit); + + pygedit_register_classes (mdict); + pygedit_add_constants (gedit, "GEDIT_"); + + /* Retreive the Python type for gedit.Plugin */ + PyGeditPlugin_Type = (PyTypeObject *) PyDict_GetItemString (mdict, "Plugin"); + if (PyGeditPlugin_Type == NULL) + { + PyErr_Print (); + return; + } +} + +static gboolean +gedit_python_module_load (GTypeModule *gmodule) +{ + GeditPythonModulePrivate *priv = GEDIT_PYTHON_MODULE_GET_PRIVATE (gmodule); + PyObject *main_module, *main_locals, *locals, *key, *value; + PyObject *module; + int pos = 0; + + main_module = PyImport_AddModule ("__main__"); + if (main_module == NULL) + { + g_warning ("Could not get __main__."); + return FALSE; + } + + /* If we have a special path, we register it */ + if (priv->path != NULL) + { + PyObject *sys_path = PySys_GetObject ("path"); + PyObject *path = PyString_FromString (priv->path); + + if (PySequence_Contains(sys_path, path) == 0) + PyList_Insert (sys_path, 0, path); + + Py_DECREF(path); + } + + main_locals = PyModule_GetDict (main_module); + module = PyImport_ImportModuleEx (priv->module, main_locals, main_locals, NULL); + if (!module) + { + PyErr_Print (); + return FALSE; + } + + locals = PyModule_GetDict (module); + while (PyDict_Next (locals, &pos, &key, &value)) + { + if (!PyType_Check(value)) + continue; + + if (PyObject_IsSubclass (value, (PyObject*) PyGeditPlugin_Type)) + { + priv->type = gedit_python_object_get_type (gmodule, value); + return TRUE; + } + } + + return FALSE; +} + +static void +gedit_python_module_unload (GTypeModule *module) +{ + GeditPythonModulePrivate *priv = GEDIT_PYTHON_MODULE_GET_PRIVATE (module); + gedit_debug_message (DEBUG_PLUGINS, "Unloading python module"); + + priv->type = 0; +} + +GObject * +gedit_python_module_new_object (GeditPythonModule *module) +{ + GeditPythonModulePrivate *priv = GEDIT_PYTHON_MODULE_GET_PRIVATE (module); + gedit_debug_message (DEBUG_PLUGINS, "Creating object of type %s", g_type_name (priv->type)); + + if (priv->type == 0) + return NULL; + + return g_object_new (priv->type, NULL); +} + +static void +gedit_python_module_init (GeditPythonModule *module) +{ + gedit_debug_message (DEBUG_PLUGINS, "Init of python module"); +} + +static void +gedit_python_module_finalize (GObject *object) +{ + GeditPythonModulePrivate *priv = GEDIT_PYTHON_MODULE_GET_PRIVATE (object); + gedit_debug_message (DEBUG_PLUGINS, "Finalizing python module %s", g_type_name (priv->type)); + + g_free (priv->module); + g_free (priv->path); + + G_OBJECT_CLASS (gedit_python_module_parent_class)->finalize (object); +} + +static void +gedit_python_module_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + /* no readable properties */ + g_return_if_reached (); +} + +static void +gedit_python_module_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeditPythonModule *mod = GEDIT_PYTHON_MODULE (object); + + switch (prop_id) + { + case PROP_MODULE: + GEDIT_PYTHON_MODULE_GET_PRIVATE (mod)->module = g_value_dup_string (value); + break; + case PROP_PATH: + GEDIT_PYTHON_MODULE_GET_PRIVATE (mod)->path = g_value_dup_string (value); + break; + default: + g_return_if_reached (); + } +} + +static void +gedit_python_module_class_init (GeditPythonModuleClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class); + + object_class->finalize = gedit_python_module_finalize; + object_class->get_property = gedit_python_module_get_property; + object_class->set_property = gedit_python_module_set_property; + + g_object_class_install_property + (object_class, + PROP_MODULE, + g_param_spec_string ("module", + "Module Name", + "The python module to load for this plugin", + NULL, + G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, + PROP_PATH, + g_param_spec_string ("path", + "Path", + "The python path to use when loading this module", + NULL, + G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof (GeditPythonModulePrivate)); + + module_class->load = gedit_python_module_load; + module_class->unload = gedit_python_module_unload; + + /* Init python subsystem, this should happen only once + * in the process lifetime, and doing it here is ok since + * class_init is called once */ + gedit_python_module_init_python (); +} + +GeditPythonModule * +gedit_python_module_new (const gchar *path, + const gchar *module) +{ + GeditPythonModule *result; + + if (module == NULL || module[0] == '\0') + return NULL; + + result = g_object_new (GEDIT_TYPE_PYTHON_MODULE, + "module", module, + "path", path, + NULL); + + g_type_module_set_name (G_TYPE_MODULE (result), module); + + return result; +} diff --git a/gedit/gedit-python-module.h b/gedit/gedit-python-module.h new file mode 100644 index 00000000..d84ad817 --- /dev/null +++ b/gedit/gedit-python-module.h @@ -0,0 +1,61 @@ +/* + * gedit-python-module.h + * This file is part of gedit + * + * Copyright (C) 2005 Raphael Slinckx + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef GEDIT_PYTHON_MODULE_H +#define GEDIT_PYTHON_MODULE_H + +#include +#include + +G_BEGIN_DECLS + +#define GEDIT_TYPE_PYTHON_MODULE (gedit_python_module_get_type ()) +#define GEDIT_PYTHON_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PYTHON_MODULE, GeditPythonModule)) +#define GEDIT_PYTHON_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_PYTHON_MODULE, GeditPythonModuleClass)) +#define GEDIT_IS_PYTHON_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_PYTHON_MODULE)) +#define GEDIT_IS_PYTHON_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), GEDIT_TYPE_PYTHON_MODULE)) +#define GEDIT_PYTHON_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PYTHON_MODULE, GeditPythonModuleClass)) + +typedef struct _GeditPythonModule GeditPythonModule; +typedef struct _GeditPythonModuleClass GeditPythonModuleClass; +typedef struct _GeditPythonModulePrivate GeditPythonModulePrivate; + +struct _GeditPythonModuleClass +{ + GTypeModuleClass parent_class; +}; + +struct _GeditPythonModule +{ + GTypeModule parent_instance; +}; + +GType gedit_python_module_get_type (void); + +GeditPythonModule *gedit_python_module_new (const gchar* path, + const gchar *module); + +GObject *gedit_python_module_new_object (GeditPythonModule *module); + +G_END_DECLS + +#endif diff --git a/gedit/gedit-python-plugin.c b/gedit/gedit-python-plugin.c new file mode 100644 index 00000000..4b965b35 --- /dev/null +++ b/gedit/gedit-python-plugin.c @@ -0,0 +1,149 @@ +/* + * gedit-python-plugin.c + * This file is part of gedit + * + * Copyright (C) 2005 Raphael Slinckx + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include "gedit-python-plugin.h" +#include "gedit-plugin.h" +#include "gedit-debug.h" + +#include +#include + +static GObjectClass *parent_class; + +static void +call_python_method (GeditPythonObject *object, + GeditWindow *window, + gchar *method) +{ + PyGILState_STATE state = pyg_gil_state_ensure (); + PyObject *py_ret = NULL; + + if (!PyObject_HasAttrString (object->instance, method)) + { + pyg_gil_state_release (state); + return; + } + + py_ret = PyObject_CallMethod (object->instance, + method, + "(N)", + pygobject_new (G_OBJECT (window))); + if (!py_ret) + PyErr_Print (); + + Py_XDECREF (py_ret); + pyg_gil_state_release (state); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + call_python_method ((GeditPythonObject *) plugin, window, "update_ui"); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + call_python_method ((GeditPythonObject *) plugin, window, "deactivate"); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + call_python_method ((GeditPythonObject *) plugin, window, "activate"); +} + +static void +gedit_python_object_init (GeditPythonObject *object) +{ + GeditPythonObjectClass *class; + + gedit_debug_message (DEBUG_PLUGINS, "Creating python plugin instance"); + + class = (GeditPythonObjectClass*) (((GTypeInstance*) object)->g_class); + + object->instance = PyObject_CallObject (class->type, NULL); + if (object->instance == NULL) + PyErr_Print(); +} + +static void +gedit_python_object_finalize (GObject *object) +{ + gedit_debug_message (DEBUG_PLUGINS, "Finalizing python plugin instance"); + + Py_DECREF (((GeditPythonObject *) object)->instance); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gedit_python_object_class_init (GeditPythonObjectClass *klass, + gpointer class_data) +{ + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + klass->type = (PyObject*) class_data; + + G_OBJECT_CLASS (klass)->finalize = gedit_python_object_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; +} + +GType +gedit_python_object_get_type (GTypeModule *module, + PyObject *type) +{ + GTypeInfo *info; + GType gtype; + gchar *type_name; + + info = g_new0 (GTypeInfo, 1); + + info->class_size = sizeof (GeditPythonObjectClass); + info->class_init = (GClassInitFunc) gedit_python_object_class_init; + info->instance_size = sizeof (GeditPythonObject); + info->instance_init = (GInstanceInitFunc) gedit_python_object_init; + info->class_data = type; + Py_INCREF (type); + + type_name = g_strdup_printf ("%s+GeditPythonPlugin", + PyString_AsString (PyObject_GetAttrString (type, "__name__"))); + + gedit_debug_message (DEBUG_PLUGINS, "Registering python plugin instance: %s", type_name); + gtype = g_type_module_register_type (module, + GEDIT_TYPE_PLUGIN, + type_name, + info, 0); + g_free (type_name); + + return gtype; +} diff --git a/gedit/gedit-python-plugin.h b/gedit/gedit-python-plugin.h new file mode 100644 index 00000000..8a2e4b44 --- /dev/null +++ b/gedit/gedit-python-plugin.h @@ -0,0 +1,50 @@ +/* + * gedit-python-plugin.h + * This file is part of gedit + * + * Copyright (C) 2005 Raphael Slinckx + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef GEDIT_PYTHON_OBJECT_H +#define GEDIT_PYTHON_OBJECT_H + +#include +#include +#include "gedit-plugin.h" + +G_BEGIN_DECLS + +typedef struct _GeditPythonObject GeditPythonObject; +typedef struct _GeditPythonObjectClass GeditPythonObjectClass; + +struct _GeditPythonObject +{ + GeditPlugin parent_slot; + PyObject *instance; +}; + +struct _GeditPythonObjectClass +{ + GeditPluginClass parent_slot; + PyObject *type; +}; + +GType gedit_python_object_get_type (GTypeModule *module, PyObject *type); + +G_END_DECLS + +#endif diff --git a/gedit/gedit-recent.c b/gedit/gedit-recent.c index 678b572d..678f39d2 100644 --- a/gedit/gedit-recent.c +++ b/gedit/gedit-recent.c @@ -1,9 +1,9 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-recent.c * This file is part of gedit * - * Copyright (C) 2002 James Willcox + * Copyright (C) 2002 - James Willcox + * 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 @@ -18,13 +18,15 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Boston, MA 02111-1307, USA. */ - + /* - * Modified by the gedit Team, 1998-2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ @@ -35,10 +37,8 @@ #include "gedit-recent.h" #include "gedit-prefs-manager-app.h" - static EggRecentModel *model; - EggRecentModel * gedit_recent_get_model (void) { @@ -50,7 +50,7 @@ gedit_recent_init (void) { model = egg_recent_model_new (EGG_RECENT_MODEL_SORT_MRU); egg_recent_model_set_limit (model, - gedit_prefs_manager_get_max_recents ()); + gedit_prefs_manager_get_max_recents ()); egg_recent_model_set_filter_groups (model, "gedit", NULL); } @@ -94,4 +94,3 @@ gedit_recent_remove (const gchar *uri) g_strdup (uri), (GDestroyNotify)g_free); } - diff --git a/gedit/gedit-recent.h b/gedit/gedit-recent.h index b4342078..7064ca9f 100644 --- a/gedit/gedit-recent.h +++ b/gedit/gedit-recent.h @@ -1,12 +1,48 @@ +/* + * gedit-recent.h + * This file is part of gedit + * + * Copyright (C) 2002 - James Willcox + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ #ifndef __GEDIT_RECENT_H__ #define __GEDIT_RECENT_H__ #include -EggRecentModel *gedit_recent_get_model (void); -void gedit_recent_init (void); -void gedit_recent_add (const gchar *uri); -void gedit_recent_remove (const gchar *uri); +G_BEGIN_DECLS -#endif +void gedit_recent_init (void); + +EggRecentModel *gedit_recent_get_model (void); + +void gedit_recent_add (const gchar *uri); +void gedit_recent_remove (const gchar *uri); + +G_END_DECLS + +#endif /* __GEDIT_RECENT_H__ */ diff --git a/gedit/gedit-session.c b/gedit/gedit-session.c index dacca978..bd5d0db5 100644 --- a/gedit/gedit-session.c +++ b/gedit/gedit-session.c @@ -1,8 +1,11 @@ -/* gedit-session - Basic session management for gedit +/* + * gedit-session.c - Basic session management for gedit + * This file is part of gedit * * Copyright (C) 2002 Ximian, Inc. + * Copyright (C) 2005 - Paolo Maggi * - * Authors Federico Mena-Quintero + * Author: Federico Mena-Quintero * * 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 @@ -21,9 +24,11 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. - * See the ChangeLog files for a list of changes. + * See the ChangeLog files for a list of changes. + * + * $Id$ */ @@ -31,17 +36,24 @@ #include #endif -#include +#include +#include + +#include #include -#include "bonobo-mdi-session.h" -#include "gedit2.h" -#include "gedit-mdi-child.h" +#include +#include + #include "gedit-session.h" -#include "gedit-file.h" + #include "gedit-debug.h" #include "gedit-plugins-engine.h" #include "gedit-prefs-manager-app.h" #include "gedit-metadata-manager.h" +#include "gedit-window.h" +#include "gedit-app.h" +#include "gedit-commands.h" +#include "dialogs/gedit-close-confirmation-dialog.h" /* The master client we use for SM */ static GnomeClient *master_client = NULL; @@ -49,75 +61,520 @@ static GnomeClient *master_client = NULL; /* argv[0] from main(); used as the command to restart the program */ static const char *program_argv0 = NULL; -static void -interaction_function (GnomeClient *client, gint key, GnomeDialogType dialog_type, gpointer shutdown) +/* globals vars used during the interaction. We are + * assuming there can only be one interaction at a time + */ +static gint interaction_key; +static GSList *window_dirty_list; + +static void ask_next_confirmation (void); + +#define GEDIT_SESSION_LIST_OF_DOCS_TO_SAVE "gedit-session-list-of-docs-to-save-key" + +static gchar * +get_session_dir () +{ + gchar *gedit_dir; + gchar *session_dir; + + gedit_dir = gnome_util_home_file ("gedit"); + session_dir = g_build_filename (gedit_dir, "sessions", NULL); + g_free (gedit_dir); + + return session_dir; +} + +static gchar * +get_session_file_path (GnomeClient *client) { const gchar *prefix; + gchar *session_dir; + gchar *session_file; + gchar *session_path; + + prefix = gnome_client_get_config_prefix (client); + gedit_debug_message (DEBUG_SESSION, "Prefix: %s", prefix); - gedit_debug (DEBUG_SESSION, ""); + session_file = g_strndup (prefix, strlen (prefix) - 1); + gedit_debug_message (DEBUG_SESSION, "Session File: %s", session_file); - /* Save all unsaved files */ + session_dir = get_session_dir (); - if (GPOINTER_TO_INT (shutdown)) - gedit_file_save_all (); + session_path = g_build_filename (session_dir, + session_file, + NULL); - /* Save session data */ + g_free (session_dir); + g_free (session_file); - prefix = gnome_client_get_config_prefix (client); + gedit_debug_message (DEBUG_SESSION, "Session Path: %s", session_path); + + return session_path; +} + +static gboolean +ensure_session_dir (void) +{ + gboolean ret = TRUE; + gchar *dir; + + dir = get_session_dir (); + + if (g_file_test (dir, G_FILE_TEST_IS_DIR) == FALSE) + ret = (g_mkdir_with_parents (dir, 488) == 0); + + g_free (dir); + + return ret; +} + +static int +save_window_session (xmlTextWriterPtr writer, + GeditWindow *window) +{ + const gchar *role; + GeditPanel *panel; + GList *docs, *l; + int ret; + GeditDocument *active_document; + + gedit_debug (DEBUG_SESSION); + + active_document = gedit_window_get_active_document (window); + + ret = xmlTextWriterStartElement (writer, (xmlChar *) "window"); + if (ret < 0) + return ret; + + role = gtk_window_get_role (GTK_WINDOW (window)); + if (role != NULL) + { + ret = xmlTextWriterWriteAttribute (writer, "role", role); + if (ret < 0) + return ret; + } + + ret = xmlTextWriterStartElement (writer, (xmlChar *) "side-pane"); + if (ret < 0) + return ret; + + panel = gedit_window_get_side_panel (window); + ret = xmlTextWriterWriteAttribute (writer, + "visible", + GTK_WIDGET_VISIBLE (panel) ? "yes": "no"); + if (ret < 0) + return ret; + + ret = xmlTextWriterEndElement (writer); /* side-pane */ + if (ret < 0) + return ret; + + ret = xmlTextWriterStartElement (writer, (xmlChar *) "bottom-panel"); + if (ret < 0) + return ret; + + panel = gedit_window_get_bottom_panel (window); + ret = xmlTextWriterWriteAttribute (writer, + "visible", + GTK_WIDGET_VISIBLE (panel) ? "yes" : "no"); + if (ret < 0) + return ret; + + ret = xmlTextWriterEndElement (writer); /* bottom-panel */ + if (ret < 0) + return ret; + + docs = gedit_window_get_documents (window); + l = docs; + while (l != NULL) + { + gchar *uri; + + ret = xmlTextWriterStartElement (writer, (xmlChar *) "document"); + if (ret < 0) + return ret; + + uri = gedit_document_get_uri (GEDIT_DOCUMENT (l->data)); + + if (uri != NULL) + { + ret = xmlTextWriterWriteAttribute (writer, + "uri", + uri); + + g_free (uri); + + if (ret < 0) + return ret; + } + + if (active_document == GEDIT_DOCUMENT (l->data)) + { + ret = xmlTextWriterWriteAttribute (writer, + "active", + "yes"); + if (ret < 0) + return ret; + } + + ret = xmlTextWriterEndElement (writer); /* document */ + if (ret < 0) + return ret; + + l = g_list_next (l); + } + g_list_free (docs); + + ret = xmlTextWriterEndElement (writer); /* window */ + + return ret; +} + +static void +save_session () +{ + int ret; + gchar *fname; + xmlTextWriterPtr writer; + const GList *windows; + + fname = get_session_file_path (master_client); + + gedit_debug_message (DEBUG_SESSION, "Session file: %s", fname); + + if (!ensure_session_dir ()) + { + g_warning ("Cannot create or write in session directory"); + return; + } + + writer = xmlNewTextWriterFilename (fname, 0); + if (writer == NULL) + { + g_warning ("Cannot write the session file '%s'", fname); + return; + } + + ret = xmlTextWriterSetIndent (writer, 1); + if (ret < 0) + goto out; + + ret = xmlTextWriterSetIndentString (writer, (const xmlChar *) " "); + if (ret < 0) + goto out; + + /* create and set the root node for the session */ + ret = xmlTextWriterStartElement (writer, (const xmlChar *) "session"); + if (ret < 0) + goto out; + + windows = gedit_app_get_windows (gedit_app_get_default ()); + while (windows != NULL) + { + ret = save_window_session (writer, + GEDIT_WINDOW (windows->data)); + if (ret < 0) + goto out; + + windows = g_list_next (windows); + } + + ret = xmlTextWriterEndElement (writer); /* session */ + if (ret < 0) + goto out; + + ret = xmlTextWriterEndDocument (writer); + +out: + xmlFreeTextWriter (writer); + + if (ret < 0) + unlink (fname); + + g_free (fname); +} + +static void +finish_interaction (gboolean cancel_shutdown) +{ + /* save session file even if shutdown was cancelled */ + save_session (); + + gnome_interaction_key_return (interaction_key, + cancel_shutdown); + + interaction_key = 0; +} + +static void +window_handled (GeditWindow *window) +{ + window_dirty_list = g_slist_remove (window_dirty_list, window); + + /* whee... we made it! */ + if (window_dirty_list == NULL) + finish_interaction (FALSE); + else + ask_next_confirmation (); +} + +static void +window_state_change (GeditWindow *window, + GParamSpec *pspec, + gpointer data) +{ + GeditWindowState state; + GList *unsaved_docs; + GList *docs_to_save; + GList *l; + gboolean done = TRUE; + + state = gedit_window_get_state (window); + + /* we are still saving */ + if (state & GEDIT_WINDOW_STATE_SAVING) + return; + + unsaved_docs = gedit_window_get_unsaved_documents (window); + + docs_to_save = g_object_get_data (G_OBJECT (window), + GEDIT_SESSION_LIST_OF_DOCS_TO_SAVE); + + + for (l = docs_to_save; l != NULL; l = l->next) + { + if (g_list_find (unsaved_docs, l->data)) + { + done = FALSE; + break; + } + } + + if (done) + { + g_signal_handlers_disconnect_by_func (window, window_state_change, data); + g_list_free (docs_to_save); + g_object_set_data (G_OBJECT (window), + GEDIT_SESSION_LIST_OF_DOCS_TO_SAVE, + NULL); + + window_handled (window); + } + + g_list_free (unsaved_docs); +} + +static void +close_confirmation_dialog_response_handler (GeditCloseConfirmationDialog *dlg, + gint response_id, + GeditWindow *window) +{ + const GList *selected_documents; + GSList *l; + + gedit_debug (DEBUG_COMMANDS); - gedit_debug (DEBUG_SESSION, "Prefix: %s", prefix); + switch (response_id) + { + case GTK_RESPONSE_YES: + /* save selected docs */ + + g_signal_connect (window, + "notify::state", + G_CALLBACK (window_state_change), + NULL); + + selected_documents = gedit_close_confirmation_dialog_get_selected_documents (dlg); + + g_return_if_fail (g_object_get_data (G_OBJECT (window), + GEDIT_SESSION_LIST_OF_DOCS_TO_SAVE) == NULL); + + g_object_set_data (G_OBJECT (window), + GEDIT_SESSION_LIST_OF_DOCS_TO_SAVE, + g_list_copy (selected_documents)); + + _gedit_cmd_file_save_documents_list (window, selected_documents); + + // FIXME: also need to lock the window to prevent further changes.. + + break; + + case GTK_RESPONSE_NO: + /* dont save */ + window_handled (window); + break; + + default: + /* disconnect window_state_changed where needed */ + for (l = window_dirty_list; l != NULL; l = l->next) + g_signal_handlers_disconnect_by_func (window, + window_state_change, NULL); + g_slist_free (window_dirty_list); + window_dirty_list = NULL; + + /* cancel shutdown */ + finish_interaction (TRUE); + + break; + } - gnome_config_push_prefix (prefix); + gtk_widget_destroy (GTK_WIDGET (dlg)); +} + +static void +show_confirmation_dialog (GeditWindow *window) +{ + GList *unsaved_docs; + GtkWidget *dlg; - bonobo_mdi_save_state (BONOBO_MDI (gedit_mdi), "Session"); + gedit_debug (DEBUG_SESSION); - gnome_config_pop_prefix (); - gnome_config_sync (); + unsaved_docs = gedit_window_get_unsaved_documents (window); + + g_return_if_fail (unsaved_docs != NULL); + + if (unsaved_docs->next == NULL) + { + /* There is only one unsaved document */ + GeditTab *tab; + GeditDocument *doc; - gnome_interaction_key_return (key, FALSE); + doc = GEDIT_DOCUMENT (unsaved_docs->data); + + tab = gedit_tab_get_from_document (doc); + g_return_if_fail (tab != NULL); + + gedit_window_set_active_tab (window, tab); + + dlg = gedit_close_confirmation_dialog_new_single ( + GTK_WINDOW (window), + doc, + TRUE); + } + else + { + dlg = gedit_close_confirmation_dialog_new (GTK_WINDOW (window), + unsaved_docs, + TRUE); + } + + g_list_free (unsaved_docs); + + g_signal_connect (dlg, + "response", + G_CALLBACK (close_confirmation_dialog_response_handler), + window); + + gtk_widget_show (dlg); +} + +static void +ask_next_confirmation () +{ + g_return_if_fail (window_dirty_list != NULL); + + /* pop up the confirmation dialog for the first window + * in the dirty list. The next confirmation is asked once + * this one has been handled. + */ + show_confirmation_dialog (GEDIT_WINDOW (window_dirty_list->data)); +} + +static void +save_all_docs_and_save_session () +{ + GeditApp *app; + const GList *l; + + app = gedit_app_get_default (); + + if (window_dirty_list != NULL) + { + g_critical ("global variable window_dirty_list not NULL"); + window_dirty_list = NULL; + } + + for (l = gedit_app_get_windows (app); l != NULL; l = l->next) + { + if (gedit_window_get_unsaved_documents (GEDIT_WINDOW (l->data)) != NULL) + { + window_dirty_list = g_slist_prepend (window_dirty_list, l->data); + } + } + + /* no modified docs, go on and save session */ + if (window_dirty_list == NULL) + { + finish_interaction (FALSE); + + return; + } - gedit_debug (DEBUG_SESSION, "END"); + ask_next_confirmation (); +} + +static void +interaction_function (GnomeClient *client, + gint key, + GnomeDialogType dialog_type, + gpointer shutdown) +{ + gedit_debug (DEBUG_SESSION); + + /* sanity checks */ + g_return_if_fail (client == master_client); + + if (interaction_key != 0) + g_critical ("global variable interaction_key not NULL"); + interaction_key = key; + + /* If we are shutting down, give the user the chance to save + * first, otherwise just ignore untitled documents documents. + */ + if (GPOINTER_TO_INT (shutdown)) + { + save_all_docs_and_save_session (); + } + else + { + finish_interaction (FALSE); + } } /* save_yourself handler for the master client */ static gboolean -client_save_yourself_cb (GnomeClient *client, - gint phase, - GnomeSaveStyle save_style, - gboolean shutdown, - GnomeInteractStyle interact_style, - gboolean fast, - gpointer data) +client_save_yourself_cb (GnomeClient *client, + gint phase, + GnomeSaveStyle save_style, + gboolean shutdown, + GnomeInteractStyle interact_style, + gboolean fast, + gpointer data) { - const gchar *prefix; + gchar *argv[] = { "rm", "-f", NULL }; - char *argv[] = { "rm", "-r", NULL }; - - gedit_debug (DEBUG_SESSION, ""); + gedit_debug (DEBUG_SESSION); gnome_client_request_interaction (client, GNOME_DIALOG_NORMAL, interaction_function, GINT_TO_POINTER (shutdown)); - - prefix = gnome_client_get_config_prefix (client); - - gedit_debug (DEBUG_SESSION, "Prefix: %s", prefix); /* Tell the session manager how to discard this save */ - - argv[2] = gnome_config_get_real_path (prefix); + argv[2] = get_session_file_path (client); gnome_client_set_discard_command (client, 3, argv); + g_free (argv[2]); + /* Tell the session manager how to clone or restart this instance */ argv[0] = (char *) program_argv0; - argv[1] = NULL; /* "--debug-session"; */ - - gnome_client_set_clone_command (client, 1 /*2*/, argv); - gnome_client_set_restart_command (client, 1 /*2*/, argv); + argv[1] = NULL; + + gnome_client_set_clone_command (client, 1, argv); + gnome_client_set_restart_command (client, 1, argv); - gedit_debug (DEBUG_SESSION, "END"); + gedit_debug_message (DEBUG_SESSION, "END"); return TRUE; } @@ -126,27 +583,28 @@ client_save_yourself_cb (GnomeClient *client, static void client_die_cb (GnomeClient *client, gpointer data) { - gedit_debug (DEBUG_SESSION, ""); +#if 0 + gedit_debug (DEBUG_SESSION); if (!client->save_yourself_emitted) gedit_file_close_all (); - gedit_debug (DEBUG_FILE, "All files closed."); + gedit_debug_message (DEBUG_FILE, "All files closed."); bonobo_mdi_destroy (BONOBO_MDI (gedit_mdi)); - gedit_debug (DEBUG_FILE, "Unref gedit_mdi."); + gedit_debug_message (DEBUG_FILE, "Unref gedit_mdi."); g_object_unref (G_OBJECT (gedit_mdi)); - gedit_debug (DEBUG_FILE, "Unref gedit_mdi: DONE"); + gedit_debug_message (DEBUG_FILE, "Unref gedit_mdi: DONE"); - gedit_debug (DEBUG_FILE, "Unref gedit_app_server."); + gedit_debug_message (DEBUG_FILE, "Unref gedit_app_server."); bonobo_object_unref (gedit_app_server); - gedit_debug (DEBUG_FILE, "Unref gedit_app_server: DONE"); - + gedit_debug_message (DEBUG_FILE, "Unref gedit_app_server: DONE"); +#endif gedit_prefs_manager_app_shutdown (); gedit_metadata_manager_shutdown (); gedit_plugins_engine_shutdown (); @@ -163,21 +621,23 @@ client_die_cb (GnomeClient *client, gpointer data) void gedit_session_init (const char *argv0) { - gedit_debug (DEBUG_SESSION, ""); + gedit_debug (DEBUG_SESSION); if (master_client) return; program_argv0 = argv0; - + master_client = gnome_master_client (); - g_signal_connect (master_client, "save_yourself", + g_signal_connect (master_client, + "save_yourself", G_CALLBACK (client_save_yourself_cb), NULL); - g_signal_connect (master_client, "die", + g_signal_connect (master_client, + "die", G_CALLBACK (client_die_cb), - NULL); + NULL); } /** @@ -193,39 +653,132 @@ gboolean gedit_session_is_restored (void) { gboolean restored; - - gedit_debug (DEBUG_SESSION, ""); + + gedit_debug (DEBUG_SESSION); if (!master_client) return FALSE; restored = (gnome_client_get_flags (master_client) & GNOME_CLIENT_RESTORED) != 0; - gedit_debug (DEBUG_SESSION, restored ? "RESTORED" : "NOT RESTORED"); + gedit_debug_message (DEBUG_SESSION, restored ? "RESTORED" : "NOT RESTORED"); return restored; } -/* Callback used from bonobo_mdi_restore_state() */ -static BonoboMDIChild * -mdi_child_create_cb (const gchar *str) +static void +parse_window (xmlNodePtr node) { - GeditMDIChild *child; + GeditWindow *window; + xmlChar *role; + xmlNodePtr child; - gedit_debug (DEBUG_SESSION, ""); + role = xmlGetProp (node, (const xmlChar *) "role"); + gedit_debug_message (DEBUG_SESSION, "Window role: %s", role); - /* The config string is simply a filename */ - if (str != NULL) - { - gedit_debug (DEBUG_SESSION, "URI: %s", str); + window = _gedit_app_restore_window (gedit_app_get_default (), role); + + if (role != NULL) + xmlFree (role); - /* FIXME */ - child = gedit_mdi_child_new_with_uri (str, NULL); + if (window == NULL) + { + g_warning ("Couldn't restore window"); + return; } - else - child = gedit_mdi_child_new (); - return (child == NULL) ? NULL : BONOBO_MDI_CHILD (child); + child = node->children; + + while (child != NULL) + { + if (strcmp ((char *) child->name, "side-pane") == 0) + { + xmlChar *visible; + + visible = xmlGetProp (child, (const xmlChar *) "visible"); + + if ((visible != NULL) && + (strcmp ((char *) visible, "yes") == 0)) + { + gedit_debug_message (DEBUG_SESSION, "Side panel visible"); + _gedit_window_set_side_panel_visible (window, + TRUE); + } + else + { + gedit_debug_message (DEBUG_SESSION, "Side panel _NOT_ visible"); + _gedit_window_set_side_panel_visible (window, + FALSE); + + } + + if (visible != NULL) + xmlFree (visible); + } + else if (strcmp ((char *) child->name, "bottom-panel") == 0) + { + xmlChar *visible; + + visible = xmlGetProp (child, (const xmlChar *) "visible"); + + if ((visible != NULL) && + (strcmp ((char *) visible, "yes") == 0)) + { + gedit_debug_message (DEBUG_SESSION, "Bottom panel visible"); + _gedit_window_set_bottom_panel_visible (window, + TRUE); + } + else + { + gedit_debug_message (DEBUG_SESSION, "Bottom panel _NOT_ visible"); + _gedit_window_set_bottom_panel_visible (window, + FALSE); + + } + + if (visible != NULL) + xmlFree (visible); + } + else if (strcmp ((char *) child->name, "document") == 0) + { + xmlChar *uri; + xmlChar *active; + + uri = xmlGetProp (child, (const xmlChar *) "uri"); + if (uri != NULL) + { + gboolean jump_to; + + active = xmlGetProp (child, (const xmlChar *) "active"); + if (active != NULL) + { + jump_to = (strcmp ((char *) active, "yes") == 0); + xmlFree (active); + } + else + { + jump_to = FALSE; + } + + gedit_debug_message (DEBUG_SESSION, + "URI: %s (%s)", + (gchar *) uri, + jump_to ? "active" : "not active"); + + gedit_window_create_tab_from_uri (window, + (const gchar *)uri, + NULL, + 0, + FALSE, + jump_to); + + xmlFree (uri); + } + } + + child = child->next; + } + gtk_widget_show (GTK_WIDGET (window)); } /** @@ -239,15 +792,43 @@ mdi_child_create_cb (const gchar *str) gboolean gedit_session_load (void) { - int retval; + xmlDocPtr doc; + xmlNodePtr child; + gchar *fname; - gedit_debug (DEBUG_SESSION, ""); + gedit_debug (DEBUG_SESSION); - gnome_config_push_prefix (gnome_client_get_config_prefix (master_client)); + fname = get_session_file_path (master_client); + gedit_debug_message (DEBUG_SESSION, "Session file: %s", fname); + + doc = xmlParseFile (fname); + g_free (fname); - retval = bonobo_mdi_restore_state (BONOBO_MDI (gedit_mdi), "Session", - mdi_child_create_cb); + if (doc == NULL) + return FALSE; + + child = xmlDocGetRootElement (doc); + + /* skip the session node */ + child = child->children; + + while (child != NULL) + { + if (xmlStrEqual (child->name, (const xmlChar *) "window")) + { + gedit_debug_message (DEBUG_SESSION, "Restore window"); + + parse_window (child); - gnome_config_pop_prefix (); - return retval; + // ephy_gui_window_update_user_time (widget, user_time); + + //gtk_widget_show (widget); + } + + child = child->next; + } + + xmlFreeDoc (doc); + + return TRUE; } diff --git a/gedit/gedit-session.h b/gedit/gedit-session.h index 1edc8c5d..61e51332 100644 --- a/gedit/gedit-session.h +++ b/gedit/gedit-session.h @@ -1,6 +1,9 @@ -/* gedit-session - Basic session management for gedit +/* + * gedit-session.h - Basic session management for gedit + * This file is part of gedit * * Copyright (C) 2002 Ximian, Inc. + * Copyright (C) 2005 - Paolo Maggi * * Author: Federico Mena-Quintero * @@ -21,16 +24,24 @@ */ /* - * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. - * See the ChangeLog files for a list of changes. + * See the ChangeLog files for a list of changes. + * + * $Id */ #ifndef __GEDIT_SESSION_H__ #define __GEDIT_SESSION_H__ -void gedit_session_init (const char *argv0); -gboolean gedit_session_is_restored (void); -gboolean gedit_session_load (void); +#include + +G_BEGIN_DECLS + +void gedit_session_init (const char *argv0); +gboolean gedit_session_is_restored (void); +gboolean gedit_session_load (void); + +G_END_DECLS -#endif +#endif /* __GEDIT_SESSION_H__ */ diff --git a/gedit/gedit-spinner.c b/gedit/gedit-spinner.c new file mode 100644 index 00000000..ee044795 --- /dev/null +++ b/gedit/gedit-spinner.c @@ -0,0 +1,828 @@ +/* + * gedit-spinner.c + * This file is part of gedit + * + * Copyright (C) 2005 - Paolo Maggi + * Copyright (C) 2002-2004 Marco Pesenti Gritti + * Copyright (C) 2004 Christian Persch + * Copyright (C) 2000 - Eazel, Inc. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This widget was originally written by Andy Hertzfeld for + * Nautilus. It was then modified by Marco Pesenti Gritti and Christian Persch + * for Epiphany. + * + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-spinner.h" + +#include +#include +#include +#include + +/* Spinner cache implementation */ + +#define GEDIT_TYPE_SPINNER_CACHE (gedit_spinner_cache_get_type()) +#define GEDIT_SPINNER_CACHE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCache)) +#define GEDIT_SPINNER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCacheClass)) +#define GEDIT_IS_SPINNER_CACHE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), GEDIT_TYPE_SPINNER_CACHE)) +#define GEDIT_IS_SPINNER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GEDIT_TYPE_SPINNER_CACHE)) +#define GEDIT_SPINNER_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCacheClass)) + +typedef struct _GeditSpinnerCache GeditSpinnerCache; +typedef struct _GeditSpinnerCacheClass GeditSpinnerCacheClass; +typedef struct _GeditSpinnerCachePrivate GeditSpinnerCachePrivate; +typedef struct _GeditSpinnerImages GeditSpinnerImages; + +struct _GeditSpinnerImages +{ + GtkIconSize size; + gint width; + gint height; + GdkPixbuf *quiescent_pixbuf; + GList *images; +}; + +struct _GeditSpinnerCacheClass +{ + GObjectClass parent_class; +}; + +struct _GeditSpinnerCache +{ + GObject parent_object; + + /*< private >*/ + GeditSpinnerCachePrivate *priv; +}; + +#define GEDIT_SPINNER_CACHE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCachePrivate)) + +struct _GeditSpinnerCachePrivate +{ + GtkIconTheme *icon_theme; + GeditSpinnerImages *originals; + + /* List of GeditSpinnerImages scaled to different sizes */ + GList *images; +}; + +static void gedit_spinner_cache_class_init (GeditSpinnerCacheClass *klass); +static void gedit_spinner_cache_init (GeditSpinnerCache *cache); + +static GObjectClass *cache_parent_class = NULL; + +static GType +gedit_spinner_cache_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) + { + static const GTypeInfo our_info = + { + sizeof (GeditSpinnerCacheClass), + NULL, + NULL, + (GClassInitFunc) gedit_spinner_cache_class_init, + NULL, + NULL, + sizeof (GeditSpinnerCache), + 0, + (GInstanceInitFunc) gedit_spinner_cache_init + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "GeditSpinnerCache", + &our_info, 0); + } + + return type; +} + +static void +gedit_spinner_images_free (GeditSpinnerImages *images) +{ + if (images != NULL) + { + g_list_foreach (images->images, (GFunc) g_object_unref, NULL); + g_object_unref (images->quiescent_pixbuf); + + g_free (images); + } +} + +static GeditSpinnerImages * +gedit_spinner_images_copy (GeditSpinnerImages *images) +{ + GeditSpinnerImages *copy = g_new (GeditSpinnerImages, 1); + + copy->size = images->size; + copy->width = images->width; + copy->height = images->height; + + copy->quiescent_pixbuf = g_object_ref (images->quiescent_pixbuf); + copy->images = g_list_copy (images->images); + g_list_foreach (copy->images, (GFunc) g_object_ref, NULL); + + return copy; +} + +static void +gedit_spinner_cache_unload (GeditSpinnerCache *cache) +{ + g_list_foreach (cache->priv->images, (GFunc) gedit_spinner_images_free, NULL); + cache->priv->images = NULL; + cache->priv->originals = NULL; +} + +static GdkPixbuf * +extract_frame (GdkPixbuf *grid_pixbuf, + int x, + int y, + int size) +{ + GdkPixbuf *pixbuf; + + if (x + size > gdk_pixbuf_get_width (grid_pixbuf) || + y + size > gdk_pixbuf_get_height (grid_pixbuf)) + { + return NULL; + } + + pixbuf = gdk_pixbuf_new_subpixbuf (grid_pixbuf, + x, y, + size, size); + g_return_val_if_fail (pixbuf != NULL, NULL); + + return pixbuf; +} + +static void +gedit_spinner_cache_load (GeditSpinnerCache *cache) +{ + GeditSpinnerImages *images; + GdkPixbuf *icon_pixbuf, *pixbuf; + GtkIconInfo *icon_info; + int grid_width, grid_height, x, y, size, h, w; + const char *icon; + + /* LOG ("GeditSpinnerCache loading"); */ + + gedit_spinner_cache_unload (cache); + + /* START_PROFILER ("loading spinner animation") */ + + /* Load the animation */ + icon_info = gtk_icon_theme_lookup_icon (cache->priv->icon_theme, + "gnome-spinner", -1, 0); + if (icon_info == NULL) + { + /* STOP_PROFILER ("loading spinner animation") */ + + g_warning ("Throbber animation not found."); + return; + } + + size = gtk_icon_info_get_base_size (icon_info); + icon = gtk_icon_info_get_filename (icon_info); + g_return_if_fail (icon != NULL); + + icon_pixbuf = gdk_pixbuf_new_from_file (icon, NULL); + if (icon_pixbuf == NULL) + { + /* STOP_PROFILER ("loading spinner animation") */ + + g_warning ("Could not load the spinner file."); + gtk_icon_info_free (icon_info); + return; + } + + grid_width = gdk_pixbuf_get_width (icon_pixbuf); + grid_height = gdk_pixbuf_get_height (icon_pixbuf); + + images = g_new (GeditSpinnerImages, 1); + cache->priv->images = g_list_prepend (NULL, images); + cache->priv->originals = images; + + images->size = GTK_ICON_SIZE_INVALID; + images->width = images->height = size; + images->images = NULL; + images->quiescent_pixbuf = NULL; + + for (y = 0; y < grid_height; y += size) + { + for (x = 0; x < grid_width ; x += size) + { + pixbuf = extract_frame (icon_pixbuf, x, y, size); + + if (pixbuf) + { + images->images = + g_list_prepend (images->images, pixbuf); + } + else + { + g_warning ("Cannot extract frame from the grid."); + } + } + } + images->images = g_list_reverse (images->images); + + gtk_icon_info_free (icon_info); + g_object_unref (icon_pixbuf); + + /* Load the rest icon */ + icon_info = gtk_icon_theme_lookup_icon (cache->priv->icon_theme, + "gnome-spinner-rest", -1, 0); + if (icon_info == NULL) + { + /* STOP_PROFILER ("loading spinner animation") */ + + g_warning ("Throbber rest icon not found."); + return; + } + + size = gtk_icon_info_get_base_size (icon_info); + icon = gtk_icon_info_get_filename (icon_info); + g_return_if_fail (icon != NULL); + + icon_pixbuf = gdk_pixbuf_new_from_file (icon, NULL); + gtk_icon_info_free (icon_info); + + if (icon_pixbuf == NULL) + { + /* STOP_PROFILER ("loading spinner animation") */ + + g_warning ("Could not load spinner rest icon."); + gedit_spinner_images_free (images); + return; + } + + images->quiescent_pixbuf = icon_pixbuf; + + w = gdk_pixbuf_get_width (icon_pixbuf); + h = gdk_pixbuf_get_height (icon_pixbuf); + images->width = MAX (images->width, w); + images->height = MAX (images->height, h); + + /* STOP_PROFILER ("loading spinner animation") */ +} + +static int +compare_size (gconstpointer images_ptr, + gconstpointer size_ptr) +{ + const GeditSpinnerImages *images = (const GeditSpinnerImages *) images_ptr; + GtkIconSize size = GPOINTER_TO_INT (size_ptr); + + if (images->size == size) + { + return 0; + } + + return -1; +} + +static GdkPixbuf * +scale_to_size (GdkPixbuf *pixbuf, + int dw, + int dh) +{ + GdkPixbuf *result; + int pw, ph; + + pw = gdk_pixbuf_get_width (pixbuf); + ph = gdk_pixbuf_get_height (pixbuf); + + if (pw != dw || ph != dh) + { + result = gdk_pixbuf_scale_simple (pixbuf, dw, dh, + GDK_INTERP_BILINEAR); + } + else + { + result = g_object_ref (pixbuf); + } + + return result; +} + +static GeditSpinnerImages * +gedit_spinner_cache_get_images (GeditSpinnerCache *cache, + GtkIconSize size) +{ + GeditSpinnerImages *images; + GdkPixbuf *pixbuf, *scaled_pixbuf; + GList *element, *l; + int h, w; + + /* LOG ("Getting animation images at size %d", size); */ + + if (cache->priv->images == NULL || cache->priv->originals == NULL) + { + return NULL; + } + + element = g_list_find_custom (cache->priv->images, + GINT_TO_POINTER (size), + (GCompareFunc) compare_size); + if (element != NULL) + { + return gedit_spinner_images_copy ((GeditSpinnerImages *) element->data); + } + + if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default (), size, &w, &h)) + { + g_warning ("Failed to lookup icon size."); + return NULL; + } + + images = g_new (GeditSpinnerImages, 1); + images->size = size; + images->width = w; + images->height = h; + images->images = NULL; + + /* START_PROFILER ("scaling spinner animation") */ + + for (l = cache->priv->originals->images; l != NULL; l = l->next) + { + pixbuf = (GdkPixbuf *) l->data; + scaled_pixbuf = scale_to_size (pixbuf, w, h); + + images->images = g_list_prepend (images->images, scaled_pixbuf); + } + images->images = g_list_reverse (images->images); + + images->quiescent_pixbuf = + scale_to_size (cache->priv->originals->quiescent_pixbuf, w, h); + + /* store in cache */ + cache->priv->images = g_list_prepend (cache->priv->images, images); + + /* STOP_PROFILER ("scaling spinner animation") */ + + return gedit_spinner_images_copy (images); +} + +static void +gedit_spinner_cache_init (GeditSpinnerCache *cache) +{ + cache->priv = GEDIT_SPINNER_CACHE_GET_PRIVATE (cache); + + /* LOG ("GeditSpinnerCache initialising"); */ + + /* FIXME: icon theme is per-screen, not global */ + cache->priv->icon_theme = gtk_icon_theme_get_default (); + g_signal_connect_swapped (cache->priv->icon_theme, "changed", + G_CALLBACK (gedit_spinner_cache_load), cache); + + gedit_spinner_cache_load (cache); +} + +static void +gedit_spinner_cache_finalize (GObject *object) +{ + GeditSpinnerCache *cache = GEDIT_SPINNER_CACHE (object); + + /* LOG ("GeditSpinnerCache finalising"); */ + + g_signal_handlers_disconnect_by_func + (cache->priv->icon_theme, G_CALLBACK(gedit_spinner_cache_load), cache); + + gedit_spinner_cache_unload (cache); + + G_OBJECT_CLASS (cache_parent_class)->finalize (object); +} + +static void +gedit_spinner_cache_class_init (GeditSpinnerCacheClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + cache_parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gedit_spinner_cache_finalize; + + g_type_class_add_private (object_class, sizeof (GeditSpinnerCachePrivate)); +} + +static GeditSpinnerCache *spinner_cache = NULL; + +static GeditSpinnerCache * +gedit_spinner_cache_ref (void) +{ + if (spinner_cache == NULL) + { + GeditSpinnerCache **cache_ptr; + + spinner_cache = g_object_new (GEDIT_TYPE_SPINNER_CACHE, NULL); + cache_ptr = &spinner_cache; + g_object_add_weak_pointer (G_OBJECT (spinner_cache), + (gpointer *) cache_ptr); + + return spinner_cache; + } + else + { + return g_object_ref (spinner_cache); + } +} + +/* Spinner implementation */ + +#define SPINNER_TIMEOUT 100 /* Milliseconds Per Frame */ + +#define GEDIT_SPINNER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SPINNER, GeditSpinnerPrivate)) + +struct _GeditSpinnerPrivate +{ + GtkIconTheme *icon_theme; + GeditSpinnerCache *cache; + GtkIconSize size; + GeditSpinnerImages *images; + GList *current_image; + guint timer_task; +}; + +static void gedit_spinner_class_init (GeditSpinnerClass *class); +static void gedit_spinner_init (GeditSpinner *spinner); + +static GObjectClass *parent_class = NULL; + +GType +gedit_spinner_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) + { + static const GTypeInfo our_info = + { + sizeof (GeditSpinnerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gedit_spinner_class_init, + NULL, + NULL, /* class_data */ + sizeof (GeditSpinner), + 0, /* n_preallocs */ + (GInstanceInitFunc) gedit_spinner_init + }; + + type = g_type_register_static (GTK_TYPE_EVENT_BOX, + "GeditSpinner", + &our_info, 0); + } + + return type; +} + +static gboolean +gedit_spinner_load_images (GeditSpinner *spinner) +{ + GeditSpinnerPrivate *details = spinner->priv; + + if (details->images == NULL) + { + /* START_PROFILER ("gedit_spinner_load_images") */ + + details->images = + gedit_spinner_cache_get_images (details->cache, details->size); + + if (details->images != NULL) + { + details->current_image = details->images->images; + } + + /* STOP_PROFILER ("gedit_spinner_load_images") */ + } + + return details->images != NULL; +} + +static void +gedit_spinner_unload_images (GeditSpinner *spinner) +{ + gedit_spinner_images_free (spinner->priv->images); + spinner->priv->images = NULL; + spinner->priv->current_image = NULL; +} + +static void +icon_theme_changed_cb (GtkIconTheme *icon_theme, + GeditSpinner *spinner) +{ + gedit_spinner_unload_images (spinner); + gtk_widget_queue_resize (GTK_WIDGET (spinner)); +} + +static void +gedit_spinner_init (GeditSpinner *spinner) +{ + GtkWidget *widget = GTK_WIDGET (spinner); + + gtk_widget_set_events (widget, + gtk_widget_get_events (widget) + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + + spinner->priv = GEDIT_SPINNER_GET_PRIVATE (spinner); + + spinner->priv->cache = gedit_spinner_cache_ref (); + spinner->priv->size = GTK_ICON_SIZE_INVALID; + + /* FIXME: icon theme is per-screen, not global */ + spinner->priv->icon_theme = gtk_icon_theme_get_default (); + g_signal_connect (spinner->priv->icon_theme, "changed", + G_CALLBACK (icon_theme_changed_cb), spinner); + +} + +static GdkPixbuf * +select_spinner_image (GeditSpinner *spinner) +{ + GeditSpinnerPrivate *details = spinner->priv; + GeditSpinnerImages *images = details->images; + + g_return_val_if_fail (images != NULL, NULL); + + if (spinner->priv->timer_task == 0) + { + if (images->quiescent_pixbuf != NULL) + { + return g_object_ref (details->images->quiescent_pixbuf); + } + + return NULL; + } + + g_return_val_if_fail (details->current_image != NULL, NULL); + + return g_object_ref (details->current_image->data); +} + +static int +gedit_spinner_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GeditSpinner *spinner = GEDIT_SPINNER (widget); + GdkPixbuf *pixbuf; + GdkGC *gc; + int x_offset, y_offset, width, height; + GdkRectangle pix_area, dest; + + if (!GTK_WIDGET_DRAWABLE (spinner)) + { + return TRUE; + } + + if (!gedit_spinner_load_images (spinner)) + { + return TRUE; + } + + pixbuf = select_spinner_image (spinner); + if (pixbuf == NULL) + { + return FALSE; + } + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + + /* Compute the offsets for the image centered on our allocation */ + x_offset = (widget->allocation.width - width) / 2; + y_offset = (widget->allocation.height - height) / 2; + + pix_area.x = x_offset + widget->allocation.x; + pix_area.y = y_offset + widget->allocation.y; + pix_area.width = width; + pix_area.height = height; + + if (!gdk_rectangle_intersect (&event->area, &pix_area, &dest)) + { + g_object_unref (pixbuf); + return FALSE; + } + + gc = gdk_gc_new (widget->window); + gdk_draw_pixbuf (widget->window, gc, pixbuf, + dest.x - x_offset - widget->allocation.x, + dest.y - y_offset - widget->allocation.y, + dest.x, dest.y, + dest.width, dest.height, + GDK_RGB_DITHER_MAX, 0, 0); + g_object_unref (gc); + + g_object_unref (pixbuf); + + return FALSE; +} + +static gboolean +bump_spinner_frame_cb (GeditSpinner *spinner) +{ + GList *frame; + + if (!GTK_WIDGET_DRAWABLE (spinner)) + { + return TRUE; + } + + frame = spinner->priv->current_image; + + if (g_list_next (frame) != NULL) + { + frame = frame->next; + } + else + { + frame = g_list_first (frame); + } + + spinner->priv->current_image = frame; + + gtk_widget_queue_draw (GTK_WIDGET (spinner)); + + /* run again */ + return TRUE; +} + +/** + * gedit_spinner_start: + * @spinner: a #GeditSpinner + * + * Start the spinner animation. + **/ +void +gedit_spinner_start (GeditSpinner *spinner) +{ + if (spinner->priv->timer_task == 0) + { + + if (spinner->priv->images != NULL) + { + /* reset to first frame */ + spinner->priv->current_image = + spinner->priv->images->images; + } + + spinner->priv->timer_task = + g_timeout_add (SPINNER_TIMEOUT, + (GSourceFunc) bump_spinner_frame_cb, + spinner); + } +} + +static void +gedit_spinner_remove_update_callback (GeditSpinner *spinner) +{ + if (spinner->priv->timer_task != 0) + { + g_source_remove (spinner->priv->timer_task); + spinner->priv->timer_task = 0; + } +} + +/** + * gedit_spinner_stop: + * @spinner: a #GeditSpinner + * + * Stop the spinner animation. + **/ +void +gedit_spinner_stop (GeditSpinner *spinner) +{ + if (spinner->priv->timer_task != 0) + { + gedit_spinner_remove_update_callback (spinner); + gtk_widget_queue_draw (GTK_WIDGET (spinner)); + } +} + +/* + * gedit_spinner_set_size: + * @spinner: a #GeditSpinner + * @size: the size of type %GtkIconSize + * + * Set the size of the spinner. Use %GTK_ICON_SIZE_INVALID to use the + * native size of the icons. + **/ +void +gedit_spinner_set_size (GeditSpinner *spinner, + GtkIconSize size) +{ + if (size != spinner->priv->size) + { + gedit_spinner_unload_images (spinner); + + spinner->priv->size = size; + + gtk_widget_queue_resize (GTK_WIDGET (spinner)); + } +} + +static void +gedit_spinner_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GeditSpinner *spinner = GEDIT_SPINNER (widget); + + if (!gedit_spinner_load_images (spinner)) + { + requisition->width = requisition->height = 0; + gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget), + spinner->priv->size, + &requisition->width, + &requisition->height); + return; + } + + requisition->width = spinner->priv->images->width; + requisition->height = spinner->priv->images->height; + + /* allocate some extra margin so we don't butt up against toolbar edges */ + if (spinner->priv->size != GTK_ICON_SIZE_MENU) + { + requisition->width += 4; + requisition->height += 4; + } +} + +static void +gedit_spinner_finalize (GObject *object) +{ + GeditSpinner *spinner = GEDIT_SPINNER (object); + + g_signal_handlers_disconnect_by_func + (spinner->priv->icon_theme, + G_CALLBACK (icon_theme_changed_cb), spinner); + + gedit_spinner_remove_update_callback (spinner); + gedit_spinner_unload_images (spinner); + + g_object_unref (spinner->priv->cache); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gedit_spinner_class_init (GeditSpinnerClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + + parent_class = g_type_class_peek_parent (class); + + object_class->finalize = gedit_spinner_finalize; + + widget_class->expose_event = gedit_spinner_expose; + widget_class->size_request = gedit_spinner_size_request; + + g_type_class_add_private (object_class, sizeof (GeditSpinnerPrivate)); +} + +/* + * gedit_spinner_new: + * + * Create a new #GeditSpinner. The spinner is a widget + * that gives the user feedback about network status with + * an animated image. + * + * Return Value: the spinner #GtkWidget + **/ +GtkWidget * +gedit_spinner_new (void) +{ + return GTK_WIDGET (g_object_new (GEDIT_TYPE_SPINNER, + "visible-window", FALSE, + NULL)); +} diff --git a/gedit/gedit-spinner.h b/gedit/gedit-spinner.h new file mode 100644 index 00000000..c28a3cdd --- /dev/null +++ b/gedit/gedit-spinner.h @@ -0,0 +1,96 @@ +/* + * gedit-spinner.h + * This file is part of gedit + * + * Copyright (C) 2005 - Paolo Maggi + * Copyright (C) 2000 - Eazel, Inc. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This widget was originally written by Andy Hertzfeld for + * Nautilus. + * + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_SPINNER_H__ +#define __GEDIT_SPINNER_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_SPINNER (gedit_spinner_get_type ()) +#define GEDIT_SPINNER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_SPINNER, GeditSpinner)) +#define GEDIT_SPINNER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_SPINNER, GeditSpinnerClass)) +#define GEDIT_IS_SPINNER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_SPINNER)) +#define GEDIT_IS_SPINNER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_SPINNER)) +#define GEDIT_SPINNER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_SPINNER, GeditSpinnerClass)) + + +/* Private structure type */ +typedef struct _GeditSpinnerPrivate GeditSpinnerPrivate; + +/* + * Main object structure + */ +typedef struct _GeditSpinner GeditSpinner; + +struct _GeditSpinner +{ + GtkEventBox parent; + + /*< private >*/ + GeditSpinnerPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditSpinnerClass GeditSpinnerClass; + +struct _GeditSpinnerClass +{ + GtkEventBoxClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_spinner_get_type (void) G_GNUC_CONST;; + +GtkWidget *gedit_spinner_new (void); + +void gedit_spinner_start (GeditSpinner *throbber); + +void gedit_spinner_stop (GeditSpinner *throbber); + +void gedit_spinner_set_size (GeditSpinner *spinner, + GtkIconSize size); + +G_END_DECLS + +#endif /* __GEDIT_SPINNER_H__ */ diff --git a/gedit/gedit-statusbar.c b/gedit/gedit-statusbar.c new file mode 100644 index 00000000..dcf683e5 --- /dev/null +++ b/gedit/gedit-statusbar.c @@ -0,0 +1,415 @@ +/* + * gedit-statusbar.c + * This file is part of gedit + * + * Copyright (C) 2005 - Paolo Borelli + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "gedit-statusbar.h" +#include "gedit-tooltips.h" + +#define GEDIT_STATUSBAR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_STATUSBAR, GeditStatusbarPrivate)) + +struct _GeditStatusbarPrivate +{ + GtkWidget *overwrite_mode_statusbar; + GtkWidget *cursor_position_statusbar; + + GtkWidget *state_frame; + GtkWidget *load_image; + GtkWidget *save_image; + GtkWidget *print_image; + + GtkWidget *error_frame; + GtkWidget *error_event_box; + + GeditTooltips *tooltips; + + /* tmp flash timeout data */ + guint flash_timeout; + guint flash_context_id; + guint flash_message_id; +}; + +G_DEFINE_TYPE(GeditStatusbar, gedit_statusbar, GTK_TYPE_STATUSBAR) + +static void +gedit_statusbar_notify (GObject *object, + GParamSpec *pspec) +{ + /* don't allow gtk_statusbar_set_has_resize_grip to mess with us. + * See _gedit_statusbar_set_has_resize_grip for an explanation. + */ + if (strcmp (g_param_spec_get_name (pspec), "has-resize-grip") == 0) + { + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (object), FALSE); + return; + } + + if (G_OBJECT_CLASS (gedit_statusbar_parent_class)->notify) + G_OBJECT_CLASS (gedit_statusbar_parent_class)->notify (object, pspec); +} + +static void +gedit_statusbar_finalize (GObject *object) +{ + GeditStatusbar *statusbar = GEDIT_STATUSBAR (object); + + g_object_unref (statusbar->priv->tooltips); + + if (statusbar->priv->flash_timeout > 0) + g_source_remove (statusbar->priv->flash_timeout); + + G_OBJECT_CLASS (gedit_statusbar_parent_class)->finalize (object); +} + +static void +gedit_statusbar_class_init (GeditStatusbarClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->notify = gedit_statusbar_notify; + object_class->finalize = gedit_statusbar_finalize; + + g_type_class_add_private (object_class, sizeof (GeditStatusbarPrivate)); +} + +static void +gedit_statusbar_init (GeditStatusbar *statusbar) +{ + GtkWidget *hbox; + GtkWidget *error_image; + + statusbar->priv = GEDIT_STATUSBAR_GET_PRIVATE (statusbar); + + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), FALSE); + + statusbar->priv->overwrite_mode_statusbar = gtk_statusbar_new (); + gtk_widget_show (statusbar->priv->overwrite_mode_statusbar); + gtk_widget_set_size_request (statusbar->priv->overwrite_mode_statusbar, + 80, + 10); + + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar->priv->overwrite_mode_statusbar), + TRUE); + gtk_box_pack_end (GTK_BOX (statusbar), + statusbar->priv->overwrite_mode_statusbar, + FALSE, TRUE, 0); + + statusbar->priv->cursor_position_statusbar = gtk_statusbar_new (); + gtk_widget_show (statusbar->priv->cursor_position_statusbar); + gtk_widget_set_size_request (statusbar->priv->cursor_position_statusbar, + 160, + 10); + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar->priv->cursor_position_statusbar), + FALSE); + gtk_box_pack_end (GTK_BOX (statusbar), + statusbar->priv->cursor_position_statusbar, + FALSE, TRUE, 0); + + statusbar->priv->state_frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (statusbar->priv->state_frame), GTK_SHADOW_IN); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (statusbar->priv->state_frame), hbox); + + statusbar->priv->load_image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU); + statusbar->priv->save_image = gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); + statusbar->priv->print_image = gtk_image_new_from_stock (GTK_STOCK_PRINT, GTK_ICON_SIZE_MENU); + + gtk_widget_show (hbox); + + gtk_box_pack_start (GTK_BOX (hbox), + statusbar->priv->load_image, + FALSE, TRUE, 4); + gtk_box_pack_start (GTK_BOX (hbox), + statusbar->priv->save_image, + FALSE, TRUE, 4); + gtk_box_pack_start (GTK_BOX (hbox), + statusbar->priv->print_image, + FALSE, TRUE, 4); + + gtk_box_pack_start (GTK_BOX (statusbar), + statusbar->priv->state_frame, + FALSE, TRUE, 0); + + statusbar->priv->error_frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (statusbar->priv->error_frame), GTK_SHADOW_IN); + + error_image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_MENU); + gtk_misc_set_padding (GTK_MISC (error_image), 4, 0); + gtk_widget_show (error_image); + + statusbar->priv->error_event_box = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (statusbar->priv->error_event_box), + FALSE); + gtk_widget_show (statusbar->priv->error_event_box); + + gtk_container_add (GTK_CONTAINER (statusbar->priv->error_frame), + statusbar->priv->error_event_box); + gtk_container_add (GTK_CONTAINER (statusbar->priv->error_event_box), + error_image); + + gtk_box_pack_start (GTK_BOX (statusbar), + statusbar->priv->error_frame, + FALSE, TRUE, 0); + + gtk_box_reorder_child (GTK_BOX (statusbar), + statusbar->priv->error_frame, + 0); + + statusbar->priv->tooltips = gedit_tooltips_new (); + g_object_ref (G_OBJECT (statusbar->priv->tooltips)); + gtk_object_sink (GTK_OBJECT (statusbar->priv->tooltips)); +} + +/** + * gedit_statusbar_new: + * + * Creates a new #GeditStatusbar. + * + * Return value: the new #GeditStatusbar object + **/ +GtkWidget * +gedit_statusbar_new (void) +{ + return GTK_WIDGET (g_object_new (GEDIT_TYPE_STATUSBAR, NULL)); +} + +/** + * gedit_set_has_resize_grip: + * @statusbar: a #GeditStatusbar + * @show: if the resize grip is shown + * + * Sets if a resize grip showld be shown. + * + **/ + /* + * I don't like this much, in a perfect world it would have been + * possible to override the parent property and use + * gtk_statusbar_set_has_resize_grip. Unfortunately this is not + * possible and it's not even possible to intercept the notify signal + * since the parent property should always be set to false thus when + * using set_resize_grip (FALSE) the property doesn't change and the + * notification is not emitted. + * For now just add this private method; if needed we can turn it into + * a property. + */ +void +_gedit_statusbar_set_has_resize_grip (GeditStatusbar *bar, + gboolean show) +{ + g_return_if_fail (GEDIT_IS_STATUSBAR (bar)); + + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (bar->priv->overwrite_mode_statusbar), + show); +} + +/** + * gedit_statusbar_set_overwrite: + * @statusbar: a #GeditStatusbar + * @overwrite: if the overwrite mode is set + * + * Sets the overwrite mode on the statusbar. + **/ +void +gedit_statusbar_set_overwrite (GeditStatusbar *statusbar, + gboolean overwrite) +{ + gchar *msg; + + g_return_if_fail (GEDIT_IS_STATUSBAR (statusbar)); + + gtk_statusbar_pop (GTK_STATUSBAR (statusbar->priv->overwrite_mode_statusbar), 0); + + if (overwrite) + msg = g_strdup (_(" OVR")); + else + msg = g_strdup (_(" INS")); + + gtk_statusbar_push (GTK_STATUSBAR (statusbar->priv->overwrite_mode_statusbar), 0, msg); + + g_free (msg); +} + +void +gedit_statusbar_clear_overwrite (GeditStatusbar *statusbar) +{ + g_return_if_fail (GEDIT_IS_STATUSBAR (statusbar)); + + gtk_statusbar_pop (GTK_STATUSBAR (statusbar->priv->overwrite_mode_statusbar), 0); +} + +/** + * gedit_statusbar_cursor_position: + * @statusbar: an #GeditStatusbar + * @line: line position + * @col: column position + * + * Sets the cursor position on the statusbar. + **/ +void +gedit_statusbar_set_cursor_position (GeditStatusbar *statusbar, + gint line, + gint col) +{ + gchar *msg; + + g_return_if_fail (GEDIT_IS_STATUSBAR (statusbar)); + + gtk_statusbar_pop (GTK_STATUSBAR (statusbar->priv->cursor_position_statusbar), 0); + + if ((line == -1) && (col == -1)) + return; + + /* Translators: "Ln" is an abbreviation for "Line", Col is an abbreviation for "Column". Please, + use abbreviations if possible to avoid space problems. */ + msg = g_strdup_printf (_(" Ln %d, Col %d"), line, col); + + gtk_statusbar_push (GTK_STATUSBAR (statusbar->priv->cursor_position_statusbar), 0, msg); + + g_free (msg); +} + +static gboolean +remove_message_timeout (GeditStatusbar *statusbar) +{ + gtk_statusbar_remove (GTK_STATUSBAR (statusbar), + statusbar->priv->flash_context_id, + statusbar->priv->flash_message_id); + + /* remove the timeout */ + statusbar->priv->flash_timeout = 0; + return FALSE; +} + +/** + * gedit_statusbar_flash_message: + * @statusbar: a #GeditStatusbar + * @context_id: message context_id + * @format: message to flash on the statusbar + * + * Flash a temporary message on the statusbar. + */ +void +gedit_statusbar_flash_message (GeditStatusbar *statusbar, + guint context_id, + const gchar *format, ...) +{ + const guint32 flash_length = 3000; /* three seconds */ + va_list args; + gchar *msg; + + g_return_if_fail (GEDIT_IS_STATUSBAR (statusbar)); + g_return_if_fail (format != NULL); + + va_start (args, format); + msg = g_strdup_vprintf (format, args); + va_end (args); + + /* remove a currently ongoing flash message */ + if (statusbar->priv->flash_timeout > 0) + { + g_source_remove (statusbar->priv->flash_timeout); + statusbar->priv->flash_timeout = 0; + + gtk_statusbar_remove (GTK_STATUSBAR (statusbar), + statusbar->priv->flash_context_id, + statusbar->priv->flash_message_id); + } + + statusbar->priv->flash_context_id = context_id; + statusbar->priv->flash_message_id = gtk_statusbar_push (GTK_STATUSBAR (statusbar), + context_id, + msg); + + statusbar->priv->flash_timeout = g_timeout_add (flash_length, + (GtkFunction) remove_message_timeout, + statusbar); + + g_free (msg); +} + +void +gedit_statusbar_set_window_state (GeditStatusbar *statusbar, + GeditWindowState state, + gint num_of_errors) +{ + g_return_if_fail (GEDIT_IS_STATUSBAR (statusbar)); + + gtk_widget_hide (statusbar->priv->state_frame); + gtk_widget_hide (statusbar->priv->save_image); + gtk_widget_hide (statusbar->priv->load_image); + gtk_widget_hide (statusbar->priv->print_image); + + if (state & GEDIT_WINDOW_STATE_SAVING) + { + gtk_widget_show (statusbar->priv->state_frame); + gtk_widget_show (statusbar->priv->save_image); + } + if (state & GEDIT_WINDOW_STATE_LOADING) + { + gtk_widget_show (statusbar->priv->state_frame); + gtk_widget_show (statusbar->priv->load_image); + } + + if (state & GEDIT_WINDOW_STATE_PRINTING) + { + gtk_widget_show (statusbar->priv->state_frame); + gtk_widget_show (statusbar->priv->print_image); + } + + if (state & GEDIT_WINDOW_STATE_ERROR) + { + gchar *tip; + + tip = g_strdup_printf (ngettext("There is a tab with errors", + "There are %d tabs with errors", + num_of_errors), + num_of_errors); + + gedit_tooltips_set_tip (statusbar->priv->tooltips, + statusbar->priv->error_event_box, + tip, + NULL); + + g_free (tip); + + gtk_widget_show (statusbar->priv->error_frame); + } + else + gtk_widget_hide (statusbar->priv->error_frame); +} + + diff --git a/gedit/gedit-statusbar.h b/gedit/gedit-statusbar.h new file mode 100644 index 00000000..6efb929e --- /dev/null +++ b/gedit/gedit-statusbar.h @@ -0,0 +1,99 @@ +/* + * gedit-statusbar.h + * This file is part of gedit + * + * Copyright (C) 2005 - Paolo Borelli + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + */ + +#ifndef GEDIT_STATUSBAR_H +#define GEDIT_STATUSBAR_H + +#include +#include + +G_BEGIN_DECLS + +#define GEDIT_TYPE_STATUSBAR (gedit_statusbar_get_type ()) +#define GEDIT_STATUSBAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_STATUSBAR, GeditStatusbar)) +#define GEDIT_STATUSBAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_STATUSBAR, GeditStatusbarClass)) +#define GEDIT_IS_STATUSBAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_STATUSBAR)) +#define GEDIT_IS_STATUSBAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_STATUSBAR)) +#define GEDIT_STATUSBAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_STATUSBAR, GeditStatusbarClass)) + +typedef struct _GeditStatusbar GeditStatusbar; +typedef struct _GeditStatusbarPrivate GeditStatusbarPrivate; +typedef struct _GeditStatusbarClass GeditStatusbarClass; + +struct _GeditStatusbar +{ + GtkStatusbar parent; + + /* */ + GeditStatusbarPrivate *priv; +}; + +struct _GeditStatusbarClass +{ + GtkStatusbarClass parent_class; +}; + +GType gedit_statusbar_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_statusbar_new (void); + +/* FIXME: status is not defined in any .h */ +#define GeditStatus gint +void gedit_statusbar_set_window_state (GeditStatusbar *statusbar, + GeditWindowState state, + gint num_of_errors); + +void gedit_statusbar_set_overwrite (GeditStatusbar *statusbar, + gboolean overwrite); + +void gedit_statusbar_set_cursor_position (GeditStatusbar *statusbar, + gint line, + gint col); + +void gedit_statusbar_clear_overwrite (GeditStatusbar *statusbar); + +void gedit_statusbar_flash_message (GeditStatusbar *statusbar, + guint context_id, + const gchar *format, + ...) G_GNUC_PRINTF(3, 4); +/* FIXME: these would be nice for plugins... +void gedit_statusbar_add_widget (GeditStatusbar *statusbar, + GtkWidget *widget); +void gedit_statusbar_remove_widget (GeditStatusbar *statusbar, + GtkWidget *widget); +*/ + +/* + * Non exported functions + */ +void _gedit_statusbar_set_has_resize_grip (GeditStatusbar *statusbar, + gboolean show); + +G_END_DECLS + +#endif diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c new file mode 100644 index 00000000..5da87730 --- /dev/null +++ b/gedit/gedit-tab.c @@ -0,0 +1,1979 @@ +/* + * gedit-tab.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include + +#include "gedit-app.h" +#include "gedit-notebook.h" +#include "gedit-tab.h" +#include "gedit-utils.h" +#include "gedit-message-area.h" +#include "gedit-io-error-message-area.h" +#include "gedit-print-job-preview.h" +#include "gedit-progress-message-area.h" +#include "gedit-debug.h" +#include "gedit-prefs-manager-app.h" +#include "gedit-recent.h" +#include "gedit-convert.h" + +#define GEDIT_TAB_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_TAB, GeditTabPrivate)) + +#define GEDIT_TAB_KEY "GEDIT_TAB_KEY" + +struct _GeditTabPrivate +{ + GeditTabState state; + + GtkWidget *view; + GtkWidget *view_scrolled_window; + + GtkWidget *message_area; + GtkWidget *print_preview; + + GeditPrintJob *print_job; + + /* tmp data for saving */ + gchar *tmp_save_uri; + + /* tmp data for loading */ + gint tmp_line_pos; + const GeditEncoding *tmp_encoding; + + GTimer *timer; + guint times_called; + + gboolean not_editable; + + GeditDocumentSaveFlags save_flags; +}; + +G_DEFINE_TYPE(GeditTab, gedit_tab, GTK_TYPE_VBOX) + +enum +{ + PROP_0, + PROP_NAME, + PROP_STATE +}; + + +static void +gedit_tab_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditTab *tab = GEDIT_TAB (object); + + switch (prop_id) + { + case PROP_NAME: + g_value_take_string (value, + _gedit_tab_get_name (tab)); + break; + case PROP_STATE: + g_value_set_int (value, + gedit_tab_get_state (tab)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_tab_finalize (GObject *object) +{ + GeditTab *tab = GEDIT_TAB (object); + + if (tab->priv->print_job != NULL) + { + g_print ("Cancelling printing\n"); + + gtk_source_print_job_cancel (GTK_SOURCE_PRINT_JOB (tab->priv->print_job)); + g_object_unref (tab->priv->print_job); + } + + if (tab->priv->timer != NULL) + g_timer_destroy (tab->priv->timer); + + g_free (tab->priv->tmp_save_uri); + + G_OBJECT_CLASS (gedit_tab_parent_class)->finalize (object); +} + +static void +gedit_tab_class_init (GeditTabClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_tab_finalize; + object_class->get_property = gedit_tab_get_property; + + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + "Name", + "The tab's name", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_STATE, + g_param_spec_int ("state", + "State", + "The tab's state", + 0, /* GEDIT_TAB_STATE_NORMAL */ + GEDIT_TAB_NUM_OF_STATES - 1, + 0, /* GEDIT_TAB_STATE_NORMAL */ + G_PARAM_READABLE)); + + g_type_class_add_private (object_class, sizeof (GeditTabPrivate)); +} + +GeditTabState +gedit_tab_get_state (GeditTab *tab) +{ + g_return_val_if_fail (GEDIT_IS_TAB (tab), GEDIT_TAB_STATE_NORMAL); + + return tab->priv->state; +} + +static void +set_cursor_according_to_state (GtkTextView *view, + GeditTabState state) +{ + GdkCursor *cursor; + GdkWindow *text_window; + GdkWindow *left_window; + + text_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_TEXT); + left_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_LEFT); + + if ((state == GEDIT_TAB_STATE_LOADING) || + (state == GEDIT_TAB_STATE_REVERTING) || + (state == GEDIT_TAB_STATE_SAVING) || + (state == GEDIT_TAB_STATE_PRINTING) || + (state == GEDIT_TAB_STATE_PRINT_PREVIEWING) || + (state == GEDIT_TAB_STATE_CLOSING)) + { + cursor = gdk_cursor_new_for_display ( + gtk_widget_get_display (GTK_WIDGET (view)), + GDK_WATCH); + + if (text_window != NULL) + gdk_window_set_cursor (text_window, cursor); + if (left_window != NULL) + gdk_window_set_cursor (left_window, cursor); + + gdk_cursor_unref (cursor); + } + else + { + cursor = gdk_cursor_new_for_display ( + gtk_widget_get_display (GTK_WIDGET (view)), + GDK_XTERM); + + if (text_window != NULL) + gdk_window_set_cursor (text_window, cursor); + if (left_window != NULL) + gdk_window_set_cursor (left_window, NULL); + + gdk_cursor_unref (cursor); + } +} + +static void +view_realized (GtkTextView *view, + GeditTab *tab) +{ + set_cursor_according_to_state (view, tab->priv->state); +} + +static void +set_view_properties_according_to_state (GeditTab *tab, + GeditTabState state) +{ + gboolean val; + + val = ((state == GEDIT_TAB_STATE_NORMAL) && + (tab->priv->print_preview == NULL) && + !tab->priv->not_editable); + gtk_text_view_set_editable (GTK_TEXT_VIEW (tab->priv->view), val); + + val = ((state != GEDIT_TAB_STATE_LOADING) && + (state != GEDIT_TAB_STATE_CLOSING)); + gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (tab->priv->view), val); + + val = ((state != GEDIT_TAB_STATE_LOADING) && + (state != GEDIT_TAB_STATE_CLOSING) && + (gedit_prefs_manager_get_highlight_current_line ())); + gtk_source_view_set_highlight_current_line (GTK_SOURCE_VIEW (tab->priv->view), val); +} + +static void +gedit_tab_set_state (GeditTab *tab, + GeditTabState state) +{ + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail ((state >= 0) && (state < GEDIT_TAB_NUM_OF_STATES)); + + if (tab->priv->state == state) + return; + + tab->priv->state = state; + + set_view_properties_according_to_state (tab, state); + + if ((state == GEDIT_TAB_STATE_LOADING_ERROR) || // FIXME: add other states if needed + (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)) + { + gtk_widget_hide (tab->priv->view_scrolled_window); + } + else + { + if (tab->priv->print_preview == NULL) + gtk_widget_show (tab->priv->view_scrolled_window); + } + + set_cursor_according_to_state (GTK_TEXT_VIEW (tab->priv->view), + state); + + g_object_notify (G_OBJECT (tab), "state"); +} + +static void +document_uri_notify_handler (GeditDocument *document, + GParamSpec *pspec, + GeditTab *tab) +{ + g_object_notify (G_OBJECT (tab), "name"); +} + +static void +document_modified_changed (GtkTextBuffer *document, + GeditTab *tab) +{ + g_object_notify (G_OBJECT (tab), "name"); +} + +static void +set_message_area (GeditTab *tab, + GtkWidget *message_area) +{ + if (tab->priv->message_area == message_area) + return; + + if (tab->priv->message_area != NULL) + gtk_widget_destroy (tab->priv->message_area); + + tab->priv->message_area = message_area; + + if (message_area == NULL) + return; + + gtk_box_pack_start (GTK_BOX (tab), + tab->priv->message_area, + FALSE, + FALSE, + 0); + + g_object_add_weak_pointer (G_OBJECT (tab->priv->message_area), + (gpointer *)&tab->priv->message_area); +} + +static void +remove_tab (GeditTab *tab) +{ + GeditNotebook *notebook; + + notebook = GEDIT_NOTEBOOK (gtk_widget_get_parent (GTK_WIDGET (tab))); + + gedit_notebook_remove_tab (notebook, tab); +} + +static void +unrecoverable_loading_error_message_area_response (GeditMessageArea *message_area, + gint response_id, + GeditTab *tab) +{ + remove_tab (tab); +} + +static void +recoverable_loading_error_message_area_response (GeditMessageArea *message_area, + gint response_id, + GeditTab *tab) +{ + GeditDocument *doc; + const gchar *uri; + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + uri = gedit_document_get_uri (doc); + g_return_if_fail (uri != NULL); + + if (response_id == GTK_RESPONSE_OK) + { + const GeditEncoding *encoding; + + encoding = gedit_conversion_error_message_area_get_encoding ( + GTK_WIDGET (message_area)); + + g_return_if_fail (encoding != NULL); + + set_message_area (tab, NULL); + gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING); + + tab->priv->tmp_encoding = encoding; + + gedit_document_load (doc, + uri, + encoding, + tab->priv->tmp_line_pos, + FALSE); + } + else + { + gedit_recent_remove (uri); + + unrecoverable_loading_error_message_area_response (message_area, + response_id, + tab); + } +} + +static void +file_already_open_warning_message_area_response (GtkWidget *message_area, + gint response_id, + GeditTab *tab) +{ + GeditView *view; + + view = gedit_tab_get_view (tab); + + if (response_id == GTK_RESPONSE_YES) + { + tab->priv->not_editable = FALSE; + + gtk_text_view_set_editable (GTK_TEXT_VIEW (view), + TRUE); + } + + gtk_widget_destroy (message_area); + + gtk_widget_grab_focus (GTK_WIDGET (view)); +} + +static void +load_cancelled (GeditMessageArea *area, + gint response_id, + GeditTab *tab) +{ + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + + g_object_ref (tab); + gedit_document_load_cancel (gedit_tab_get_document (tab)); + g_object_unref (tab); +} + +static void +unrecoverable_reverting_error_message_area_response (GeditMessageArea *message_area, + gint response_id, + GeditTab *tab) +{ + GeditView *view; + + gedit_tab_set_state (tab, + GEDIT_TAB_STATE_NORMAL); + + set_message_area (tab, NULL); + + view = gedit_tab_get_view (tab); + + gtk_widget_grab_focus (GTK_WIDGET (view)); +} + +#define MAX_MSG_LENGTH 100 + +static void +show_loading_message_area (GeditTab *tab) +{ + GtkWidget *area; + GeditDocument *doc = NULL; + const gchar *short_name; + gchar *name; + gchar *dirname = NULL; + gchar *msg = NULL; + gint len; + + if (tab->priv->message_area != NULL) + return; + + gedit_debug (DEBUG_DOCUMENT); + + doc = gedit_tab_get_document (tab); + g_return_if_fail (doc != NULL); + + 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) + { + name = gedit_utils_str_middle_truncate (short_name, + MAX_MSG_LENGTH); + } + else + { + gchar *uri; + gchar *str; + + name = g_strdup (short_name); + + uri = gedit_document_get_uri_for_display (doc); + str = gedit_utils_uri_get_dirname (uri); + g_free (uri); + + if (str != NULL) + { + /* 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 = gedit_utils_str_middle_truncate (str, + MAX (20, MAX_MSG_LENGTH - len)); + g_free (str); + } + } + + if (tab->priv->state == GEDIT_TAB_STATE_REVERTING) + { + if (dirname != NULL) + { + /* 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_markup_printf_escaped (_("Reverting %s from %s"), + name, + dirname); + } + else + { + msg = g_markup_printf_escaped (_("Reverting %s"), + name); + } + + area = gedit_progress_message_area_new (GTK_STOCK_REVERT_TO_SAVED, + msg, + TRUE); + } + else + { + if (dirname != NULL) + { + /* 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_markup_printf_escaped (_("Loading %s from %s"), + name, + dirname); + } + else + { + msg = g_markup_printf_escaped (_("Loading %s"), + name); + } + + area = gedit_progress_message_area_new (GTK_STOCK_OPEN, + msg, + TRUE); + } + + g_signal_connect (area, + "response", + G_CALLBACK (load_cancelled), + tab); + + gtk_widget_show (area); + + set_message_area (tab, area); + + g_free (msg); + g_free (name); + g_free (dirname); +} + +static void +show_saving_message_area (GeditTab *tab) +{ + GtkWidget *area; + GeditDocument *doc = NULL; + gchar *short_name; + gchar *from; + gchar *to = NULL; + gchar *msg = NULL; + gint len; + + g_return_if_fail (tab->priv->tmp_save_uri != NULL); + + if (tab->priv->message_area != NULL) + return; + + gedit_debug (DEBUG_DOCUMENT); + + doc = gedit_tab_get_document (tab); + g_return_if_fail (doc != NULL); + + 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 = gedit_utils_str_middle_truncate (short_name, + MAX_MSG_LENGTH); + g_free (short_name); + } + else + { + gchar *str; + + from = short_name; + + to = gnome_vfs_format_uri_for_display (tab->priv->tmp_save_uri); + + str = gedit_utils_str_middle_truncate (to, + MAX (20, MAX_MSG_LENGTH - len)); + g_free (to); + + to = str; + } + + if (to != NULL) + { + /* 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_markup_printf_escaped (_("Saving %s to %s"), + from, + to); + } + else + { + msg = g_markup_printf_escaped (_("Saving %s"), to); + } + + area = gedit_progress_message_area_new (GTK_STOCK_SAVE, + msg, + FALSE); + + gtk_widget_show (area); + + set_message_area (tab, area); + + g_free (msg); + g_free (to); + g_free (from); +} + +static void +message_area_set_progress (GeditTab *tab, + GnomeVFSFileSize size, + GnomeVFSFileSize total_size) +{ + if (tab->priv->message_area == NULL) + return; + + gedit_debug_message (DEBUG_DOCUMENT, "%Ld/%Ld", size, total_size); + + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + + if (total_size == 0) + { + if (size != 0) + gedit_progress_message_area_pulse ( + GEDIT_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + else + gedit_progress_message_area_set_fraction ( + GEDIT_PROGRESS_MESSAGE_AREA (tab->priv->message_area), + 0); + } + else + { + gdouble frac; + + frac = (gdouble)size / (gdouble)total_size; + + gedit_progress_message_area_set_fraction ( + GEDIT_PROGRESS_MESSAGE_AREA (tab->priv->message_area), + frac); + } +} + +static void +document_loading (GeditDocument *document, + GnomeVFSFileSize size, + GnomeVFSFileSize total_size, + GeditTab *tab) +{ + double et; + + g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_LOADING) || + (tab->priv->state == GEDIT_TAB_STATE_REVERTING)); + + gedit_debug_message (DEBUG_DOCUMENT, "%Ld/%Ld", size, total_size); + + if (tab->priv->timer == NULL) + { + g_return_if_fail (tab->priv->times_called == 0); + tab->priv->timer = g_timer_new (); + } + + et = g_timer_elapsed (tab->priv->timer, NULL); + + if (tab->priv->times_called == 1) + { + if ((total_size == 0) || (total_size > 51200UL) /* 50 KB */) + { + show_loading_message_area (tab); + } + } + else + { + if ((tab->priv->times_called == 3) && (total_size != 0)) + { + gdouble total_time; + + /* et : total_time = size : total_size */ + total_time = (et * total_size)/size; + + if ((total_time - et) > 3.0) + { + show_loading_message_area (tab); + } + } + else + { + if (et > 3.0) + { + show_loading_message_area (tab); + } + } + } + + message_area_set_progress (tab, size, total_size); + + tab->priv->times_called++; +} + +static gboolean +remove_tab_idle (GeditTab *tab) +{ + remove_tab (tab); + + return FALSE; +} + +static void +document_loaded (GeditDocument *document, + const GError *error, + GeditTab *tab) +{ + GtkWidget *emsg; + gchar *uri; + const GeditEncoding *encoding; + + g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_LOADING) || + (tab->priv->state == GEDIT_TAB_STATE_REVERTING)); + + g_timer_destroy (tab->priv->timer); + tab->priv->timer = NULL; + tab->priv->times_called = 0; + + set_message_area (tab, NULL); + + uri = gedit_document_get_uri (document); + + if (error != NULL) + { + if (tab->priv->state == GEDIT_TAB_STATE_LOADING) + gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING_ERROR); + else + gedit_tab_set_state (tab, GEDIT_TAB_STATE_REVERTING_ERROR); + + encoding = gedit_document_get_encoding (document); + + if (error->domain == GEDIT_DOCUMENT_ERROR) + { + if (error->code == GNOME_VFS_ERROR_CANCELLED) + { + /* remove the tab, but in an idle handler, since + * we are in the handler of doc loaded and we + * don't want doc and tab to be finalized now. + */ + g_idle_add ((GSourceFunc) remove_tab_idle, tab); + + goto end; + } + else + { + gedit_recent_remove (uri); + + if (tab->priv->state == GEDIT_TAB_STATE_LOADING_ERROR) + { + emsg = gedit_unrecoverable_loading_error_message_area_new (uri, + error); + g_signal_connect (emsg, + "response", + G_CALLBACK (unrecoverable_loading_error_message_area_response), + tab); + } + else + { + g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_REVERTING_ERROR); + + emsg = gedit_unrecoverable_reverting_error_message_area_new (uri, + error); + + g_signal_connect (emsg, + "response", + G_CALLBACK (unrecoverable_reverting_error_message_area_response), + tab); + } + + set_message_area (tab, emsg); + } + } + else + { + g_return_if_fail ((error->domain == G_CONVERT_ERROR) || + (error->domain == GEDIT_CONVERT_ERROR)); + + // TODO: different error messages if tab->priv->state == GEDIT_TAB_STATE_REVERTING? + // note that while reverting encoding should be ok, so this is unlikely to happen + emsg = gedit_conversion_error_while_loading_message_area_new ( + uri, + tab->priv->tmp_encoding, + error); + + set_message_area (tab, emsg); + + g_signal_connect (emsg, + "response", + G_CALLBACK (recoverable_loading_error_message_area_response), + tab); + } + + gedit_message_area_set_default_response (GEDIT_MESSAGE_AREA (emsg), + GTK_RESPONSE_CANCEL); + + gtk_widget_show (emsg); + + return; + } + else + { + GList *all_documents; + GList *l; + + g_return_if_fail (uri != NULL); + + gedit_recent_add (uri); + + all_documents = gedit_app_get_documents (gedit_app_get_default ()); + + for (l = all_documents; l != NULL; l = g_list_next (l)) + { + GeditDocument *d = GEDIT_DOCUMENT (l->data); + + if (d != document) + { + gchar *u; + + u = gedit_document_get_uri (d); + + if ((u != NULL) && + gnome_vfs_uris_match (uri, u)) + { + GtkWidget *w; + GeditView *view; + + view = gedit_tab_get_view (tab); + + tab->priv->not_editable = TRUE; + + w = gedit_file_already_open_warning_message_area_new (uri); + + set_message_area (tab, w); + + gedit_message_area_set_default_response (GEDIT_MESSAGE_AREA (w), + GTK_RESPONSE_CANCEL); + + gtk_widget_show (w); + + g_signal_connect (w, + "response", + G_CALLBACK (file_already_open_warning_message_area_response), + tab); + + g_free (u); + + break; + } + + g_free (u); + } + } + + g_list_free (all_documents); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL); + } + + end: + g_free (uri); + + tab->priv->tmp_line_pos = 0; + tab->priv->tmp_encoding = NULL; +} + +static void +document_saving (GeditDocument *document, + GnomeVFSFileSize size, + GnomeVFSFileSize total_size, + GeditTab *tab) +{ + double et; + + g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_SAVING); + + gedit_debug_message (DEBUG_DOCUMENT, "%Ld/%Ld", size, total_size); + + if (tab->priv->timer == NULL) + { + g_return_if_fail (tab->priv->times_called == 0); + tab->priv->timer = g_timer_new (); + } + + et = g_timer_elapsed (tab->priv->timer, NULL); + + if (tab->priv->times_called == 1) + { + if ((total_size == 0) || (total_size > 51200UL) /* 50 KB */) + { + show_saving_message_area (tab); + } + } + else + { + if ((tab->priv->times_called == 3) && (total_size != 0)) + { + gdouble total_time; + + /* et : total_time = size : total_size */ + total_time = (et * total_size)/size; + + if ((total_time - et) > 3.0) + { + show_saving_message_area (tab); + } + } + else + { + if (et > 3.0) + { + show_saving_message_area (tab); + } + } + } + + message_area_set_progress (tab, size, total_size); + + tab->priv->times_called++; +} + +static void +reset_tmp_data_for_saving (GeditTab *tab) +{ + g_free (tab->priv->tmp_save_uri); + tab->priv->tmp_save_uri = NULL; + tab->priv->tmp_encoding = NULL; +} + +static void +unrecoverable_saving_error_message_area_response (GeditMessageArea *message_area, + gint response_id, + GeditTab *tab) +{ + GeditView *view; + + if (tab->priv->print_preview != NULL) + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW); + else + gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL); + + set_message_area (tab, NULL); + + view = gedit_tab_get_view (tab); + + gtk_widget_grab_focus (GTK_WIDGET (view)); +} + +static void +no_backup_error_message_area_response (GeditMessageArea *message_area, + gint response_id, + GeditTab *tab) +{ + if (response_id == GTK_RESPONSE_YES) + { + GeditDocument *doc; + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + set_message_area (tab, NULL); + + g_return_if_fail (tab->priv->tmp_save_uri != NULL); + g_return_if_fail (tab->priv->tmp_encoding != NULL); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING); + + /* don't bug the user again with this... */ + tab->priv->save_flags |= GEDIT_DOCUMENT_SAVE_IGNORE_BACKUP; + + /* Force saving */ + gedit_document_save (doc, tab->priv->save_flags); + } + else + { + reset_tmp_data_for_saving (tab); + + unrecoverable_saving_error_message_area_response (message_area, + response_id, + tab); + } +} + +static void +externally_modified_error_message_area_response (GeditMessageArea *message_area, + gint response_id, + GeditTab *tab) +{ + if (response_id == GTK_RESPONSE_YES) + { + GeditDocument *doc; + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + set_message_area (tab, NULL); + + g_return_if_fail (tab->priv->tmp_save_uri != NULL); + g_return_if_fail (tab->priv->tmp_encoding != NULL); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING); + + /* ignore mtime should not be persisted in save flags across saves */ + + /* Force saving */ + gedit_document_save (doc, tab->priv->save_flags | GEDIT_DOCUMENT_SAVE_IGNORE_MTIME); + } + else + { + reset_tmp_data_for_saving (tab); + + unrecoverable_saving_error_message_area_response (message_area, + response_id, + tab); + } +} + +static void +recoverable_saving_error_message_area_response (GeditMessageArea *message_area, + gint response_id, + GeditTab *tab) +{ + GeditDocument *doc; + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + if (response_id == GTK_RESPONSE_OK) + { + const GeditEncoding *encoding; + + encoding = gedit_conversion_error_message_area_get_encoding ( + GTK_WIDGET (message_area)); + + g_return_if_fail (encoding != NULL); + + set_message_area (tab, NULL); + + g_return_if_fail (tab->priv->tmp_save_uri != NULL); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING); + + tab->priv->tmp_encoding = encoding; + + g_print ("Force saving with URI '%s'\n", + tab->priv->tmp_save_uri); + + gedit_document_save_as (doc, + tab->priv->tmp_save_uri, + tab->priv->tmp_encoding, + tab->priv->save_flags); + } + else + { + reset_tmp_data_for_saving (tab); + + unrecoverable_saving_error_message_area_response (message_area, + response_id, + tab); + } +} + +static void +document_saved (GeditDocument *document, + const GError *error, + GeditTab *tab) +{ + GtkWidget *emsg; + + g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_SAVING); + + g_return_if_fail (tab->priv->tmp_save_uri != NULL); + g_return_if_fail (tab->priv->tmp_encoding != NULL); + + g_timer_destroy (tab->priv->timer); + tab->priv->timer = NULL; + tab->priv->times_called = 0; + + set_message_area (tab, NULL); + + if (error != NULL) + { + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING_ERROR); + + if (error->domain == GEDIT_DOCUMENT_ERROR) + { + if (error->code == GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED) + { + /* This error is recoverable */ + emsg = gedit_externally_modified_saving_error_message_area_new ( + tab->priv->tmp_save_uri, + error); + g_return_if_fail (emsg != NULL); + + set_message_area (tab, emsg); + + g_signal_connect (emsg, + "response", + G_CALLBACK (externally_modified_error_message_area_response), + tab); + } + else if (error->code == GEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP) + { + /* This error is recoverable */ + emsg = gedit_no_backup_saving_error_message_area_new ( + tab->priv->tmp_save_uri, + error); + g_return_if_fail (emsg != NULL); + + set_message_area (tab, emsg); + + g_signal_connect (emsg, + "response", + G_CALLBACK (no_backup_error_message_area_response), + tab); + } + else + { + /* These errors are _NOT_ recoverable */ + gedit_recent_remove (tab->priv->tmp_save_uri); + + emsg = gedit_unrecoverable_saving_error_message_area_new (tab->priv->tmp_save_uri, + error); + g_return_if_fail (emsg != NULL); + + set_message_area (tab, emsg); + + g_signal_connect (emsg, + "response", + G_CALLBACK (unrecoverable_saving_error_message_area_response), + tab); + + reset_tmp_data_for_saving (tab); + } + } + else + { + /* This error is recoverable */ + g_return_if_fail (error->domain == G_CONVERT_ERROR); + + emsg = gedit_conversion_error_while_saving_message_area_new ( + tab->priv->tmp_save_uri, + tab->priv->tmp_encoding, + error); + + set_message_area (tab, emsg); + + g_signal_connect (emsg, + "response", + G_CALLBACK (recoverable_saving_error_message_area_response), + tab); + } + + gedit_message_area_set_default_response (GEDIT_MESSAGE_AREA (emsg), + GTK_RESPONSE_CANCEL); + + gtk_widget_show (emsg); + + } + else + { + gedit_recent_add (tab->priv->tmp_save_uri); + + if (tab->priv->print_preview != NULL) + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW); + else + gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL); + + reset_tmp_data_for_saving (tab); + } + +} + +static void +gedit_tab_init (GeditTab *tab) +{ + GtkWidget *sw; + GeditDocument *doc; + + tab->priv = GEDIT_TAB_GET_PRIVATE (tab); + + tab->priv->state = GEDIT_TAB_STATE_NORMAL; + + tab->priv->not_editable = FALSE; + + tab->priv->save_flags = 0; + + /* Create the scrolled window */ + sw = gtk_scrolled_window_new (NULL, NULL); + tab->priv->view_scrolled_window = sw; + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + /* Create the view */ + doc = gedit_document_new (); + g_object_set_data (G_OBJECT (doc), GEDIT_TAB_KEY, tab); + + tab->priv->view = gedit_view_new (doc); + g_object_unref (doc); + gtk_widget_show (tab->priv->view); + g_object_set_data (G_OBJECT (tab->priv->view), GEDIT_TAB_KEY, tab); + + gtk_box_pack_end (GTK_BOX (tab), sw, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (sw), tab->priv->view); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), + GTK_SHADOW_IN); + gtk_widget_show (sw); + + g_signal_connect (doc, + "notify::uri", + G_CALLBACK (document_uri_notify_handler), + tab); + g_signal_connect (doc, + "modified_changed", + G_CALLBACK (document_modified_changed), + tab); + g_signal_connect (doc, + "loading", + G_CALLBACK (document_loading), + tab); + g_signal_connect (doc, + "loaded", + G_CALLBACK (document_loaded), + tab); + g_signal_connect (doc, + "saving", + G_CALLBACK (document_saving), + tab); + g_signal_connect (doc, + "saved", + G_CALLBACK (document_saved), + tab); + + g_signal_connect_after(tab->priv->view, + "realize", + G_CALLBACK (view_realized), + tab); +} + +GtkWidget * +_gedit_tab_new (void) +{ + return GTK_WIDGET (g_object_new (GEDIT_TYPE_TAB, NULL)); +} + +/* Whether create is TRUE, creates a new empty document if location does + not refer to an existing file */ +GtkWidget * +_gedit_tab_new_from_uri (const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create) +{ + GeditTab *tab; + + gboolean ret; + + g_return_val_if_fail (uri != NULL, NULL); + + tab = GEDIT_TAB (_gedit_tab_new ()); + + ret = _gedit_tab_load (tab, + uri, + encoding, + line_pos, + create); + + if (!ret) + { + g_object_unref (tab); + return NULL; + } + + return GTK_WIDGET (tab); +} + +GeditView * +gedit_tab_get_view (GeditTab *tab) +{ + return GEDIT_VIEW (tab->priv->view); +} + +/* This is only an helper function */ +GeditDocument * +gedit_tab_get_document (GeditTab *tab) +{ + return GEDIT_DOCUMENT (gtk_text_view_get_buffer ( + GTK_TEXT_VIEW (tab->priv->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 = 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 + { + #if 0 + if (gedit_document_get_readonly (doc)) + { + tab_name = g_strdup_printf ("%s [%s]", docname, + /*Read only*/ _("RO")); + } + else + { + tab_name = g_strdup_printf ("%s", docname); + } +#endif + tab_name = g_strdup (docname); + } + + g_free (docname); + g_free (name); + + return tab_name; +} + +gchar * +_gedit_tab_get_tooltips (GeditTab *tab) +{ + GeditDocument *doc; + gchar *tip; + gchar *uri; + gchar *ruri; + gchar *mime_type; + const gchar *mime_description = NULL; + gchar *mime_full_description; + gchar *encoding; + const GeditEncoding *enc; + + 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 = gedit_utils_replace_home_dir_with_tilde (uri); + g_free (uri); + + switch (tab->priv->state) + { + case GEDIT_TAB_STATE_LOADING_ERROR: + tip = g_markup_printf_escaped(_("Error opening file %s."), + ruri); + break; + + case GEDIT_TAB_STATE_REVERTING_ERROR: + tip = g_markup_printf_escaped(_("Error reverting file %s."), + ruri); + break; + + case GEDIT_TAB_STATE_SAVING_ERROR: + tip = g_markup_printf_escaped(_("Error saving file %s."), + ruri); + break; + default: + mime_type = gedit_document_get_mime_type (doc); + mime_description = gnome_vfs_mime_get_description (mime_type); + + if (mime_description == NULL) + mime_full_description = g_strdup (mime_type); + else + mime_full_description = g_strdup_printf ("%s (%s)", + mime_description, mime_type); + + g_free (mime_type); + + enc = gedit_document_get_encoding (doc); + + if (enc == NULL) + encoding = g_strdup (_("Unicode (UTF-8)")); + else + encoding = gedit_encoding_to_string (enc); + + tip = g_markup_printf_escaped ("%s %s\n\n" + "%s %s\n" + "%s %s", + _("Name:"), ruri, + _("MIME Type:"), mime_full_description, + _("Encoding:"), encoding); + + g_free (encoding); + g_free (mime_full_description); + + break; + } + + g_free (ruri); + + return tip; +} + +static GdkPixbuf * +resize_icon (GdkPixbuf *pixbuf, + gint size) +{ + guint width, height; + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + /* if the icon is larger than the nominal size, scale down */ + if (MAX (width, height) > size) + { + GdkPixbuf *scaled_pixbuf; + + if (width > height) + { + height = height * size / width; + width = size; + } + else + { + width = width * size / height; + height = size; + } + + scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf, + width, + height, + GDK_INTERP_BILINEAR); + g_object_unref (pixbuf); + pixbuf = scaled_pixbuf; + } + + return pixbuf; +} + +static GdkPixbuf * +get_icon (GtkIconTheme *theme, + const gchar *uri, + const gchar *mime_type, + gint size) +{ + gchar *icon; + GdkPixbuf *pixbuf; + + icon = gnome_icon_lookup (theme, NULL, uri, NULL, NULL, + mime_type, 0, NULL); + + + g_return_val_if_fail (icon != NULL, NULL); + + pixbuf = gtk_icon_theme_load_icon (theme, icon, size, 0, NULL); + g_free (icon); + if (pixbuf == NULL) + return NULL; + + return resize_icon (pixbuf, size); +} + +static GdkPixbuf * +get_stock_icon (GtkIconTheme *theme, + const gchar *stock, + gint size) +{ + GdkPixbuf *pixbuf; + + pixbuf = gtk_icon_theme_load_icon (theme, stock, size, 0, NULL); + if (pixbuf == NULL) + return NULL; + + return resize_icon (pixbuf, size); +} + +/* FIXME: add support for theme changed. I think it should be as easy as + call g_object_notify (tab, "name") when the icon theme changes */ +GdkPixbuf * +_gedit_tab_get_icon (GeditTab *tab) +{ + GdkPixbuf *pixbuf; + GtkIconTheme *theme; + GdkScreen *screen; + gint icon_size; + + g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL); + + screen = gtk_widget_get_screen (GTK_WIDGET (tab)); + + theme = gtk_icon_theme_get_for_screen (screen); + g_return_val_if_fail (theme != NULL, NULL); + + gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (GTK_WIDGET (tab)), + GTK_ICON_SIZE_MENU, + NULL, + &icon_size); + + switch (tab->priv->state) + { + case GEDIT_TAB_STATE_LOADING: + pixbuf = get_stock_icon (theme, + GTK_STOCK_OPEN, + icon_size); + break; + case GEDIT_TAB_STATE_REVERTING: + pixbuf = get_stock_icon (theme, + GTK_STOCK_REVERT_TO_SAVED, + icon_size); + break; + case GEDIT_TAB_STATE_SAVING: + pixbuf = get_stock_icon (theme, + GTK_STOCK_SAVE, + icon_size); + break; + case GEDIT_TAB_STATE_PRINTING: + pixbuf = get_stock_icon (theme, + GTK_STOCK_PRINT, + icon_size); + break; + case GEDIT_TAB_STATE_PRINT_PREVIEWING: + case GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW: + pixbuf = get_stock_icon (theme, + GTK_STOCK_PRINT_PREVIEW, + icon_size); + break; + + case GEDIT_TAB_STATE_LOADING_ERROR: + case GEDIT_TAB_STATE_REVERTING_ERROR: + case GEDIT_TAB_STATE_SAVING_ERROR: + case GEDIT_TAB_STATE_GENERIC_ERROR: + pixbuf = get_stock_icon (theme, + GTK_STOCK_DIALOG_ERROR, + icon_size); + break; + default: + { + gchar *raw_uri; + gchar *mime_type; + GeditDocument *doc; + + doc = gedit_tab_get_document (tab); + + raw_uri = gedit_document_get_uri (doc); + mime_type = gedit_document_get_mime_type (doc); + + pixbuf = get_icon (theme, raw_uri, mime_type, icon_size); + + g_free (raw_uri); + g_free (mime_type); + } + } + + return pixbuf; +} + +GeditTab * +gedit_tab_get_from_document (GeditDocument *doc) +{ + gpointer res; + + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL); + + res = g_object_get_data (G_OBJECT (doc), GEDIT_TAB_KEY); + + return (res != NULL) ? GEDIT_TAB (res) : NULL; +} + +gboolean +_gedit_tab_load (GeditTab *tab, + const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create) +{ + GeditDocument *doc; + + g_return_val_if_fail (GEDIT_IS_TAB (tab), FALSE); + g_return_val_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL, FALSE); + + doc = gedit_tab_get_document (tab); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING); + + tab->priv->tmp_line_pos = line_pos; + tab->priv->tmp_encoding = encoding; + + return gedit_document_load (doc, + uri, + encoding, + line_pos, + create); +} + +void +_gedit_tab_revert (GeditTab *tab) +{ + GeditDocument *doc; + gchar *uri; + + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL); + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_REVERTING); + + uri = gedit_document_get_uri (doc); + g_return_if_fail (uri != NULL); + + tab->priv->tmp_line_pos = 0; + tab->priv->tmp_encoding = gedit_document_get_encoding (doc); + + gedit_document_load (doc, + uri, + tab->priv->tmp_encoding, + 0, + FALSE); + + g_free (uri); +} + +void +_gedit_tab_save (GeditTab *tab) +{ + GeditDocument *doc; + + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_NORMAL) || + (tab->priv->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)); + g_return_if_fail (tab->priv->tmp_save_uri == NULL); + g_return_if_fail (tab->priv->tmp_encoding == NULL); + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + g_return_if_fail (!gedit_document_is_untitled (doc)); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING); + + /* uri used in error messages, will be freed in document_loaded */ + tab->priv->tmp_save_uri = gedit_document_get_uri (doc); + tab->priv->tmp_encoding = gedit_document_get_encoding (doc); + + gedit_document_save (doc, tab->priv->save_flags); +} + +void +_gedit_tab_save_as (GeditTab *tab, + const gchar *uri, + const GeditEncoding *encoding) +{ + GeditDocument *doc; + + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_NORMAL) || + (tab->priv->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)); + g_return_if_fail (encoding != NULL); + + g_return_if_fail (tab->priv->tmp_save_uri == NULL); + g_return_if_fail (tab->priv->tmp_encoding == NULL); + + doc = gedit_tab_get_document (tab); + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING); + + /* uri used in error messages... strdup because errors are async + * and the string can go away, will be freed in document_loaded */ + tab->priv->tmp_save_uri = g_strdup (uri); + tab->priv->tmp_encoding = encoding; + + /* reset the save flags, when saving as */ + tab->priv->save_flags = 0; + + gedit_document_save_as (doc, uri, encoding, tab->priv->save_flags); +} + +static void +print_preview_destroyed (GtkWidget *preview, + GeditTab *tab) +{ + tab->priv->print_preview = NULL; + + if (tab->priv->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW) + gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL); + else + gtk_widget_show (tab->priv->view_scrolled_window); +} + +static void +set_print_preview (GeditTab *tab, GtkWidget *print_preview) +{ + if (tab->priv->print_preview == print_preview) + return; + + if (tab->priv->print_preview != NULL) + gtk_widget_destroy (tab->priv->print_preview); + + + tab->priv->print_preview = print_preview; + + gtk_box_pack_end (GTK_BOX (tab), + tab->priv->print_preview, + TRUE, + TRUE, + 0); + + gtk_widget_grab_focus (tab->priv->print_preview); + + g_signal_connect (tab->priv->print_preview, + "destroy", + G_CALLBACK (print_preview_destroyed), + tab); +} + +#define MIN_PAGES 15 + +static void +print_page_cb (GtkSourcePrintJob *pjob, GeditTab *tab) +{ + gchar *str; + gint page_num; + gint total; + + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + + total = gtk_source_print_job_get_page_count (pjob); + + if (total < MIN_PAGES) + return; + + page_num = gtk_source_print_job_get_page (pjob); + + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + + gtk_widget_show (tab->priv->message_area); + + str = g_strdup_printf (_("Rendering page %d of %d..."), page_num, total); + + gedit_progress_message_area_set_text (GEDIT_PROGRESS_MESSAGE_AREA (tab->priv->message_area), + str); + g_free (str); + + gedit_progress_message_area_set_fraction (GEDIT_PROGRESS_MESSAGE_AREA (tab->priv->message_area), + 1.0 * page_num / total); +} + +static void +preview_finished_cb (GtkSourcePrintJob *pjob, GeditTab *tab) +{ + GnomePrintJob *gjob; + GtkWidget *preview = NULL; + + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + set_message_area (tab, NULL); /* destroy the message area */ + + gjob = gtk_source_print_job_get_print_job (pjob); + + preview = gedit_print_job_preview_new (gjob); + g_object_unref (gjob); + + set_print_preview (tab, preview); + + gtk_widget_show (preview); + g_object_unref (pjob); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW); +} + +static void +print_finished_cb (GtkSourcePrintJob *pjob, GeditTab *tab) +{ + GnomePrintJob *gjob; + + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + set_message_area (tab, NULL); /* destroy the message area */ + + gjob = gtk_source_print_job_get_print_job (pjob); + + gnome_print_job_print (gjob); + g_object_unref (gjob); + + gedit_print_job_save_config (GEDIT_PRINT_JOB (pjob)); + + g_object_unref (pjob); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL); +} + +static void +print_cancelled (GeditMessageArea *area, + gint response_id, + GeditTab *tab) +{ + g_return_if_fail (GEDIT_IS_PROGRESS_MESSAGE_AREA (tab->priv->message_area)); + + gtk_source_print_job_cancel (GTK_SOURCE_PRINT_JOB (tab->priv->print_job)); + g_object_unref (tab->priv->print_job); + + set_message_area (tab, NULL); /* destroy the message area */ + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL); +} + +static void +show_printing_message_area (GeditTab *tab, + gboolean preview) +{ + GtkWidget *area; + + if (preview) + area = gedit_progress_message_area_new (GTK_STOCK_PRINT_PREVIEW, + "", + TRUE); + else + area = gedit_progress_message_area_new (GTK_STOCK_PRINT, + "", + TRUE); + + + g_signal_connect (area, + "response", + G_CALLBACK (print_cancelled), + tab); + + set_message_area (tab, area); +} + +void +_gedit_tab_print (GeditTab *tab, + GeditPrintJob *pjob, + GtkTextIter *start, + GtkTextIter *end) +{ + GeditDocument *doc; + + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail (GEDIT_IS_PRINT_JOB (pjob)); + g_return_if_fail (start != NULL); + g_return_if_fail (end != NULL); + + doc = GEDIT_DOCUMENT (gtk_source_print_job_get_buffer (GTK_SOURCE_PRINT_JOB (pjob))); + g_return_if_fail (doc != NULL); + g_return_if_fail (gedit_tab_get_document (tab) == doc); + g_return_if_fail (gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)); + g_return_if_fail (gtk_text_iter_get_buffer (end) == GTK_TEXT_BUFFER (doc)); + + g_return_if_fail (tab->priv->print_job == NULL); + g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_NORMAL) || + (tab->priv->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)); + + g_object_ref (pjob); + tab->priv->print_job = pjob; + g_object_add_weak_pointer (G_OBJECT (pjob), + (gpointer *) &tab->priv->print_job); + + show_printing_message_area (tab, FALSE); + + g_signal_connect (pjob, "begin_page", (GCallback) print_page_cb, tab); + g_signal_connect (pjob, "finished", (GCallback) print_finished_cb, tab); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_PRINTING); + + if (!gtk_source_print_job_print_range_async (GTK_SOURCE_PRINT_JOB (pjob), start, end)) + { + /* FIXME: go in error state */ + gtk_text_view_set_editable (GTK_TEXT_VIEW (tab->priv->view), + !tab->priv->not_editable); + g_warning ("Async print preview failed"); + g_object_unref (pjob); + } +} + +void +_gedit_tab_print_preview (GeditTab *tab, + GeditPrintJob *pjob, + GtkTextIter *start, + GtkTextIter *end) +{ + GeditDocument *doc; + + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail (GEDIT_IS_PRINT_JOB (pjob)); + g_return_if_fail (start != NULL); + g_return_if_fail (end != NULL); + + doc = GEDIT_DOCUMENT (gtk_source_print_job_get_buffer (GTK_SOURCE_PRINT_JOB (pjob))); + g_return_if_fail (doc != NULL); + g_return_if_fail (gedit_tab_get_document (tab) == doc); + g_return_if_fail (gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)); + g_return_if_fail (gtk_text_iter_get_buffer (end) == GTK_TEXT_BUFFER (doc)); + + g_return_if_fail (tab->priv->print_job == NULL); + g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL); + + g_object_ref (pjob); + tab->priv->print_job = pjob; + g_object_add_weak_pointer (G_OBJECT (pjob), + (gpointer *) &tab->priv->print_job); + + show_printing_message_area (tab, TRUE); + + g_signal_connect (pjob, "begin_page", (GCallback) print_page_cb, tab); + g_signal_connect (pjob, "finished", (GCallback) preview_finished_cb, tab); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_PRINT_PREVIEWING); + + if (!gtk_source_print_job_print_range_async (GTK_SOURCE_PRINT_JOB (pjob), start, end)) + { + /* FIXME: go in error state */ + gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL); + g_warning ("Async print preview failed"); + g_object_unref (pjob); + } +} + +void +_gedit_tab_mark_for_closing (GeditTab *tab) +{ + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL); + + gedit_tab_set_state (tab, GEDIT_TAB_STATE_CLOSING); +} + +gboolean +_gedit_tab_can_close (GeditTab *tab) +{ + GeditDocument *doc; + GeditTabState ts; + + g_return_val_if_fail (GEDIT_IS_TAB (tab), FALSE); + + ts = gedit_tab_get_state (tab); + + /* if we are loading or reverting, the tab can be closed */ + if ((ts == GEDIT_TAB_STATE_LOADING) || + (ts == GEDIT_TAB_STATE_LOADING_ERROR) || + (ts == GEDIT_TAB_STATE_REVERTING) || + (ts == GEDIT_TAB_STATE_REVERTING_ERROR)) /* CHECK: I'm not sure this is the right behavior for REVERTING ERROR */ + return TRUE; + + /* Do not close tab with saving errors */ + if (ts == GEDIT_TAB_STATE_SAVING_ERROR) + return FALSE; + + doc = gedit_tab_get_document (tab); + + /* TODO: we need to save the file also if it has been externally + modified - Paolo (Oct 10, 2005) */ + + return (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)) && + !gedit_document_get_deleted (doc)); +} + diff --git a/gedit/gedit-tab.h b/gedit/gedit-tab.h new file mode 100644 index 00000000..009f85cc --- /dev/null +++ b/gedit/gedit-tab.h @@ -0,0 +1,149 @@ +/* + * gedit-tab.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_TAB_H__ +#define __GEDIT_TAB_H__ + +#include + +#include +#include +#include + +G_BEGIN_DECLS + +typedef enum +{ + GEDIT_TAB_STATE_NORMAL = 0, + GEDIT_TAB_STATE_LOADING, + GEDIT_TAB_STATE_REVERTING, + GEDIT_TAB_STATE_SAVING, + GEDIT_TAB_STATE_PRINTING, + GEDIT_TAB_STATE_PRINT_PREVIEWING, + GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW, + GEDIT_TAB_STATE_GENERIC_NOT_EDITABLE, + GEDIT_TAB_STATE_LOADING_ERROR, + GEDIT_TAB_STATE_REVERTING_ERROR, + GEDIT_TAB_STATE_SAVING_ERROR, + GEDIT_TAB_STATE_GENERIC_ERROR, + GEDIT_TAB_STATE_CLOSING, + GEDIT_TAB_NUM_OF_STATES /* This is not a valid state */ +} GeditTabState; + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_TAB (gedit_tab_get_type()) +#define GEDIT_TAB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_TAB, GeditTab)) +#define GEDIT_TAB_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_TAB, GeditTab const)) +#define GEDIT_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_TAB, GeditTabClass)) +#define GEDIT_IS_TAB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_TAB)) +#define GEDIT_IS_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_TAB)) +#define GEDIT_TAB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_TAB, GeditTabClass)) + +/* Private structure type */ +typedef struct _GeditTabPrivate GeditTabPrivate; + +/* + * Main object structure + */ +typedef struct _GeditTab GeditTab; + +struct _GeditTab +{ + GtkVBox vbox; + + /*< private > */ + GeditTabPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditTabClass GeditTabClass; + +struct _GeditTabClass +{ + GtkVBoxClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_tab_get_type (void) G_GNUC_CONST; + +GeditView *gedit_tab_get_view (GeditTab *tab); + +/* This is only an helper function */ +GeditDocument *gedit_tab_get_document (GeditTab *tab); + +GeditTab *gedit_tab_get_from_document (GeditDocument *doc); + +GeditTabState gedit_tab_get_state (GeditTab *tab); + +/* + * Non exported methods + */ +GtkWidget *_gedit_tab_new (void); + +/* Whether create is TRUE, creates a new empty document if location does + not refer to an existing file */ +GtkWidget *_gedit_tab_new_from_uri (const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create); +gchar *_gedit_tab_get_name (GeditTab *tab); +gchar *_gedit_tab_get_tooltips (GeditTab *tab); +GdkPixbuf *_gedit_tab_get_icon (GeditTab *tab); +gboolean _gedit_tab_load (GeditTab *tab, + const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create); +void _gedit_tab_revert (GeditTab *tab); +void _gedit_tab_save (GeditTab *tab); +void _gedit_tab_save_as (GeditTab *tab, + const gchar *uri, + const GeditEncoding *encoding); +void _gedit_tab_print (GeditTab *tab, + GeditPrintJob *pjob, + GtkTextIter *start, + GtkTextIter *end); +void _gedit_tab_print_preview (GeditTab *tab, + GeditPrintJob *pjob, + GtkTextIter *start, + GtkTextIter *end); +void _gedit_tab_mark_for_closing (GeditTab *tab); + +gboolean _gedit_tab_can_close (GeditTab *tab); + +G_END_DECLS + +#endif /* __GEDIT_TAB_H__ */ diff --git a/gedit/gedit-tooltips.c b/gedit/gedit-tooltips.c index 66ebe5e7..15a3249a 100644 --- a/gedit/gedit-tooltips.c +++ b/gedit/gedit-tooltips.c @@ -67,7 +67,8 @@ static void gedit_tooltips_unset_tip_window (GeditTooltips * tooltips); static gboolean get_keyboard_mode (GtkWidget * widget); static GtkObjectClass *parent_class; -static const gchar *tooltips_data_key = "_GeditTooltipsData"; +static const gchar tooltips_data_key[] = "_GeditTooltipsData"; + GType gedit_tooltips_get_type (void) @@ -204,6 +205,8 @@ gedit_tooltips_destroy (GtkObject * object) } gedit_tooltips_unset_tip_window (tooltips); + + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void @@ -238,7 +241,6 @@ gedit_tooltips_update_screen (GeditTooltips * tooltips, (tooltips->tip_window), "closed", G_CALLBACK (tip_window_display_closed), tooltips); - } void @@ -267,7 +269,7 @@ gedit_tooltips_force_window (GeditTooltips * tooltips) TRUE); gtk_misc_set_alignment (GTK_MISC (tooltips->tip_label), 0.5, 0.5); - gtk_label_set_ellipsize (GTK_LABEL (tooltips->tip_label), + gtk_label_set_ellipsize (GTK_LABEL (tooltips->tip_label), PANGO_ELLIPSIZE_MIDDLE); gtk_label_set_max_width_chars (GTK_LABEL (tooltips->tip_label), 125); @@ -381,11 +383,14 @@ gedit_tooltips_set_tip (GeditTooltips * tooltips, static gint gedit_tooltips_paint_window (GeditTooltips * tooltips) { + GtkRequisition req; + + gtk_widget_size_request (tooltips->tip_window, &req); gtk_paint_flat_box (tooltips->tip_window->style, tooltips->tip_window->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, GTK_WIDGET (tooltips->tip_window), "tooltip", - 0, 0, -1, -1); + 0, 0, req.width, req.height); return FALSE; } @@ -395,11 +400,13 @@ gedit_tooltips_draw_tips (GeditTooltips * tooltips) { GtkRequisition requisition; GtkWidget *widget; - GtkStyle *style; - gint x, y, w, h, scr_w, scr_h; + gint x, y, w, h; GeditTooltipsData *data; gboolean keyboard_mode; GdkScreen *screen; + GdkScreen *pointer_screen; + gint monitor_num, px, py; + GdkRectangle monitor; if (!tooltips->tip_window) gedit_tooltips_force_window (tooltips); @@ -407,7 +414,6 @@ gedit_tooltips_draw_tips (GeditTooltips * tooltips) g_get_current_time (&tooltips->last_popdown); gtk_widget_ensure_style (tooltips->tip_window); - style = tooltips->tip_window->style; widget = tooltips->active_tips_data->widget; @@ -416,8 +422,6 @@ gedit_tooltips_draw_tips (GeditTooltips * tooltips) gedit_tooltips_update_screen (tooltips, FALSE); screen = gtk_widget_get_screen (widget); - scr_w = gdk_screen_get_width (screen); - scr_h = gdk_screen_get_height (screen); data = tooltips->active_tips_data; @@ -442,12 +446,23 @@ gedit_tooltips_draw_tips (GeditTooltips * tooltips) x -= (w / 2 + 4); - if ((x + w) > scr_w) - x -= (x + w) - scr_w; - else if (x < 0) - x = 0; + gdk_display_get_pointer (gdk_screen_get_display (screen), + &pointer_screen, &px, &py, NULL); - if ((y + h + widget->allocation.height + 4) > scr_h) + if (pointer_screen != screen) + { + px = x; + py = y; + } + monitor_num = gdk_screen_get_monitor_at_point (screen, px, py); + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + + if ((x + w) > monitor.x + monitor.width) + x -= (x + w) - (monitor.x + monitor.width); + else if (x < monitor.x) + x = monitor.x; + + if ((y + h + widget->allocation.height + 4) > monitor.y + monitor.height) y = y - h - 4; else y = y + widget->allocation.height + 4; @@ -469,6 +484,7 @@ gedit_tooltips_timeout (gpointer data) GDK_THREADS_LEAVE (); + tooltips->timer_tag = 0; return FALSE; } diff --git a/gedit/gedit-tooltips.h b/gedit/gedit-tooltips.h index fc2bb6cd..9686bd38 100644 --- a/gedit/gedit-tooltips.h +++ b/gedit/gedit-tooltips.h @@ -29,11 +29,7 @@ #include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - +G_BEGIN_DECLS #define GEDIT_TYPE_TOOLTIPS (gedit_tooltips_get_type ()) #define GEDIT_TOOLTIPS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_TOOLTIPS, GeditTooltips)) @@ -81,6 +77,7 @@ struct _GeditTooltipsClass { }; GType gedit_tooltips_get_type (void) G_GNUC_CONST; + GeditTooltips *gedit_tooltips_new (void); void gedit_tooltips_enable (GeditTooltips * tooltips); @@ -96,8 +93,6 @@ void gedit_tooltips_force_window (GeditTooltips * tooltips); void _gedit_tooltips_toggle_keyboard_mode (GtkWidget * widget); -#ifdef __cplusplus +G_END_DECLS -} -#endif /* __cplusplus */ #endif /* __GEDIT_TOOLTIPS_H__ */ diff --git a/gedit/gedit-ui.h b/gedit/gedit-ui.h new file mode 100644 index 00000000..b1379b42 --- /dev/null +++ b/gedit/gedit-ui.h @@ -0,0 +1,152 @@ +/* + * gedit-ui.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_UI_H__ +#define __GEDIT_UI_H__ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "gedit-commands.h" + +G_BEGIN_DECLS + +static const GtkActionEntry gedit_always_sensitive_menu_entries[] = +{ + /* Toplevel */ + { "File", NULL, N_("_File") }, + { "Edit", NULL, N_("_Edit") }, + { "View", NULL, N_("_View") }, + { "Search", NULL, N_("_Search") }, + { "Tools", NULL, N_("_Tools") }, + { "Documents", NULL, N_("_Documents") }, + { "Help", NULL, N_("_Help") }, + + /* File menu */ + { "FileNew", GTK_STOCK_NEW, NULL, "N", + N_("Create a new document"), G_CALLBACK (gedit_cmd_file_new) }, + { "FileOpen", GTK_STOCK_OPEN, N_("_Open..."), "O", + N_("Open a file"), G_CALLBACK (gedit_cmd_file_open) }, + { "FileOpenURI", NULL, N_("Open _Location..."), "L", + N_("Open a file from a specified location"), G_CALLBACK (gedit_cmd_file_open_uri) }, + { "FilePageSetup", NULL, N_("Page Set_up..."), NULL, + N_("Setup the page settings"), G_CALLBACK (gedit_cmd_file_page_setup) }, + + /* Edit menu */ + { "EditPreferences", GTK_STOCK_PREFERENCES, N_("Pr_eferences"), NULL, + N_("Configure the application"), G_CALLBACK (gedit_cmd_edit_preferences) }, + + /* Help menu */ + {"HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", + N_("Open the gedit manual"), G_CALLBACK (gedit_cmd_help_contents) }, + { "HelpAbout", GTK_STOCK_ABOUT, NULL, NULL, + N_("About this application"), G_CALLBACK (gedit_cmd_help_about) } +}; + +static const GtkActionEntry gedit_menu_entries[] = +{ + /* File menu */ + { "FileSave", GTK_STOCK_SAVE, NULL, "S", + N_("Save the current file"), G_CALLBACK (gedit_cmd_file_save) }, + { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("Save _As..."), "S", + N_("Save the current file with a different name"), G_CALLBACK (gedit_cmd_file_save_as) }, + { "FileRevert", GTK_STOCK_REVERT_TO_SAVED, NULL, NULL, + N_("Revert to a saved version of the file"), G_CALLBACK (gedit_cmd_file_revert) }, + { "FilePrintPreview", GTK_STOCK_PRINT_PREVIEW, N_("Print Previe_w"),"P", + N_("Print preview"), G_CALLBACK (gedit_cmd_file_print_preview) }, + { "FilePrint", GTK_STOCK_PRINT, N_("_Print..."), "P", + N_("Print the current page"), G_CALLBACK (gedit_cmd_file_print) }, + { "FileClose", GTK_STOCK_CLOSE, NULL, "W", + N_("Close the current file"), G_CALLBACK (gedit_cmd_file_close) }, + { "FileQuit", GTK_STOCK_QUIT, NULL, "Q", + N_("Quit the program"), G_CALLBACK (gedit_cmd_file_quit) }, + + /* Edit menu */ + { "EditUndo", GTK_STOCK_UNDO, NULL, "Z", + N_("Undo the last action"), G_CALLBACK (gedit_cmd_edit_undo) }, + { "EditRedo", GTK_STOCK_REDO, NULL, "Z", + N_("Redo the last undone action"), G_CALLBACK (gedit_cmd_edit_redo) }, + { "EditCut", GTK_STOCK_CUT, NULL, "X", + N_("Cut the selection"), G_CALLBACK (gedit_cmd_edit_cut) }, + { "EditCopy", GTK_STOCK_COPY, NULL, "C", + N_("Copy the selection"), G_CALLBACK (gedit_cmd_edit_copy) }, + { "EditPaste", GTK_STOCK_PASTE, NULL, "V", + N_("Paste the clipboard"), G_CALLBACK (gedit_cmd_edit_paste) }, + { "EditDelete", GTK_STOCK_DELETE, NULL, NULL, + N_("Delete the selected text"), G_CALLBACK (gedit_cmd_edit_delete) }, + { "EditSelectAll", NULL, N_("Select _All"), "A", + N_("Select the entire document"), G_CALLBACK (gedit_cmd_edit_select_all) }, + + /* View menu */ + { "ViewHighlightMode", NULL, N_("_Highlight Mode") }, + + /* Search menu */ + { "SearchFind", GTK_STOCK_FIND, N_("_Find..."), "F", + N_("Search for text"), G_CALLBACK (gedit_cmd_search_find) }, + { "SearchFindNext", NULL, N_("Find Ne_xt"), "G", + N_("Search forwards for the same text"), G_CALLBACK (gedit_cmd_search_find_next) }, + { "SearchFindPrevious", NULL, N_("Find Pre_vious"), "G", + N_("Search backwards for the same text"), G_CALLBACK (gedit_cmd_search_find_prev) }, + { "SearchReplace", GTK_STOCK_FIND_AND_REPLACE, N_("_Replace..."), "R", + N_("Search for and replace text"), G_CALLBACK (gedit_cmd_search_replace) }, + { "SearchGoToLine", GTK_STOCK_JUMP_TO, N_("Go to _Line..."), "I", + N_("Go to a specific line"), G_CALLBACK (gedit_cmd_search_goto_line) }, + + /* Documents menu */ + { "FileSaveAll", GTK_STOCK_SAVE, N_("_Save All"), "L", + N_("Save all open files"), G_CALLBACK (gedit_cmd_file_save_all) }, + { "FileCloseAll", GTK_STOCK_CLOSE, N_("_Close All"), "W", + N_("Close all open files"), G_CALLBACK (gedit_cmd_file_close_all) }, + { "DocumentsMoveToNewWindow", NULL, N_("_Move to New Window"), NULL, + N_("Move the current document to a new window"), G_CALLBACK (gedit_cmd_documents_move_to_new_window) }, +}; + +static const GtkToggleActionEntry gedit_toggle_menu_entries[] = +{ + { "ViewToolbar", NULL, N_("_Toolbar"), NULL, + N_("Show or hide the toolbar in the current window"), + G_CALLBACK (gedit_cmd_view_show_toolbar), TRUE }, + { "ViewStatusbar", NULL, N_("_Statusbar"), NULL, + N_("Show or hide the statusbar in the current window"), + G_CALLBACK (gedit_cmd_view_show_statusbar), TRUE }, + { "ViewSidePane", NULL, N_("Side _Pane"), "F9", + N_("Show or hide the side pane in the current window"), + G_CALLBACK (gedit_cmd_view_show_side_pane), FALSE }, + { "ViewBottomPanel", NULL, N_("_Bottom Panel"), "F9", + N_("Show or hide the bottom panel in the current window"), + G_CALLBACK (gedit_cmd_view_show_bottom_panel), FALSE } +}; + +G_END_DECLS + +#endif /* __GEDIT_UI_H__ */ diff --git a/gedit/gedit-ui.xml b/gedit/gedit-ui.xml index 78c5c6cc..c0f4b045 100644 --- a/gedit/gedit-ui.xml +++ b/gedit/gedit-ui.xml @@ -1,350 +1,152 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gedit/gedit-utils.c b/gedit/gedit-utils.c index e31d1c4f..4b92e9b4 100644 --- a/gedit/gedit-utils.c +++ b/gedit/gedit-utils.c @@ -1,10 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * 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 @@ -23,9 +23,11 @@ */ /* - * Modified by the gedit Team, 1998-2002. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -45,11 +47,12 @@ #include #include #include +#include #include +#include #include "gedit-utils.h" -#include "gedit2.h" -#include "bonobo-mdi.h" + #include "gedit-document.h" #include "gedit-prefs-manager.h" #include "gedit-debug.h" @@ -57,189 +60,6 @@ #define STDIN_DELAY_MICROSECONDS 100000 -/* =================================================== */ -/* Flash */ - -struct _MessageInfo { - BonoboWindow * win; - guint timeoutid; - guint handlerid; -}; - -typedef struct _MessageInfo MessageInfo; - -MessageInfo *current_mi = NULL; - -static gint remove_message_timeout (MessageInfo * mi); -static void remove_timeout_cb (GtkWidget *win, MessageInfo *mi); -static void bonobo_window_flash (BonoboWindow * win, const gchar * flash); - -static gint -remove_message_timeout (MessageInfo * mi) -{ - BonoboUIComponent *ui_component; - - GDK_THREADS_ENTER (); - - ui_component = bonobo_mdi_get_ui_component_from_window (mi->win); - g_return_val_if_fail (ui_component != NULL, FALSE); - - bonobo_ui_component_set_status (ui_component, " ", NULL); - - g_signal_handler_disconnect (G_OBJECT (mi->win), mi->handlerid); - - g_free (mi); - current_mi = NULL; - - GDK_THREADS_LEAVE (); - - return FALSE; /* removes the timeout */ -} - -/* Called if the win is destroyed before the timeout occurs. */ -static void -remove_timeout_cb (GtkWidget *win, MessageInfo *mi) -{ - g_source_remove (mi->timeoutid); - g_free (mi); - - if (mi == current_mi) - current_mi = NULL; -} - -static const guint32 flash_length = 3000; /* 3 seconds, I hope */ - -/** - * bonobo_win_flash - * @app: Pointer a Bonobo window object - * @flash: Text of message to be flashed - * - * Description: - * Flash the message in the statusbar for a few moments; if no - * statusbar, do nothing. For trivial little status messages, - * e.g. "Auto saving..." - **/ - -static void -bonobo_window_flash (BonoboWindow * win, const gchar * flash) -{ - BonoboUIComponent *ui_component; - g_return_if_fail (win != NULL); - g_return_if_fail (BONOBO_IS_WINDOW (win)); - g_return_if_fail (flash != NULL); - - ui_component = bonobo_mdi_get_ui_component_from_window (win); - g_return_if_fail (ui_component != NULL); - - if (current_mi != NULL) - { - g_source_remove (current_mi->timeoutid); - remove_message_timeout (current_mi); - } - - if (bonobo_ui_component_path_exists (ui_component, "/status", NULL)) - { - MessageInfo * mi; - - bonobo_ui_component_set_status (ui_component, flash, NULL); - - mi = g_new(MessageInfo, 1); - - mi->timeoutid = - g_timeout_add (flash_length, - (GSourceFunc) remove_message_timeout, - mi); - - mi->handlerid = - g_signal_connect (GTK_OBJECT (win), - "destroy", - G_CALLBACK (remove_timeout_cb), - mi); - - mi->win = win; - - current_mi = mi; - } -} - -/* ========================================================== */ - -/** - * gedit_utils_flash: - * @msg: Message to flash on the statusbar - * - * Flash a temporary message on the statusbar of gedit. - **/ -void -gedit_utils_flash (const gchar *msg) -{ - g_return_if_fail (msg != NULL); - - bonobo_window_flash (bonobo_mdi_get_active_window (BONOBO_MDI (gedit_mdi)), msg); -} - -/** - * gedit_utils_flash_va: - * @format: - **/ -void -gedit_utils_flash_va (gchar *format, ...) -{ - va_list args; - gchar *msg; - - g_return_if_fail (format != NULL); - - va_start (args, format); - msg = g_strdup_vprintf (format, args); - va_end (args); - - gedit_utils_flash (msg); - g_free (msg); -} - -void -gedit_utils_set_status (const gchar *msg) -{ - BonoboWindow *win; - BonoboUIComponent *ui_component; - - win = gedit_get_active_window (); - g_return_if_fail (BONOBO_IS_WINDOW (win)); - - ui_component = bonobo_mdi_get_ui_component_from_window (win); - g_return_if_fail (ui_component != NULL); - - if (current_mi != NULL) - { - g_source_remove (current_mi->timeoutid); - remove_message_timeout (current_mi); - } - - if (bonobo_ui_component_path_exists (ui_component, "/status", NULL)) - { - bonobo_ui_component_set_status (ui_component, (msg != NULL) ? msg : " ", NULL); - - current_mi = NULL; - } -} - -void -gedit_utils_set_status_va (gchar *format, ...) -{ - va_list args; - gchar *msg; - - g_return_if_fail (format != NULL); - - va_start (args, format); - msg = g_strdup_vprintf (format, args); - va_end (args); - - gedit_utils_set_status (msg); - g_free (msg); -} - gboolean gedit_utils_uri_has_file_scheme (const gchar *uri) { @@ -257,44 +77,66 @@ gedit_utils_uri_has_file_scheme (const gchar *uri) } gboolean -gedit_utils_is_uri_read_only (const gchar* uri) +gedit_utils_uri_has_writable_scheme (const gchar *uri) { - gchar* file_uri = NULL; - gchar* canonical_uri = NULL; + gchar *canonical_uri; + gchar *scheme; + GSList *writable_schemes; + gboolean res; - gint res; + canonical_uri = gnome_vfs_make_uri_canonical (uri); + g_return_val_if_fail (canonical_uri != NULL, FALSE); - g_return_val_if_fail (uri != NULL, TRUE); - - gedit_debug (DEBUG_FILE, "URI: %s", uri); + scheme = gnome_vfs_get_uri_scheme (canonical_uri); + g_return_val_if_fail (scheme != NULL, FALSE); - /* FIXME: all remote files are marked as readonly */ - if (!gedit_utils_uri_has_file_scheme (uri)) - return TRUE; - - canonical_uri = gnome_vfs_make_uri_canonical (uri); - g_return_val_if_fail (canonical_uri != NULL, TRUE); + g_free (canonical_uri); - gedit_debug (DEBUG_FILE, "CANONICAL URI: %s", canonical_uri); + writable_schemes = gedit_prefs_manager_get_writable_vfs_schemes (); - file_uri = gnome_vfs_get_local_path_from_uri (canonical_uri); - if (file_uri == NULL) - { - gedit_debug (DEBUG_FILE, "FILE URI: NULL"); + /* CHECK: should we use g_ascii_strcasecmp? - Paolo (Nov 6, 2005) */ + res = (g_slist_find_custom (writable_schemes, + scheme, + (GCompareFunc)strcmp) != NULL); + + g_slist_foreach (writable_schemes, (GFunc)g_free, NULL); + g_slist_free (writable_schemes); + + g_free (scheme); + + return res; +} + +void +gedit_utils_menu_position_under_widget (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + gpointer user_data) +{ + GtkWidget *w = GTK_WIDGET (user_data); + GtkRequisition requisition; + + gdk_window_get_origin (w->window, x, y); + gtk_widget_size_request (GTK_WIDGET (menu), &requisition); - return TRUE; + if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL) + { + *x += w->allocation.x + w->allocation.width - requisition.width; + } + else + { + *x += w->allocation.x; } - - res = access (file_uri, W_OK); - g_free (canonical_uri); - g_free (file_uri); + *y += w->allocation.y + w->allocation.height; - return res; + *push_in = TRUE; } -static GtkWidget * -gedit_gtk_button_new_with_stock_icon (const gchar *label, const gchar *stock_id) +GtkWidget * +gedit_gtk_button_new_with_stock_icon (const gchar *label, + const gchar *stock_id) { GtkWidget *button; @@ -306,9 +148,11 @@ gedit_gtk_button_new_with_stock_icon (const gchar *label, const gchar *stock_id) return button; } -GtkWidget* -gedit_dialog_add_button (GtkDialog *dialog, const gchar* text, const gchar* stock_id, - gint response_id) +GtkWidget * +gedit_dialog_add_button (GtkDialog *dialog, + const gchar *text, + const gchar *stock_id, + gint response_id) { GtkWidget *button; @@ -347,11 +191,11 @@ g_utf8_caselessnmatch (const char *s1, const char *s2, gssize n1, gssize n2) g_return_val_if_fail (n2 > 0, FALSE); casefold = g_utf8_casefold (s1, n1); - normalized_s1 = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL); + normalized_s1 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD); g_free (casefold); casefold = g_utf8_casefold (s2, n2); - normalized_s2 = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL); + normalized_s2 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD); g_free (casefold); len_s1 = strlen (normalized_s1); @@ -436,7 +280,7 @@ gedit_utils_uri_exists (const gchar* text_uri) g_return_val_if_fail (text_uri != NULL, FALSE); - gedit_debug (DEBUG_FILE, "text_uri: %s", text_uri); + gedit_debug_message (DEBUG_FILE, "text_uri: %s", text_uri); uri = gnome_vfs_uri_new (text_uri); g_return_val_if_fail (uri != NULL, FALSE); @@ -445,13 +289,60 @@ gedit_utils_uri_exists (const gchar* text_uri) gnome_vfs_uri_unref (uri); - gedit_debug (DEBUG_FILE, res ? "TRUE" : "FALSE"); + gedit_debug_message (DEBUG_FILE, res ? "TRUE" : "FALSE"); return res; } +gchar* +gedit_utils_escape_search_text (const gchar* text) +{ + GString *str; + gint length; + const gchar *p; + const gchar *end; + + if (text == NULL) + return NULL; + + gedit_debug_message (DEBUG_SEARCH, "Text: %s", text); + + length = strlen (text); + + str = g_string_new (""); + + p = text; + end = text + length; + + while (p != end) + { + const gchar *next; + next = g_utf8_next_char (p); + + switch (*p) + { + case '\n': + g_string_append (str, "\\n"); + break; + case '\r': + g_string_append (str, "\\r"); + break; + case '\t': + g_string_append (str, "\\t"); + break; + default: + g_string_append_len (str, p, next - p); + break; + } + + p = next; + } + + return g_string_free (str, FALSE); +} + gchar * -gedit_utils_convert_search_text (const gchar *text) +gedit_utils_unescape_search_text (const gchar *text) { GString *str; gint length; @@ -459,8 +350,9 @@ gedit_utils_convert_search_text (const gchar *text) const gchar *cur; const gchar *end; const gchar *prev; - - g_return_val_if_fail (text != NULL, NULL); + + if (text == NULL) + return NULL; length = strlen (text); @@ -572,7 +464,7 @@ gedit_utils_get_stdin (void) } void -gedit_warning (GtkWindow *parent, gchar *format, ...) +gedit_warning (GtkWindow *parent, const gchar *format, ...) { va_list args; gchar *str; @@ -584,12 +476,12 @@ gedit_warning (GtkWindow *parent, gchar *format, ...) str = g_strdup_vprintf (format, args); va_end (args); - dialog = gtk_message_dialog_new ( + dialog = gtk_message_dialog_new_with_markup ( parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - "%s", str); + str); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); @@ -683,51 +575,35 @@ gedit_utils_make_valid_utf8 (const char *name) } g_string_append (string, remainder); - g_string_append (string, _(" (invalid Unicode)")); + g_string_append (string, " (invalid encoding)"); + g_assert (g_utf8_validate (string->str, -1, NULL)); return g_string_free (string, FALSE); } +/* Note that this function replace home dir with ~ */ gchar * -gedit_utils_uri_get_basename (const char *uri) +gedit_utils_uri_get_dirname (const gchar *uri) { - GnomeVFSURI *vfs_uri; - char *name; - - /* Make VFS version of URI. */ - vfs_uri = gnome_vfs_uri_new (uri); - if (vfs_uri == NULL) { - return NULL; - } - - /* Extract name part. */ - name = gnome_vfs_uri_extract_short_name (vfs_uri); - gnome_vfs_uri_unref (vfs_uri); - - return name; -} - -gchar * -gedit_utils_uri_get_dirname (const char *uri) -{ - GnomeVFSURI *vfs_uri; - gchar *name; gchar *res; + gchar *str; + + // CHECK: does it work with uri chaining? - Paolo + str = g_path_get_dirname (uri); + g_return_val_if_fail (str != NULL, "."); - /* Make VFS version of URI. */ - vfs_uri = gnome_vfs_uri_new (uri); - if (vfs_uri == NULL) { + if ((strlen (str) == 1) && (*str == '.')) + { + g_free (str); + return NULL; } - /* Extract name part. */ - name = gnome_vfs_uri_extract_dirname (vfs_uri); - gnome_vfs_uri_unref (vfs_uri); - - res = g_strdup_printf ("file:///%s", name); - g_free (name); + res = gedit_utils_replace_home_dir_with_tilde (str); + g_free (str); + return res; } @@ -848,4 +724,152 @@ gedit_utils_get_window_workspace (GtkWindow *gtkwindow) return ret; } +void +gedit_utils_activate_url (GtkAboutDialog *about, + const gchar *url, + gpointer data) +{ + gnome_url_show (url, NULL); +} + +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_uri (const gchar *uri) +{ + const guchar *p; + if (uri == NULL) + return FALSE; + + if (!has_valid_scheme (uri)) + return FALSE; + + /* We expect to have a fully valid set of characters */ + for (p = uri; *p; p++) { + if (*p == '%') + { + ++p; + if (!g_ascii_isxdigit (*p)) + return FALSE; + + ++p; + if (!g_ascii_isxdigit (*p)) + return FALSE; + } + else + { + if (*p <= 32 || *p >= 128) + return FALSE; + } + } + + return TRUE; +} + + + +#define GEDIT_MISSING_FILE N_("Unable to find file %s.\n\nPlease, check your installation.") +#define GEDIT_MISSING_WIDGETS N_("Unable to find the required widgets inside file %s..\n\nPlease, check your installation.") + +/** + * gedit_utils_get_glade_widgets: + * @filename: the path to the glade file + * @root_node: the root node in the glade file + * @error_widget: a pointer were a #GtkLabel + * @widget_name: the name of the first widget + * @...: a pointer were the first widget is returned, followed by more + * name / widget pairs and terminated by NULL. + * + * This function gets the requested widgets from a glade file. In case + * of error it returns FALSE and sets error_widget to a GtkLabel containing + * the error message to display. + * + * Returns FALSE if an error occurs, TRUE on success. + */ +gboolean +gedit_utils_get_glade_widgets (const gchar *filename, + const gchar *root_node, + GtkWidget **error_widget, + const gchar *widget_name, + ...) +{ + GtkWidget *label; + GladeXML *gui; + va_list args; + const gchar *name; + gchar *msg; + gboolean ret = TRUE; + + g_return_val_if_fail (filename != NULL, FALSE); + g_return_val_if_fail (error_widget != NULL, FALSE); + g_return_val_if_fail (widget_name != NULL, FALSE); + + *error_widget = NULL; + + gui = glade_xml_new (filename, root_node, NULL); + if (!gui) + { + msg = g_strdup_printf (GEDIT_MISSING_FILE, filename); + label = gtk_label_new (msg); + + gtk_label_set_use_markup (GTK_LABEL (label), TRUE); + + g_free (msg); + + *error_widget = label; + + return FALSE; + } + + va_start (args, widget_name); + for (name = widget_name; name; name = va_arg (args, const gchar *) ) + { + GtkWidget **wid; + + wid = va_arg (args, GtkWidget **); + *wid = glade_xml_get_widget (gui, name); + if (*wid == NULL) + { + msg = g_strdup_printf (GEDIT_MISSING_WIDGETS, filename); + label = gtk_label_new (msg); + + gtk_label_set_use_markup (GTK_LABEL (label), TRUE); + + g_free (msg); + + *error_widget = label; + + ret = FALSE; + + break; + } + } + va_end (args); + + g_object_unref (gui); + + return ret; +} diff --git a/gedit/gedit-utils.h b/gedit/gedit-utils.h index fc20af3e..5267d843 100644 --- a/gedit/gedit-utils.h +++ b/gedit/gedit-utils.h @@ -1,10 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * 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) 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 @@ -19,13 +19,15 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. * * + * Boston, MA 02111-1307, USA. */ /* - * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_UTILS_H__ @@ -34,65 +36,94 @@ #include #include #include +#include +#include #include #include #include +G_BEGIN_DECLS + +/* useful macro */ +#define GBOOLEAN_TO_POINTER(i) ((gpointer) ((i) ? 2 : 1)) +#define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((((gint)(i)) == 2) ? TRUE : FALSE)) -/* some common error strings, %s must be a file path */ -#define MISSING_FILE N_("Could not find \"%s\". Please, reinstall gedit.\n") -#define MISSING_WIDGETS N_("Could not find the required widgets inside\"%s\". Please, reinstall gedit.\n") +#define IS_VALID_BOOLEAN(v) (((v == TRUE) || (v == FALSE)) ? TRUE : FALSE) enum { GEDIT_ALL_WORKSPACES = 0xffffffff }; +gboolean gedit_utils_uri_has_writable_scheme (const gchar *uri); +gboolean gedit_utils_uri_has_file_scheme (const gchar *uri); + +void gedit_utils_menu_position_under_widget (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + gpointer user_data); + +GtkWidget *gedit_gtk_button_new_with_stock_icon (const gchar *label, + const gchar *stock_id); + +GtkWidget *gedit_dialog_add_button (GtkDialog *dialog, + const gchar *text, + const gchar *stock_id, + gint response_id); -void gedit_utils_flash (const gchar *msg); -void gedit_utils_flash_va (gchar *format, ...); +gchar *gedit_utils_str_middle_truncate (const gchar *string, + guint truncate_length); -void gedit_utils_set_status (const gchar *msg); -void gedit_utils_set_status_va (gchar *format, ...); +gboolean g_utf8_caselessnmatch (const char *s1, + const char *s2, + gssize n1, + gssize n2); +void gedit_utils_set_atk_name_description (GtkWidget *widget, + const gchar *name, + const gchar *description); -gboolean gedit_utils_is_uri_read_only (const gchar* uri); -gboolean gedit_utils_uri_has_file_scheme (const gchar *uri); +void gedit_utils_set_atk_relation (GtkWidget *obj1, + GtkWidget *obj2, + AtkRelationType rel_type); -GtkWidget *gedit_dialog_add_button (GtkDialog *dialog, - const gchar* text, - const gchar* stock_id, - gint response_id); +gboolean gedit_utils_uri_exists (const gchar* text_uri); -gchar *gedit_utils_str_middle_truncate (const gchar *string, - guint truncate_length); +gchar *gedit_utils_escape_search_text (const gchar *text); -gboolean g_utf8_caselessnmatch (const char *s1, const char *s2, gssize n1, gssize n2); +gchar *gedit_utils_unescape_search_text (const gchar *text); -void gedit_utils_set_atk_name_description (GtkWidget *widget, const gchar *name, - const gchar *description); -void gedit_utils_set_atk_relation (GtkWidget *obj1, GtkWidget *obj2, - AtkRelationType rel_type); +gchar *gedit_utils_get_stdin (void); -gboolean gedit_utils_uri_exists (const gchar* text_uri); +void gedit_warning (GtkWindow *parent, + const gchar *format, + ...) G_GNUC_PRINTF(2, 3); -gchar *gedit_utils_convert_search_text (const gchar *text); +gchar *gedit_utils_str_middle_truncate (const char *string, + guint truncate_length); -gchar *gedit_utils_get_stdin (void); +gchar *gedit_utils_make_valid_utf8 (const char *name); -void gedit_warning (GtkWindow *parent, gchar *format, ...); +/* Note that this function replace home dir with ~ */ +gchar *gedit_utils_uri_get_dirname (const char *uri); -gchar *gedit_utils_str_middle_truncate (const char *string, - guint truncate_length); +gchar *gedit_utils_replace_home_dir_with_tilde (const gchar *uri); -gchar *gedit_utils_make_valid_utf8 (const char *name); +guint gedit_utils_get_current_workspace (GdkScreen *screen); -gchar *gedit_utils_uri_get_basename (const char *uri); +guint gedit_utils_get_window_workspace (GtkWindow *gtkwindow); -gchar *gedit_utils_uri_get_dirname (const char *uri); +void gedit_utils_activate_url (GtkAboutDialog *about, + const gchar *url, + gpointer data); -gchar *gedit_utils_replace_home_dir_with_tilde (const gchar *uri); +gboolean gedit_utils_is_valid_uri (const gchar *uri); -guint gedit_utils_get_current_workspace (GdkScreen *screen); +gboolean gedit_utils_get_glade_widgets (const gchar *filename, + const gchar *root_node, + GtkWidget **error_widget, + const gchar *widget_name, + ...) G_GNUC_NULL_TERMINATED; -guint gedit_utils_get_window_workspace (GtkWindow *gtkwindow); +G_END_DECLS #endif /* __GEDIT_UTILS_H__ */ diff --git a/gedit/gedit-view.c b/gedit/gedit-view.c index 2a05ea60..97754e15 100644 --- a/gedit/gedit-view.c +++ b/gedit/gedit-view.c @@ -1,10 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-view.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 @@ -23,9 +23,11 @@ */ /* - * Modified by the gedit Team, 1998-2002. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. - * See the ChangeLog files for a list of changes. + * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -33,145 +35,146 @@ #endif #include +#include -#include #include -#include + +#include #include "gedit-view.h" #include "gedit-debug.h" -#include "gedit-menus.h" #include "gedit-prefs-manager-app.h" #include "gedit-marshal.h" +#include "gedit-utils.h" +#include "sexy-icon-entry.h" -#define MIN_NUMBER_WINDOW_WIDTH 20 #define GEDIT_VIEW_SCROLL_MARGIN 0.02 +#define GEDIT_VIEW_SEARCH_DIALOG_TIMEOUT 5000 -struct _GeditViewPrivate +#define MIN_SEARCH_COMPLETION_KEY_LEN 3 + +#define GEDIT_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_VIEW, GeditViewPrivate)) + +typedef enum { - GtkSourceView *text_view; + GOTO_LINE, + SEARCH +} SearchMode; - GeditDocument *document; +struct _GeditViewPrivate +{ + GtkTooltips *tooltips; + + SearchMode search_mode; + + GtkTextIter start_search_iter; - gboolean line_numbers_visible; + /* used to restore the search state if an + * incremental search is cancelled + */ + gchar *old_search_text; + guint old_search_flags; - GtkWidget *cursor_position_statusbar; - GtkWidget *overwrite_mode_statusbar; + /* used to remeber the state of the last + * incremental search (the document search + * state may be changed by the search dialog) + */ + guint search_flags; + gboolean wrap_around; - gboolean overwrite_mode; -}; + GtkWidget *search_window; + GtkWidget *search_entry; -enum -{ - POPULATE_POPUP, - LAST_SIGNAL + guint typeselect_flush_timeout; + guint search_entry_changed_id; + + gboolean disable_popdown; }; -static guint signals[LAST_SIGNAL] = { 0 }; - -static void gedit_view_class_init (GeditViewClass *klass); -static void gedit_view_init (GeditView *view); -static void gedit_view_finalize (GObject *object); - -static void gedit_view_update_cursor_position_statusbar - (GtkTextBuffer *buffer, - GeditView* view); -static void gedit_view_cursor_moved (GtkTextBuffer *buffer, - const GtkTextIter *new_location, - GtkTextMark *mark, - GeditView *view); -static void gedit_view_update_overwrite_mode_statusbar (GtkTextView* w, GeditView* view); -static void gedit_view_doc_readonly_changed_handler (GeditDocument *document, - gboolean readonly, - GeditView *view); -static void gedit_view_populate_popup (GtkTextView *textview, GtkMenu *menu, gpointer data); - -static GtkVBoxClass *parent_class = NULL; - -GType -gedit_view_get_type (void) -{ - static GType view_type = 0; - - if (view_type == 0) - { - static const GTypeInfo our_info = - { - sizeof (GeditViewClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gedit_view_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GeditView), - 0, /* n_preallocs */ - (GInstanceInitFunc) gedit_view_init - }; - - view_type = g_type_register_static (GTK_TYPE_VBOX, - "GeditView", - &our_info, - 0); - } +/* The search entry completion is shared among all the views */ +GtkListStore *search_completion_model = NULL; - return view_type; -} +static void gedit_view_destroy (GtkObject *object); +static void gedit_view_finalize (GObject *object); +static void gedit_view_move_cursor (GtkTextView *text_view, + GtkMovementStep step, + gint count, + gboolean extend_selection); -static void -gedit_view_grab_focus (GtkWidget *widget) -{ - GeditView *view; - - gedit_debug (DEBUG_VIEW, ""); - - view = GEDIT_VIEW (widget); +static gboolean start_interactive_search (GeditView *view); +static gboolean start_interactive_goto_line (GeditView *view); - gtk_widget_grab_focus (GTK_WIDGET (view->priv->text_view)); -} +G_DEFINE_TYPE(GeditView, gedit_view, GTK_TYPE_SOURCE_VIEW) -void -gedit_view_set_editable (GeditView *view, gboolean editable) +/* Signals */ +enum { - gedit_debug (DEBUG_VIEW, ""); + START_INTERACTIVE_SEARCH, + START_INTERACTIVE_GOTO_LINE, + LAST_SIGNAL +}; - g_return_if_fail (GEDIT_IS_VIEW (view)); +static guint view_signals [LAST_SIGNAL] = { 0 }; - gtk_text_view_set_editable (GTK_TEXT_VIEW (view->priv->text_view), - editable); -} +typedef enum +{ + GEDIT_SEARCH_ENTRY_NORMAL, + GEDIT_SEARCH_ENTRY_NOT_FOUND +} GeditSearchEntryBgColor; static void -gedit_view_doc_readonly_changed_handler (GeditDocument *document, gboolean readonly, - GeditView *view) +document_read_only_notify_handler (GeditDocument *document, + GParamSpec *pspec, + GeditView *view) { - gedit_debug (DEBUG_VIEW, ""); - - g_return_if_fail (GEDIT_IS_VIEW (view)); + gedit_debug (DEBUG_VIEW); - gedit_view_set_editable (view, !readonly); + gtk_text_view_set_editable (GTK_TEXT_VIEW (view), + !gedit_document_get_readonly (document)); } static void gedit_view_class_init (GeditViewClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - object_class->finalize = gedit_view_finalize; - - GTK_WIDGET_CLASS (klass)->grab_focus = gedit_view_grab_focus; - - signals[POPULATE_POPUP] = - g_signal_new ("populate_popup", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GeditViewClass, populate_popup), + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass); + GtkTextViewClass *textview_class = GTK_TEXT_VIEW_CLASS (klass); + GtkBindingSet *binding_set; + + gtkobject_class->destroy = gedit_view_destroy; + object_class->finalize = gedit_view_finalize; + + klass->start_interactive_search = start_interactive_search; + klass->start_interactive_goto_line = start_interactive_goto_line; + textview_class->move_cursor = gedit_view_move_cursor; + + view_signals[START_INTERACTIVE_SEARCH] = + g_signal_new ("start_interactive_search", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GeditViewClass, start_interactive_search), + NULL, NULL, + gedit_marshal_BOOLEAN__NONE, + G_TYPE_BOOLEAN, 0); + + view_signals[START_INTERACTIVE_GOTO_LINE] = + g_signal_new ("start_interactive_goto_line", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GeditViewClass, start_interactive_goto_line), NULL, NULL, - gedit_marshal_VOID__OBJECT, - G_TYPE_NONE, - 1, - GTK_TYPE_MENU); + gedit_marshal_BOOLEAN__NONE, + G_TYPE_BOOLEAN, 0); + + g_type_class_add_private (klass, sizeof (GeditViewPrivate)); + + binding_set = gtk_binding_set_by_class (klass); + + gtk_binding_entry_add_signal (binding_set, GDK_k, GDK_CONTROL_MASK, "start_interactive_search", 0); + gtk_binding_entry_add_signal (binding_set, GDK_K, GDK_CONTROL_MASK, "start_interactive_search", 0); + + gtk_binding_entry_add_signal (binding_set, GDK_i, GDK_CONTROL_MASK, "start_interactive_goto_line", 0); + gtk_binding_entry_add_signal (binding_set, GDK_I, GDK_CONTROL_MASK, "start_interactive_goto_line", 0); } static void @@ -182,7 +185,8 @@ move_cursor (GtkTextView *text_view, GtkTextBuffer *buffer = text_view->buffer; if (extend_selection) - gtk_text_buffer_move_mark_by_name (buffer, "insert", + gtk_text_buffer_move_mark_by_name (buffer, + "insert", new_location); else gtk_text_buffer_place_cursor (buffer, new_location); @@ -197,57 +201,57 @@ move_cursor (GtkTextView *text_view, /* * This feature is implemented in gedit and not in gtksourceview since the latter - * has a similar feature called smart home/end that it is non-capatible with this - * one and is more "invasive". May be in the future we will move this feature in - * gtksourceview. + * has a similar feature called smart home/end that it is not compatible with this + * one and is more "invasive". Maybe in the future we will move this feature in + * gtksourceview or even better in gtktextview. */ static void gedit_view_move_cursor (GtkTextView *text_view, GtkMovementStep step, gint count, - gboolean extend_selection, - gpointer data) + gboolean extend_selection) { GtkTextBuffer *buffer = text_view->buffer; GtkTextMark *mark; GtkTextIter cur, iter; - if (step != GTK_MOVEMENT_DISPLAY_LINE_ENDS) - return; + /* really make sure gtksourceview's home/end is disabled */ + g_return_if_fail (!gtk_source_view_get_smart_home_end ( + GTK_SOURCE_VIEW (text_view))); - g_return_if_fail (!gtk_source_view_get_smart_home_end (GTK_SOURCE_VIEW (text_view))); - mark = gtk_text_buffer_get_insert (buffer); gtk_text_buffer_get_iter_at_mark (buffer, &cur, mark); iter = cur; - if ((count == -1) && gtk_text_iter_starts_line (&iter)) + if (step == GTK_MOVEMENT_DISPLAY_LINE_ENDS && + (count == -1) && gtk_text_iter_starts_line (&iter)) { /* Find the iter of the first character on the line. */ while (!gtk_text_iter_ends_line (&cur)) { - gunichar c = gtk_text_iter_get_char (&cur); + gunichar c; + + c = gtk_text_iter_get_char (&cur); if (g_unichar_isspace (c)) gtk_text_iter_forward_char (&cur); else break; } - if (!gtk_text_iter_equal (&cur, &iter)) - { + /* if we are clearing selection, we need to move_cursor even + * if we are at proper iter because selection_bound may need + * to be moved */ + if (!gtk_text_iter_equal (&cur, &iter) || !extend_selection) move_cursor (text_view, &cur, extend_selection); - g_signal_stop_emission_by_name (text_view, "move-cursor"); - } - - return; } - - if ((count == 1) && gtk_text_iter_ends_line (&iter)) + else if (step == GTK_MOVEMENT_DISPLAY_LINE_ENDS && + (count == 1) && gtk_text_iter_ends_line (&iter)) { /* Find the iter of the last character on the line. */ while (!gtk_text_iter_starts_line (&cur)) { gunichar c; + gtk_text_iter_backward_char (&cur); c = gtk_text_iter_get_char (&cur); if (!g_unichar_isspace (c)) @@ -258,39 +262,36 @@ gedit_view_move_cursor (GtkTextView *text_view, } } - if (!gtk_text_iter_equal (&cur, &iter)) - { + /* if we are clearing selection, we need to move_cursor even + * if we are at proper iter because selection_bound may need + * to be moved */ + if (!gtk_text_iter_equal (&cur, &iter) || !extend_selection) move_cursor (text_view, &cur, extend_selection); - g_signal_stop_emission_by_name (text_view, "move-cursor"); - } + } + else + { + /* note that we chain up to GtkTextView skipping GtkSourceView */ + (* GTK_TEXT_VIEW_CLASS (gedit_view_parent_class)->move_cursor) (text_view, + step, + count, + extend_selection); } } -static void -gedit_view_init (GeditView *view) +static gboolean +scroll_to_cursor_on_init (GeditView *view) { - GtkSourceView *text_view; - GtkWidget *sw; /* the scrolled window */ - GdkColor background, text, selection, sel_text; - - gedit_debug (DEBUG_VIEW, ""); + gedit_view_scroll_to_cursor (view); - view->priv = g_new0 (GeditViewPrivate, 1); - - view->priv->document = NULL; - view->priv->line_numbers_visible = FALSE; + return FALSE; +} - /* Create the scrolled window */ - sw = gtk_scrolled_window_new (NULL, NULL); - g_return_if_fail (sw != NULL); +static void +gedit_view_init (GeditView *view) +{ + gedit_debug (DEBUG_VIEW); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - text_view = GTK_SOURCE_VIEW (gtk_source_view_new ()); - g_return_if_fail (text_view != NULL); - view->priv->text_view = text_view; + view->priv = GEDIT_VIEW_GET_PRIVATE (view); /* * Set tab, fonts, wrap mode, colors, etc. according @@ -298,8 +299,10 @@ gedit_view_init (GeditView *view) */ if (!gedit_prefs_manager_get_use_default_font ()) { - gchar *editor_font = gedit_prefs_manager_get_editor_font (); - + gchar *editor_font; + + editor_font = gedit_prefs_manager_get_editor_font (); + gedit_view_set_font (view, FALSE, editor_font); g_free (editor_font); @@ -307,90 +310,85 @@ gedit_view_init (GeditView *view) if (!gedit_prefs_manager_get_use_default_colors ()) { + GdkColor background; + GdkColor text; + GdkColor selection; + GdkColor sel_text; + background = gedit_prefs_manager_get_background_color (); text = gedit_prefs_manager_get_text_color (); selection = gedit_prefs_manager_get_selection_color (); sel_text = gedit_prefs_manager_get_selected_text_color (); - gedit_view_set_colors (view, FALSE, - &background, &text, &selection, &sel_text); + gedit_view_set_colors (view, + FALSE, + &background, + &text, + &selection, + &sel_text); } - gedit_view_set_wrap_mode (view, gedit_prefs_manager_get_wrap_mode ()); - - gedit_view_set_auto_indent (view, gedit_prefs_manager_get_auto_indent ()); - - gedit_view_set_tab_size (view, gedit_prefs_manager_get_tabs_size ()); - gedit_view_set_insert_spaces_instead_of_tabs (view, - gedit_prefs_manager_get_insert_spaces ()); - - g_object_set (G_OBJECT (view->priv->text_view), + g_object_set (G_OBJECT (view), + "wrap_mode", gedit_prefs_manager_get_wrap_mode (), + "show_line_numbers", gedit_prefs_manager_get_display_line_numbers (), + "auto_indent", gedit_prefs_manager_get_auto_indent (), + "tabs_width", gedit_prefs_manager_get_tabs_size (), + "insert_spaces_instead_of_tabs", gedit_prefs_manager_get_insert_spaces (), "show_margin", gedit_prefs_manager_get_display_right_margin (), "margin", gedit_prefs_manager_get_right_margin_position (), "highlight_current_line", gedit_prefs_manager_get_highlight_current_line (), "smart_home_end", FALSE, /* Never changes this */ NULL); - gtk_box_pack_start (GTK_BOX (view), sw, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (view->priv->text_view)); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_IN); - - g_signal_connect (G_OBJECT (view->priv->text_view), "populate-popup", - G_CALLBACK (gedit_view_populate_popup), view); - - g_signal_connect (G_OBJECT (view->priv->text_view), "move-cursor", - G_CALLBACK (gedit_view_move_cursor), view); + /* Make sure that the view is scrolled to the cursor so + * that "gedit +100 foo.txt" works. + * We would like to this on the first expose handler so that + * it would look instantaneous, but this isn't currently + * possible: see bug #172277 and bug #311728. + * So we need to do this in an idle handler. + */ + g_idle_add ((GSourceFunc) scroll_to_cursor_on_init, view); + + view->priv->typeselect_flush_timeout = 0; + view->priv->wrap_around = TRUE; } -static void -gedit_view_finalize (GObject *object) +static void +gedit_view_destroy (GtkObject *object) { GeditView *view; - gedit_debug (DEBUG_VIEW, "%d", object->ref_count); - - g_return_if_fail (object != NULL); - g_return_if_fail (GEDIT_IS_VIEW (object)); - - view = GEDIT_VIEW (object); - - g_return_if_fail (GEDIT_IS_VIEW (view)); - g_return_if_fail (view->priv != NULL); - - g_return_if_fail (view->priv->document != NULL); - - g_signal_handlers_disconnect_matched (G_OBJECT (view->priv->document), - (GSignalMatchType)G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); - - g_object_unref (view->priv->document); - view->priv->document = NULL; + view = GEDIT_VIEW (object); - g_free (view->priv); - - G_OBJECT_CLASS (parent_class)->finalize (object); - - gedit_debug (DEBUG_VIEW, "END"); + if (view->priv->search_window != NULL) + { + gtk_widget_destroy (view->priv->search_window); + view->priv->search_window = NULL; + view->priv->search_entry = NULL; + + if (view->priv->typeselect_flush_timeout != 0) + { + g_source_remove (view->priv->typeselect_flush_timeout); + view->priv->typeselect_flush_timeout = 0; + } + } + + (* GTK_OBJECT_CLASS (gedit_view_parent_class)->destroy) (object); } -static gboolean -scroll_to_cursor (GtkTextView *view) +static void +gedit_view_finalize (GObject *object) { - GtkTextBuffer *buffer = NULL; - - gedit_debug (DEBUG_VIEW, ""); - - buffer = gtk_text_view_get_buffer (view); - g_return_val_if_fail (buffer != NULL, FALSE); + GeditView *view; - gtk_text_view_scroll_to_mark (view, - gtk_text_buffer_get_insert (buffer), - 0.25, - FALSE, - 0.0, - 0.0); + view = GEDIT_VIEW (object); - return FALSE; + g_free (view->priv->old_search_text); + + if (view->priv->tooltips != NULL) + g_object_unref (view->priv->tooltips); + + (* G_OBJECT_CLASS (gedit_view_parent_class)->finalize) (object); } /** @@ -398,68 +396,35 @@ scroll_to_cursor (GtkTextView *view) * @doc: a #GeditDocument * * Creates a new #GeditView object displaying the @doc document. - * One document can be shared among many views. @doc cannot be NULL. - * The view adds its own reference count to the document; - * it does not take over an existing reference. + * @doc cannot be NULL. * * Return value: a new #GeditView **/ -GeditView* +GtkWidget * gedit_view_new (GeditDocument *doc) { - GeditView *view; - - gedit_debug (DEBUG_VIEW, "START"); - - g_return_val_if_fail (doc != NULL, NULL); - - view = GEDIT_VIEW (g_object_new (GEDIT_TYPE_VIEW, NULL)); - g_return_val_if_fail (view != NULL, NULL); - - gtk_text_view_set_buffer (GTK_TEXT_VIEW (view->priv->text_view), - GTK_TEXT_BUFFER (doc)); - - view->priv->document = doc; - g_object_ref (view->priv->document); + GtkWidget *view; - if (gedit_prefs_manager_get_display_line_numbers ()) - gedit_view_show_line_numbers (view, TRUE); - - g_signal_connect (GTK_TEXT_BUFFER (doc), - "changed", - G_CALLBACK (gedit_view_update_cursor_position_statusbar), - view); - - g_signal_connect (GTK_TEXT_BUFFER (doc), - "mark_set",/* cursor moved */ - G_CALLBACK (gedit_view_cursor_moved), - view); + gedit_debug_message (DEBUG_VIEW, "START"); - g_signal_connect (GTK_TEXT_VIEW (view->priv->text_view), - "toggle_overwrite",/* cursor moved */ - G_CALLBACK (gedit_view_update_overwrite_mode_statusbar), - view); + g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL); + view = GTK_WIDGET (g_object_new (GEDIT_TYPE_VIEW, NULL)); + + gtk_text_view_set_buffer (GTK_TEXT_VIEW (view), + GTK_TEXT_BUFFER (doc)); + g_signal_connect (doc, - "readonly_changed", - G_CALLBACK (gedit_view_doc_readonly_changed_handler), + "notify::read-only", + G_CALLBACK (document_read_only_notify_handler), view); - /* Make sure that the view is scrolled to the cursor so - * that "gedit +100 foo.txt" works. - * We would like to this in the expose handler so that - * it would look instantaneous, but this isn't currently - * possible: see bug #172277 and bug #311728. - * So we need to do this in an idle handler. - */ - g_idle_add ((GSourceFunc) scroll_to_cursor, view->priv->text_view); + gtk_text_view_set_editable (GTK_TEXT_VIEW (view), + !gedit_document_get_readonly (doc)); - gtk_text_view_set_editable (GTK_TEXT_VIEW (view->priv->text_view), - !gedit_document_is_readonly (doc)); - - gedit_debug (DEBUG_VIEW, "END: %d", G_OBJECT (view)->ref_count); + gedit_debug_message (DEBUG_VIEW, "END: %d", G_OBJECT (view)->ref_count); - gtk_widget_show_all (GTK_WIDGET (view)); + gtk_widget_show_all (view); return view; } @@ -467,20 +432,22 @@ gedit_view_new (GeditDocument *doc) void gedit_view_cut_clipboard (GeditView *view) { - GtkTextBuffer* buffer = NULL; + GtkTextBuffer *buffer = NULL; - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->priv->text_view)); + g_return_if_fail (GEDIT_IS_VIEW (view)); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); g_return_if_fail (buffer != NULL); - g_return_if_fail (view->priv->document != NULL); /* FIXME: what is default editability of a buffer? */ gtk_text_buffer_cut_clipboard (buffer, - gtk_clipboard_get (GDK_NONE), - !gedit_document_is_readonly (view->priv->document)); + gtk_clipboard_get (GDK_NONE), + !gedit_document_get_readonly ( + GEDIT_DOCUMENT (buffer))); - gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view->priv->text_view), + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view), gtk_text_buffer_get_insert (buffer), GEDIT_VIEW_SCROLL_MARGIN, FALSE, @@ -491,15 +458,17 @@ gedit_view_cut_clipboard (GeditView *view) void gedit_view_copy_clipboard (GeditView *view) { - GtkTextBuffer* buffer = NULL; + GtkTextBuffer *buffer = NULL; - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->priv->text_view)); + g_return_if_fail (GEDIT_IS_VIEW (view)); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); g_return_if_fail (buffer != NULL); - gtk_text_buffer_copy_clipboard (buffer, - gtk_clipboard_get (GDK_NONE)); + gtk_text_buffer_copy_clipboard (buffer, + gtk_clipboard_get (GDK_NONE)); /* on copy do not scroll, we are already on screen */ } @@ -507,21 +476,23 @@ gedit_view_copy_clipboard (GeditView *view) void gedit_view_paste_clipboard (GeditView *view) { - GtkTextBuffer* buffer = NULL; + GtkTextBuffer *buffer = NULL; - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); + + g_return_if_fail (GEDIT_IS_VIEW (view)); - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->priv->text_view)); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); g_return_if_fail (buffer != NULL); - g_return_if_fail (view->priv->document != NULL); /* FIXME: what is default editability of a buffer? */ gtk_text_buffer_paste_clipboard (buffer, - gtk_clipboard_get (GDK_NONE), - NULL, - !gedit_document_is_readonly (view->priv->document)); + gtk_clipboard_get (GDK_NONE), + NULL, + !gedit_document_get_readonly ( + GEDIT_DOCUMENT (buffer))); - gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view->priv->text_view), + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view), gtk_text_buffer_get_insert (buffer), GEDIT_VIEW_SCROLL_MARGIN, FALSE, @@ -532,20 +503,22 @@ gedit_view_paste_clipboard (GeditView *view) void gedit_view_delete_selection (GeditView *view) { - GtkTextBuffer* buffer = NULL; + GtkTextBuffer *buffer = NULL; - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->priv->text_view)); + g_return_if_fail (GEDIT_IS_VIEW (view)); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); g_return_if_fail (buffer != NULL); - g_return_if_fail (view->priv->document != NULL); /* FIXME: what is default editability of a buffer? */ - gtk_text_buffer_delete_selection (buffer, - TRUE, - !gedit_document_is_readonly (view->priv->document)); - - gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view->priv->text_view), + gtk_text_buffer_delete_selection (buffer, + TRUE, + !gedit_document_get_readonly ( + GEDIT_DOCUMENT (buffer))); + + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view), gtk_text_buffer_get_insert (buffer), GEDIT_VIEW_SCROLL_MARGIN, FALSE, @@ -553,15 +526,21 @@ gedit_view_delete_selection (GeditView *view) 0.0); } -GeditDocument* -gedit_view_get_document (const GeditView *view) +void +gedit_view_select_all (GeditView *view) { - gedit_debug (DEBUG_VIEW, ""); - - g_return_val_if_fail (GEDIT_IS_VIEW (view), NULL); - g_return_val_if_fail (view->priv != NULL, NULL); + GtkTextBuffer *buffer = NULL; + GtkTextIter start, end; + + gedit_debug (DEBUG_VIEW); - return view->priv->document; + g_return_if_fail (GEDIT_IS_VIEW (view)); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + g_return_if_fail (buffer != NULL); + + gtk_text_buffer_get_bounds (buffer, &start, &end); + gtk_text_buffer_select_range (buffer, &start, &end); } void @@ -569,17 +548,16 @@ gedit_view_scroll_to_cursor (GeditView *view) { GtkTextBuffer* buffer = NULL; - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); g_return_if_fail (GEDIT_IS_VIEW (view)); - g_return_if_fail (view->priv != NULL); - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->priv->text_view)); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); g_return_if_fail (buffer != NULL); - gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view->priv->text_view), + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view), gtk_text_buffer_get_insert (buffer), - GEDIT_VIEW_SCROLL_MARGIN, + 0.25, FALSE, 0.0, 0.0); @@ -629,7 +607,7 @@ modify_cursor_color (GtkWidget *textview, const gchar *name; gchar *rc_temp; - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); name = get_widget_name (textview); g_return_if_fail (name != NULL); @@ -669,65 +647,65 @@ gedit_view_set_colors (GeditView *view, GdkColor *selection, GdkColor *sel_text) { - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); g_return_if_fail (GEDIT_IS_VIEW (view)); /* just a bit of paranoia */ - gtk_widget_ensure_style (GTK_WIDGET (view->priv->text_view)); + gtk_widget_ensure_style (GTK_WIDGET (view)); if (!def) { if (backgroud != NULL) - gtk_widget_modify_base (GTK_WIDGET (view->priv->text_view), + gtk_widget_modify_base (GTK_WIDGET (view), GTK_STATE_NORMAL, backgroud); if (selection != NULL) { - gtk_widget_modify_base (GTK_WIDGET (view->priv->text_view), + gtk_widget_modify_base (GTK_WIDGET (view), GTK_STATE_SELECTED, selection); - - gtk_widget_modify_base (GTK_WIDGET (view->priv->text_view), + gtk_widget_modify_base (GTK_WIDGET (view), GTK_STATE_ACTIVE, selection); } if (sel_text != NULL) { - gtk_widget_modify_text (GTK_WIDGET (view->priv->text_view), + gtk_widget_modify_text (GTK_WIDGET (view), GTK_STATE_SELECTED, sel_text); - - gtk_widget_modify_text (GTK_WIDGET (view->priv->text_view), + gtk_widget_modify_text (GTK_WIDGET (view), GTK_STATE_ACTIVE, sel_text); } if (text != NULL) { - gtk_widget_modify_text (GTK_WIDGET (view->priv->text_view), + gtk_widget_modify_text (GTK_WIDGET (view), GTK_STATE_NORMAL, text); - modify_cursor_color (GTK_WIDGET (view->priv->text_view), text); + modify_cursor_color (GTK_WIDGET (view), text); } } else { GtkRcStyle *rc_style; - rc_style = gtk_widget_get_modifier_style (GTK_WIDGET (view->priv->text_view)); + rc_style = gtk_widget_get_modifier_style (GTK_WIDGET (view)); rc_style->color_flags [GTK_STATE_NORMAL] = 0; rc_style->color_flags [GTK_STATE_SELECTED] = 0; rc_style->color_flags [GTK_STATE_ACTIVE] = 0; - gtk_widget_modify_style (GTK_WIDGET (view->priv->text_view), rc_style); + gtk_widget_modify_style (GTK_WIDGET (view), rc_style); /* It must be called after the text color has been modified */ - modify_cursor_color (GTK_WIDGET (view->priv->text_view), NULL); + modify_cursor_color (GTK_WIDGET (view), NULL); } } void -gedit_view_set_font (GeditView* view, gboolean def, const gchar* font_name) +gedit_view_set_font (GeditView *view, + gboolean def, + const gchar *font_name) { - gedit_debug (DEBUG_VIEW, ""); + gedit_debug (DEBUG_VIEW); g_return_if_fail (GEDIT_IS_VIEW (view)); @@ -740,7 +718,7 @@ gedit_view_set_font (GeditView* view, gboolean def, const gchar* font_name) font_desc = pango_font_description_from_string (font_name); g_return_if_fail (font_desc != NULL); - gtk_widget_modify_font (GTK_WIDGET (view->priv->text_view), font_desc); + gtk_widget_modify_font (GTK_WIDGET (view), font_desc); pango_font_description_free (font_desc); } @@ -748,214 +726,984 @@ gedit_view_set_font (GeditView* view, gboolean def, const gchar* font_name) { GtkRcStyle *rc_style; - rc_style = gtk_widget_get_modifier_style (GTK_WIDGET (view->priv->text_view)); + rc_style = gtk_widget_get_modifier_style (GTK_WIDGET (view)); if (rc_style->font_desc) pango_font_description_free (rc_style->font_desc); rc_style->font_desc = NULL; - gtk_widget_modify_style (GTK_WIDGET (view->priv->text_view), rc_style); + gtk_widget_modify_style (GTK_WIDGET (view), rc_style); } } -void -gedit_view_set_wrap_mode (GeditView* view, GtkWrapMode wrap_mode) +static void +add_search_completion_entry (const gchar *text) { - gedit_debug (DEBUG_VIEW, ""); - - g_return_if_fail (GEDIT_IS_VIEW (view)); + gboolean valid; + GtkTreeModel *model; + GtkTreeIter iter; + + if (text == NULL) + return; + + if (g_utf8_strlen (text, -1) < MIN_SEARCH_COMPLETION_KEY_LEN) + return; + + g_return_if_fail (GTK_IS_TREE_MODEL (search_completion_model)); + + model = GTK_TREE_MODEL (search_completion_model); - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->priv->text_view), wrap_mode); -} + /* Get the first iter in the list */ + valid = gtk_tree_model_get_iter_first (model, &iter); -void -gedit_view_set_tab_size (GeditView* view, gint tab_size) + while (valid) + { + /* Walk through the list, reading each row */ + gchar *str_data; + + gtk_tree_model_get (model, + &iter, + 0, + &str_data, + -1); + + if (strcmp (text, str_data) == 0) + { + g_free (str_data); + gtk_list_store_move_after (GTK_LIST_STORE (model), + &iter, + NULL); + + return; + } + + g_free (str_data); + + valid = gtk_tree_model_iter_next (model, &iter); + } + + gtk_list_store_prepend (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), + &iter, + 0, + text, + -1); +} + +static void +set_entry_background (GtkWidget *entry, + GeditSearchEntryBgColor col) { - gedit_debug (DEBUG_VIEW, "Tab size: %d", tab_size); + if (col == GEDIT_SEARCH_ENTRY_NOT_FOUND) + { + GdkColor red; + GdkColor white; - g_return_if_fail (GEDIT_IS_VIEW (view)); + /* FIXME: a11y and theme */ - g_object_set (G_OBJECT (view->priv->text_view), - "tabs_width", tab_size, - NULL); + gdk_color_parse ("#FF6666", &red); + gdk_color_parse ("white", &white); + + gtk_widget_modify_base (entry, + GTK_STATE_NORMAL, + &red); + gtk_widget_modify_text (entry, + GTK_STATE_NORMAL, + &white); + } + else /* reset */ + { + gtk_widget_modify_base (entry, + GTK_STATE_NORMAL, + NULL); + gtk_widget_modify_text (entry, + GTK_STATE_NORMAL, + NULL); + } } -void -gedit_view_show_line_numbers (GeditView* view, gboolean visible) +static gboolean +run_search (GeditView *view, + const gchar *entry_text, + gboolean search_backward, + gboolean wrap_around, + gboolean typing) { - gedit_debug (DEBUG_VIEW, ""); + GtkTextIter start_iter; + GtkTextIter match_start; + GtkTextIter match_end; + gboolean found = FALSE; + GeditDocument *doc; - g_object_set (G_OBJECT (view->priv->text_view), - "show_line_numbers", visible, - NULL); + g_return_val_if_fail (view->priv->search_mode == SEARCH, FALSE); + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + + start_iter = view->priv->start_search_iter; + + if (*entry_text != '\0') + { + if (!search_backward) + { + if (!typing) + { + /* forward and _NOT_ typing */ + gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &start_iter, + &match_end); + + gtk_text_iter_order (&match_end, &start_iter); + } + + /* run search */ + found = gedit_document_search_forward (doc, + &start_iter, + NULL, + &match_start, + &match_end); + } + else if (!typing) + { + /* backward and not typing */ + gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &start_iter, + &match_end); + + /* run search */ + found = gedit_document_search_backward (doc, + NULL, + &start_iter, + &match_start, + &match_end); + } + else + { + /* backward (while typing) */ + g_return_val_if_reached (FALSE); + + } + + if (!found && wrap_around) + { + if (!search_backward) + found = gedit_document_search_forward (doc, + NULL, + NULL, /* FIXME: set the end_inter */ + &match_start, + &match_end); + else + found = gedit_document_search_backward (doc, + NULL, /* FIXME: set the start_inter */ + NULL, + &match_start, + &match_end); + } + } + else + { + gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &start_iter, + NULL); + } + + if (found) + { + gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), + &match_start); + + gtk_text_buffer_move_mark_by_name (GTK_TEXT_BUFFER (doc), + "selection_bound", &match_end); + } + else + { + if (typing) + { + gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), + &view->priv->start_search_iter); + } + } + + if (found || (*entry_text == '\0')) + { + gedit_view_scroll_to_cursor (view); + + set_entry_background (view->priv->search_entry, + GEDIT_SEARCH_ENTRY_NORMAL); + } + else + { + set_entry_background (view->priv->search_entry, + GEDIT_SEARCH_ENTRY_NOT_FOUND); + } + + return found; } -void -gedit_view_set_cursor_position_statusbar (GeditView *view, GtkWidget* status) +/* Cut and paste from gtkwindow.c */ +static void +send_focus_change (GtkWidget *widget, + gboolean in) { - gedit_debug (DEBUG_VIEW, ""); + GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE); - g_return_if_fail (GEDIT_IS_VIEW (view)); - - view->priv->cursor_position_statusbar = status; + g_object_ref (widget); + + if (in) + GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); + else + GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); + + fevent->focus_change.type = GDK_FOCUS_CHANGE; + fevent->focus_change.window = g_object_ref (widget->window); + fevent->focus_change.in = in; + + gtk_widget_event (widget, fevent); + + g_object_notify (G_OBJECT (widget), "has-focus"); - if ((status != NULL) && (view->priv->document != NULL)) - gedit_view_update_cursor_position_statusbar - (GTK_TEXT_BUFFER (view->priv->document), - view); + g_object_unref (widget); + gdk_event_free (fevent); } -void -gedit_view_set_overwrite_mode_statusbar (GeditView *view, GtkWidget* status) +static void +hide_search_window (GeditView *view, gboolean cancel) { - gedit_debug (DEBUG_VIEW, ""); + if (view->priv->disable_popdown) + return; - g_return_if_fail (GEDIT_IS_VIEW (view)); + if (view->priv->search_entry_changed_id != 0) + { + g_signal_handler_disconnect (view->priv->search_entry, + view->priv->search_entry_changed_id); + view->priv->search_entry_changed_id = 0; + } + + if (view->priv->typeselect_flush_timeout != 0) + { + g_source_remove (view->priv->typeselect_flush_timeout); + view->priv->typeselect_flush_timeout = 0; + } + + /* send focus-in event */ + send_focus_change (GTK_WIDGET (view->priv->search_entry), FALSE); + gtk_widget_hide (view->priv->search_window); - view->priv->overwrite_mode_statusbar = status; + if (cancel) + { + GtkTextBuffer *buffer; + + buffer = GTK_TEXT_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + gtk_text_buffer_place_cursor (buffer, &view->priv->start_search_iter); + + gedit_view_scroll_to_cursor (view); + } +} + +static gboolean +search_entry_flush_timeout (GeditView *view) +{ + GDK_THREADS_ENTER (); + + view->priv->typeselect_flush_timeout = 0; + hide_search_window (view, TRUE); - view->priv->overwrite_mode = !GTK_TEXT_VIEW (view->priv->text_view)->overwrite_mode; + GDK_THREADS_LEAVE (); - if (status != NULL) - gedit_view_update_overwrite_mode_statusbar (GTK_TEXT_VIEW (view->priv->text_view), - view); + return FALSE; } - + static void -gedit_view_update_cursor_position_statusbar (GtkTextBuffer *buffer, GeditView* view) +update_search_window_position (GeditView *view) { - gchar *msg; - guint row, col/*, chars*/; - GtkTextIter iter; - GtkTextIter start; - guint tab_size; + gint x, y; + gint view_x, view_y; + GdkWindow *view_window = GTK_WIDGET (view)->window; + + gtk_widget_realize (view->priv->search_window); - gedit_debug (DEBUG_VIEW, ""); + gdk_window_get_origin (view_window, &view_x, &view_y); - if (view->priv->cursor_position_statusbar == NULL) - return; - - /* clear any previous message, underflow is allowed */ - gtk_statusbar_pop (GTK_STATUSBAR (view->priv->cursor_position_statusbar), 0); + x = MAX (12, view_x + 12); + y = MAX (12, view_y - 12); - gtk_text_buffer_get_iter_at_mark (buffer, - &iter, - gtk_text_buffer_get_insert (buffer)); + gtk_window_move (GTK_WINDOW (view->priv->search_window), x, y); +} + +static gboolean +search_window_delete_event (GtkWidget *widget, + GdkEventAny *event, + GeditView *view) +{ + hide_search_window (view, TRUE); + + return TRUE; +} + +static gboolean +search_window_button_press_event (GtkWidget *widget, + GdkEventButton *event, + GeditView *view) +{ + hide_search_window (view, TRUE); - row = gtk_text_iter_get_line (&iter); + gtk_propagate_event (GTK_WIDGET (view), (GdkEvent *)event); + + return FALSE; +} + +static void +search_again (GeditView *view, + gboolean search_backward) +{ + const gchar *entry_text; + + g_return_if_fail (view->priv->search_mode == SEARCH); + + /* SEARCH mode */ + /* renew the flush timeout */ + if (view->priv->typeselect_flush_timeout != 0) + { + g_source_remove (view->priv->typeselect_flush_timeout); + view->priv->typeselect_flush_timeout = + g_timeout_add (GEDIT_VIEW_SEARCH_DIALOG_TIMEOUT, + (GSourceFunc)search_entry_flush_timeout, + view); + } - /* - chars = gtk_text_iter_get_line_offset (&iter); - */ + entry_text = gtk_entry_get_text (GTK_ENTRY (view->priv->search_entry)); - start = iter; - gtk_text_iter_set_line_offset (&start, 0); - col = 0; + add_search_completion_entry (entry_text); + + run_search (view, + entry_text, + search_backward, + view->priv->wrap_around, + FALSE); +} - tab_size = gtk_source_view_get_tabs_width ( - GTK_SOURCE_VIEW (view->priv->text_view)); +static gboolean +search_window_scroll_event (GtkWidget *widget, + GdkEventScroll *event, + GeditView *view) +{ + gboolean retval = FALSE; - while (!gtk_text_iter_equal (&start, &iter)) + if (view->priv->search_mode == GOTO_LINE) + return retval; + + /* SEARCH mode */ + if (event->direction == GDK_SCROLL_UP) { - if (gtk_text_iter_get_char (&start) == '\t') - - col += (tab_size - (col % tab_size)); - else - ++col; + search_again (view, TRUE); + retval = TRUE; + } + else if (event->direction == GDK_SCROLL_DOWN) + { + search_again (view, FALSE); + retval = TRUE; + } + + return retval; +} - gtk_text_iter_forward_char (&start); +static gboolean +search_window_key_press_event (GtkWidget *widget, + GdkEventKey *event, + GeditView *view) +{ + gboolean retval = FALSE; + + /* close window and cancel the search */ + if (event->keyval == GDK_Escape || + event->keyval == GDK_Tab) + { + if (view->priv->search_mode == SEARCH) + { + GeditDocument *doc; + + /* restore document search so that Find Next does the right thing */ + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + gedit_document_set_search_text (doc, + view->priv->old_search_text, + view->priv->old_search_flags); + + } + + hide_search_window (view, TRUE); + retval = TRUE; } - /* - if (col == chars) - msg = g_strdup_printf (_(" Ln %d, Col %d"), row + 1, col + 1); - else - msg = g_strdup_printf (_(" Ln %d, Col %d-%d"), row + 1, chars + 1, col + 1); - */ + if (view->priv->search_mode == GOTO_LINE) + return retval; + + /* SEARCH mode */ - /* Translators: "Ln" is an abbreviation for "Line", Col is an abbreviation for "Column". Please, - use abbreviations if possible to avoid space problems. */ - msg = g_strdup_printf (_(" Ln %d, Col %d"), row + 1, col + 1); - - gtk_statusbar_push (GTK_STATUSBAR (view->priv->cursor_position_statusbar), - 0, msg); + /* select previous matching iter */ + if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up) + { + search_again (view, TRUE); + retval = TRUE; + } - g_free (msg); + if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) && + (event->keyval == GDK_g || event->keyval == GDK_G)) + { + search_again (view, TRUE); + retval = TRUE; + } + + /* select next matching iter */ + if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down) + { + search_again (view, FALSE); + retval = TRUE; + } + + if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK) && + (event->keyval == GDK_g || event->keyval == GDK_G)) + { + search_again (view, FALSE); + retval = TRUE; + } + + return retval; +} + +static void +search_entry_activate (GtkEntry *entry, + GeditView *view) +{ + hide_search_window (view, FALSE); +} + +static void +wrap_around_menu_item_toggled (GtkCheckMenuItem *checkmenuitem, + GeditView *view) +{ + view->priv->wrap_around = gtk_check_menu_item_get_active (checkmenuitem); +} + +static void +match_entire_word_menu_item_toggled (GtkCheckMenuItem *checkmenuitem, + GeditView *view) +{ + GEDIT_SEARCH_SET_ENTIRE_WORD (view->priv->search_flags, + gtk_check_menu_item_get_active (checkmenuitem)); +} + +static void +match_case_menu_item_toggled (GtkCheckMenuItem *checkmenuitem, + GeditView *view) +{ + GEDIT_SEARCH_SET_CASE_SENSITIVE (view->priv->search_flags, + gtk_check_menu_item_get_active (checkmenuitem)); +} + +static gboolean +real_search_enable_popdown (gpointer data) +{ + GeditView *view = (GeditView *)data; + + GDK_THREADS_ENTER (); + + view->priv->disable_popdown = FALSE; + + GDK_THREADS_LEAVE (); + + return FALSE; } + +static void +search_enable_popdown (GtkWidget *widget, + GeditView *view) +{ + g_timeout_add (200, real_search_enable_popdown, view); + /* renew the flush timeout */ + if (view->priv->typeselect_flush_timeout != 0) + g_source_remove (view->priv->typeselect_flush_timeout); + + view->priv->typeselect_flush_timeout = + g_timeout_add (GEDIT_VIEW_SEARCH_DIALOG_TIMEOUT, + (GSourceFunc)search_entry_flush_timeout, + view); +} + +static void +search_entry_populate_popup (GtkEntry *entry, + GtkMenu *menu, + GeditView *view) +{ + GtkWidget *menu_item; + + view->priv->disable_popdown = TRUE; + g_signal_connect (menu, "hide", + G_CALLBACK (search_enable_popdown), view); + + if (view->priv->search_mode == GOTO_LINE) + return; + + /* separator */ + menu_item = gtk_menu_item_new (); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item); + gtk_widget_show (menu_item); + + /* create "Wrap Around" menu item. */ + menu_item = gtk_check_menu_item_new_with_mnemonic (_("_Wrap Around")); + g_signal_connect (G_OBJECT (menu_item), "toggled", + G_CALLBACK (wrap_around_menu_item_toggled), + view); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), + view->priv->wrap_around); + gtk_widget_show (menu_item); + + /* create "Match Entire Word Only" menu item. */ + menu_item = gtk_check_menu_item_new_with_mnemonic (_("Match _Entire Word Only")); + g_signal_connect (G_OBJECT (menu_item), "toggled", + G_CALLBACK (match_entire_word_menu_item_toggled), + view); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), + GEDIT_SEARCH_IS_ENTIRE_WORD (view->priv->search_flags)); + gtk_widget_show (menu_item); + + /* create "Match Case" menu item. */ + menu_item = gtk_check_menu_item_new_with_mnemonic (_("_Match Case")); + g_signal_connect (G_OBJECT (menu_item), "toggled", + G_CALLBACK (match_case_menu_item_toggled), + view); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), + GEDIT_SEARCH_IS_CASE_SENSITIVE (view->priv->search_flags)); + gtk_widget_show (menu_item); +} + static void -gedit_view_cursor_moved (GtkTextBuffer *buffer, - const GtkTextIter *new_location, - GtkTextMark *mark, - GeditView *view) +search_entry_insert_text (GtkEditable *editable, + const gchar *text, + gint length, + gint *position, + GeditView *view) { - gedit_debug (DEBUG_VIEW, ""); + if (view->priv->search_mode == GOTO_LINE) + { + gunichar c; + const gchar *p; + const gchar *end; + + p = text; + end = text + length; + + while (p != end) { + const gchar *next; + next = g_utf8_next_char (p); + + c = g_utf8_get_char (p); + + if (!g_unichar_isdigit (c)) { + g_signal_stop_emission_by_name (editable, "insert_text"); + break; + } + + p = next; + } + } + else + { + /* SEARCH mode */ + static gboolean insert_text = FALSE; + gchar *escaped_text; + gint new_len; + + gedit_debug_message (DEBUG_SEARCH, "Text: %s", text); - if (mark == gtk_text_buffer_get_insert (buffer)) - gedit_view_update_cursor_position_statusbar (buffer, view); + /* To avoid recursive behavior */ + if (insert_text) + return; + + escaped_text = gedit_utils_escape_search_text (text); + + gedit_debug_message (DEBUG_SEARCH, "Escaped Text: %s", escaped_text); + + new_len = strlen (escaped_text); + + if (new_len == length) + { + g_free (escaped_text); + return; + } + + insert_text = TRUE; + + g_signal_stop_emission_by_name (editable, "insert_text"); + + gtk_editable_insert_text (editable, escaped_text, new_len, position); + + insert_text = FALSE; + + g_free (escaped_text); + } } static void -gedit_view_update_overwrite_mode_statusbar (GtkTextView* w, GeditView* view) +customize_for_search_mode (GeditView *view) { - gchar *msg; + GtkWidget *icon; - gedit_debug (DEBUG_VIEW, ""); - - view->priv->overwrite_mode = !view->priv->overwrite_mode; + if (view->priv->search_mode == SEARCH) + { + icon = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); + + gtk_tooltips_set_tip (view->priv->tooltips, + view->priv->search_entry, + _("String you want to search for"), + NULL); + } + else + { + icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU); + + gtk_tooltips_set_tip (view->priv->tooltips, + view->priv->search_entry, + _("Line you want to move the cursor to"), + NULL); + } + + gtk_widget_show (icon); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(view->priv->search_entry), + SEXY_ICON_ENTRY_PRIMARY, + GTK_IMAGE (icon)); +} + +static void +ensure_search_window (GeditView *view) +{ + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *toplevel; + GtkEntryCompletion *completion; + - if (view->priv->overwrite_mode_statusbar == NULL) + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); + + if (view->priv->search_window != NULL) + { + if (GTK_WINDOW (toplevel)->group) + gtk_window_group_add_window (GTK_WINDOW (toplevel)->group, + GTK_WINDOW (view->priv->search_window)); + else if (GTK_WINDOW (view->priv->search_window)->group) + gtk_window_group_remove_window (GTK_WINDOW (view->priv->search_window)->group, + GTK_WINDOW (view->priv->search_window)); + + customize_for_search_mode (view); + return; + } + + view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP); + + if (GTK_WINDOW (toplevel)->group) + gtk_window_group_add_window (GTK_WINDOW (toplevel)->group, + GTK_WINDOW (view->priv->search_window)); + + gtk_window_set_modal (GTK_WINDOW (view->priv->search_window), TRUE); + + g_signal_connect (view->priv->search_window, "delete_event", + G_CALLBACK (search_window_delete_event), + view); + g_signal_connect (view->priv->search_window, "key_press_event", + G_CALLBACK (search_window_key_press_event), + view); + g_signal_connect (view->priv->search_window, "button_press_event", + G_CALLBACK (search_window_button_press_event), + view); + g_signal_connect (view->priv->search_window, "scroll_event", + G_CALLBACK (search_window_scroll_event), + view); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + gtk_widget_show (frame); + gtk_container_add (GTK_CONTAINER (view->priv->search_window), frame); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox); + gtk_container_add (GTK_CONTAINER (frame), vbox); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); + + /* add entry */ + view->priv->search_entry = sexy_icon_entry_new (); + gtk_widget_show (view->priv->search_entry); - /* clear any previous message, underflow is allowed */ - gtk_statusbar_pop (GTK_STATUSBAR (view->priv->overwrite_mode_statusbar), 0); + g_signal_connect (view->priv->search_entry, "populate_popup", + G_CALLBACK (search_entry_populate_popup), + view); + g_signal_connect (view->priv->search_entry, "activate", + G_CALLBACK (search_entry_activate), + view); + /* CHECK: do we really need to connect to preedit too? -- Paolo + g_signal_connect (GTK_ENTRY (view->priv->search_entry)->im_context, "preedit-changed", + G_CALLBACK (gtk_view_search_preedit_changed), + view); + */ + g_signal_connect (view->priv->search_entry, + "insert_text", + G_CALLBACK (search_entry_insert_text), + view); + + gtk_container_add (GTK_CONTAINER (vbox), + view->priv->search_entry); + + if (search_completion_model == NULL) + { + /* Create a tree model and use it as the completion model */ + search_completion_model = gtk_list_store_new (1, G_TYPE_STRING); + } - if (view->priv->overwrite_mode) - msg = g_strdup (_(" OVR")); - else - msg = g_strdup (_(" INS")); + /* Create the completion object for the search entry */ + completion = gtk_entry_completion_new (); + gtk_entry_completion_set_model (completion, + GTK_TREE_MODEL (search_completion_model)); + + /* Use model column 0 as the text column */ + gtk_entry_completion_set_text_column (completion, 0); - gtk_statusbar_push (GTK_STATUSBAR (view->priv->overwrite_mode_statusbar), - 0, msg); + gtk_entry_completion_set_minimum_key_length (completion, + MIN_SEARCH_COMPLETION_KEY_LEN); - g_free (msg); + /* Assign the completion to the entry */ + gtk_entry_set_completion (GTK_ENTRY (view->priv->search_entry), + completion); + g_object_unref (completion); + + gtk_widget_realize (view->priv->search_entry); + + view->priv->tooltips = gtk_tooltips_new (); + g_object_ref (G_OBJECT (view->priv->tooltips)); + gtk_object_sink (GTK_OBJECT (view->priv->tooltips)); + + customize_for_search_mode (view); } -static void -gedit_view_populate_popup (GtkTextView *textview, GtkMenu *menu, gpointer view) +static gboolean +get_selected_text (GtkTextBuffer *doc, gchar **selected_text, gint *len) { - g_signal_emit (G_OBJECT (view), signals[POPULATE_POPUP], 0, menu); + GtkTextIter start, end; + + g_return_val_if_fail (selected_text != NULL, FALSE); + g_return_val_if_fail (*selected_text == NULL, FALSE); + + if (!gtk_text_buffer_get_selection_bounds (doc, &start, &end)) + { + if (len != NULL) + len = 0; + + return FALSE; + } + + *selected_text = gtk_text_buffer_get_slice (doc, &start, &end, TRUE); + + if (len != NULL) + *len = g_utf8_strlen (*selected_text, -1); + + return TRUE; } -GtkTextView * -gedit_view_get_gtk_text_view (const GeditView *view) +static void +init_search_entry (GeditView *view) { - gedit_debug (DEBUG_VIEW, ""); + GtkTextBuffer *buffer; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + if (view->priv->search_mode == GOTO_LINE) + { + gint line; + gchar *line_str; + + line = gtk_text_iter_get_line (&view->priv->start_search_iter); + + line_str = g_strdup_printf ("%d", line + 1); + + gtk_entry_set_text (GTK_ENTRY (view->priv->search_entry), + line_str); + + g_free (line_str); + + return; + } + else + { + /* SEARCH mode */ + gboolean selection_exists; + gchar *find_text = NULL; + gchar *old_find_text; + guint old_find_flags = 0; + gint sel_len = 0; + + g_free (view->priv->old_search_text); + + old_find_text = gedit_document_get_search_text (GEDIT_DOCUMENT (buffer), + &old_find_flags); + if (old_find_text != NULL) + { + view->priv->old_search_text = old_find_text; + add_search_completion_entry (old_find_text); + } - g_return_val_if_fail (GEDIT_IS_VIEW (view), NULL); + if (old_find_flags != 0) + { + view->priv->old_search_flags = old_find_flags; + } - return GTK_TEXT_VIEW (view->priv->text_view); + selection_exists = get_selected_text (buffer, + &find_text, + &sel_len); + + if (selection_exists && (find_text != NULL) && (sel_len <= 160)) + { + gtk_entry_set_text (GTK_ENTRY (view->priv->search_entry), + find_text); + } + else + { + gtk_entry_set_text (GTK_ENTRY (view->priv->search_entry), + ""); + } + + g_free (find_text); + } } -void -gedit_view_set_auto_indent (GeditView *view, gboolean enable) +static void +search_init (GtkWidget *entry, + GeditView *view) { - gedit_debug (DEBUG_VIEW, ""); + GeditDocument *doc; + const gchar *entry_text; - g_return_if_fail (GEDIT_IS_VIEW (view)); + /* renew the flush timeout */ + if (view->priv->typeselect_flush_timeout != 0) + { + g_source_remove (view->priv->typeselect_flush_timeout); + view->priv->typeselect_flush_timeout = + g_timeout_add (GEDIT_VIEW_SEARCH_DIALOG_TIMEOUT, + (GSourceFunc)search_entry_flush_timeout, + view); + } + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + + entry_text = gtk_entry_get_text (GTK_ENTRY (entry)); + + if (view->priv->search_mode == SEARCH) + { + gchar *search_text; + guint search_flags; + + search_text = gedit_document_get_search_text (doc, &search_flags); - gtk_source_view_set_auto_indent (view->priv->text_view, - enable); + if ((search_text == NULL) || + (strcmp (search_text, entry_text) != 0) || + search_flags != view->priv->search_flags) + { + gedit_document_set_search_text (doc, + entry_text, + view->priv->search_flags); + } + + g_free (search_text); + + run_search (view, + entry_text, + FALSE, + view->priv->wrap_around, + TRUE); + } + else + { + if (*entry_text != '\0') + { + gboolean moved; + gint line; + + line = MAX (atoi (entry_text) - 1, 0); + moved = gedit_document_goto_line (doc, line); + gedit_view_scroll_to_cursor (view); + + if (!moved) + set_entry_background (view->priv->search_entry, + GEDIT_SEARCH_ENTRY_NOT_FOUND); + else + set_entry_background (view->priv->search_entry, + GEDIT_SEARCH_ENTRY_NORMAL); + } + } } -void -gedit_view_set_insert_spaces_instead_of_tabs (GeditView *view, gboolean enable) -{ - gedit_debug (DEBUG_VIEW, ""); +static gboolean +start_interactive_search_real (GeditView *view) +{ + GtkTextBuffer *buffer; + + if ((view->priv->search_window != NULL) && + GTK_WIDGET_VISIBLE (view->priv->search_window)) + return TRUE; - g_return_if_fail (GEDIT_IS_VIEW (view)); + if (!GTK_WIDGET_HAS_FOCUS (view)) + return FALSE; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + if (view->priv->search_mode == SEARCH) + gtk_text_buffer_get_selection_bounds (buffer, &view->priv->start_search_iter, NULL); + else + gtk_text_buffer_get_iter_at_mark (buffer, + &view->priv->start_search_iter, + gtk_text_buffer_get_insert (buffer)); + + ensure_search_window (view); + + /* done, show it */ + update_search_window_position (view); + gtk_widget_show (view->priv->search_window); - gtk_source_view_set_insert_spaces_instead_of_tabs (view->priv->text_view, - enable); + if (view->priv->search_entry_changed_id == 0) + { + view->priv->search_entry_changed_id = + g_signal_connect (view->priv->search_entry, "changed", + G_CALLBACK (search_init), + view); + } + + init_search_entry (view); + + view->priv->typeselect_flush_timeout = + g_timeout_add (GEDIT_VIEW_SEARCH_DIALOG_TIMEOUT, + (GSourceFunc) search_entry_flush_timeout, + view); + + gtk_widget_grab_focus (view->priv->search_entry); + + send_focus_change (view->priv->search_entry, TRUE); + + return TRUE; +} + +static gboolean +start_interactive_search (GeditView *view) +{ + view->priv->search_mode = SEARCH; + + return start_interactive_search_real (view); +} + +static gboolean +start_interactive_goto_line (GeditView *view) +{ + view->priv->search_mode = GOTO_LINE; + + return start_interactive_search_real (view); } diff --git a/gedit/gedit-view.h b/gedit/gedit-view.h index 52142a04..9023d588 100644 --- a/gedit/gedit-view.h +++ b/gedit/gedit-view.h @@ -1,10 +1,10 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-view.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) 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 @@ -19,11 +19,11 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. * * + * Boston, MA 02111-1307, USA. */ /* - * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a + * Modified by the gedit Team, 1998-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. */ @@ -31,79 +31,79 @@ #ifndef __GEDIT_VIEW_H__ #define __GEDIT_VIEW_H__ - #include -#include - -#define GEDIT_TYPE_VIEW (gedit_view_get_type ()) -#define GEDIT_VIEW(obj) (GTK_CHECK_CAST ((obj), GEDIT_TYPE_VIEW, GeditView)) -#define GEDIT_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_VIEW, GeditViewClass)) -#define GEDIT_IS_VIEW(obj) (GTK_CHECK_TYPE ((obj), GEDIT_TYPE_VIEW)) -#define GEDIT_IS_VIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_VIEW)) -#define GEDIT_VIEW_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GEDIT_TYPE_VIEW, GeditViewClass)) +#include +#include -typedef struct _GeditView GeditView; -typedef struct _GeditViewClass GeditViewClass; +G_BEGIN_DECLS +/* + * Type checking and casting macros + */ +#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)) + +/* Private structure type */ typedef struct _GeditViewPrivate GeditViewPrivate; +/* + * Main object structure + */ +typedef struct _GeditView GeditView; + struct _GeditView { - GtkVBox box; + GtkSourceView view; + /*< private > */ GeditViewPrivate *priv; }; +/* + * Class definition + */ +typedef struct _GeditViewClass GeditViewClass; + struct _GeditViewClass { - GtkVBoxClass parent_class; - - void (* populate_popup) (GeditView *view, - GtkMenu *menu); + GtkSourceViewClass parent_class; + + /* FIXME: Do we need placeholders ? */ + gboolean (* start_interactive_search) (GeditView *view); + gboolean (* start_interactive_goto_line)(GeditView *view); }; +/* + * Public methods + */ +GtkType gedit_view_get_type (void) G_GNUC_CONST; -GtkType gedit_view_get_type (void) G_GNUC_CONST; - -GeditView* 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_scroll_to_cursor (GeditView *view); - -GeditDocument* gedit_view_get_document (const GeditView *view); - -void gedit_view_set_colors (GeditView *view, - gboolean def, - GdkColor *backgroud, - GdkColor *text, - GdkColor *selection, - GdkColor *sel_text); - -void gedit_view_set_font (GeditView *view, - gboolean def, - const gchar *font_name); - -void gedit_view_set_wrap_mode (GeditView *view, GtkWrapMode wrap_mode); -void gedit_view_set_tab_size (GeditView *view, gint tab_size); -void gedit_view_set_insert_spaces_instead_of_tabs - (GeditView *view, gboolean enable); - -void gedit_view_set_auto_indent (GeditView *view, gboolean enable); +GtkWidget *gedit_view_new (GeditDocument *doc); -void gedit_view_show_line_numbers (GeditView *view, gboolean visible); +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_cursor_position_statusbar (GeditView *view, GtkWidget* status); -void gedit_view_set_overwrite_mode_statusbar (GeditView *view, GtkWidget* status); +void gedit_view_set_colors (GeditView *view, + gboolean def, + GdkColor *backgroud, + GdkColor *text, + GdkColor *selection, + GdkColor *sel_text); -GtkTextView *gedit_view_get_gtk_text_view (const GeditView *view); +void gedit_view_set_font (GeditView *view, + gboolean def, + const gchar *font_name); -void gedit_view_set_editable (GeditView *view, gboolean editable); +G_END_DECLS #endif /* __GEDIT_VIEW_H__ */ - diff --git a/gedit/gedit-window-private.h b/gedit/gedit-window-private.h new file mode 100644 index 00000000..6ebbee24 --- /dev/null +++ b/gedit/gedit-window-private.h @@ -0,0 +1,93 @@ +/* + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_WINDOW_PRIVATE_H__ +#define __GEDIT_WINDOW_PRIVATE_H__ + +#include "gedit/gedit-window.h" +#include "gedit-prefs-manager.h" +#include "recent-files/egg-recent-view-uimanager.h" + +G_BEGIN_DECLS + +/* WindowPrivate is in a separate .h so that we can access it from gedit-commands */ + +struct _GeditWindowPrivate +{ + GtkWidget *notebook; + + GtkWidget *side_panel; + GtkWidget *bottom_panel; + + GtkWidget *hpaned; + GtkWidget *vpaned; + + /* statusbar and context ids for statusbar messages */ + GtkWidget *statusbar; + guint generic_message_cid; + guint tip_message_cid; + + /* Menus & Toolbars */ + GtkUIManager *manager; + GtkActionGroup *action_group; + GtkActionGroup *always_sensitive_action_group; + GtkActionGroup *languages_action_group; + GtkActionGroup *documents_list_action_group; + guint documents_list_menu_ui_id; + GtkWidget *toolbar; + GtkWidget *toolbar_recent_menu; + GeditToolbarSetting toolbar_style; + + EggRecentViewUIManager *recent_view_uim; + + GeditTab *active_tab; + gint num_tabs; + + gint num_tabs_with_error; + + gint width; + gint height; + GdkWindowState window_state; + + gint side_panel_size; + gint bottom_panel_size; + + gboolean removing_tabs; + + GeditWindowState state; + + GtkWindowGroup *window_group; + + gchar *default_path; +}; + +G_END_DECLS + +#endif /* __GEDIT_WINDOW_PRIVATE_H__ */ diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c new file mode 100644 index 00000000..7ac596c9 --- /dev/null +++ b/gedit/gedit-window.c @@ -0,0 +1,3105 @@ +/* + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include "gedit-ui.h" +#include "gedit-window.h" +#include "gedit-window-private.h" +#include "gedit-app.h" +#include "gedit-notebook.h" +#include "gedit-statusbar.h" +#include "gedit-utils.h" +#include "gedit-commands.h" +#include "gedit-debug.h" +#include "gedit-languages-manager.h" +#include "gedit-prefs-manager-app.h" +#include "gedit-panel.h" +#include "gedit-recent.h" +#include "gedit-documents-panel.h" +#include "gedit-plugins-engine.h" + +#include "recent-files/egg-recent-model.h" +#include "recent-files/egg-recent-view.h" +#include "recent-files/egg-recent-view-gtk.h" +#include "recent-files/egg-recent-view-uimanager.h" + +#define GEDIT_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_WINDOW, GeditWindowPrivate)) + +/* Signals */ +enum +{ + TAB_ADDED, + TAB_REMOVED, + TABS_REORDERED, + ACTIVE_TAB_CHANGED, + ACTIVE_TAB_STATE_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum +{ + PROP_0, + PROP_STATE +}; + +enum +{ + TARGET_URI_LIST = 100 +}; + +static const GtkTargetEntry drag_types[] = +{ + { "text/uri-list", 0, TARGET_URI_LIST }, +}; + +G_DEFINE_TYPE(GeditWindow, gedit_window, GTK_TYPE_WINDOW) + +static void +gedit_window_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditWindow *window = GEDIT_WINDOW (object); + + switch (prop_id) + { + case PROP_STATE: + g_value_set_int (value, + gedit_window_get_state (window)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_window_finalize (GObject *object) +{ + GeditWindow *window = GEDIT_WINDOW (object); + + g_object_unref (window->priv->manager); + + g_object_unref (window->priv->window_group); + + g_free (window->priv->default_path); + + G_OBJECT_CLASS (gedit_window_parent_class)->finalize (object); +} + +static void +gedit_window_destroy (GtkObject *object) +{ + GeditWindow *window; + + window = GEDIT_WINDOW (object); + + if (gedit_prefs_manager_window_height_can_set ()) + gedit_prefs_manager_set_window_height (window->priv->height); + + if (gedit_prefs_manager_window_width_can_set ()) + gedit_prefs_manager_set_window_width (window->priv->width); + + if (gedit_prefs_manager_window_state_can_set ()) + gedit_prefs_manager_set_window_state (window->priv->window_state); + + if ((window->priv->side_panel_size > 0) && + gedit_prefs_manager_side_panel_size_can_set ()) + gedit_prefs_manager_set_side_panel_size ( + window->priv->side_panel_size); + + if ((window->priv->bottom_panel_size > 0) && + gedit_prefs_manager_bottom_panel_size_can_set ()) + gedit_prefs_manager_set_bottom_panel_size ( + window->priv->bottom_panel_size); + + /* do it here, because recent_view_uim finalization + * requires that widgets are still there + */ + if (window->priv->recent_view_uim != NULL) + { + g_object_unref (window->priv->recent_view_uim); + window->priv->recent_view_uim = NULL; + } + + GTK_OBJECT_CLASS (gedit_window_parent_class)->destroy (object); +} + +static gboolean +gedit_window_window_state_event (GtkWidget *widget, + GdkEventWindowState *event) +{ + GeditWindow *window = GEDIT_WINDOW (widget); + + window->priv->window_state = event->new_window_state; + + if (event->changed_mask & + (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) + { + gboolean show; + + show = !(event->new_window_state & + (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)); + + _gedit_statusbar_set_has_resize_grip (GEDIT_STATUSBAR (window->priv->statusbar), + show); + } + + return FALSE; +} + +static gboolean +gedit_window_configure_event (GtkWidget *widget, + GdkEventConfigure *event) +{ + GeditWindow *window = GEDIT_WINDOW (widget); + + window->priv->width = event->width; + window->priv->height = event->height; + + 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 force events to be first passed to the focused widget and then + * we chain up the default handler... this is the opposite of Gtk default + * behavior so we need to keep an eye open to see if anything breaks. + */ +static gboolean +gedit_window_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + GtkWidget *focused_widget; + gboolean handled = FALSE; + + focused_widget = gtk_window_get_focus (GTK_WINDOW (widget)); + + if (focused_widget) + { + handled = gtk_widget_event (focused_widget, + (GdkEvent*) event); + } + + if (handled) + return TRUE; + else + return GTK_WIDGET_CLASS (gedit_window_parent_class)->key_press_event (widget, event); +} + +static void +gedit_window_class_init (GeditWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkObjectClass *gobject_class = GTK_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = gedit_window_finalize; + object_class->get_property = gedit_window_get_property; + + gobject_class->destroy = gedit_window_destroy; + + widget_class->window_state_event = gedit_window_window_state_event; + widget_class->configure_event = gedit_window_configure_event; + widget_class->key_press_event = gedit_window_key_press_event; + + signals[TAB_ADDED] = + g_signal_new ("tab_added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeditWindowClass, tab_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GEDIT_TYPE_TAB); + signals[TAB_REMOVED] = + g_signal_new ("tab_removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeditWindowClass, tab_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GEDIT_TYPE_TAB); + signals[TABS_REORDERED] = + g_signal_new ("tabs_reordered", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeditWindowClass, tabs_reordered), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + 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, + g_cclosure_marshal_VOID__OBJECT, + 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, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_object_class_install_property (object_class, + PROP_STATE, + g_param_spec_int ("state", + "State", + "The window's state", + 0, /* GEDIT_WINDOW_STATE_NORMAL */ + G_MAXINT, + 0, /* GEDIT_WINDOW_STATE_NORMAL */ + G_PARAM_READABLE)); + + g_type_class_add_private (object_class, sizeof(GeditWindowPrivate)); +} + +static void +menu_item_select_cb (GtkMenuItem *proxy, + GeditWindow *window) +{ + GtkAction *action; + char *message; + + action = g_object_get_data (G_OBJECT (proxy), "gtk-action"); + g_return_if_fail (action != NULL); + + g_object_get (G_OBJECT (action), "tooltip", &message, NULL); + if (message) + { + gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar), + window->priv->tip_message_cid, message); + g_free (message); + } +} + +static void +menu_item_deselect_cb (GtkMenuItem *proxy, + GeditWindow *window) +{ + gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar), + window->priv->tip_message_cid); +} + +static void +connect_proxy_cb (GtkUIManager *manager, + GtkAction *action, + GtkWidget *proxy, + GeditWindow *window) +{ + if (GTK_IS_MENU_ITEM (proxy)) + { + g_signal_connect (proxy, "select", + G_CALLBACK (menu_item_select_cb), window); + g_signal_connect (proxy, "deselect", + G_CALLBACK (menu_item_deselect_cb), window); + } +} + +static void +disconnect_proxy_cb (GtkUIManager *manager, + GtkAction *action, + GtkWidget *proxy, + GeditWindow *window) +{ + if (GTK_IS_MENU_ITEM (proxy)) + { + g_signal_handlers_disconnect_by_func + (proxy, G_CALLBACK (menu_item_select_cb), window); + g_signal_handlers_disconnect_by_func + (proxy, G_CALLBACK (menu_item_deselect_cb), window); + } +} + +/* Returns TRUE if toolbar is visible */ +static gboolean +set_toolbar_style (GeditWindow *window, + GeditWindow *origin) +{ + gboolean visible; + GeditToolbarSetting style; + GtkAction *action; + + if (origin == NULL) + visible = gedit_prefs_manager_get_toolbar_visible (); + else + visible = GTK_WIDGET_VISIBLE (origin->priv->toolbar); + + /* Set visibility */ + if (visible) + gtk_widget_show (window->priv->toolbar); + else + gtk_widget_hide (window->priv->toolbar); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewToolbar"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + /* Set style */ + if (origin == NULL) + style = gedit_prefs_manager_get_toolbar_buttons_style (); + else + style = origin->priv->toolbar_style; + + window->priv->toolbar_style = style; + + switch (style) + { + case GEDIT_TOOLBAR_SYSTEM: + gedit_debug_message (DEBUG_WINDOW, "GEDIT: SYSTEM"); + gtk_toolbar_unset_style ( + GTK_TOOLBAR (window->priv->toolbar)); + break; + + case GEDIT_TOOLBAR_ICONS: + gedit_debug_message (DEBUG_WINDOW, "GEDIT: ICONS"); + gtk_toolbar_set_style ( + GTK_TOOLBAR (window->priv->toolbar), + GTK_TOOLBAR_ICONS); + break; + + case GEDIT_TOOLBAR_ICONS_AND_TEXT: + gedit_debug_message (DEBUG_WINDOW, "GEDIT: ICONS_AND_TEXT"); + gtk_toolbar_set_style ( + GTK_TOOLBAR (window->priv->toolbar), + GTK_TOOLBAR_BOTH); + break; + + case GEDIT_TOOLBAR_ICONS_BOTH_HORIZ: + gedit_debug_message (DEBUG_WINDOW, "GEDIT: ICONS_BOTH_HORIZ"); + gtk_toolbar_set_style ( + GTK_TOOLBAR (window->priv->toolbar), + GTK_TOOLBAR_BOTH_HORIZ); + break; + } + + return visible; +} + +static void +set_sensitivity_according_to_tab (GeditWindow *window, + GeditTab *tab) +{ + GeditDocument *doc; + GeditView *view; + GtkAction *action; + gboolean b; + gboolean state_normal; + GeditTabState state; + + g_return_if_fail (GEDIT_TAB (tab)); + + gedit_debug (DEBUG_WINDOW); + + state = gedit_tab_get_state (tab); + state_normal = (state == GEDIT_TAB_STATE_NORMAL); + + view = gedit_tab_get_view (tab); + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + + action = gtk_action_group_get_action (window->priv->action_group, + "FileSave"); + gtk_action_set_sensitive (action, + (state_normal || + (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)) && + !gedit_document_get_readonly (doc)); + + action = gtk_action_group_get_action (window->priv->action_group, + "FileSaveAs"); + gtk_action_set_sensitive (action, + state_normal || + (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)); + + action = gtk_action_group_get_action (window->priv->action_group, + "FileRevert"); + gtk_action_set_sensitive (action, + !gedit_document_is_untitled (doc) && + state_normal); + + action = gtk_action_group_get_action (window->priv->action_group, + "FilePrintPreview"); + gtk_action_set_sensitive (action, + state_normal); + + action = gtk_action_group_get_action (window->priv->action_group, + "FilePrint"); + gtk_action_set_sensitive (action, + state_normal || + (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)); + + action = gtk_action_group_get_action (window->priv->action_group, + "FileClose"); + + gtk_action_set_sensitive (action, + (state != GEDIT_TAB_STATE_CLOSING) && + (state != GEDIT_TAB_STATE_SAVING) && + (state != GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW) && + (state != GEDIT_TAB_STATE_SAVING_ERROR)); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditUndo"); + gtk_action_set_sensitive (action, + state_normal && + gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER (doc))); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditRedo"); + gtk_action_set_sensitive (action, + state_normal && + gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER (doc))); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditCut"); + gtk_action_set_sensitive (action, + state_normal && + _gedit_document_get_has_selection (doc)); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditCopy"); + gtk_action_set_sensitive (action, + state_normal && + _gedit_document_get_has_selection (doc)); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditPaste"); + gtk_action_set_sensitive (action, + state_normal); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditDelete"); + gtk_action_set_sensitive (action, + state_normal && + _gedit_document_get_has_selection (doc)); + + action = gtk_action_group_get_action (window->priv->action_group, + "SearchFind"); + gtk_action_set_sensitive (action, + state_normal); + + action = gtk_action_group_get_action (window->priv->action_group, + "SearchReplace"); + gtk_action_set_sensitive (action, + state_normal); + + b = gedit_document_get_can_search_again (doc); + action = gtk_action_group_get_action (window->priv->action_group, + "SearchFindNext"); + gtk_action_set_sensitive (action, state_normal && b); + + action = gtk_action_group_get_action (window->priv->action_group, + "SearchFindPrevious"); + gtk_action_set_sensitive (action, state_normal && b); + + action = gtk_action_group_get_action (window->priv->action_group, + "SearchGoToLine"); + gtk_action_set_sensitive (action, state_normal); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewHighlightMode"); + gtk_action_set_sensitive (action, + (state != GEDIT_TAB_STATE_CLOSING) && + gedit_prefs_manager_get_enable_syntax_highlighting ()); + + gedit_plugins_engine_update_plugins_ui (window, FALSE); +} + +static void +language_toggled (GtkToggleAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + const GSList *languages; + const GtkSourceLanguage *lang; + gint n; + + if (gtk_toggle_action_get_active (action) == FALSE) + return; + + doc = gedit_window_get_active_document (window); + if (doc == NULL) + return; + + n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (n < 0) + { + /* Normal (no highlighting) */ + lang = NULL; + } + else + { + languages = gedit_languages_manager_get_available_languages_sorted ( + gedit_get_languages_manager ()); + + lang = GTK_SOURCE_LANGUAGE (g_slist_nth_data ((GSList *) languages, n)); + } + + gedit_document_set_language (doc, (GtkSourceLanguage *) lang); +} + +static void +create_language_menu_item (GtkSourceLanguage *lang, + gint index, + guint ui_id, + GeditWindow *window) +{ + GtkAction *section_action; + GtkRadioAction *action; + GtkAction *normal_action; + GSList *group; + gchar *section; + gchar *lang_name; + gchar *tip; + gchar *path; + + section = gtk_source_language_get_section (lang); + + /* check if the section submenu exists or create it */ + section_action = gtk_action_group_get_action (window->priv->languages_action_group, + section); + + if (section_action == NULL) + { + // CHECK: escaping strings + section_action = gtk_action_new (section, + section, + NULL, + NULL); + + gtk_action_group_add_action (window->priv->languages_action_group, + section_action); + g_object_unref (section_action); + + gtk_ui_manager_add_ui (window->priv->manager, + ui_id, + "/MenuBar/ViewMenu/ViewHighlightModeMenu/LanguagesMenuPlaceholder", + section, section, + GTK_UI_MANAGER_MENU, + FALSE); + } + + /* now add the language item to the section */ + lang_name = gtk_source_language_get_name (lang); + tip = g_strdup_printf (_("Use %s highlight mode"), lang_name); + path = g_strdup_printf ("/MenuBar/ViewMenu/ViewHighlightModeMenu/LanguagesMenuPlaceholder/%s", + section); + + // CHECK: escaping strings + action = gtk_radio_action_new (lang_name, + lang_name, + tip, + NULL, + index); + + gtk_action_group_add_action (window->priv->languages_action_group, + GTK_ACTION (action)); + g_object_unref (action); + + /* add the action to the same radio group of the "Normal" action */ + normal_action = gtk_action_group_get_action (window->priv->languages_action_group, + "LangNormal"); + group = gtk_radio_action_get_group (GTK_RADIO_ACTION (normal_action)); + gtk_radio_action_set_group (action, group); + + g_signal_connect (action, + "activate", + G_CALLBACK (language_toggled), + window); + + gtk_ui_manager_add_ui (window->priv->manager, + ui_id, + path, + lang_name, lang_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); + + g_free (path); + g_free (tip); + g_free (lang_name); + g_free (section); +} + +static void +create_languages_menu (GeditWindow *window) +{ + GtkRadioAction *action_normal; + const GSList *languages; + const GSList *l; + guint id; + gint i; + + gedit_debug (DEBUG_WINDOW); + + /* add the "Normal" item before all the others */ + action_normal = gtk_radio_action_new ("LangNormal", + _("Normal"), + _("Use Normal highlight mode"), + NULL, + -1); + + gtk_action_group_add_action (window->priv->languages_action_group, + GTK_ACTION (action_normal)); + g_object_unref (action_normal); + + g_signal_connect (action_normal, + "activate", + G_CALLBACK (language_toggled), + window); + + id = gtk_ui_manager_new_merge_id (window->priv->manager); + + gtk_ui_manager_add_ui (window->priv->manager, + id, + "/MenuBar/ViewMenu/ViewHighlightModeMenu/LanguagesMenuPlaceholder", + "LangNormal", "LangNormal", + GTK_UI_MANAGER_MENUITEM, + TRUE); + + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action_normal), TRUE); + + /* now add all the known languages */ + languages = gedit_languages_manager_get_available_languages_sorted ( + gedit_get_languages_manager ()); + + for (l = languages, i = 0; l != NULL; l = l->next, ++i) + create_language_menu_item (GTK_SOURCE_LANGUAGE (l->data), + i, + id, + window); +} + +static void +update_languages_menu (GeditWindow *window) +{ + GeditDocument *doc; + GList *actions; + GList *l; + GtkAction *action; + GtkSourceLanguage *lang; + gchar *lang_name; + + doc = gedit_window_get_active_document (window); + if (doc == NULL) + return; + + lang = gedit_document_get_language (doc); + if (lang != NULL) + lang_name = gtk_source_language_get_name (lang); + else + lang_name = g_strdup ("LangNormal"); + + actions = gtk_action_group_list_actions (window->priv->languages_action_group); + + /* prevent recursion */ + for (l = actions; l != NULL; l = l->next) + { + g_signal_handlers_block_by_func (GTK_ACTION (l->data), + G_CALLBACK (language_toggled), + window); + } + + action = gtk_action_group_get_action (window->priv->languages_action_group, + lang_name); + + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + + for (l = actions; l != NULL; l = l->next) + { + g_signal_handlers_unblock_by_func (GTK_ACTION (l->data), + G_CALLBACK (language_toggled), + window); + } + + g_list_free (actions); + g_free (lang_name); +} + +static void +open_recent_gtk (EggRecentViewGtk *view, + EggRecentItem *item, + GeditWindow *window) +{ + gedit_cmd_file_open_recent (item, window); +} + +static void +open_recent_uim (GtkAction *action, + GeditWindow *window) +{ + EggRecentItem *item; + + item = egg_recent_view_uimanager_get_item (window->priv->recent_view_uim, + action); + g_return_if_fail (item != NULL); + + gedit_cmd_file_open_recent (item, window); +} + +#define TIP_MAX_URI_LEN 100 + +static void +recent_tooltip_func_gtk (GtkTooltips *tooltips, + GtkWidget *menu, + EggRecentItem *item, + gpointer user_data) +{ + gchar *tip; + gchar *uri_for_display; + gchar *trunc_uri; + + uri_for_display = egg_recent_item_get_uri_for_display (item); + g_return_if_fail (uri_for_display != NULL); + + trunc_uri = gedit_utils_str_middle_truncate (uri_for_display, + TIP_MAX_URI_LEN); + g_free (uri_for_display); + + /* Translators: %s is a URI */ + tip = g_strdup_printf (_("Open '%s'"), trunc_uri); + + g_free (trunc_uri); + + gtk_tooltips_set_tip (tooltips, GTK_WIDGET (menu), tip, NULL); + + g_free (tip); +} + +static char * +recent_tooltip_func_uim (EggRecentItem *item, + gpointer user_data) +{ + gchar *tip; + gchar *uri_for_display; + gchar *trunc_uri; + + uri_for_display = egg_recent_item_get_uri_for_display (item); + g_return_val_if_fail (uri_for_display != NULL, NULL); + + trunc_uri = gedit_utils_str_middle_truncate (uri_for_display, + TIP_MAX_URI_LEN); + g_free (uri_for_display); + + /* Translators: %s is a URI */ + tip = g_strdup_printf (_("Open '%s'"), trunc_uri); + + g_free (trunc_uri); + + return tip; +} + +#undef TIP_MAX_URI_LEN + +static void +build_recent_tool_menu (GtkMenuToolButton *button, + GeditWindow *window) +{ + EggRecentViewGtk *view; + EggRecentModel *model; + + model = gedit_recent_get_model (); + view = egg_recent_view_gtk_new (window->priv->toolbar_recent_menu, + NULL); + + egg_recent_view_gtk_show_icons (view, TRUE); + egg_recent_view_gtk_show_numbers (view, FALSE); + + /* elipsize if if gets too large */ + egg_recent_view_gtk_set_label_width (view, 50); + + egg_recent_view_gtk_set_tooltip_func (view, recent_tooltip_func_gtk, NULL); + + egg_recent_view_set_model (EGG_RECENT_VIEW (view), model); + + g_signal_connect (view, + "activate", + G_CALLBACK (open_recent_gtk), + window); + + gtk_widget_show (window->priv->toolbar_recent_menu); + + /* this callback must run just once for lazy initialization: + * we can now disconnect it + */ + g_signal_handlers_disconnect_by_func (button, + G_CALLBACK (build_recent_tool_menu), + window); +} + +static void +set_non_homogeneus (GtkWidget *widget, gpointer data) +{ + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE); +} + +static void +create_menu_bar_and_toolbar (GeditWindow *window, + GtkWidget *main_box) +{ + GtkActionGroup *action_group; + GtkAction *action; + GtkUIManager *manager; + GtkWidget *menubar; + EggRecentModel *recent_model; + EggRecentViewUIManager *recent_view; + GtkToolItem *open_button; + GError *error = NULL; + + gedit_debug (DEBUG_WINDOW); + + manager = gtk_ui_manager_new (); + window->priv->manager = manager; + + gtk_window_add_accel_group (GTK_WINDOW (window), + gtk_ui_manager_get_accel_group (manager)); + + action_group = gtk_action_group_new ("GeditWindowAlwaysSensitiveActions"); + gtk_action_group_set_translation_domain (action_group, NULL); + gtk_action_group_add_actions (action_group, + gedit_always_sensitive_menu_entries, + G_N_ELEMENTS (gedit_always_sensitive_menu_entries), + window); + + gtk_ui_manager_insert_action_group (manager, action_group, 0); + g_object_unref (action_group); + window->priv->always_sensitive_action_group = action_group; + + action_group = gtk_action_group_new ("GeditWindowActions"); + gtk_action_group_set_translation_domain (action_group, NULL); + gtk_action_group_add_actions (action_group, + gedit_menu_entries, + G_N_ELEMENTS (gedit_menu_entries), + window); + gtk_action_group_add_toggle_actions (action_group, + gedit_toggle_menu_entries, + G_N_ELEMENTS (gedit_toggle_menu_entries), + window); + + gtk_ui_manager_insert_action_group (manager, action_group, 0); + g_object_unref (action_group); + window->priv->action_group = action_group; + + /* set short labels to use in the toolbar */ + action = gtk_action_group_get_action (action_group, "FileSave"); + g_object_set (action, "short_label", _("Save"), NULL); + action = gtk_action_group_get_action (action_group, "SearchFind"); + g_object_set (action, "short_label", _("Find"), NULL); + action = gtk_action_group_get_action (action_group, "SearchReplace"); + g_object_set (action, "short_label", _("Replace"), NULL); + + /* set which actions should have priority on the toolbar */ + action = gtk_action_group_get_action (action_group, "FileSave"); + g_object_set (action, "is_important", TRUE, NULL); + action = gtk_action_group_get_action (action_group, "EditUndo"); + g_object_set (action, "is_important", TRUE, NULL); + + /* now load the UI definition */ + if (gtk_ui_manager_add_ui_from_file (manager, "gedit-ui.xml", NULL)) // REMOVE ME... just to allow running without install + ; + else + + gtk_ui_manager_add_ui_from_file (manager, GEDIT_UI_DIR "gedit-ui.xml", &error); + if (error != NULL) + { + g_warning ("Could not merge gedit-ui.xml: %s", error->message); + g_error_free (error); + } + + /* show tooltips in the statusbar */ + g_signal_connect (manager, + "connect_proxy", + G_CALLBACK (connect_proxy_cb), + window); + g_signal_connect (manager, + "disconnect_proxy", + G_CALLBACK (disconnect_proxy_cb), + window); + + /* recent files menu */ + recent_model = gedit_recent_get_model (); + recent_view = egg_recent_view_uimanager_new (manager, + "/MenuBar/FileMenu/FileRecentsPlaceholder", + G_CALLBACK (open_recent_uim), + window); + window->priv->recent_view_uim = recent_view; + egg_recent_view_uimanager_show_icons (recent_view, FALSE); + egg_recent_view_uimanager_set_tooltip_func (recent_view, + recent_tooltip_func_uim, + window); + egg_recent_view_set_model (EGG_RECENT_VIEW (recent_view), recent_model); + + /* languages menu */ + action_group = gtk_action_group_new ("LanguagesActions"); + gtk_action_group_set_translation_domain (action_group, NULL); + window->priv->languages_action_group = action_group; + gtk_ui_manager_insert_action_group (manager, action_group, 0); + g_object_unref (action_group); + create_languages_menu (window); + + /* list of open documents menu */ + action_group = gtk_action_group_new ("DocumentsListActions"); + gtk_action_group_set_translation_domain (action_group, NULL); + window->priv->documents_list_action_group = action_group; + gtk_ui_manager_insert_action_group (manager, action_group, 0); + g_object_unref (action_group); + + menubar = gtk_ui_manager_get_widget (manager, "/MenuBar"); + gtk_box_pack_start (GTK_BOX (main_box), + menubar, + FALSE, + FALSE, + 0); + + window->priv->toolbar = gtk_ui_manager_get_widget (manager, "/ToolBar"); + gtk_box_pack_start (GTK_BOX (main_box), + window->priv->toolbar, + FALSE, + FALSE, + 0); + + /* add the custom Open button to the toolbar */ + open_button = gtk_menu_tool_button_new_from_stock (GTK_STOCK_OPEN); + + /* the popup menu is actually built the first time it's showed */ + window->priv->toolbar_recent_menu = gtk_menu_new (); + gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), + window->priv->toolbar_recent_menu); + g_signal_connect (open_button, + "show-menu", + G_CALLBACK (build_recent_tool_menu), + window); + + /* not very nice the way we access the tooltops object + * but I can't see a better way and I don't want a differen GtkTooltip + * just for this tool button. + */ + gtk_tool_item_set_tooltip (open_button, + GTK_TOOLBAR (window->priv->toolbar)->tooltips, + _("Open a file"), + NULL); + gtk_menu_tool_button_set_arrow_tooltip (GTK_MENU_TOOL_BUTTON (open_button), + GTK_TOOLBAR (window->priv->toolbar)->tooltips, + _("Open a recently used file"), + NULL); + + action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, + "FileOpen"); + g_object_set (action, + "is_important", TRUE, + "short_label", _("Open"), + NULL); + gtk_action_connect_proxy (action, GTK_WIDGET (open_button)); + + gtk_toolbar_insert (GTK_TOOLBAR (window->priv->toolbar), open_button, 1); + + set_toolbar_style (window, NULL); + + gtk_container_foreach (GTK_CONTAINER (window->priv->toolbar), + (GtkCallback)set_non_homogeneus, + NULL); +} + +static void +documents_list_menu_activate (GtkToggleAction *action, + GeditWindow *window) +{ + gint n; + + if (gtk_toggle_action_get_active (action) == FALSE) + return; + + n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook), n); +} + +static void +update_documents_list_menu (GeditWindow *window) +{ + GeditWindowPrivate *p = window->priv; + GList *actions, *l; + gint n, i; + guint id; + GSList *group = NULL; + + gedit_debug (DEBUG_WINDOW); + + g_return_if_fail (p->documents_list_action_group != NULL); + + if (p->documents_list_menu_ui_id != 0) + gtk_ui_manager_remove_ui (p->manager, + p->documents_list_menu_ui_id); + + actions = gtk_action_group_list_actions (p->documents_list_action_group); + for (l = actions; l != NULL; l = l->next) + { + g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data), + G_CALLBACK (documents_list_menu_activate), + window); + gtk_action_group_remove_action (p->documents_list_action_group, + GTK_ACTION (l->data)); + } + g_list_free (actions); + + n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (p->notebook)); + + id = (n > 0) ? gtk_ui_manager_new_merge_id (p->manager) : 0; + + for (i = 0; i < n; i++) + { + GtkWidget *tab; + GtkRadioAction *action; + gchar *action_name; + gchar *tab_name; //CHECK: must escape underscores and gmarkup + gchar *tip; // ditto as above + gchar *accel; + + tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (p->notebook), i); + + /* NOTE: the action is associated to the position of the tab in + * the notebook not to the tab itself! This is needed to work + * around the gtk+ bug #170727: gtk leaves around the accels + * of the action. Since the accel depends on the tab position + * the problem is worked around, action with the same name always + * get the same accel. + */ + action_name = g_strdup_printf ("Tab_%d", i); + tab_name = _gedit_tab_get_name (GEDIT_TAB (tab)); + tip = g_strdup_printf (_("Activate %s"), tab_name); + + /* alt + 1, 2, 3... 0 to switch to the first ten tabs */ + accel = (i < 10) ? g_strdup_printf ("%d", (i + 1) % 10) : NULL; + + action = gtk_radio_action_new (action_name, + tab_name, + tip, + NULL, + i); + + if (group != NULL) + gtk_radio_action_set_group (action, group); + + /* note that group changes each time we add an action, so it must be updated */ + group = gtk_radio_action_get_group (action); + + gtk_action_group_add_action_with_accel (p->documents_list_action_group, + GTK_ACTION (action), + accel); + + g_signal_connect (action, + "activate", + G_CALLBACK (documents_list_menu_activate), + window); + + gtk_ui_manager_add_ui (p->manager, + id, + "/MenuBar/DocumentsMenu/DocumentsListPlaceholder", + action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); + + if (GEDIT_TAB (tab) == p->active_tab) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + + g_object_unref (action); + + g_free (action_name); + g_free (tab_name); + g_free (tip); + g_free (accel); + } + + p->documents_list_menu_ui_id = id; +} + +/* Returns TRUE if status bar is visible */ +static gboolean +set_statusbar_style (GeditWindow *window, + GeditWindow *origin) +{ + GtkAction *action; + + gboolean visible; + + if (origin == NULL) + visible = gedit_prefs_manager_get_statusbar_visible (); + else + visible = GTK_WIDGET_VISIBLE (origin->priv->statusbar); + + if (visible) + gtk_widget_show (window->priv->statusbar); + else + gtk_widget_hide (window->priv->statusbar); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewStatusbar"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + return visible; +} + +static void +create_statusbar (GeditWindow *window, + GtkWidget *main_box) +{ + gedit_debug (DEBUG_WINDOW); + + window->priv->statusbar = gedit_statusbar_new (); + + 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"); + + gtk_box_pack_end (GTK_BOX (main_box), + window->priv->statusbar, + FALSE, + TRUE, + 0); + + set_statusbar_style (window, NULL); +} + +static GeditWindow * +clone_window (GeditWindow *origin) +{ + GtkWindow *window; + GeditApp *app; + + gedit_debug (DEBUG_WINDOW); + + app = gedit_app_get_default (); + + window = GTK_WINDOW (gedit_app_create_window (app)); + + gtk_window_set_default_size (window, + origin->priv->width, + origin->priv->height); + + if ((origin->priv->window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0) + { + gtk_window_set_default_size (window, + gedit_prefs_manager_get_default_window_width (), + gedit_prefs_manager_get_default_window_height ()); + + gtk_window_maximize (window); + } + else + { + gtk_window_set_default_size (window, + origin->priv->width, + origin->priv->height); + + gtk_window_unmaximize (window); + } + + if ((origin->priv->window_state & GDK_WINDOW_STATE_STICKY ) != 0) + gtk_window_stick (window); + else + gtk_window_unstick (window); + + gtk_paned_set_position (GTK_PANED (GEDIT_WINDOW (window)->priv->hpaned), + gtk_paned_get_position (GTK_PANED (origin->priv->hpaned))); + + gtk_paned_set_position (GTK_PANED (GEDIT_WINDOW (window)->priv->vpaned), + gtk_paned_get_position (GTK_PANED (origin->priv->vpaned))); + + if (GTK_WIDGET_VISIBLE (origin->priv->side_panel)) + gtk_widget_show (GEDIT_WINDOW (window)->priv->side_panel); + else + gtk_widget_hide (GEDIT_WINDOW (window)->priv->side_panel); + + if (GTK_WIDGET_VISIBLE (origin->priv->bottom_panel)) + gtk_widget_show (GEDIT_WINDOW (window)->priv->bottom_panel); + else + gtk_widget_hide (GEDIT_WINDOW (window)->priv->bottom_panel); + + set_statusbar_style (GEDIT_WINDOW (window), origin); + set_toolbar_style (GEDIT_WINDOW (window), origin); + + return GEDIT_WINDOW (window); +} + +static void +update_cursor_position_statusbar (GtkTextBuffer *buffer, + GeditWindow *window) +{ + gint row, col; + GtkTextIter iter; + GtkTextIter start; + guint tab_size; + GeditView *view; + + gedit_debug (DEBUG_WINDOW); + + if (buffer != GTK_TEXT_BUFFER (gedit_window_get_active_document (window))) + return; + + view = gedit_window_get_active_view (window); + + gtk_text_buffer_get_iter_at_mark (buffer, + &iter, + gtk_text_buffer_get_insert (buffer)); + + row = gtk_text_iter_get_line (&iter); + + start = iter; + gtk_text_iter_set_line_offset (&start, 0); + col = 0; + + tab_size = gtk_source_view_get_tabs_width (GTK_SOURCE_VIEW (view)); + + while (!gtk_text_iter_equal (&start, &iter)) + { + /* FIXME: Are we Unicode compliant here? */ + if (gtk_text_iter_get_char (&start) == '\t') + + col += (tab_size - (col % tab_size)); + else + ++col; + + gtk_text_iter_forward_char (&start); + } + + gedit_statusbar_set_cursor_position ( + GEDIT_STATUSBAR (window->priv->statusbar), + row + 1, + col + 1); +} + +static void +update_overwrite_mode_statusbar (GtkTextView *view, + GeditWindow *window) +{ + if (view != GTK_TEXT_VIEW (gedit_window_get_active_view (window))) + return; + + /* Note that we have to use !gtk_text_view_get_overwrite since we + are in the in the signal handler of "toggle overwrite" that is + G_SIGNAL_RUN_LAST + */ + gedit_statusbar_set_overwrite ( + GEDIT_STATUSBAR (window->priv->statusbar), + !gtk_text_view_get_overwrite (view)); +} + +#define MAX_TITLE_LENGTH 100 + +static void +set_title (GeditWindow *window) +{ + GeditDocument *doc = NULL; + gchar *name; + gchar *dirname = NULL; + gchar *title = NULL; + gint len; + + if (window->priv->active_tab == NULL) + { + gtk_window_set_title (GTK_WINDOW (window), "gedit"); + return; + } + + doc = gedit_tab_get_document (window->priv->active_tab); + g_return_if_fail (doc != NULL); + + 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 = gedit_utils_str_middle_truncate (name, + MAX_TITLE_LENGTH); + g_free (name); + name = tmp; + } + else + { + gchar *uri; + gchar *str; + + uri = gedit_document_get_uri_for_display (doc); + str = gedit_utils_uri_get_dirname (uri); + g_free (uri); + + if (str != NULL) + { + /* 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 = 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 (gedit_document_get_readonly (doc)) + { + if (dirname != NULL) + title = g_strdup_printf ("%s [%s] (%s) - gedit", + name, + _("Read Only"), + dirname); + else + title = g_strdup_printf ("%s [%s] - gedit", + name, + _("Read Only")); + } + else + { + if (dirname != NULL) + title = g_strdup_printf ("%s (%s) - gedit", + name, + dirname); + else + title = g_strdup_printf ("%s - gedit", + name); + } + + gtk_window_set_title (GTK_WINDOW (window), title); + + g_free (dirname); + g_free (name); + g_free (title); +} + +#undef MAX_TITLE_LENGTH + +static void +notebook_switch_page (GtkNotebook *book, + GtkNotebookPage *pg, + gint page_num, + GeditWindow *window) +{ + GeditView *view; + GeditTab *tab; + GtkAction *action; + gchar *action_name; + + /* CHECK: I don't know why but it seems notebook_switch_page is called + two times every time the user change the active tab */ + + tab = GEDIT_TAB (gtk_notebook_get_nth_page (book, page_num)); + if (tab == window->priv->active_tab) + return; + + /* set the active tab */ + window->priv->active_tab = tab; + + set_title (window); + set_sensitivity_according_to_tab (window, tab); + + /* activate the right item in the documents menu */ + action_name = g_strdup_printf ("Tab_%d", page_num); + action = gtk_action_group_get_action (window->priv->documents_list_action_group, + action_name); + + /* sometimes the action doesn't exist yet, and the proper action + * is set active during the documents list menu creation + * CHECK: would it be nicer if active_tab was a property and we monitored the notify signal? + */ + if (action != NULL) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + + g_free (action_name); + + /* update the syntax menu */ + update_languages_menu (window); + + view = gedit_tab_get_view (tab); + + /* sync the statusbar */ + update_cursor_position_statusbar (GTK_TEXT_BUFFER (gedit_tab_get_document (tab)), + window); + gedit_statusbar_set_overwrite (GEDIT_STATUSBAR (window->priv->statusbar), + gtk_text_view_get_overwrite (GTK_TEXT_VIEW (view))); + + g_signal_emit (G_OBJECT (window), + signals[ACTIVE_TAB_CHANGED], + 0, + window->priv->active_tab); +} + +static void +set_sensitivity_according_to_window_state (GeditWindow *window) +{ + GtkAction *action; + // GtkWidget *recent_file_menu; + + /* 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 = gtk_action_group_get_action (window->priv->action_group, + "FileQuit"); + gtk_action_set_sensitive (action, + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING) && + !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING)); + + action = gtk_action_group_get_action (window->priv->action_group, + "FileCloseAll"); + gtk_action_set_sensitive (action, + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING) && + !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING)); + + action = gtk_action_group_get_action (window->priv->action_group, + "FileSaveAll"); + gtk_action_set_sensitive (action, + !(window->priv->state & GEDIT_WINDOW_STATE_PRINTING)); + + action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, + "FileNew"); + gtk_action_set_sensitive (action, + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + + action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, + "FileOpen"); + gtk_action_set_sensitive (action, + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + + action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, + "FileOpenURI"); + gtk_action_set_sensitive (action, + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + + /* FIXME + recent_file_menu = gtk_ui_manager_get_widget (window->priv->manager, + "/MenuBar/FileMenu/FileRecentsPlaceholder"); + gtk_widget_set_sensitive (recent_file_menu, + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + */ + + gedit_notebook_set_close_buttons_sensitive (GEDIT_NOTEBOOK (window->priv->notebook), + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + + gedit_notebook_set_tab_drag_and_drop_enabled (GEDIT_NOTEBOOK (window->priv->notebook), + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + + if ((window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION) != 0) + { + // FIXME: View menu and Find should be active when in SAVING_SESSION state + + if (gtk_action_group_get_sensitive (window->priv->action_group)) + gtk_action_group_set_sensitive (window->priv->action_group, + FALSE); + } + else + { + if (!gtk_action_group_get_sensitive (window->priv->action_group)) + gtk_action_group_set_sensitive (window->priv->action_group, + window->priv->num_tabs > 0); + } +} + +static void +analyze_tab_state (GeditTab *tab, + GeditWindow *window) +{ + GeditTabState ts; + + ts = gedit_tab_get_state (tab); + + switch (ts) + { + case GEDIT_TAB_STATE_LOADING: + case GEDIT_TAB_STATE_REVERTING: + window->priv->state |= GEDIT_WINDOW_STATE_LOADING; + break; + + case GEDIT_TAB_STATE_SAVING: + window->priv->state |= GEDIT_WINDOW_STATE_SAVING; + break; + + case GEDIT_TAB_STATE_PRINTING: + case GEDIT_TAB_STATE_PRINT_PREVIEWING: + window->priv->state |= GEDIT_WINDOW_STATE_PRINTING; + break; + + case GEDIT_TAB_STATE_LOADING_ERROR: + case GEDIT_TAB_STATE_REVERTING_ERROR: + case GEDIT_TAB_STATE_SAVING_ERROR: + case GEDIT_TAB_STATE_GENERIC_ERROR: + window->priv->state |= GEDIT_WINDOW_STATE_ERROR; + ++window->priv->num_tabs_with_error; + default: + /* NOP */ + break; + } +} + +static void +update_window_state (GeditWindow *window) +{ + GeditWindowState old_ws; + gint old_num_of_errors; + + gedit_debug_message (DEBUG_WINDOW, "Old state: %x", window->priv->state); + + old_ws = window->priv->state; + old_num_of_errors = window->priv->num_tabs_with_error; + + window->priv->state = old_ws & GEDIT_WINDOW_STATE_SAVING_SESSION; + + window->priv->num_tabs_with_error = 0; + + gtk_container_foreach (GTK_CONTAINER (window->priv->notebook), + (GtkCallback)analyze_tab_state, + window); + + gedit_debug_message (DEBUG_WINDOW, "New state: %x", window->priv->state); + + if (old_ws != window->priv->state) + { + set_sensitivity_according_to_window_state (window); + + gedit_statusbar_set_window_state (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->state, + window->priv->num_tabs_with_error); + + g_object_notify (G_OBJECT (window), "state"); + } + else if (old_num_of_errors != window->priv->num_tabs_with_error) + { + gedit_statusbar_set_window_state (GEDIT_STATUSBAR (window->priv->statusbar), + window->priv->state, + window->priv->num_tabs_with_error); + } + +} + +static void +sync_state (GeditTab *tab, GParamSpec *pspec, GeditWindow *window) +{ + gedit_debug (DEBUG_WINDOW); + + update_window_state (window); + + if (tab != window->priv->active_tab) + return; + + set_sensitivity_according_to_tab (window, tab); + + g_signal_emit (G_OBJECT (window), signals[ACTIVE_TAB_STATE_CHANGED], 0); +} + +static void +sync_name (GeditTab *tab, GParamSpec *pspec, GeditWindow *window) +{ + GtkAction *action; + gchar *action_name; + gchar *tab_name; // CHECK escaping + gchar *tip; + gint n; + GeditDocument *doc; + + if (tab != window->priv->active_tab) + return; + + set_title (window); + + /* sync the item in the documents list menu */ + n = gtk_notebook_page_num (GTK_NOTEBOOK (window->priv->notebook), + GTK_WIDGET (tab)); + action_name = g_strdup_printf ("Tab_%d", n); + action = gtk_action_group_get_action (window->priv->documents_list_action_group, + action_name); + g_return_if_fail (action != NULL); + + tab_name = _gedit_tab_get_name (tab); + tip = g_strdup_printf (_("Activate %s"), tab_name); + + g_object_set (action, "label", tab_name, NULL); + g_object_set (action, "tooltip", tip, NULL); + + g_free (action_name); + g_free (tab_name); + g_free (tip); + + doc = gedit_tab_get_document (tab); + action = gtk_action_group_get_action (window->priv->action_group, + "FileRevert"); + gtk_action_set_sensitive (action, + !gedit_document_is_untitled (doc)); + + gedit_plugins_engine_update_plugins_ui (window, FALSE); +} + +static void +drag_data_received_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer data) +{ + GtkWidget *target_window; + gchar **uris; + GSList *uri_list = NULL; + gint i; + + if (info != TARGET_URI_LIST) + return; + + g_return_if_fail (widget != NULL); + + target_window = gtk_widget_get_toplevel (widget); + g_return_if_fail (GEDIT_IS_WINDOW (target_window)); + + if ((GEDIT_WINDOW(target_window)->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION) != 0) + return; + + uris = g_uri_list_extract_uris ((gchar *) selection_data->data); + + for (i = 0; uris[i] != NULL; i++) + uri_list = g_slist_prepend (uri_list, g_strdup (uris[i])); + + g_strfreev (uris); + + if (uri_list == NULL) + return; + + uri_list = g_slist_reverse (uri_list); + + gedit_cmd_load_files (GEDIT_WINDOW (target_window), + uri_list, + NULL); + + g_slist_foreach (uri_list, (GFunc) g_free, NULL); + g_slist_free (uri_list); +} + +/* + * Override the gtk_text_view_drag_motion and drag_drop + * functions to get URIs + * + * If the mime type is text/uri-list, then we will accept + * the potential drop, or request the data (depending on the + * function). + * + * If the drag context has any other mime type, then pass the + * information onto the GtkTextView's standard handlers. + * (widget_class->function_name). + * + * See bug #89881 for details + */ + +static gboolean +drag_motion_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GtkTargetList *tl; + GtkWidgetClass *widget_class; + gboolean result; + + tl = gtk_target_list_new (drag_types, + G_N_ELEMENTS (drag_types)); + + /* If this is a URL, deal with it here, or pass to the text view */ + if (gtk_drag_dest_find_target (widget, context, tl) != GDK_NONE) + { + gdk_drag_status (context, context->suggested_action, time); + result = TRUE; + } + else + { + widget_class = GTK_WIDGET_GET_CLASS (widget); + result = (*widget_class->drag_motion) (widget, context, x, y, time); + } + + gtk_target_list_unref (tl); + + return result; +} + +static gboolean +drag_drop_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GtkTargetList *tl; + GtkWidgetClass *widget_class; + gboolean result; + GdkAtom target; + + tl = gtk_target_list_new (drag_types, + G_N_ELEMENTS (drag_types)); + + /* If this is a URL, just get the drag data */ + target = gtk_drag_dest_find_target (widget, context, tl); + if (target != GDK_NONE) + { + gtk_drag_get_data (widget, context, target, time); + result = TRUE; + } + else + { + widget_class = GTK_WIDGET_GET_CLASS (widget); + result = (*widget_class->drag_drop) (widget, context, x, y, time); + } + + gtk_target_list_unref (tl); + + return result; +} + +static void +can_search_again (GeditDocument *doc, + GParamSpec *pspec, + GeditWindow *window) +{ + gboolean sensitive; + GtkAction *action; + + if (doc != gedit_window_get_active_document (window)) + return; + + sensitive = gedit_document_get_can_search_again (doc); + + action = gtk_action_group_get_action (window->priv->action_group, + "SearchFindNext"); + gtk_action_set_sensitive (action, sensitive); + + action = gtk_action_group_get_action (window->priv->action_group, + "SearchFindPrevious"); + gtk_action_set_sensitive (action, sensitive); +} + +static void +can_undo (GeditDocument *doc, + gboolean can, + GeditWindow *window) +{ + GtkAction *action; + + if (doc != gedit_window_get_active_document (window)) + return; + + action = gtk_action_group_get_action (window->priv->action_group, + "EditUndo"); + gtk_action_set_sensitive (action, can); +} + +static void +can_redo (GeditDocument *doc, + gboolean can, + GeditWindow *window) +{ + GtkAction *action; + + if (doc != gedit_window_get_active_document (window)) + return; + + action = gtk_action_group_get_action (window->priv->action_group, + "EditRedo"); + gtk_action_set_sensitive (action, can); +} + +static void +selection_changed (GeditDocument *doc, + GParamSpec *pspec, + GeditWindow *window) +{ + GeditTab *tab; + GtkAction *action; + GeditTabState state; + gboolean state_normal; + + gedit_debug (DEBUG_WINDOW); + + if (doc != gedit_window_get_active_document (window)) + return; + + tab = gedit_tab_get_from_document (doc); + state = gedit_tab_get_state (tab); + state_normal = (state == GEDIT_TAB_STATE_NORMAL); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditCut"); + gtk_action_set_sensitive (action, + state_normal && + _gedit_document_get_has_selection (doc)); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditCopy"); + gtk_action_set_sensitive (action, + state_normal && + _gedit_document_get_has_selection (doc)); + + action = gtk_action_group_get_action (window->priv->action_group, + "EditDelete"); + gtk_action_set_sensitive (action, + state_normal && + _gedit_document_get_has_selection (doc)); +} + +static void +sync_languages_menu (GeditDocument *doc, + GParamSpec *pspec, + GeditWindow *window) +{ + update_languages_menu (window); +} + +static void +update_default_path (GeditWindow *window, + GeditDocument *doc) +{ + gchar *uri; + + uri = gedit_document_get_uri (doc); + // CHECK: what does it happens when loading from stdin? - Paolo + g_return_if_fail (uri != NULL); + + if (gedit_utils_uri_has_file_scheme (uri)) + { + gchar *default_path; + + // CHECK: does it work with uri chaining? - Paolo + default_path = g_path_get_dirname (uri); + + g_return_if_fail (strlen (default_path) >= 5 /* strlen ("file:") */); + if (strcmp (default_path, "file:") == 0) + { + g_free (default_path); + + default_path = g_strdup ("file:///"); + } + + g_free (window->priv->default_path); + + window->priv->default_path = default_path; + + gedit_debug_message (DEBUG_WINDOW, + "New default path: %s", default_path); + } + + g_free (uri); +} + +static void +doc_loaded (GeditDocument *doc, + const GError *error, + GeditWindow *window) +{ + if (error != NULL) + { + gedit_debug_message (DEBUG_WINDOW, "Error"); + return; + } + + update_default_path (window, doc); +} + +static void +doc_saved (GeditDocument *doc, + const GError *error, + GeditWindow *window) +{ + if (error != NULL) + { + gedit_debug_message (DEBUG_WINDOW, "Error"); + return; + } + + if (!_gedit_document_is_saving_as (doc)) + { + gedit_debug_message (DEBUG_WINDOW, "Not saving as"); + return; + } + + update_default_path (window, doc); +} + +static void +notebook_tab_added (GeditNotebook *notebook, + GeditTab *tab, + GeditWindow *window) +{ + GeditView *view; + GeditDocument *doc; + GtkTargetList *tl; + GtkAction *action; + + gedit_debug (DEBUG_WINDOW); + + g_return_if_fail ((window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION) == 0); + + ++window->priv->num_tabs; + + /* Set sensitivity */ + if (!gtk_action_group_get_sensitive (window->priv->action_group)) + gtk_action_group_set_sensitive (window->priv->action_group, + TRUE); + + action = gtk_action_group_get_action (window->priv->action_group, + "DocumentsMoveToNewWindow"); + gtk_action_set_sensitive (action, + window->priv->num_tabs > 1); + + + view = gedit_tab_get_view (tab); + doc = gedit_tab_get_document (tab); + + /* 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 (doc, + "cursor-moved", + G_CALLBACK (update_cursor_position_statusbar), + window); + g_signal_connect (doc, + "notify::can-search-again", + G_CALLBACK (can_search_again), + window); + g_signal_connect (doc, + "can-undo", + G_CALLBACK (can_undo), + window); + g_signal_connect (doc, + "can-redo", + G_CALLBACK (can_redo), + window); + g_signal_connect (doc, + "notify::has-selection", + G_CALLBACK (selection_changed), + window); + g_signal_connect (doc, + "notify::language", + G_CALLBACK (sync_languages_menu), + window); + g_signal_connect (doc, + "loaded", + G_CALLBACK (doc_loaded), + window); + g_signal_connect (doc, + "saved", + G_CALLBACK (doc_saved), + window); + g_signal_connect (view, + "toggle_overwrite", + G_CALLBACK (update_overwrite_mode_statusbar), + window); + + update_documents_list_menu (window); + + /* CHECK: it seems to me this does not work when tab are moved between + windows */ + /* Drag and drop support */ + tl = gtk_drag_dest_get_target_list (GTK_WIDGET (view)); + g_return_if_fail (tl != NULL); + + gtk_target_list_add_table (tl, drag_types, G_N_ELEMENTS (drag_types)); + + g_signal_connect (view, + "drag_data_received", + G_CALLBACK (drag_data_received_cb), + NULL); + + /* Get signals before the standard text view functions to deal + * with uris for text files. + */ + g_signal_connect (view, + "drag_motion", + G_CALLBACK (drag_motion_cb), + NULL); + g_signal_connect (view, + "drag_drop", + G_CALLBACK (drag_drop_cb), + NULL); + + update_window_state (window); + + g_signal_emit (G_OBJECT (window), signals[TAB_ADDED], 0, tab); +} + +static void +notebook_tab_removed (GeditNotebook *notebook, + GeditTab *tab, + GeditWindow *window) +{ + GeditView *view; + GeditDocument *doc; + GtkAction *action; + + gedit_debug (DEBUG_WINDOW); + + g_return_if_fail ((window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION) == 0); + + --window->priv->num_tabs; + + view = gedit_tab_get_view (tab); + doc = gedit_tab_get_document (tab); + + g_signal_handlers_disconnect_by_func (tab, + G_CALLBACK (sync_name), + window); + g_signal_handlers_disconnect_by_func (tab, + G_CALLBACK (sync_state), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (update_cursor_position_statusbar), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (can_search_again), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (can_undo), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (can_redo), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (selection_changed), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (sync_languages_menu), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (doc_loaded), + window); + g_signal_handlers_disconnect_by_func (doc, + G_CALLBACK (doc_saved), + window); + g_signal_handlers_disconnect_by_func (view, + G_CALLBACK (update_overwrite_mode_statusbar), + window); + g_signal_handlers_disconnect_by_func (view, + G_CALLBACK (drag_data_received_cb), + NULL); + g_signal_handlers_disconnect_by_func (view, + G_CALLBACK (drag_motion_cb), + NULL); + g_signal_handlers_disconnect_by_func (view, + G_CALLBACK (drag_drop_cb), + NULL); + + g_return_if_fail (window->priv->num_tabs >= 0); + if (window->priv->num_tabs == 0) + { + GeditApp *app; + + app = gedit_app_get_default (); + + window->priv->active_tab = NULL; + + set_title (window); + + /* Remove line and col info */ + gedit_statusbar_set_cursor_position ( + GEDIT_STATUSBAR (window->priv->statusbar), + -1, + -1); + + gedit_statusbar_clear_overwrite ( + GEDIT_STATUSBAR (window->priv->statusbar)); + } + + if (!window->priv->removing_tabs) + { + update_documents_list_menu (window); + } + else + { + if (window->priv->num_tabs == 0) + update_documents_list_menu (window); + } + + /* Set sensitivity */ + if (window->priv->num_tabs == 0) + { + if (gtk_action_group_get_sensitive (window->priv->action_group)) + gtk_action_group_set_sensitive (window->priv->action_group, + FALSE); + + // FIXME: Quit and the view menu should be active + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewHighlightMode"); + + gtk_action_set_sensitive (action, FALSE); + + gedit_plugins_engine_update_plugins_ui (window, FALSE); + } + + if (window->priv->num_tabs <= 1) + { + action = gtk_action_group_get_action (window->priv->action_group, + "DocumentsMoveToNewWindow"); + gtk_action_set_sensitive (action, + FALSE); + } + + update_window_state (window); + + g_signal_emit (G_OBJECT (window), signals[TAB_REMOVED], 0, tab); +} + +static void +notebook_tabs_reordered (GeditNotebook *notebook, + GeditWindow *window) +{ + update_documents_list_menu (window); + + g_signal_emit (G_OBJECT (window), signals[TABS_REORDERED], 0); +} + +static void +notebook_tab_detached (GeditNotebook *notebook, + GeditTab *tab, + GeditWindow *window) +{ + GeditWindow *new_window; + + new_window = clone_window (window); + + gedit_notebook_move_tab (notebook, + GEDIT_NOTEBOOK (_gedit_window_get_notebook (new_window)), + tab, 0); + + gtk_window_set_position (GTK_WINDOW (new_window), + GTK_WIN_POS_MOUSE); + + gtk_widget_show (GTK_WIDGET (new_window)); +} + +static void +notebook_tab_close_request (GeditNotebook *notebook, + GeditTab *tab, + GtkWindow *window) +{ + /* CHECK: we are destroying the tab before the default handler + * seems to be ok, but we need to keep an eye on this. */ + _gedit_cmd_file_close_tab (tab, GEDIT_WINDOW (window)); +} + +static gboolean +show_notebook_popup_menu (GtkNotebook *notebook, + GeditWindow *window, + GdkEventButton *event) +{ + GtkWidget *menu; +// GtkAction *action; + + menu = gtk_ui_manager_get_widget (window->priv->manager, "/NotebookPopup"); + g_return_val_if_fail (menu != NULL, FALSE); + +// CHECK do we need this? +#if 0 + /* allow extensions to sync when showing the popup */ + action = gtk_action_group_get_action (window->priv->action_group, + "NotebookPopupAction"); + g_return_val_if_fail (action != NULL, FALSE); + gtk_action_activate (action); +#endif + if (event != NULL) + { + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + NULL, NULL, + event->button, event->time); + } + else + { + GtkWidget *tab; + GtkWidget *tab_label; + + tab = GTK_WIDGET (gedit_window_get_active_tab (window)); + g_return_val_if_fail (tab != NULL, FALSE); + + tab_label = gtk_notebook_get_tab_label (notebook, tab); + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + gedit_utils_menu_position_under_widget, tab_label, + 0, gtk_get_current_event_time ()); + + gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE); + } + + return TRUE; +} + +static gboolean +notebook_button_press_event (GtkNotebook *notebook, + GdkEventButton *event, + GeditWindow *window) +{ + if (GDK_BUTTON_PRESS == event->type && 3 == event->button) + { + return show_notebook_popup_menu (notebook, window, event); + } + + return FALSE; +} + +static gboolean +notebook_popup_menu (GtkNotebook *notebook, + GeditWindow *window) +{ + /* Only respond if the notebook is the actual focus */ + if (GEDIT_IS_NOTEBOOK (gtk_window_get_focus (GTK_WINDOW (window)))) + { + return show_notebook_popup_menu (notebook, window, NULL); + } + + return FALSE; +} + +static void +side_panel_size_allocate (GtkWidget *widget, + GtkAllocation *allocation, + GeditWindow *window) +{ + window->priv->side_panel_size = allocation->width; +} + +static void +side_panel_hide (GtkWidget *panel, + GeditWindow *window) +{ + _gedit_window_set_side_panel_visible (window, FALSE); +} + +static void +create_side_panel (GeditWindow *window) +{ + GtkAction *action; + gboolean visible; + GtkWidget *documents_panel; + + gedit_debug (DEBUG_WINDOW); + + window->priv->side_panel = gedit_panel_new (); + + gtk_paned_pack1 (GTK_PANED (window->priv->hpaned), + window->priv->side_panel, + FALSE, + FALSE); + gtk_widget_set_size_request (window->priv->side_panel, 100, -1); + + g_signal_connect (window->priv->side_panel, + "size_allocate", + G_CALLBACK (side_panel_size_allocate), + window); + + g_signal_connect (window->priv->side_panel, + "hide", + G_CALLBACK (side_panel_hide), + window); + + gtk_paned_set_position (GTK_PANED (window->priv->hpaned), + MAX (100, gedit_prefs_manager_get_side_panel_size ())); + + documents_panel = gedit_documents_panel_new (window); + gedit_panel_add_item_with_stock_icon (GEDIT_PANEL (window->priv->side_panel), + documents_panel, + "Documents", + GTK_STOCK_FILE); + + visible = gedit_prefs_manager_get_side_pane_visible (); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewSidePane"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + if (visible) + gtk_widget_show (window->priv->side_panel); +} + +static void +bottom_panel_size_allocate (GtkWidget *widget, + GtkAllocation *allocation, + GeditWindow *window) +{ + window->priv->bottom_panel_size = allocation->height; +} + +static void +bottom_panel_hide (GtkWidget *panel, + GeditWindow *window) +{ + _gedit_window_set_bottom_panel_visible (window, FALSE); +} + +static void +create_bottom_panel (GeditWindow *window) +{ + GtkAction *action; + gboolean visible; + + gedit_debug (DEBUG_WINDOW); + + window->priv->bottom_panel = gedit_panel_new (); + gtk_paned_pack2 (GTK_PANED (window->priv->vpaned), + window->priv->bottom_panel, + FALSE, + FALSE); + + g_signal_connect (window->priv->bottom_panel, + "size_allocate", + G_CALLBACK (bottom_panel_size_allocate), + window); + + g_signal_connect (window->priv->bottom_panel, + "hide", + G_CALLBACK (bottom_panel_hide), + window); + + gtk_paned_set_position (GTK_PANED (window->priv->vpaned), + gedit_prefs_manager_get_bottom_panel_size ()); // CHECK set a min height as we do for the sidepane? + + visible = gedit_prefs_manager_get_bottom_panel_visible(); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewBottomPanel"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + if(visible) + gtk_widget_show_all (window->priv->bottom_panel); +} + +static void +gedit_window_init (GeditWindow *window) +{ + GtkWidget *main_box; + + gedit_debug (DEBUG_WINDOW); + + window->priv = GEDIT_WINDOW_GET_PRIVATE (window); + window->priv->active_tab = NULL; + window->priv->num_tabs = 0; + window->priv->removing_tabs = FALSE; + window->priv->state = GEDIT_WINDOW_STATE_NORMAL; + + window->priv->window_group = gtk_window_group_new (); + gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window)); + + main_box = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window), main_box); + gtk_widget_show (main_box); + + /* Add menu bar and toolbar bar */ + gedit_debug_message (DEBUG_WINDOW, "Add menu bar and toolbar bar"); + create_menu_bar_and_toolbar (window, main_box); + + /* Add status bar */ + gedit_debug_message (DEBUG_WINDOW, "Add statusbar"); + create_statusbar (window, main_box); + + /* Add the main area */ + gedit_debug_message (DEBUG_WINDOW, "Add main area"); + window->priv->hpaned = gtk_hpaned_new (); + gtk_box_pack_start (GTK_BOX (main_box), + window->priv->hpaned, + TRUE, + TRUE, + 0); + gtk_widget_show (window->priv->hpaned); + + gedit_debug_message (DEBUG_WINDOW, "Create side panel"); + create_side_panel (window); + + window->priv->vpaned = gtk_vpaned_new (); + gtk_paned_pack2 (GTK_PANED (window->priv->hpaned), + window->priv->vpaned, + TRUE, + FALSE); + gtk_widget_show (window->priv->vpaned); + + gedit_debug_message (DEBUG_WINDOW, "Create gedit notebook"); + window->priv->notebook = gedit_notebook_new (); + gtk_paned_pack1 (GTK_PANED (window->priv->vpaned), + window->priv->notebook, + FALSE, + TRUE); + gtk_widget_show (window->priv->notebook); + + gedit_debug_message (DEBUG_WINDOW, "Create bottom panel"); + create_bottom_panel (window); + + /* Set visibility of panels */ + // TODO + + gedit_debug_message (DEBUG_WINDOW, "Connect signals"); + /* Drag and drop support */ + gtk_drag_dest_set (GTK_WIDGET (window), + GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_HIGHLIGHT | + GTK_DEST_DEFAULT_DROP, + drag_types, + G_N_ELEMENTS (drag_types), + GDK_ACTION_COPY); + + /* Connect signals */ + g_signal_connect (window->priv->notebook, + "switch_page", + G_CALLBACK (notebook_switch_page), + window); + g_signal_connect (window->priv->notebook, + "tab_added", + G_CALLBACK (notebook_tab_added), + window); + g_signal_connect (window->priv->notebook, + "tab_removed", + G_CALLBACK (notebook_tab_removed), + window); + g_signal_connect (window->priv->notebook, + "tabs_reordered", + G_CALLBACK (notebook_tabs_reordered), + window); + g_signal_connect (window->priv->notebook, + "tab_detached", + G_CALLBACK (notebook_tab_detached), + window); + g_signal_connect (window->priv->notebook, + "tab_close_request", + G_CALLBACK (notebook_tab_close_request), + window); + g_signal_connect (window->priv->notebook, + "button-press-event", + G_CALLBACK (notebook_button_press_event), + window); + g_signal_connect (window->priv->notebook, + "popup-menu", + G_CALLBACK (notebook_popup_menu), + window); + + /* connect instead pf 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); + + gedit_debug_message (DEBUG_WINDOW, "Update plugins ui"); + gedit_plugins_engine_update_plugins_ui (window, TRUE); + + gedit_debug_message (DEBUG_WINDOW, "END"); +} + +GeditView * +gedit_window_get_active_view (GeditWindow *window) +{ + GeditView *view; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + if (window->priv->active_tab == NULL) + return NULL; + + view = gedit_tab_get_view (GEDIT_TAB (window->priv->active_tab)); + + return view; +} + +GeditDocument * +gedit_window_get_active_document (GeditWindow *window) +{ + GeditView *view; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + view = gedit_window_get_active_view (window); + if (view == NULL) + return NULL; + + return GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); +} + +GtkWidget * +_gedit_window_get_notebook (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return window->priv->notebook; +} + +GeditTab * +gedit_window_create_tab (GeditWindow *window, + gboolean jump_to) +{ + GeditTab *tab; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + tab = GEDIT_TAB (_gedit_tab_new ()); + gtk_widget_show (GTK_WIDGET (tab)); + + gedit_notebook_add_tab (GEDIT_NOTEBOOK (window->priv->notebook), + tab, + -1, + jump_to); + + return tab; +} + +GeditTab * +gedit_window_create_tab_from_uri (GeditWindow *window, + const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create, + gboolean jump_to) +{ + GtkWidget *tab; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + g_return_val_if_fail (uri != NULL, NULL); + + tab = _gedit_tab_new_from_uri (uri, + encoding, + line_pos, + create); + if (tab == NULL) + return NULL; + + gtk_widget_show (tab); + + gedit_notebook_add_tab (GEDIT_NOTEBOOK (window->priv->notebook), + GEDIT_TAB (tab), + -1, + jump_to); + + return GEDIT_TAB (tab); +} + +GeditTab * +gedit_window_get_active_tab (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return (window->priv->active_tab == NULL) ? + NULL : GEDIT_TAB (window->priv->active_tab); +} + +static void +add_document (GeditTab *tab, GList **res) +{ + GeditDocument *doc; + + doc = gedit_tab_get_document (tab); + + *res = g_list_prepend (*res, doc); +} + +/* Returns a newly allocated list with all the documents in the window */ +GList * +gedit_window_get_documents (GeditWindow *window) +{ + GList *res = NULL; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + gtk_container_foreach (GTK_CONTAINER (window->priv->notebook), + (GtkCallback)add_document, + &res); + + res = g_list_reverse (res); + + return res; +} + +static void +add_view (GeditTab *tab, GList **res) +{ + GeditView *view; + + view = gedit_tab_get_view (tab); + + *res = g_list_prepend (*res, view); +} + +/* Returns a newly allocated list with all the views in the window */ +GList * +gedit_window_get_views (GeditWindow *window) +{ + GList *res = NULL; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + gtk_container_foreach (GTK_CONTAINER (window->priv->notebook), + (GtkCallback)add_view, + &res); + + res = g_list_reverse (res); + + return res; +} + +void +gedit_window_close_tab (GeditWindow *window, + GeditTab *tab) +{ + g_return_if_fail (GEDIT_IS_WINDOW (window)); + g_return_if_fail (GEDIT_IS_TAB (tab)); + g_return_if_fail ((gedit_tab_get_state (tab) != GEDIT_TAB_STATE_SAVING) && + (gedit_tab_get_state (tab) != GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)); + + gedit_notebook_remove_tab (GEDIT_NOTEBOOK (window->priv->notebook), + tab); +} + +// CHECK: these should be priv? pbor. +void +gedit_window_close_all_tabs (GeditWindow *window) +{ + g_return_if_fail (GEDIT_IS_WINDOW (window)); + g_return_if_fail (!(window->priv->state & GEDIT_WINDOW_STATE_SAVING) && + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + + window->priv->removing_tabs = TRUE; + + gedit_notebook_remove_all_tabs (GEDIT_NOTEBOOK (window->priv->notebook)); + + window->priv->removing_tabs = FALSE; +} + +void +gedit_window_close_tabs (GeditWindow *window, + const GList *tabs) +{ + g_return_if_fail (GEDIT_IS_WINDOW (window)); + g_return_if_fail (!(window->priv->state & GEDIT_WINDOW_STATE_SAVING) && + !(window->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION)); + + if (tabs == NULL) + return; + + window->priv->removing_tabs = TRUE; + + while (tabs != NULL) + { + if (tabs->next == NULL) + window->priv->removing_tabs = FALSE; + + gedit_notebook_remove_tab (GEDIT_NOTEBOOK (window->priv->notebook), + GEDIT_TAB (tabs->data)); + + tabs = g_list_next (tabs); + } + + g_return_if_fail (window->priv->removing_tabs == FALSE); +} + +void +_gedit_window_set_statusbar_visible (GeditWindow *window, + gboolean visible) +{ + GtkAction *action; + static gboolean recursione_guard = FALSE; + + gedit_debug (DEBUG_WINDOW); + + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + if (recursione_guard) + return; + + recursione_guard = TRUE; + + visible = (visible != FALSE); + + if (visible) + gtk_widget_show (window->priv->statusbar); + else + gtk_widget_hide (window->priv->statusbar); + + if (gedit_prefs_manager_statusbar_visible_can_set ()) + gedit_prefs_manager_set_statusbar_visible (visible); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewStatusbar"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + recursione_guard = FALSE; +} + +void +_gedit_window_set_toolbar_visible (GeditWindow *window, + gboolean visible) +{ + GtkAction *action; + static gboolean recursione_guard = FALSE; + + gedit_debug (DEBUG_WINDOW); + + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + if (recursione_guard) + return; + + recursione_guard = TRUE; + + visible = (visible != FALSE); + + if (visible) + gtk_widget_show (window->priv->toolbar); + else + gtk_widget_hide (window->priv->toolbar); + + if (gedit_prefs_manager_toolbar_visible_can_set ()) + gedit_prefs_manager_set_toolbar_visible (visible); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewToolbar"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + recursione_guard = FALSE; +} + +void +_gedit_window_set_side_panel_visible (GeditWindow *window, + gboolean visible) +{ + GtkAction *action; + static gboolean recursion_guard = FALSE; + gboolean show = FALSE; + + gedit_debug (DEBUG_WINDOW); + + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + if (recursion_guard) + return; + + recursion_guard = TRUE; + + visible = (visible != FALSE); + + if (visible && + (GTK_WIDGET_VISIBLE (window->priv->side_panel) != visible)) + { + gtk_widget_show (window->priv->side_panel); + show = TRUE; + } + else + { + gtk_widget_hide (window->priv->side_panel); + if (window->priv->active_tab) + gtk_widget_grab_focus (GTK_WIDGET ( + gedit_tab_get_view (GEDIT_TAB (window->priv->active_tab)))); + } + + if (gedit_prefs_manager_side_pane_visible_can_set ()) + gedit_prefs_manager_set_side_pane_visible (visible); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewSidePane"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + if (show) + { + /* g_print ("GRAB side panel\n"); */ + gtk_widget_grab_focus (window->priv->side_panel); + } + + recursion_guard = FALSE; +} + +void +_gedit_window_set_bottom_panel_visible (GeditWindow *window, + gboolean visible) +{ + GtkAction *action; + static gboolean recursion_guard = FALSE; + gboolean show = FALSE; + + gedit_debug (DEBUG_WINDOW); + + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + if (recursion_guard) + return; + + recursion_guard = TRUE; + + visible = (visible != FALSE); + + if (visible && + (GTK_WIDGET_VISIBLE (window->priv->bottom_panel) != visible)) + { + gtk_widget_show (window->priv->bottom_panel); + show = TRUE; + } + else + { + gtk_widget_hide (window->priv->bottom_panel); + if (window->priv->active_tab) + gtk_widget_grab_focus (GTK_WIDGET ( + gedit_tab_get_view (GEDIT_TAB (window->priv->active_tab)))); + } + + if (gedit_prefs_manager_bottom_panel_visible_can_set ()) + gedit_prefs_manager_set_bottom_panel_visible (visible); + + action = gtk_action_group_get_action (window->priv->action_group, + "ViewBottomPanel"); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible) + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible); + + if (show) + { + /* g_print ("GRAB bottom panel\n"); */ + gtk_widget_grab_focus (window->priv->bottom_panel); + } + + recursion_guard = FALSE; +} + +GeditWindow * +_gedit_window_move_tab_to_new_window (GeditWindow *window, + GeditTab *tab) +{ + GeditWindow *new_window; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL); + g_return_val_if_fail (gtk_notebook_get_n_pages ( + GTK_NOTEBOOK (window->priv->notebook)) > 1, + NULL); + + new_window = clone_window (window); + + gedit_notebook_move_tab (GEDIT_NOTEBOOK (window->priv->notebook), + GEDIT_NOTEBOOK (new_window->priv->notebook), + tab, + -1); + + gtk_widget_show (GTK_WIDGET (new_window)); + + return new_window; +} + +void +gedit_window_set_active_tab (GeditWindow *window, + GeditTab *tab) +{ + gint page_num; + + g_return_if_fail (GEDIT_IS_WINDOW (window)); + g_return_if_fail (GEDIT_IS_TAB (tab)); + + page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->priv->notebook), + GTK_WIDGET (tab)); + g_return_if_fail (page_num != -1); + + gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook), + page_num); +} + +GtkWindowGroup * +gedit_window_get_group (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return window->priv->window_group; +} + +gboolean +_gedit_window_is_removing_tabs (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), FALSE); + + return window->priv->removing_tabs; +} + +GtkUIManager * +gedit_window_get_ui_manager (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return window->priv->manager; +} + +GeditPanel * +gedit_window_get_side_panel (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return GEDIT_PANEL (window->priv->side_panel); +} + +GeditPanel * +gedit_window_get_bottom_panel (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return GEDIT_PANEL (window->priv->bottom_panel); +} + +GtkWidget * +gedit_window_get_statusbar (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), 0); + + return window->priv->statusbar; +} + +GeditWindowState +gedit_window_get_state (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), GEDIT_WINDOW_STATE_NORMAL); + + return window->priv->state; +} + +G_CONST_RETURN gchar * +_gedit_window_get_default_path (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return window->priv->default_path; +} + +/* Returns the documents that need to be saved before closing the window */ +GList * +gedit_window_get_unsaved_documents (GeditWindow *window) +{ + GList *unsaved_docs = NULL; + GList *docs; + GList *l; + + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + docs = gedit_window_get_documents (window); + + for (l = docs; l != NULL; l = l->next) + { + GeditTab *tab; + GeditDocument *doc; + + doc = GEDIT_DOCUMENT (l->data); + tab = gedit_tab_get_from_document (doc); + + if (!_gedit_tab_can_close (tab)) + unsaved_docs = g_list_prepend (unsaved_docs, doc); + } + + g_list_free (docs); + + return g_list_reverse (unsaved_docs); +} + +void +_gedit_window_set_saving_session_state (GeditWindow *window, + gboolean saving_session) +{ + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + GeditWindowState old_state = window->priv->state; + + if (saving_session) + window->priv->state |= GEDIT_WINDOW_STATE_SAVING_SESSION; + else + window->priv->state &= ~GEDIT_WINDOW_STATE_SAVING_SESSION; + + if (old_state != window->priv->state) + { + set_sensitivity_according_to_window_state (window); + + g_object_notify (G_OBJECT (window), "state"); + } +} + diff --git a/gedit/gedit-window.h b/gedit/gedit-window.h new file mode 100644 index 00000000..dea1235b --- /dev/null +++ b/gedit/gedit-window.h @@ -0,0 +1,180 @@ +/* + * gedit-window.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_WINDOW_H__ +#define __GEDIT_WINDOW_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +typedef enum +{ + GEDIT_WINDOW_STATE_NORMAL = 0, + GEDIT_WINDOW_STATE_SAVING = 1 << 1, + GEDIT_WINDOW_STATE_PRINTING = 1 << 2, + GEDIT_WINDOW_STATE_LOADING = 1 << 3, + GEDIT_WINDOW_STATE_ERROR = 1 << 4, + GEDIT_WINDOW_STATE_SAVING_SESSION = 1 << 5 +} GeditWindowState; + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_WINDOW (gedit_window_get_type()) +#define GEDIT_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_WINDOW, GeditWindow)) +#define GEDIT_WINDOW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_WINDOW, GeditWindow const)) +#define GEDIT_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_WINDOW, GeditWindowClass)) +#define GEDIT_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_WINDOW)) +#define GEDIT_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_WINDOW)) +#define GEDIT_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_WINDOW, GeditWindowClass)) + +/* Private structure type */ +typedef struct _GeditWindowPrivate GeditWindowPrivate; + +/* + * Main object structure + */ +typedef struct _GeditWindow GeditWindow; + +struct _GeditWindow +{ + GtkWindow window; + + /*< private > */ + GeditWindowPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditWindowClass GeditWindowClass; + +struct _GeditWindowClass +{ + GtkWindowClass parent_class; + + /* Signals */ + void (* tab_added) (GeditWindow *window, + GeditTab *tab); + void (* tab_removed) (GeditWindow *window, + GeditTab *tab); + void (* tabs_reordered) (GeditWindow *window); + void (* active_tab_changed) (GeditWindow *window, + GeditTab *tab); + void (* active_tab_state_changed) + (GeditWindow *window); +}; + +/* + * Public methods + */ +GType gedit_window_get_type (void) G_GNUC_CONST; + +GeditTab *gedit_window_create_tab (GeditWindow *window, + gboolean jump_to); + +GeditTab *gedit_window_create_tab_from_uri (GeditWindow *window, + const gchar *uri, + const GeditEncoding *encoding, + gint line_pos, + gboolean create, + gboolean jump_to); + +void gedit_window_close_tab (GeditWindow *window, + GeditTab *tab); + +void gedit_window_close_all_tabs (GeditWindow *window); + +void gedit_window_close_tabs (GeditWindow *window, + const GList *tabs); + +GeditTab *gedit_window_get_active_tab (GeditWindow *window); + +void gedit_window_set_active_tab (GeditWindow *window, + GeditTab *tab); + +/* Helper functions */ +GeditView *gedit_window_get_active_view (GeditWindow *window); +GeditDocument *gedit_window_get_active_document (GeditWindow *window); + +/* Returns a newly allocated list with all the documents in the window */ +GList *gedit_window_get_documents (GeditWindow *window); + +/* Returns a newly allocated list with all the documents that need to be + saved before closing the window */ +GList *gedit_window_get_unsaved_documents (GeditWindow *window); + +/* Returns a newly allocated list with all the views in the window */ +GList *gedit_window_get_views (GeditWindow *window); + +GtkWindowGroup *gedit_window_get_group (GeditWindow *window); + +GeditPanel *gedit_window_get_side_panel (GeditWindow *window); + +GeditPanel *gedit_window_get_bottom_panel (GeditWindow *window); + +GtkWidget *gedit_window_get_statusbar (GeditWindow *window); + +GtkUIManager *gedit_window_get_ui_manager (GeditWindow *window); + +GeditWindowState gedit_window_get_state (GeditWindow *window); + +/* + * Non exported functions + */ +GtkWidget *_gedit_window_get_notebook (GeditWindow *window); + +void _gedit_window_set_statusbar_visible (GeditWindow *window, + gboolean visible); +void _gedit_window_set_toolbar_visible (GeditWindow *window, + gboolean visible); +void _gedit_window_set_side_panel_visible (GeditWindow *window, + gboolean visible); +void _gedit_window_set_bottom_panel_visible (GeditWindow *window, + gboolean visible); +GeditWindow *_gedit_window_move_tab_to_new_window (GeditWindow *window, + GeditTab *tab); +gboolean _gedit_window_is_removing_tabs (GeditWindow *window); + +GtkWidget *_gedit_window_get_search_panel (GeditWindow *window); + +G_CONST_RETURN gchar + *_gedit_window_get_default_path (GeditWindow *window); + +void _gedit_window_set_saving_session_state (GeditWindow *window, + gboolean saving_session); + +G_END_DECLS + +#endif /* __GEDIT_WINDOW_H__ */ diff --git a/gedit/gedit.c b/gedit/gedit.c new file mode 100644 index 00000000..3c0fc6b8 --- /dev/null +++ b/gedit/gedit.c @@ -0,0 +1,547 @@ +/* + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include "gedit-app.h" +#include "gedit-commands.h" +#include "gedit-convert.h" +#include "gedit-debug.h" +#include "gedit-encodings.h" +#include "gedit-metadata-manager.h" +#include "gedit-plugins-engine.h" +#include "gedit-prefs-manager-app.h" +#include "gedit-recent.h" +#include "gedit-session.h" +#include "gedit-utils.h" +#include "gedit-window.h" + +#include "bacon-message-connection.h" + +static guint32 startup_timestamp = 0; +static BaconMessageConnection *connection; + +/* command line */ +static gint line_position = 0; +static gchar *encoding_charset = NULL; +static const GeditEncoding *encoding; +static gboolean new_window_option = FALSE; +static gboolean new_document_option = FALSE; +static GSList *file_list = NULL; + +static const struct poptOption options [] = +{ + { "encoding", '\0', POPT_ARG_STRING, &encoding_charset, 0, + N_("Set the character encoding to be used to open the files listed on the command line"), NULL }, + + { "new-window", '\0', POPT_ARG_NONE, &new_window_option, 0, + N_("Create a new toplevel window in an existing instance of gedit"), NULL }, + + { "new-document", '\0', POPT_ARG_NONE, &new_document_option, 0, + N_("Create a new document in an existing instance of gedit"), NULL }, + + {NULL, '\0', 0, NULL, 0} +}; + +static void +gedit_get_command_line_data (GnomeProgram *program) +{ + GValue value = { 0, }; + poptContext ctx; + gchar **args; + + g_value_init (&value, G_TYPE_POINTER); + g_object_get_property (G_OBJECT (program), + GNOME_PARAM_POPT_CONTEXT, + &value); + ctx = g_value_get_pointer (&value); + g_value_unset (&value); + + args = (gchar **) poptGetArgs(ctx); + + if (args) + { + gint i; + + for (i = 0; args[i]; i++) + { + if (*args[i] == '+') + { + if (*(args[i] + 1) == '\0') + /* goto the last line of the document */ + line_position = G_MAXINT; + else + line_position = atoi (args[i] + 1); + } + else + { + gchar *uri; + gchar *canonical_uri; + + /* Note for the future: + * + * paolo: and flame whoever tells + * you that file:///gnome/test_files/hëllò + * doesn't work --- that's not a valid URI + * + * federico: well, another solution that + * does not requires patch to _from_shell_args + * is to check that the string returned by it + * contains only ASCII chars + * paolo: hmmmm, isn't there + * gnome_vfs_is_uri_valid() or something? + * : I will use gedit_utils_is_valid_uri () + * + */ + + uri = gnome_vfs_make_uri_from_shell_arg (args[i]); + canonical_uri = gnome_vfs_make_uri_canonical (uri); + g_free (uri); + + g_print ("URI: %s\n", canonical_uri); + + if (gedit_utils_is_valid_uri (canonical_uri)) + file_list = g_slist_prepend (file_list, + canonical_uri); + else + g_print (_("%s: malformed file name or URI.\n"), + args[i]); + } + } + + file_list = g_slist_reverse (file_list); + } + + if (encoding_charset) + { + encoding = gedit_encoding_get_from_charset (encoding_charset); + if (encoding == NULL) + g_print (_("%s: invalid encoding.\n"), + encoding_charset); + + g_free (encoding_charset); + encoding_charset = NULL; + } + + poptFreeContext (ctx); +} + +static guint32 +get_startup_timestamp () +{ + const gchar *startup_id_env; + gchar *startup_id = NULL; + gchar *time_str; + gchar *end; + gulong retval = 0; + + /* we don't unset the env, since startup-notification + * may still need it */ + startup_id_env = g_getenv ("DESKTOP_STARTUP_ID"); + if (startup_id_env == NULL) + goto out; + + startup_id = g_strdup (startup_id_env); + + time_str = g_strrstr (startup_id, "_TIME"); + if (time_str == NULL) + goto out; + + errno = 0; + + /* Skip past the "_TIME" part */ + time_str += 5; + + retval = strtoul (time_str, &end, 0); + if (end == time_str || errno != 0) + retval = 0; + + out: + g_free (startup_id); + + return (retval > 0) ? retval : 0; +} + +/* serverside */ +static void +on_message_received (const char *message, + gpointer data) +{ + gchar **commands; + gchar **params; + gint workspace; + gint i; + GeditApp *app; + GeditWindow *window; + + g_return_if_fail (message != NULL); + + gedit_debug_message (DEBUG_APP, "Received message:\n%s\n", message); + + commands = g_strsplit (message, "\v", -1); + + /* header */ + params = g_strsplit (commands[0], "\t", 2); + startup_timestamp = atoi (params[0]); //CHECK if this is safe + workspace = atoi (params[1]); + g_strfreev (params); + + /* body */ + i = 1; + while (commands[i]) + { + params = g_strsplit (commands[i], "\t", -1); + + if (strcmp (params[0], "NEW-WINDOW") == 0) + { + new_window_option = TRUE; + } + else if (strcmp (params[0], "NEW-DOCUMENT") == 0) + { + new_document_option = TRUE; + } + else if (strcmp (params[0], "OPEN-URIS") == 0) + { + gint n_uris, i; + gchar **uris; + + line_position = atoi (params[1]); + if (params[2] != '\0'); + encoding = gedit_encoding_get_from_charset (params[2]); + + n_uris = atoi (params[3]); + uris = g_strsplit (params[4], " ", n_uris); + + for (i = 0; i < n_uris; i++) + file_list = g_slist_prepend (file_list, uris[i]); + file_list = g_slist_reverse (file_list); + + /* the list takes ownerhip of the strings, + * only free the array */ + g_free (uris); + } + else + { + g_warning ("Unexpected bacon command"); + } + + g_strfreev (params); + ++i; + } + + g_strfreev (commands); + + /* execute the commands */ + + app = gedit_app_get_default (); + + if (new_window_option) + { + window = gedit_app_create_window (app); + } + else + { + /* get a window in the current workspace (if exists) and raise it */ + window = _gedit_app_get_window_in_workspace (app, workspace); + } + + /* set the proper interaction time on the window. + * fall back to roundtripping to the X server. lame. */ + if (startup_timestamp <= 0) + { + if (!GTK_WIDGET_REALIZED (window)) + gtk_widget_realize (GTK_WIDGET (window)); + + startup_timestamp = gdk_x11_get_server_time (GTK_WIDGET (window)->window); + } + + gdk_x11_window_set_user_time (GTK_WIDGET (window)->window, + startup_timestamp); + + if (file_list != NULL) + { + gedit_cmd_load_files_from_prompt (window, + file_list, + encoding, + line_position); + + if (new_document_option) + gedit_window_create_tab (window, TRUE); + } + else + { + GeditDocument *doc; + doc = gedit_window_get_active_document (window); + + if (doc == NULL || + !gedit_document_is_untouched (doc) || + new_document_option) + gedit_window_create_tab (window, TRUE); + } + + gtk_window_present (GTK_WINDOW (window)); + + /* free the file list and reset to default */ + g_slist_foreach (file_list, (GFunc) g_free, NULL); + g_slist_free (file_list); + file_list = NULL; + + new_window_option = FALSE; + new_document_option = FALSE; + encoding = NULL; + line_position = 0; +} + +/* clientside */ +static void +send_bacon_message (void) +{ + gint ws; + GString *command; + + /* the messages have the following format: + * <---- header -----> <---- body -----> + * timestamp \t workspace \v OP1 \t arg \t arg \v OP2 \t arg \t arg|... + * + * when the arg is a list of uri, they are separated by a space. + * So the delimiters are \v for the commands, \t for the tokens in + * a command and ' ' for the uris: note that such delimiters cannot + * be part of an uri, this way parsing is easier. + */ + + ws = gedit_utils_get_current_workspace (gdk_screen_get_default ()); + + command = g_string_new (NULL); + + /* header */ + g_string_append_printf (command, + "%" G_GUINT32_FORMAT "\t%d", + startup_timestamp, + ws); + + /* NEW-WINDOW command */ + if (new_window_option) + { + command = g_string_append_c (command, '\v'); + command = g_string_append (command, "NEW-WINDOW"); + } + + /* NEW-DOCUMENT command */ + if (new_document_option) + { + command = g_string_append_c (command, '\v'); + command = g_string_append (command, "NEW-DOCUMENT"); + } + + /* OPEN_URIS command, optionally specify line_num and encoding */ + if (file_list) + { + GSList *l; + + command = g_string_append_c (command, '\v'); + command = g_string_append (command, "OPEN-URIS"); + + g_string_append_printf (command, + "\t%d\t%s\t%d\t", + line_position, + encoding_charset ? encoding_charset : "", + g_slist_length (file_list)); + + for (l = file_list; l != NULL; l = l->next) + { + command = g_string_append (command, l->data); + if (l->next != NULL) + command = g_string_append_c (command, ' '); + } + } + + bacon_message_connection_send (connection, + command->str); + + g_string_free (command, TRUE); +} + +int +main (int argc, char *argv[]) +{ + GnomeProgram *program; + GeditWindow *window; + GeditApp *app; + gboolean restored = FALSE; + + /* Setup debugging */ + gedit_debug_init (); + gedit_debug_message (DEBUG_APP, "Startup"); + + setlocale (LC_ALL, ""); + + bindtextdomain (GETTEXT_PACKAGE, GEDIT_LOCALEDIR); + textdomain (GETTEXT_PACKAGE); + + startup_timestamp = get_startup_timestamp(); + + gedit_debug_message (DEBUG_APP, "Run gnome_program_init"); + + /* Initialize gnome program */ + program = gnome_program_init ("gedit", VERSION, + LIBGNOMEUI_MODULE, argc, argv, + GNOME_PARAM_POPT_TABLE, options, + GNOME_PARAM_HUMAN_READABLE_NAME, + _("Text Editor"), + GNOME_PARAM_APP_DATADIR, DATADIR, + NULL); + + gedit_debug_message (DEBUG_APP, "Done gnome_program_init"); + + /* Must be called after gnome_program_init to avoid problem with the + * translation of --help messages */ + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + gedit_debug_message (DEBUG_APP, "Create bacon connection"); + + connection = bacon_message_connection_new ("gedit"); + + if (connection != NULL) + { + if (!bacon_message_connection_get_is_server (connection)) + { + gedit_debug_message (DEBUG_APP, "I'm a client"); + + gedit_get_command_line_data (program); + + send_bacon_message (); + + /* we never popup a window... tell startup-notification + * that we are done. + */ + gdk_notify_startup_complete (); + + bacon_message_connection_free (connection); + + exit (0); + } + else + { + gedit_debug_message (DEBUG_APP, "I'm a server"); + + bacon_message_connection_set_callback (connection, + on_message_received, + NULL); + } + } + else + g_warning ("Cannot create the 'gedit' connection."); + + gedit_debug_message (DEBUG_APP, "Set icon"); + + /* Set default icon */ + gtk_window_set_default_icon_name ("text-editor"); + + /* Load user preferences */ + gedit_debug_message (DEBUG_APP, "Init prefs manager"); + gedit_prefs_manager_app_init (); + + gedit_debug_message (DEBUG_APP, "Init recent files"); + gedit_recent_init (); + + /* Init plugins engine */ + gedit_debug_message (DEBUG_APP, "Init plugins"); + gedit_plugins_engine_init (); + + gedit_debug_message (DEBUG_APP, "Init authentication manager"); + gnome_authentication_manager_init (); + gtk_about_dialog_set_url_hook (gedit_utils_activate_url, NULL, NULL); + + /* Initialize session management */ + gedit_debug_message (DEBUG_APP, "Init session manager"); + gedit_session_init (argv[0]); + + if (gedit_session_is_restored ()) + restored = gedit_session_load (); + + if (!restored) + { + gedit_debug_message (DEBUG_APP, "Analyze command line data"); + gedit_get_command_line_data (program); + + gedit_debug_message (DEBUG_APP, "Get default app"); + app = gedit_app_get_default (); + + gedit_debug_message (DEBUG_APP, "Create main window"); + window = gedit_app_create_window (app); + + if (file_list != NULL) + { + gedit_debug_message (DEBUG_APP, "Load files"); + gedit_cmd_load_files_from_prompt (window, file_list, encoding, line_position); + } + else + { + gedit_debug_message (DEBUG_APP, "Create tab"); + gedit_window_create_tab (window, TRUE); + } + + gedit_debug_message (DEBUG_APP, "Show window"); + gtk_widget_show (GTK_WIDGET (window)); + + g_slist_foreach (file_list, (GFunc) g_free, NULL); + g_slist_free (file_list); + file_list = NULL; + + g_free (encoding_charset); + + new_window_option = FALSE; + new_document_option = FALSE; + encoding = NULL; + line_position = 0; + } + + gedit_debug_message (DEBUG_APP, "Start gtk-main"); + gtk_main(); + + gedit_plugins_engine_shutdown (); + gedit_prefs_manager_app_shutdown (); + gedit_metadata_manager_shutdown (); + + g_object_unref (program); + + return 0; +} diff --git a/gedit/recent-files/Makefile.am b/gedit/recent-files/Makefile.am index e64a0c2a..f1574782 100644 --- a/gedit/recent-files/Makefile.am +++ b/gedit/recent-files/Makefile.am @@ -8,16 +8,16 @@ header_DATA = \ egg-recent-model.h \ egg-recent-item.h \ egg-recent-view.h \ - egg-recent-view-bonobo.h \ egg-recent-view-gtk.h \ + egg-recent-view-uimanager.h \ egg-recent-util.h EGG_FILES = \ egg-recent-model.c \ egg-recent-item.c \ egg-recent-view.c \ - egg-recent-view-bonobo.c \ egg-recent-view-gtk.c \ + egg-recent-view-uimanager.c \ egg-recent-util.c \ $(header_DATA) diff --git a/gedit/recent-files/egg-recent-model.c b/gedit/recent-files/egg-recent-model.c index e5c2ed78..4d3a4d24 100644 --- a/gedit/recent-files/egg-recent-model.c +++ b/gedit/recent-files/egg-recent-model.c @@ -99,7 +99,7 @@ typedef struct { GSList *states; GList *items; EggRecentItem *current_item; -}ParseInfo; +} ParseInfo; typedef enum { STATE_START, @@ -113,10 +113,10 @@ typedef enum { STATE_GROUP } ParseState; -typedef struct _ChangedData { +typedef struct { EggRecentModel *model; GList *list; -}ChangedData; +} ChangedData; #define TAG_RECENT_FILES "RecentFiles" #define TAG_RECENT_ITEM "RecentItem" @@ -308,17 +308,23 @@ egg_recent_model_read_raw (EggRecentModel *model, FILE *file) -static void -parse_info_init (ParseInfo *info) +static ParseInfo * +parse_info_init (void) { - info->states = g_slist_prepend (NULL, STATE_START); - info->items = NULL; + ParseInfo *retval; + + retval = g_new0 (ParseInfo, 1); + retval->states = g_slist_prepend (NULL, STATE_START); + retval->items = NULL; + + return retval; } static void parse_info_free (ParseInfo *info) { g_slist_free (info->states); + g_free (info); } static void @@ -447,15 +453,22 @@ end_element_handler (GMarkupParseContext *context, switch (peek_state (info)) { case STATE_RECENT_ITEM: - info->items = g_list_append (info->items, - info->current_item); - if (info->current_item->uri == NULL || - strlen (info->current_item->uri) == 0) - g_warning ("URI NOT LOADED"); + if (!info->current_item) { + g_warning ("No recent item found\n"); + break; + } + + if (!info->current_item->uri) { + g_warning ("Invalid item found\n"); + break; + } + + info->items = g_list_prepend (info->items, + info->current_item); info->current_item = NULL; - break; + break; default: - break; + break; } pop_state (info); @@ -570,23 +583,23 @@ egg_recent_model_group_match (EggRecentItem *item, GSList *groups) } static GList * -egg_recent_model_filter (EggRecentModel *model, - GList *list) +egg_recent_model_filter (EggRecentModel *model, GList *list) { - EggRecentItem *item; GList *newlist = NULL; + GList *l; gchar *mime_type; gchar *uri; g_return_val_if_fail (list != NULL, NULL); - while (list) { + for (l = list; l != NULL ; l = l->next) { + EggRecentItem *item = (EggRecentItem *) l->data; gboolean pass_mime_test = FALSE; gboolean pass_group_test = FALSE; gboolean pass_scheme_test = FALSE; - item = (EggRecentItem *)list->data; - list = list->next; + g_assert (item != NULL); + uri = egg_recent_item_get_uri (item); /* filter by mime type */ @@ -629,17 +642,15 @@ egg_recent_model_filter (EggRecentModel *model, if (pass_mime_test && pass_group_test && pass_scheme_test) newlist = g_list_prepend (newlist, item); + else + egg_recent_item_unref (item); g_free (uri); } - if (newlist) { - newlist = g_list_reverse (newlist); - g_list_free (list); - } + g_list_free (list); - - return newlist; + return g_list_reverse (newlist); } @@ -816,7 +827,7 @@ egg_recent_model_read (EggRecentModel *model, FILE *file) GList *list=NULL; gchar *content; GMarkupParseContext *ctx; - ParseInfo info; + ParseInfo *info; GError *error; content = egg_recent_model_read_raw (model, file); @@ -826,35 +837,39 @@ egg_recent_model_read (EggRecentModel *model, FILE *file) return NULL; } - parse_info_init (&info); + info = parse_info_init (); - ctx = g_markup_parse_context_new (&parser, 0, &info, NULL); + ctx = g_markup_parse_context_new (&parser, 0, info, NULL); error = NULL; - if (!g_markup_parse_context_parse (ctx, content, strlen (content), - &error)) { - g_warning (error->message); + if (!g_markup_parse_context_parse (ctx, content, strlen (content), &error)) { + g_warning ("Error while parsing the .recently-used file: %s\n", + error->message); + g_error_free (error); - error = NULL; - goto out; + parse_info_free (info); + + return NULL; } error = NULL; - if (!g_markup_parse_context_end_parse (ctx, &error)) - goto out; - - g_markup_parse_context_free (ctx); -out: - list = info.items; + if (!g_markup_parse_context_end_parse (ctx, &error)) { + g_warning ("Unable to complete parsing of the .recently-used file: %s\n", + error->message); + + g_error_free (error); + g_markup_parse_context_free (ctx); + parse_info_free (info); - parse_info_free (&info); + return NULL; + } + + list = g_list_reverse (info->items); + g_markup_parse_context_free (ctx); + parse_info_free (info); g_free (content); - /* - g_print ("Total items: %d\n", g_list_length (list)); - */ - return list; } @@ -1552,16 +1567,15 @@ GList * egg_recent_model_get_list (EggRecentModel *model) { FILE *file; - GList *list=NULL; + GList *list = NULL; file = egg_recent_model_open_file (model, FALSE); if (file == NULL) return NULL; - if (egg_recent_model_lock_file (file)) { + if (egg_recent_model_lock_file (file)) list = egg_recent_model_read (model, file); - - } else { + else { g_warning ("Failed to lock: %s", strerror (errno)); fclose (file); return NULL; diff --git a/gedit/recent-files/egg-recent-util.c b/gedit/recent-files/egg-recent-util.c index dfe6f90a..4597f03c 100644 --- a/gedit/recent-files/egg-recent-util.c +++ b/gedit/recent-files/egg-recent-util.c @@ -2,7 +2,9 @@ #include #include #include +#ifndef USE_STABLE_LIBGNOMEUI #include +#endif #include #include #include @@ -58,6 +60,7 @@ GdkPixbuf * egg_recent_util_get_icon (GtkIconTheme *theme, const gchar *uri, const gchar *mime_type, int size) { +#ifndef USE_STABLE_LIBGNOMEUI gchar *icon; GdkPixbuf *pixbuf; @@ -70,6 +73,8 @@ egg_recent_util_get_icon (GtkIconTheme *theme, const gchar *uri, g_free (icon); return pixbuf; +#endif + return NULL; } gchar * diff --git a/gedit/recent-files/egg-recent-view-gtk.c b/gedit/recent-files/egg-recent-view-gtk.c index 483624c6..ca3fcf44 100644 --- a/gedit/recent-files/egg-recent-view-gtk.c +++ b/gedit/recent-files/egg-recent-view-gtk.c @@ -143,6 +143,8 @@ egg_recent_view_gtk_clear (EggRecentViewGtk *view) p = p->next; } + + g_list_free (menu_children); } diff --git a/gedit/recent-files/egg-recent-view-uimanager.c b/gedit/recent-files/egg-recent-view-uimanager.c new file mode 100644 index 00000000..72873e66 --- /dev/null +++ b/gedit/recent-files/egg-recent-view-uimanager.c @@ -0,0 +1,884 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/** + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: + * James Willcox + * Paolo Bacchilega + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#ifndef USE_STABLE_LIBGNOMEUI +#include +#endif +#include +#include "egg-recent-model.h" +#include "egg-recent-view.h" +#include "egg-recent-view-uimanager.h" +#include "egg-recent-util.h" +#include "egg-recent-item.h" + +#define EGG_RECENT_NAME_PREFIX "EggRecentAction" +#define EGG_RECENT_ACTION "EggRecentFile" +#define EGG_RECENT_SEPARATOR (NULL) + +#ifndef EGG_COMPILATION +#include +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +#define DEFAULT_LABEL_WIDTH_CHARS 30 + +struct _EggRecentViewUIManager { + GObject parent_instance; + + GCallback action_callback; + gpointer action_user_data; + + gboolean leading_sep; + gboolean trailing_sep; + + GtkUIManager *uimanager; + GtkActionGroup *action_group; + guint merge_id; + gulong changed_cb_id; + + gchar *path; + + gboolean show_icons; + gboolean show_numbers; +#ifndef USE_STABLE_LIBGNOMEUI + GnomeIconTheme *theme; +#endif + + EggUIManagerTooltipFunc tooltip_func; + gpointer tooltip_func_data; + + EggRecentModel *model; + GConfClient *client; + GtkIconSize icon_size; + + gint label_width; +}; + + +struct _EggRecentViewUIManagerMenuData { + EggRecentViewUIManager *view; + EggRecentItem *item; +}; + +typedef struct _EggRecentViewUIManagerMenuData EggRecentViewUIManagerMenuData; + +enum { + ACTIVATE, + LAST_SIGNAL +}; + +/* GObject properties */ +enum { + PROP_BOGUS, + PROP_UIMANAGER, + PROP_PATH, + PROP_SHOW_ICONS, + PROP_SHOW_NUMBERS, + PROP_LABEL_WIDTH +}; + +static guint view_signals[LAST_SIGNAL] = { 0 }; + +static void +connect_proxy_cb (GtkActionGroup *action_group, + GtkAction *action, + GtkWidget *proxy, + EggRecentViewUIManager *view) +{ + if (GTK_IS_MENU_ITEM (proxy)) + { + GtkWidget *label; + + label = GTK_BIN (proxy)->child; + + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); + gtk_label_set_max_width_chars (GTK_LABEL (label), view->label_width); + } +} + +static void +egg_recent_view_uimanager_clear (EggRecentViewUIManager *view) +{ + if (view->merge_id != 0) { + gtk_ui_manager_remove_ui (view->uimanager, view->merge_id); + view->merge_id = 0; + } + + if (view->action_group != NULL) { + gtk_ui_manager_remove_action_group (view->uimanager, view->action_group); + g_object_unref (view->action_group); + view->action_group = NULL; + } + + gtk_ui_manager_ensure_update (view->uimanager); +} + +static void +egg_recent_view_uimanager_set_list (EggRecentViewUIManager *view, GList *list) +{ + GList *scan; + guint index = 1; + + g_return_if_fail (view); + + egg_recent_view_uimanager_clear (view); + + if (view->merge_id == 0) + view->merge_id = gtk_ui_manager_new_merge_id (view->uimanager); + + if (view->action_group == NULL) { + gchar *group = g_strdup_printf ("EggRecentActions%u", + view->merge_id); + view->action_group = gtk_action_group_new (group); + g_signal_connect (view->action_group, "connect-proxy", + G_CALLBACK (connect_proxy_cb), view); + gtk_ui_manager_insert_action_group (view->uimanager, + view->action_group, -1); + g_free (group); + } + + if (view->leading_sep) { + gchar *action = g_strdup_printf ("EggRecentLeadingSeparator%u", + view->merge_id); + gtk_ui_manager_add_ui (view->uimanager, + view->merge_id, + view->path, + action, + EGG_RECENT_SEPARATOR, + GTK_UI_MANAGER_AUTO, + FALSE); + g_free (action); + } + + for (scan = list; scan; scan = scan->next, index++) { + EggRecentItem *item = scan->data; + GtkAction *action; + gchar *name; + gchar *uri; + gchar *basename; + gchar *escaped; + gchar *label; + gchar *tooltip = NULL; + + uri = egg_recent_item_get_uri_for_display (item); + if (uri == NULL) + continue; + + name = g_strdup_printf (EGG_RECENT_NAME_PREFIX"%u-%u", + view->merge_id, + index); + + if (view->tooltip_func != NULL) + tooltip = (*view->tooltip_func) (item, view->tooltip_func_data); + + if (!tooltip) + tooltip = g_strdup_printf (_("Open '%s'"), uri); + + basename = egg_recent_item_get_short_name (item); + escaped = egg_recent_util_escape_underlines (basename); + g_free (basename); + g_free (uri); + + if (view->show_numbers) { + if (index >= 10) + label = g_strdup_printf ("%d. %s", + index, + escaped); + else + label = g_strdup_printf ("_%d. %s", + index, + escaped); + g_free (escaped); + } else + label = escaped; + + action = g_object_new (GTK_TYPE_ACTION, + "name", name, + "label", label, + (view->show_icons)? "stock_id": NULL, + GTK_STOCK_OPEN, + NULL); + if (tooltip != NULL) { + g_object_set (action, "tooltip", tooltip, NULL); + g_free (tooltip); + } + egg_recent_item_ref (item); + g_object_set_data_full (G_OBJECT (action), + "egg_recent_uri", + item, + (GFreeFunc) egg_recent_item_unref); + + if (view->action_callback != NULL) { + GClosure *closure; + closure = g_cclosure_new (view->action_callback, view->action_user_data, NULL); + g_signal_connect_closure (action, "activate", closure, FALSE); + } + + gtk_action_group_add_action (view->action_group, action); + g_object_unref (action); + + gtk_ui_manager_add_ui (view->uimanager, + view->merge_id, + view->path, + name, + name, + GTK_UI_MANAGER_AUTO, + FALSE); + + g_free (name); + g_free (label); + } + + if (view->trailing_sep) { + gchar *action = g_strdup_printf ("EggRecentTrailingSeparator%u", + view->merge_id); + gtk_ui_manager_add_ui (view->uimanager, + view->merge_id, + view->path, + action, + EGG_RECENT_SEPARATOR, + GTK_UI_MANAGER_AUTO, + FALSE); + g_free (action); + } +} + +static void +egg_recent_view_uimanager_set_empty_list (EggRecentViewUIManager *view) +{ + gboolean is_embedded; + + g_return_if_fail (view); + + egg_recent_view_uimanager_clear (view); + + if (view->merge_id == 0) + view->merge_id = gtk_ui_manager_new_merge_id (view->uimanager); + + if (view->action_group == NULL) { + gchar *group = g_strdup_printf ("EggRecentActions%u", + view->merge_id); + view->action_group = gtk_action_group_new (group); + g_signal_connect (view->action_group, "connect-proxy", + G_CALLBACK (connect_proxy_cb), view); + gtk_ui_manager_insert_action_group (view->uimanager, + view->action_group, -1); + g_free (group); + } + + if (view->leading_sep) { + gchar *sep_action = g_strdup_printf ("EggRecentLeadingSeparator%u", + view->merge_id); + gtk_ui_manager_add_ui (view->uimanager, + view->merge_id, + view->path, + sep_action, + EGG_RECENT_SEPARATOR, + GTK_UI_MANAGER_AUTO, + FALSE); + g_free (sep_action); + } + + is_embedded = (view->leading_sep && view->trailing_sep); + + if (is_embedded) { + GtkAction *action; + gchar *name; + + name = g_strdup_printf (EGG_RECENT_NAME_PREFIX "%u-0", view->merge_id); + + action = g_object_new (GTK_TYPE_ACTION, + "name", name, + "label", _("Empty"), + "sensitive", FALSE, + NULL); + + gtk_action_group_add_action (view->action_group, action); + g_object_unref (action); + + gtk_ui_manager_add_ui (view->uimanager, + view->merge_id, + view->path, + name, + name, + GTK_UI_MANAGER_AUTO, + FALSE); + + g_free (name); + } + + if (view->trailing_sep) { + gchar *sep_action = g_strdup_printf ("EggRecentTrailingSeparator%u", + view->merge_id); + gtk_ui_manager_add_ui (view->uimanager, + view->merge_id, + view->path, + sep_action, + EGG_RECENT_SEPARATOR, + GTK_UI_MANAGER_AUTO, + FALSE); + g_free (sep_action); + } +} + +static void +model_changed_cb (EggRecentModel *model, + GList *list, + EggRecentViewUIManager *view) +{ + if (list != NULL) + egg_recent_view_uimanager_set_list (view, list); + else + egg_recent_view_uimanager_set_empty_list (view); + + gtk_ui_manager_ensure_update (view->uimanager); +} + +static EggRecentModel * +egg_recent_view_uimanager_get_model (EggRecentView *view_parent) +{ + EggRecentViewUIManager *view; + + g_return_val_if_fail (view_parent != NULL, NULL); + view = EGG_RECENT_VIEW_UIMANAGER (view_parent); + return view->model; +} + +static void +egg_recent_view_uimanager_set_model (EggRecentView *view_parent, + EggRecentModel *model) +{ + EggRecentViewUIManager *view; + + g_return_if_fail (view_parent != NULL); + view = EGG_RECENT_VIEW_UIMANAGER (view_parent); + + if (view->model != NULL) { + if (view->changed_cb_id != 0) + g_signal_handler_disconnect (G_OBJECT (view->model), + view->changed_cb_id); + g_object_unref (view->model); + } + + view->model = model; + g_object_ref (view->model); + + view->changed_cb_id = g_signal_connect_object (G_OBJECT (model), + "changed", + G_CALLBACK (model_changed_cb), + view, 0); + + egg_recent_model_changed (view->model); +} + +void +egg_recent_view_uimanager_set_leading_sep (EggRecentViewUIManager *view, + gboolean val) +{ + view->leading_sep = val; + egg_recent_view_uimanager_clear (view); + if (view->model) + egg_recent_model_changed (view->model); +} + +void +egg_recent_view_uimanager_set_trailing_sep (EggRecentViewUIManager *view, + gboolean val) +{ + view->trailing_sep = val; + egg_recent_view_uimanager_clear (view); + if (view->model) + egg_recent_model_changed (view->model); +} + +static void +egg_recent_view_uimanager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object); + + switch (prop_id) { + case PROP_UIMANAGER: + egg_recent_view_uimanager_set_uimanager (view, (GtkUIManager*)g_value_get_object (value)); + break; + case PROP_PATH: + egg_recent_view_uimanager_set_path (view, g_value_get_string (value)); + break; + case PROP_SHOW_ICONS: + egg_recent_view_uimanager_show_icons (view, g_value_get_boolean (value)); + break; + case PROP_SHOW_NUMBERS: + egg_recent_view_uimanager_show_numbers (view, g_value_get_boolean (value)); + break; + case PROP_LABEL_WIDTH: + egg_recent_view_uimanager_set_label_width (view, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +egg_recent_view_uimanager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object); + + switch (prop_id) { + case PROP_UIMANAGER: + g_value_set_object (value, view->uimanager); + break; + case PROP_PATH: + g_value_set_string (value, view->path); + break; + case PROP_SHOW_ICONS: + g_value_set_boolean (value, view->show_icons); + break; + case PROP_SHOW_NUMBERS: + g_value_set_boolean (value, view->show_numbers); + break; + case PROP_LABEL_WIDTH: + g_value_set_int (value, view->label_width); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +egg_recent_view_uimanager_finalize (GObject *object) +{ + EggRecentViewUIManager *view = EGG_RECENT_VIEW_UIMANAGER (object); + + if (view->changed_cb_id != 0) { + g_signal_handler_disconnect (G_OBJECT (view->model), + view->changed_cb_id); + view->changed_cb_id = 0; + } + + g_free (view->path); + + egg_recent_view_uimanager_clear (view); + + if (view->action_group != NULL) { + g_object_unref (view->action_group); + view->action_group = NULL; + } + + if (view->uimanager != NULL) { + g_object_unref (view->uimanager); + view->uimanager = NULL; + } + + if (view->model != NULL) { + g_object_unref (view->model); + view->model = NULL; + } + +#ifndef USE_STABLE_LIBGNOMEUI + if (view->theme != NULL) { + g_object_unref (view->theme); + view->theme = NULL; + } +#endif + + if (view->client != NULL) { + g_object_unref (view->client); + view->client = NULL; + } +} + +static void +egg_recent_view_uimanager_class_init (EggRecentViewUIManagerClass * klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = egg_recent_view_uimanager_set_property; + object_class->get_property = egg_recent_view_uimanager_get_property; + object_class->finalize = egg_recent_view_uimanager_finalize; + + view_signals[ACTIVATE] = g_signal_new ("activate", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EggRecentViewUIManagerClass, activate), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + EGG_TYPE_RECENT_ITEM); + + g_object_class_install_property (object_class, + PROP_UIMANAGER, + g_param_spec_object ("uimanager", + "UI Manager", + "The UI manager this object will use to update.the UI", + GTK_TYPE_UI_MANAGER, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_PATH, + g_param_spec_string ("path", + "Path", + "The UI path this object will update.", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_SHOW_ICONS, + g_param_spec_boolean ("show-icons", + "Show Icons", + "Whether or not to show icons", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_SHOW_NUMBERS, + g_param_spec_boolean ("show-numbers", + "Show Numbers", + "Whether or not to show numbers", + TRUE, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_LABEL_WIDTH, + g_param_spec_int ("label-width", + "Label Width", + "The desired width of the menu label, in characters", + -1, + G_MAXINT, + DEFAULT_LABEL_WIDTH_CHARS, + G_PARAM_READWRITE)); + + + klass->activate = NULL; +} + +static void +egg_recent_view_init (EggRecentViewClass *iface) +{ + iface->do_get_model = egg_recent_view_uimanager_get_model; + iface->do_set_model = egg_recent_view_uimanager_set_model; +} + +static void +show_menus_changed_cb (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + EggRecentViewUIManager *view) +{ + GConfValue *value; + + value = gconf_entry_get_value (entry); + g_return_if_fail (value->type == GCONF_VALUE_BOOL); + + egg_recent_view_uimanager_show_icons (view, gconf_value_get_bool (value)); +} + +#ifndef USE_STABLE_LIBGNOMEUI +static void +theme_changed_cb (GnomeIconTheme *theme, + EggRecentViewUIManager *view) +{ + if (view->model != NULL) + egg_recent_model_changed (view->model); +} +#endif + +static void +egg_recent_view_uimanager_init (EggRecentViewUIManager * view) +{ + view->client = gconf_client_get_default (); + + view->show_icons = gconf_client_get_bool (view->client, + "/desktop/gnome/interface/menus_have_icons", + NULL); + + gconf_client_add_dir (view->client, "/desktop/gnome/interface", + GCONF_CLIENT_PRELOAD_NONE, + NULL); + gconf_client_notify_add (view->client, + "/desktop/gnome/interface/menus_have_icons", + (GConfClientNotifyFunc)show_menus_changed_cb, + view, NULL, NULL); + + + view->leading_sep = FALSE; + view->trailing_sep = FALSE; + view->show_numbers = TRUE; + + view->uimanager = NULL; + view->action_group = NULL; + view->merge_id = 0; + view->changed_cb_id = 0; + + view->path = NULL; + +#ifndef USE_STABLE_LIBGNOMEUI + view->theme = gnome_icon_theme_new (); + gnome_icon_theme_set_allow_svg (view->theme, TRUE); + g_signal_connect_object (view->theme, "changed", + G_CALLBACK (theme_changed_cb), view, 0); +#endif + + view->tooltip_func = NULL; + view->tooltip_func_data = NULL; + + view->icon_size = GTK_ICON_SIZE_MENU; + view->label_width = DEFAULT_LABEL_WIDTH_CHARS; +} + +void +egg_recent_view_uimanager_set_icon_size (EggRecentViewUIManager *view, + GtkIconSize icon_size) +{ + if (view->icon_size != icon_size) { + view->icon_size = icon_size; + egg_recent_model_changed (view->model); + } else { + view->icon_size = icon_size; + } +} + +GtkIconSize +egg_recent_view_uimanager_get_icon_size (EggRecentViewUIManager *view) +{ + return view->icon_size; +} + +void +egg_recent_view_uimanager_show_icons (EggRecentViewUIManager *view, + gboolean show) +{ + view->show_icons = show; + if (view->model != NULL) + egg_recent_model_changed (view->model); +} + +void +egg_recent_view_uimanager_show_numbers (EggRecentViewUIManager *view, + gboolean show) +{ + view->show_numbers = show; + if (view->model != NULL) + egg_recent_model_changed (view->model); +} + +void +egg_recent_view_uimanager_set_tooltip_func (EggRecentViewUIManager *view, + EggUIManagerTooltipFunc func, + gpointer user_data) +{ + view->tooltip_func = func; + view->tooltip_func_data = user_data; + if (view->model) + egg_recent_model_changed (view->model); +} + +/** + * egg_recent_view_uimanager_set_uimanager: + * @view: A EggRecentViewUIManager object. + * @uimanager: The ui manager used to put the menu items in. + * + * Use this function to change the ui manager used to update the menu. + * + */ +void +egg_recent_view_uimanager_set_uimanager (EggRecentViewUIManager *view, + GtkUIManager *uimanager) +{ + g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view)); + g_return_if_fail (uimanager != NULL); + + if (view->uimanager != NULL) + g_object_unref (view->uimanager); + view->uimanager = uimanager; + g_object_ref (view->uimanager); +} + +/** + * egg_recent_view_uimanager_get_uimanager: + * @view: A EggRecentViewUIManager object. + * + */ +GtkUIManager* +egg_recent_view_uimanager_get_uimanager (EggRecentViewUIManager *view) +{ + g_return_val_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view), NULL); + return view->uimanager; +} + +/** + * egg_recent_view_uimanager_set_path: + * @view: A EggRecentViewUIManager object. + * @path: The path to put the menu items in. + * + * Use this function to change the path where the recent + * documents appear in. + * + */ +void +egg_recent_view_uimanager_set_path (EggRecentViewUIManager *view, + const gchar *path) +{ + g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view)); + g_return_if_fail (path); + + g_free (view->path); + view->path = g_strdup (path); +} + +/** + * egg_recent_view_uimanager_get_path: + * @view: A EggRecentViewUIManager object. + * + */ +G_CONST_RETURN gchar* +egg_recent_view_uimanager_get_path (EggRecentViewUIManager *view) +{ + g_return_val_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view), NULL); + return view->path; +} + +void +egg_recent_view_uimanager_set_label_width (EggRecentViewUIManager *view, + gint chars) +{ + g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view)); + view->label_width = chars; +} + +gint +egg_recent_view_uimanager_get_label_width (EggRecentViewUIManager *view) +{ + g_return_val_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view), DEFAULT_LABEL_WIDTH_CHARS); + return view->label_width; +} + +void +egg_recent_view_uimanager_set_action_func (EggRecentViewUIManager *view, + GCallback callback, + gpointer user_data) +{ + g_return_if_fail (EGG_IS_RECENT_VIEW_UIMANAGER (view)); + view->action_callback = callback; + view->action_user_data = user_data; +} + +/** + * egg_recent_view_uimanager_new: + * @appname: The name of your application. + * @limit: The maximum number of items allowed. + * + * This creates a new EggRecentViewUIManager object. + * + * Returns: a EggRecentViewUIManager object + */ +EggRecentViewUIManager * +egg_recent_view_uimanager_new (GtkUIManager *uimanager, + const gchar *path, + GCallback callback, + gpointer user_data) +{ + GObject *view; + + g_return_val_if_fail (uimanager, NULL); + g_return_val_if_fail (path, NULL); + + view = g_object_new (egg_recent_view_uimanager_get_type (), + "uimanager", uimanager, + "path", path, + NULL); + + g_return_val_if_fail (view, NULL); + + egg_recent_view_uimanager_set_action_func (EGG_RECENT_VIEW_UIMANAGER (view), + callback, + user_data); + + return EGG_RECENT_VIEW_UIMANAGER (view); +} + +/** + * egg_recent_view_uimanager_get_type: + * @: + * + * This returns a GType representing a EggRecentViewUIManager object. + * + * Returns: a GType + */ +GType +egg_recent_view_uimanager_get_type (void) +{ + static GType egg_recent_view_uimanager_type = 0; + + if(!egg_recent_view_uimanager_type) { + static const GTypeInfo egg_recent_view_uimanager_info = { + sizeof (EggRecentViewUIManagerClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc)egg_recent_view_uimanager_class_init, /* class init */ + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EggRecentViewUIManager), + 0, + (GInstanceInitFunc) egg_recent_view_uimanager_init + }; + + static const GInterfaceInfo view_info = + { + (GInterfaceInitFunc) egg_recent_view_init, + NULL, + NULL + }; + + egg_recent_view_uimanager_type = g_type_register_static (G_TYPE_OBJECT, + "EggRecentViewUIManager", + &egg_recent_view_uimanager_info, 0); + g_type_add_interface_static (egg_recent_view_uimanager_type, + EGG_TYPE_RECENT_VIEW, + &view_info); + } + + return egg_recent_view_uimanager_type; +} + +EggRecentItem* +egg_recent_view_uimanager_get_item (EggRecentViewUIManager *view, + GtkAction *action) +{ + return g_object_get_data (G_OBJECT(action), "egg_recent_uri"); +} diff --git a/gedit/recent-files/egg-recent-view-uimanager.h b/gedit/recent-files/egg-recent-view-uimanager.h new file mode 100644 index 00000000..8aed4132 --- /dev/null +++ b/gedit/recent-files/egg-recent-view-uimanager.h @@ -0,0 +1,63 @@ +/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef __EGG_RECENT_VIEW_UIMANAGER_H__ +#define __EGG_RECENT_VIEW_UIMANAGER_H__ + + +#include +#include "egg-recent-item.h" + +G_BEGIN_DECLS + +#define EGG_RECENT_VIEW_UIMANAGER(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, egg_recent_view_uimanager_get_type (), EggRecentViewUIManager) +#define EGG_RECENT_VIEW_UIMANAGER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, egg_recent_view_uimanager_get_type (), EggRecentViewUIManagerClass) +#define EGG_IS_RECENT_VIEW_UIMANAGER(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, egg_recent_view_uimanager_get_type ()) + +typedef char* (*EggUIManagerTooltipFunc) (EggRecentItem *item, + gpointer user_data); + +typedef struct _EggRecentViewUIManager EggRecentViewUIManager; +typedef struct _EggRecentViewUIManagerClass EggRecentViewUIManagerClass; + +struct _EggRecentViewUIManagerClass { + GObjectClass parent_class; + void (*activate) (EggRecentViewUIManager *view, EggRecentItem *item); +}; + +GType egg_recent_view_uimanager_get_type (void); +EggRecentViewUIManager *egg_recent_view_uimanager_new (GtkUIManager *uimanager, + const gchar *path, + GCallback callback, + gpointer user_data); +void egg_recent_view_uimanager_set_uimanager (EggRecentViewUIManager *view, + GtkUIManager *uimanager); +GtkUIManager* egg_recent_view_uimanager_get_uimanager (EggRecentViewUIManager *view); +void egg_recent_view_uimanager_set_path (EggRecentViewUIManager *view, + const gchar *path); +G_CONST_RETURN gchar *egg_recent_view_uimanager_get_path (EggRecentViewUIManager *view); +void egg_recent_view_uimanager_set_action_func (EggRecentViewUIManager *view, + GCallback callback, + gpointer user_data); +void egg_recent_view_uimanager_set_leading_sep (EggRecentViewUIManager *view, + gboolean val); +void egg_recent_view_uimanager_set_trailing_sep (EggRecentViewUIManager *view, + gboolean val); +void egg_recent_view_uimanager_show_icons (EggRecentViewUIManager *view, + gboolean show); +void egg_recent_view_uimanager_show_numbers (EggRecentViewUIManager *view, + gboolean show); +void egg_recent_view_uimanager_set_tooltip_func (EggRecentViewUIManager *view, + EggUIManagerTooltipFunc func, + gpointer user_data); +void egg_recent_view_uimanager_set_icon_size (EggRecentViewUIManager *view, + GtkIconSize icon_size); +GtkIconSize egg_recent_view_uimanager_get_icon_size (EggRecentViewUIManager *view); +EggRecentItem *egg_recent_view_uimanager_get_item (EggRecentViewUIManager *view, + GtkAction *action); +void egg_recent_view_uimanager_set_label_width (EggRecentViewUIManager *view, + gint chars); +gint egg_recent_view_uimanager_get_label_width (EggRecentViewUIManager *view); + +G_END_DECLS + + +#endif /* __EGG_RECENT_VIEW_UIMANAGER_H__ */ diff --git a/gedit/sexy-icon-entry.c b/gedit/sexy-icon-entry.c new file mode 100644 index 00000000..9cf11cbf --- /dev/null +++ b/gedit/sexy-icon-entry.c @@ -0,0 +1,921 @@ +/* + * @file libsexy/sexy-icon-entry.c Entry widget + * + * @Copyright (C) 2004-2005 Christian Hammond. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include +#include +#include + +#define ICON_MARGIN 2 +#define MAX_ICONS 2 + +#define IS_VALID_ICON_ENTRY_POSITION(pos) \ + ((pos) == SEXY_ICON_ENTRY_PRIMARY || \ + (pos) == SEXY_ICON_ENTRY_SECONDARY) + +typedef struct +{ + GtkImage *icon; + gboolean highlight; + gboolean hovered; + GdkWindow *window; + +} SexyIconInfo; + +struct _SexyIconEntryPriv +{ + SexyIconInfo icons[MAX_ICONS]; + + gulong icon_released_id; +}; + +enum +{ + ICON_PRESSED, + ICON_RELEASED, + LAST_SIGNAL +}; + +static void sexy_icon_entry_class_init(SexyIconEntryClass *klass); +static void sexy_icon_entry_editable_init(GtkEditableClass *iface); +static void sexy_icon_entry_init(SexyIconEntry *entry); +static void sexy_icon_entry_finalize(GObject *obj); +static void sexy_icon_entry_destroy(GtkObject *obj); +static void sexy_icon_entry_map(GtkWidget *widget); +static void sexy_icon_entry_unmap(GtkWidget *widget); +static void sexy_icon_entry_realize(GtkWidget *widget); +static void sexy_icon_entry_unrealize(GtkWidget *widget); +static void sexy_icon_entry_size_request(GtkWidget *widget, + GtkRequisition *requisition); +static void sexy_icon_entry_size_allocate(GtkWidget *widget, + GtkAllocation *allocation); +static gint sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event); +static gint sexy_icon_entry_enter_notify(GtkWidget *widget, + GdkEventCrossing *event); +static gint sexy_icon_entry_leave_notify(GtkWidget *widget, + GdkEventCrossing *event); +static gint sexy_icon_entry_button_press(GtkWidget *widget, + GdkEventButton *event); +static gint sexy_icon_entry_button_release(GtkWidget *widget, + GdkEventButton *event); + +static GtkEntryClass *parent_class = NULL; +static guint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE_EXTENDED(SexyIconEntry, sexy_icon_entry, GTK_TYPE_ENTRY, + 0, + G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE, + sexy_icon_entry_editable_init)); + +static void +sexy_icon_entry_class_init(SexyIconEntryClass *klass) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkEntryClass *entry_class; + + parent_class = g_type_class_peek_parent(klass); + + gobject_class = G_OBJECT_CLASS(klass); + object_class = GTK_OBJECT_CLASS(klass); + widget_class = GTK_WIDGET_CLASS(klass); + entry_class = GTK_ENTRY_CLASS(klass); + + gobject_class->finalize = sexy_icon_entry_finalize; + + object_class->destroy = sexy_icon_entry_destroy; + + widget_class->map = sexy_icon_entry_map; + widget_class->unmap = sexy_icon_entry_unmap; + widget_class->realize = sexy_icon_entry_realize; + widget_class->unrealize = sexy_icon_entry_unrealize; + widget_class->size_request = sexy_icon_entry_size_request; + widget_class->size_allocate = sexy_icon_entry_size_allocate; + widget_class->expose_event = sexy_icon_entry_expose; + widget_class->enter_notify_event = sexy_icon_entry_enter_notify; + widget_class->leave_notify_event = sexy_icon_entry_leave_notify; + widget_class->button_press_event = sexy_icon_entry_button_press; + widget_class->button_release_event = sexy_icon_entry_button_release; + + signals[ICON_PRESSED] = + g_signal_new("icon_pressed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(SexyIconEntryClass, icon_pressed), + NULL, NULL, + gtk_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + + signals[ICON_RELEASED] = + g_signal_new("icon_released", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(SexyIconEntryClass, icon_released), + NULL, NULL, + gtk_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); +} + +static void +sexy_icon_entry_editable_init(GtkEditableClass *iface) +{ +}; + +static void +sexy_icon_entry_init(SexyIconEntry *entry) +{ + entry->priv = g_new0(SexyIconEntryPriv, 1); +} + +static void +sexy_icon_entry_finalize(GObject *obj) +{ + SexyIconEntry *entry; + + g_return_if_fail(obj != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(obj)); + + entry = SEXY_ICON_ENTRY(obj); + + g_free(entry->priv); + + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(obj); +} + +static void +sexy_icon_entry_destroy(GtkObject *obj) +{ + SexyIconEntry *entry; + + entry = SEXY_ICON_ENTRY(obj); + + sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_PRIMARY, NULL); + sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_SECONDARY, NULL); + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(obj); +} + +static void +sexy_icon_entry_map(GtkWidget *widget) +{ + if (GTK_WIDGET_REALIZED(widget) && !GTK_WIDGET_MAPPED(widget)) + { + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + GTK_WIDGET_CLASS(parent_class)->map(widget); + + for (i = 0; i < MAX_ICONS; i++) + gdk_window_show(entry->priv->icons[i].window); + } +} + +static void +sexy_icon_entry_unmap(GtkWidget *widget) +{ + if (GTK_WIDGET_MAPPED(widget)) + { + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + gdk_window_hide(entry->priv->icons[i].window); + + GTK_WIDGET_CLASS(parent_class)->unmap(widget); + } +} + +static gint +get_icon_width(SexyIconEntry *entry, SexyIconEntryPosition icon_pos) +{ + GtkRequisition requisition; + gint menu_icon_width; + gint width; + SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; + + if (icon_info->icon == NULL) + return 0; + + gtk_widget_size_request(GTK_WIDGET(icon_info->icon), &requisition); + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &menu_icon_width, NULL); + + width = MAX(requisition.width, menu_icon_width); + + return width; +} + +static void +get_borders(SexyIconEntry *entry, gint *xborder, gint *yborder) +{ + GtkWidget *widget = GTK_WIDGET(entry); + gint focus_width; + gboolean interior_focus; + + gtk_widget_style_get(widget, + "interior-focus", &interior_focus, + "focus-line-width", &focus_width, + NULL); + + if (gtk_entry_get_has_frame(GTK_ENTRY(entry))) + { + *xborder = widget->style->xthickness; + *yborder = widget->style->ythickness; + } + else + { + *xborder = 0; + *yborder = 0; + } + + if (!interior_focus) + { + *xborder += focus_width; + *yborder += focus_width; + } +} + +static void +get_text_area_size(SexyIconEntry *entry, GtkAllocation *alloc) +{ + GtkWidget *widget = GTK_WIDGET(entry); + GtkRequisition requisition; + gint xborder, yborder; + + gtk_widget_get_child_requisition(widget, &requisition); + get_borders(entry, &xborder, &yborder); + + alloc->x = xborder; + alloc->y = yborder; + alloc->width = widget->allocation.width - xborder * 2; + alloc->height = requisition.height - yborder * 2; +} + +static void +get_icon_allocation(SexyIconEntry *icon_entry, + gboolean left, + GtkAllocation *widget_alloc, + GtkAllocation *text_area_alloc, + GtkAllocation *allocation, + SexyIconEntryPosition *icon_pos) +{ + gboolean rtl; + + rtl = (gtk_widget_get_direction(GTK_WIDGET(icon_entry)) == + GTK_TEXT_DIR_RTL); + + if (left) + *icon_pos = (rtl ? SEXY_ICON_ENTRY_SECONDARY : SEXY_ICON_ENTRY_PRIMARY); + else + *icon_pos = (rtl ? SEXY_ICON_ENTRY_PRIMARY : SEXY_ICON_ENTRY_SECONDARY); + + allocation->y = text_area_alloc->y; + allocation->width = get_icon_width(icon_entry, *icon_pos); + allocation->height = text_area_alloc->height; + + if (left) + allocation->x = text_area_alloc->x + ICON_MARGIN; + else + { + allocation->x = text_area_alloc->x + text_area_alloc->width - + allocation->width - ICON_MARGIN; + } +} + +static void +sexy_icon_entry_realize(GtkWidget *widget) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + GdkWindowAttr attributes; + gint attributes_mask; + int i; + + GTK_WIDGET_CLASS(parent_class)->realize(widget); + + for (i = 0; i < MAX_ICONS; i++) + { + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual(widget); + attributes.colormap = gtk_widget_get_colormap(widget); + attributes.event_mask = gtk_widget_get_events(widget); + attributes.event_mask |= + (GDK_EXPOSURE_MASK + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + + attributes_mask = GDK_WA_X | GDK_WA_Y | + GDK_WA_VISUAL | GDK_WA_COLORMAP; + + SexyIconInfo *icon_info = &entry->priv->icons[i]; + icon_info->window = gdk_window_new(widget->window, &attributes, + attributes_mask); + gdk_window_set_user_data(icon_info->window, widget); + + gdk_window_set_background(icon_info->window, + &widget->style->base[GTK_WIDGET_STATE(widget)]); + } + + gtk_widget_queue_resize(widget); +} + +static void +sexy_icon_entry_unrealize(GtkWidget *widget) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + GTK_WIDGET_CLASS(parent_class)->unrealize(widget); + + for (i = 0; i < MAX_ICONS; i++) + { + SexyIconInfo *icon_info = &entry->priv->icons[i]; + + gdk_window_destroy(icon_info->window); + icon_info->window = NULL; + } +} + +static void +sexy_icon_entry_size_request(GtkWidget *widget, GtkRequisition *requisition) +{ + GtkEntry *gtkentry; + SexyIconEntry *entry; + gint icon_widths = 0; + int i; + + gtkentry = GTK_ENTRY(widget); + entry = SEXY_ICON_ENTRY(widget); + + for (i = 0; i < MAX_ICONS; i++) + { + int icon_width = get_icon_width(entry, i); + + if (icon_width > 0) + icon_widths += icon_width + ICON_MARGIN; + } + + GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition); + + if (icon_widths > requisition->width) + requisition->width += icon_widths; +} + +static void +place_windows(SexyIconEntry *icon_entry, GtkAllocation *widget_alloc) +{ + SexyIconEntryPosition left_icon_pos; + SexyIconEntryPosition right_icon_pos; + GtkAllocation left_icon_alloc; + GtkAllocation right_icon_alloc; + GtkAllocation text_area_alloc; + + get_text_area_size(icon_entry, &text_area_alloc); + get_icon_allocation(icon_entry, TRUE, widget_alloc, &text_area_alloc, + &left_icon_alloc, &left_icon_pos); + get_icon_allocation(icon_entry, FALSE, widget_alloc, &text_area_alloc, + &right_icon_alloc, &right_icon_pos); + + if (left_icon_alloc.width > 0) + { + text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width + + ICON_MARGIN; + } + + if (right_icon_alloc.width > 0) + text_area_alloc.width -= right_icon_alloc.width + ICON_MARGIN; + + text_area_alloc.width -= text_area_alloc.x; + + gdk_window_move_resize(icon_entry->priv->icons[left_icon_pos].window, + left_icon_alloc.x, left_icon_alloc.y, + left_icon_alloc.width, left_icon_alloc.height); + + gdk_window_move_resize(icon_entry->priv->icons[right_icon_pos].window, + right_icon_alloc.x, right_icon_alloc.y, + right_icon_alloc.width, right_icon_alloc.height); + + gdk_window_move_resize(GTK_ENTRY(icon_entry)->text_area, + text_area_alloc.x, text_area_alloc.y, + text_area_alloc.width, text_area_alloc.height); +} + +static void +sexy_icon_entry_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + g_return_if_fail(SEXY_IS_ICON_ENTRY(widget)); + g_return_if_fail(allocation != NULL); + + widget->allocation = *allocation; + + GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); + + if (GTK_WIDGET_REALIZED(widget)) + place_windows(SEXY_ICON_ENTRY(widget), allocation); +} + +static GdkPixbuf * +get_pixbuf_from_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos) +{ + GdkPixbuf *pixbuf = NULL; + gchar *stock_id; + SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; + GtkIconSize size; + + switch (gtk_image_get_storage_type(GTK_IMAGE(icon_info->icon))) + { + case GTK_IMAGE_PIXBUF: + pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(icon_info->icon)); + g_object_ref(pixbuf); + break; + + case GTK_IMAGE_STOCK: + gtk_image_get_stock(GTK_IMAGE(icon_info->icon), &stock_id, &size); + pixbuf = gtk_widget_render_icon(GTK_WIDGET(entry), + stock_id, size, NULL); + break; + + default: + return NULL; + } + + return pixbuf; +} + +/* Kudos to the gnome-panel guys. */ +static void +colorshift_pixbuf(GdkPixbuf *dest, GdkPixbuf *src, int shift) +{ + gint i, j; + gint width, height, has_alpha, src_rowstride, dest_rowstride; + guchar *target_pixels; + guchar *original_pixels; + guchar *pix_src; + guchar *pix_dest; + int val; + guchar r, g, b; + + has_alpha = gdk_pixbuf_get_has_alpha(src); + width = gdk_pixbuf_get_width(src); + height = gdk_pixbuf_get_height(src); + src_rowstride = gdk_pixbuf_get_rowstride(src); + dest_rowstride = gdk_pixbuf_get_rowstride(dest); + original_pixels = gdk_pixbuf_get_pixels(src); + target_pixels = gdk_pixbuf_get_pixels(dest); + + for (i = 0; i < height; i++) + { + pix_dest = target_pixels + i * dest_rowstride; + pix_src = original_pixels + i * src_rowstride; + + for (j = 0; j < width; j++) + { + r = *(pix_src++); + g = *(pix_src++); + b = *(pix_src++); + + val = r + shift; + *(pix_dest++) = CLAMP(val, 0, 255); + + val = g + shift; + *(pix_dest++) = CLAMP(val, 0, 255); + + val = b + shift; + *(pix_dest++) = CLAMP(val, 0, 255); + + if (has_alpha) + *(pix_dest++) = *(pix_src++); + } + } +} + +static void +draw_icon(GtkWidget *widget, SexyIconEntryPosition icon_pos) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; + GdkPixbuf *pixbuf; + gint x, y, width, height; + + if (icon_info->icon == NULL) + return; + + if ((pixbuf = get_pixbuf_from_icon(entry, icon_pos)) == NULL) + return; + + gdk_drawable_get_size(icon_info->window, &width, &height); + + if (gdk_pixbuf_get_height(pixbuf) > height) + { + GdkPixbuf *temp_pixbuf; + int scale; + + scale = height - (2 * ICON_MARGIN); + + temp_pixbuf = gdk_pixbuf_scale_simple(pixbuf, scale, scale, + GDK_INTERP_BILINEAR); + + g_object_unref(pixbuf); + + pixbuf = temp_pixbuf; + } + + x = (width - gdk_pixbuf_get_width(pixbuf)) / 2; + y = (height - gdk_pixbuf_get_height(pixbuf)) / 2; + + if (icon_info->hovered) + { + GdkPixbuf *temp_pixbuf; + + temp_pixbuf = gdk_pixbuf_copy(pixbuf); + + colorshift_pixbuf(temp_pixbuf, pixbuf, 30); + + g_object_unref(pixbuf); + + pixbuf = temp_pixbuf; + } + + gdk_draw_pixbuf(icon_info->window, widget->style->black_gc, pixbuf, + 0, 0, x, y, -1, -1, + GDK_RGB_DITHER_NORMAL, 0, 0); + + g_object_unref(pixbuf); +} + +static gint +sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event) +{ + SexyIconEntry *entry; + + g_return_val_if_fail(SEXY_IS_ICON_ENTRY(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + entry = SEXY_ICON_ENTRY(widget); + + if (GTK_WIDGET_DRAWABLE(widget)) + { + gboolean found = FALSE; + int i; + + for (i = 0; i < MAX_ICONS && !found; i++) + { + SexyIconInfo *icon_info = &entry->priv->icons[i]; + + if (event->window == icon_info->window) + { + gint width; + GtkAllocation text_area_alloc; + + get_text_area_size(entry, &text_area_alloc); + gdk_drawable_get_size(icon_info->window, &width, NULL); + + gtk_paint_flat_box(widget->style, icon_info->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, + NULL, widget, "entry_bg", + 0, 0, width, text_area_alloc.height); + + draw_icon(widget, i); + + found = TRUE; + } + } + + if (!found) + GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); + } + + return FALSE; +} + +static void +update_icon(GObject *obj, GParamSpec *param, SexyIconEntry *entry) +{ + if (param != NULL) + { + const char *name = g_param_spec_get_name(param); + + if (strcmp(name, "pixbuf") && strcmp(name, "stock") && + strcmp(name, "image") && strcmp(name, "pixmap") && + strcmp(name, "icon_set") && strcmp(name, "pixbuf_animation")) + { + return; + } + } + + gtk_widget_queue_resize(GTK_WIDGET(entry)); +} + +static gint +sexy_icon_entry_enter_notify(GtkWidget *widget, GdkEventCrossing *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + if (event->window == entry->priv->icons[i].window) + { + if (sexy_icon_entry_get_icon_highlight(entry, i)) + { + entry->priv->icons[i].hovered = TRUE; + + update_icon(NULL, NULL, entry); + + break; + } + } + } + + return FALSE; +} + +static gint +sexy_icon_entry_leave_notify(GtkWidget *widget, GdkEventCrossing *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + if (event->window == entry->priv->icons[i].window) + { + if (sexy_icon_entry_get_icon_highlight(entry, i)) + { + entry->priv->icons[i].hovered = FALSE; + + update_icon(NULL, NULL, entry); + + break; + } + } + } + + return FALSE; +} + +static gint +sexy_icon_entry_button_press(GtkWidget *widget, GdkEventButton *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + if (event->window == entry->priv->icons[i].window) + { + if (event->button == 1 && + sexy_icon_entry_get_icon_highlight(entry, i)) + { + entry->priv->icons[i].hovered = FALSE; + + update_icon(NULL, NULL, entry); + } + + g_signal_emit(entry, signals[ICON_PRESSED], 0, i, event->button); + + return TRUE; + } + } + + if (GTK_WIDGET_CLASS(parent_class)->button_press_event) + return GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, + event); + + return FALSE; +} + +static gint +sexy_icon_entry_button_release(GtkWidget *widget, GdkEventButton *event) +{ + SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); + int i; + + for (i = 0; i < MAX_ICONS; i++) + { + GdkWindow *icon_window = entry->priv->icons[i].window; + + if (event->window == icon_window) + { + int width, height; + gdk_drawable_get_size(icon_window, &width, &height); + + if (event->button == 1 && + sexy_icon_entry_get_icon_highlight(entry, i) && + event->x >= 0 && event->y >= 0 && + event->x <= width && event->y <= height) + { + entry->priv->icons[i].hovered = TRUE; + + update_icon(NULL, NULL, entry); + } + + g_signal_emit(entry, signals[ICON_RELEASED], 0, i, event->button); + + return TRUE; + } + } + + if (GTK_WIDGET_CLASS(parent_class)->button_release_event) + return GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, + event); + + return FALSE; +} + +/** + * sexy_icon_entry_new + * + * Creates a new SexyIconEntry widget. + * + * Returns a new #SexyIconEntry. + */ +GtkWidget * +sexy_icon_entry_new(void) +{ + return GTK_WIDGET(g_object_new(SEXY_TYPE_ICON_ENTRY, NULL)); +} + +/** + * sexy_icon_entry_set_icon + * @entry: A #SexyIconEntry. + * @icon_pos: Icon position. + * @icon: A #GtkImage to set as the icon. + * + * Sets the icon shown in the entry + */ +void +sexy_icon_entry_set_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, + GtkImage *icon) +{ + SexyIconInfo *icon_info; + + g_return_if_fail(entry != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(entry)); + g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos)); + g_return_if_fail(icon == NULL || GTK_IS_IMAGE(icon)); + + icon_info = &entry->priv->icons[icon_pos]; + + if (icon == icon_info->icon) + return; + + if (icon_pos == SEXY_ICON_ENTRY_SECONDARY && + entry->priv->icon_released_id != 0) + { + g_signal_handler_disconnect(entry, entry->priv->icon_released_id); + entry->priv->icon_released_id = 0; + } + + if (icon == NULL) + { + if (icon_info->icon != NULL) + { + gtk_widget_destroy(GTK_WIDGET(icon_info->icon)); + icon_info->icon = NULL; + } + } + else + { + g_signal_connect(G_OBJECT(icon), "notify", + G_CALLBACK(update_icon), entry); + + icon_info->icon = icon; + } + + update_icon(NULL, NULL, entry); +} + +/** + * sexy_icon_entry_set_icon_highlight + * @entry: A #SexyIconEntry; + * @primary: Icon position. + * @highlight: TRUE if the icon should highlight on mouse-over + * + * Determines whether the icon will highlight on mouse-over. + */ +void +sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry, + SexyIconEntryPosition icon_pos, + gboolean highlight) +{ + SexyIconInfo *icon_info; + + g_return_if_fail(entry != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(entry)); + g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos)); + + icon_info = &entry->priv->icons[icon_pos]; + + if (icon_info->highlight == highlight) + return; + + icon_info->highlight = highlight; +} + +/** + * sexy_icon_entry_get_icon + * @entry: A #SexyIconEntry. + * @primary: Icon position. + * + * Retrieves the image used for the icon + * + * Returns: A #GtkImage. + */ +GtkImage * +sexy_icon_entry_get_icon(const SexyIconEntry *entry, + SexyIconEntryPosition icon_pos) +{ + g_return_val_if_fail(entry != NULL, NULL); + g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), NULL); + g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), NULL); + + return entry->priv->icons[icon_pos].icon; +} + +/** + * sexy_icon_entry_get_icon_highlight + * @entry: A #SexyIconEntry. + * @primary: Icon position. + * + * Retrieves whether entry will highlight the icon on mouseover. + * + * Returns: TRUE if icon highlights. + */ +gboolean +sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry, + SexyIconEntryPosition icon_pos) +{ + g_return_val_if_fail(entry != NULL, FALSE); + g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), FALSE); + g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), FALSE); + + return entry->priv->icons[icon_pos].highlight; +} + +static void +clear_button_clicked_cb(SexyIconEntry *icon_entry, + SexyIconEntryPosition icon_pos, + int button) +{ + if (icon_pos != SEXY_ICON_ENTRY_SECONDARY || button != 1) + return; + + gtk_entry_set_text(GTK_ENTRY(icon_entry), ""); +} + +/** + * sexy_icon_entry_add_clear_button + * @icon_entry: A #SexyIconEntry. + * + * A convenience function to add a clear button to the end of the entry. + * This is useful for search boxes. + */ +void +sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry) +{ + GtkWidget *icon; + + g_return_if_fail(icon_entry != NULL); + g_return_if_fail(SEXY_IS_ICON_ENTRY(icon_entry)); + + icon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU); + gtk_widget_show(icon); + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(icon_entry), + SEXY_ICON_ENTRY_SECONDARY, + GTK_IMAGE(icon)); + sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(icon_entry), + SEXY_ICON_ENTRY_SECONDARY, TRUE); + + if (icon_entry->priv->icon_released_id != 0) + { + g_signal_handler_disconnect(icon_entry, + icon_entry->priv->icon_released_id); + } + + icon_entry->priv->icon_released_id = + g_signal_connect(G_OBJECT(icon_entry), "icon_released", + G_CALLBACK(clear_button_clicked_cb), NULL); +} diff --git a/gedit/sexy-icon-entry.h b/gedit/sexy-icon-entry.h new file mode 100644 index 00000000..da1c07d2 --- /dev/null +++ b/gedit/sexy-icon-entry.h @@ -0,0 +1,101 @@ +/* + * @file libsexy/sexy-icon-entry.h Entry widget + * + * @Copyright (C) 2004-2005 Christian Hammond. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _SEXY_ICON_ENTRY_H_ +#define _SEXY_ICON_ENTRY_H_ + +typedef struct _SexyIconEntry SexyIconEntry; +typedef struct _SexyIconEntryClass SexyIconEntryClass; +typedef struct _SexyIconEntryPriv SexyIconEntryPriv; + +#include +#include + +#define SEXY_TYPE_ICON_ENTRY (sexy_icon_entry_get_type()) +#define SEXY_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SEXY_TYPE_ICON_ENTRY, SexyIconEntry)) +#define SEXY_ICON_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), SEXY_TYPE_ICON_ENTRY, SexyIconEntryClass)) +#define SEXY_IS_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), SEXY_TYPE_ICON_ENTRY)) +#define SEXY_IS_ICON_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), SEXY_TYPE_ICON_ENTRY)) +#define SEXY_ICON_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), SEXY_TYPE_ICON_ENTRY, SexyIconEntryClass)) + +typedef enum +{ + SEXY_ICON_ENTRY_PRIMARY, + SEXY_ICON_ENTRY_SECONDARY + +} SexyIconEntryPosition; + +struct _SexyIconEntry +{ + GtkEntry parent_object; + + SexyIconEntryPriv *priv; + + void (*gtk_reserved1)(void); + void (*gtk_reserved2)(void); + void (*gtk_reserved3)(void); + void (*gtk_reserved4)(void); +}; + +struct _SexyIconEntryClass +{ + GtkEntryClass parent_class; + + /* Signals */ + void (*icon_pressed)(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, + int button); + void (*icon_released)(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, + int button); + + void (*gtk_reserved1)(void); + void (*gtk_reserved2)(void); + void (*gtk_reserved3)(void); + void (*gtk_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType sexy_icon_entry_get_type(void); + +GtkWidget *sexy_icon_entry_new(void); + +void sexy_icon_entry_set_icon(SexyIconEntry *entry, + SexyIconEntryPosition position, + GtkImage *icon); + +void sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry, + SexyIconEntryPosition position, + gboolean highlight); + +GtkImage *sexy_icon_entry_get_icon(const SexyIconEntry *entry, + SexyIconEntryPosition position); + +gboolean sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry, + SexyIconEntryPosition position); +void sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry); + +G_END_DECLS + +#endif /* _SEXY_ICON_ENTRY_H_ */ diff --git a/gedit/update-from-bacon.sh b/gedit/update-from-bacon.sh new file mode 100644 index 00000000..99206fd0 --- /dev/null +++ b/gedit/update-from-bacon.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +function die() { + echo $* + exit 1 +} + +if test -z "$BACONDIR"; then + echo "Must set BACONDIR" + exit 1 +fi + +if test -z "$BACONFILES"; then + echo "Must set BACONFILES" + exit 1 +fi + +for FILE in $BACONFILES; do + if cmp -s $BACONDIR/$FILE $FILE; then + echo "File $FILE is unchanged" + else + cp $BACONDIR/$FILE $FILE || die "Could not move $BACONDIR/$FILE to $FILE" + echo "Updated $FILE" + fi +done diff --git a/m4/.cvsignore b/m4/.cvsignore new file mode 100644 index 00000000..9f841b0a --- /dev/null +++ b/m4/.cvsignore @@ -0,0 +1 @@ +intltool.m4 diff --git a/m4/python.m4 b/m4/python.m4 new file mode 100644 index 00000000..a1396df7 --- /dev/null +++ b/m4/python.m4 @@ -0,0 +1,62 @@ +## this one is commonly used with AM_PATH_PYTHONDIR ... +dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) +dnl Check if a module containing a given symbol is visible to python. +AC_DEFUN(AM_CHECK_PYMOD, +[AC_REQUIRE([AM_PATH_PYTHON]) +py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1) +AC_CACHE_VAL(py_cv_mod_$py_mod_var, [ +ifelse([$2],[], [prog=" +import sys +try: + import $1 +except ImportError: + sys.exit(1) +except: + sys.exit(0) +sys.exit(0)"], [prog=" +import $1 +$1.$2"]) +if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC + then + eval "py_cv_mod_$py_mod_var=yes" + else + eval "py_cv_mod_$py_mod_var=no" + fi +]) +py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"` +if test "x$py_val" != xno; then + AC_MSG_RESULT(yes) + ifelse([$3], [],, [$3 +])dnl +else + AC_MSG_RESULT(no) + ifelse([$4], [],, [$4 +])dnl +fi +]) + +dnl a macro to check for ability to create python extensions +dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) +dnl function also defines PYTHON_INCLUDES +AC_DEFUN([AM_CHECK_PYTHON_HEADERS], +[AC_REQUIRE([AM_PATH_PYTHON]) +AC_MSG_CHECKING(for headers required to compile python extensions) +dnl deduce PYTHON_INCLUDES +py_prefix=`$PYTHON -c "import sys; print sys.prefix"` +py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` +PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}" +if test "$py_prefix" != "$py_exec_prefix"; then + PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" +fi +AC_SUBST(PYTHON_INCLUDES) +dnl check if the headers exist: +save_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES" +AC_TRY_CPP([#include ],dnl +[AC_MSG_RESULT(found) +$1],dnl +[AC_MSG_RESULT(not found) +$2]) +CPPFLAGS="$save_CPPFLAGS" +]) diff --git a/plugins/ChangeLog b/plugins/ChangeLog-20051212 similarity index 100% rename from plugins/ChangeLog rename to plugins/ChangeLog-20051212 diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 79ee00f4..9e968cd5 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,5 +1,11 @@ -DIST_SUBDIRS = changecase docinfo savecopy sample time spell indent taglist shell_output sort +#DIST_SUBDIRS = changecase docinfo savecopy sample time spell indent taglist shell_output sort +DIST_SUBDIRS = changecase docinfo indent sample sort spell time taglist -SUBDIRS = changecase docinfo savecopy sample time indent taglist shell_output sort $(SPELL_PLUGIN_DIR) +#SUBDIRS = changecase docinfo savecopy sample time indent taglist shell_output sort $(SPELL_PLUGIN_DIR) +SUBDIRS = changecase docinfo indent sample sort time taglist $(SPELL_PLUGIN_DIR) + +if ENABLE_PYTHON +DIST_SUBDIRS += pythonconsole +SUBDIRS += pythonconsole +endif -EXTRA_DIST = ChangeLog diff --git a/plugins/changecase/Makefile.am b/plugins/changecase/Makefile.am index a3723c33..38f736ea 100644 --- a/plugins/changecase/Makefile.am +++ b/plugins/changecase/Makefile.am @@ -1,4 +1,4 @@ -# Change Case plugin +# changecase plugin plugindir = $(libdir)/gedit-2/plugins INCLUDES = \ @@ -6,19 +6,29 @@ INCLUDES = \ $(GEDIT_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ - -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ + -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" plugin_LTLIBRARIES = libchangecase.la -libchangecase_la_SOURCES = changecase.c +libchangecase_la_SOURCES = \ + gedit-changecase-plugin.h \ + gedit-changecase-plugin.c + libchangecase_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) +gladedir = $(datadir)/gedit-2/glade +glade_DATA = + plugin_in_files = changecase.gedit-plugin.desktop.in %.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) -EXTRA_DIST = $(plugin_in_files) +EXTRA_DIST = $(glade_DATA) $(plugin_in_files) CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) + diff --git a/plugins/changecase/changecase.gedit-plugin.desktop.in b/plugins/changecase/changecase.gedit-plugin.desktop.in index f08d3aaa..52a226f4 100644 --- a/plugins/changecase/changecase.gedit-plugin.desktop.in +++ b/plugins/changecase/changecase.gedit-plugin.desktop.in @@ -1,6 +1,8 @@ [Gedit Plugin] -Location=changecase +Module=changecase +IAge=2 _Name=Change Case _Description=Changes the case of selected text. -Author=Paolo Borelli -Copyright=Copyright © 2004 Paolo Borelli +Authors=Paolo Borelli +Copyright=Copyright © 2004-2005 Paolo Borelli +Website=http://www.gedit.org diff --git a/plugins/changecase/gedit-changecase-plugin.c b/plugins/changecase/gedit-changecase-plugin.c new file mode 100644 index 00000000..d35d7a17 --- /dev/null +++ b/plugins/changecase/gedit-changecase-plugin.c @@ -0,0 +1,386 @@ +/* + * gedit-changecase-plugin.c + * + * Copyright (C) 2004-2005 - Paolo Borelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-changecase-plugin.h" + +#include +#include + +#include + +#define WINDOW_DATA_KEY "GeditChangecasePluginWindowData" + +GEDIT_PLUGIN_REGISTER_TYPE(GeditChangecasePlugin, gedit_changecase_plugin) + +typedef enum { + TO_UPPER_CASE, + TO_LOWER_CASE, + INVERT_CASE, + TO_TITLE_CASE, +} ChangeCaseChoice; + +static void +do_upper_case (GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end) +{ + GString *s = g_string_new (NULL); + + while (!gtk_text_iter_is_end (start) && + !gtk_text_iter_equal (start, end)) + { + gunichar c, nc; + + c = gtk_text_iter_get_char (start); + nc = g_unichar_toupper (c); + g_string_append_unichar (s, nc); + + gtk_text_iter_forward_char (start); + } + + gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); + gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len); + + g_string_free (s, TRUE); +} + +static void +do_lower_case (GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end) +{ + GString *s = g_string_new (NULL); + + while (!gtk_text_iter_is_end (start) && + !gtk_text_iter_equal (start, end)) + { + gunichar c, nc; + + c = gtk_text_iter_get_char (start); + nc = g_unichar_tolower (c); + g_string_append_unichar (s, nc); + + gtk_text_iter_forward_char (start); + } + + gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); + gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len); + + g_string_free (s, TRUE); +} + +static void +do_invert_case (GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end) +{ + GString *s = g_string_new (NULL); + + while (!gtk_text_iter_is_end (start) && + !gtk_text_iter_equal (start, end)) + { + gunichar c, nc; + + c = gtk_text_iter_get_char (start); + if (g_unichar_islower (c)) + nc = g_unichar_toupper (c); + else + nc = g_unichar_tolower (c); + g_string_append_unichar (s, nc); + + gtk_text_iter_forward_char (start); + } + + gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); + gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len); + + g_string_free (s, TRUE); +} + +static void +do_title_case (GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end) +{ + GString *s = g_string_new (NULL); + + while (!gtk_text_iter_is_end (start) && + !gtk_text_iter_equal (start, end)) + { + gunichar c, nc; + + c = gtk_text_iter_get_char (start); + if (gtk_text_iter_starts_word (start)) + nc = g_unichar_totitle (c); + else + nc = g_unichar_tolower (c); + g_string_append_unichar (s, nc); + + gtk_text_iter_forward_char (start); + } + + gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); + gtk_text_buffer_insert_at_cursor (buffer, s->str, s->len); + + g_string_free (s, TRUE); +} + +static void +change_case (GeditWindow *window, + ChangeCaseChoice choice) +{ + GeditDocument *doc; + GtkTextIter start, end; + + gedit_debug (DEBUG_PLUGINS); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &start, &end)) + { + return; + } + + gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc)); + + switch (choice) + { + case TO_UPPER_CASE: + do_upper_case (GTK_TEXT_BUFFER (doc), &start, &end); + break; + case TO_LOWER_CASE: + do_lower_case (GTK_TEXT_BUFFER (doc), &start, &end); + break; + case INVERT_CASE: + do_invert_case (GTK_TEXT_BUFFER (doc), &start, &end); + break; + case TO_TITLE_CASE: + do_title_case (GTK_TEXT_BUFFER (doc), &start, &end); + break; + default: + g_return_if_reached (); + } + + gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc)); +} + +static void +upper_case_cb (GtkAction *action, + GeditWindow *window) +{ + change_case (window, TO_UPPER_CASE); +} + +static void +lower_case_cb (GtkAction *action, + GeditWindow *window) +{ + change_case (window, TO_LOWER_CASE); +} + +static void +invert_case_cb (GtkAction *action, + GeditWindow *window) +{ + change_case (window, INVERT_CASE); +} + +static void +title_case_cb (GtkAction *action, + GeditWindow *window) +{ + change_case (window, TO_TITLE_CASE); +} + +static const GtkActionEntry action_entries[] = +{ + { "ChangeCase", NULL, N_("C_hange Case") }, + { "UpperCase", NULL, N_("All _Upper Case"), NULL, + N_("Change selected text to upper case"), + G_CALLBACK (upper_case_cb) }, + { "LowerCase", NULL, N_("All _Lower Case"), NULL, + N_("Change selected text to lower case"), + G_CALLBACK (lower_case_cb) }, + { "InvertCase", NULL, N_("_Invert Case"), NULL, + N_("Invert the case of selected text"), + G_CALLBACK (invert_case_cb) }, + { "TitleCase", NULL, N_("_Title Case"), NULL, + N_("Capitalize the first letter of each selected word"), + G_CALLBACK (title_case_cb) } +}; + +const gchar submenu[] = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +""; + +static void +gedit_changecase_plugin_init (GeditChangecasePlugin *plugin) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditChangecasePlugin initializing"); +} + +static void +gedit_changecase_plugin_finalize (GObject *object) +{ + G_OBJECT_CLASS (gedit_changecase_plugin_parent_class)->finalize (object); + + gedit_debug_message (DEBUG_PLUGINS, "GeditChangecasePlugin finalizing"); +} + +typedef struct +{ + GtkActionGroup *action_group; + guint ui_id; +} WindowData; + +static void +free_window_data (WindowData *data) +{ + g_return_if_fail (data != NULL); + + g_free (data); +} + +static void +update_ui_real (GeditWindow *window, + WindowData *data) +{ + GtkTextView *view; + GtkAction *action; + + gedit_debug (DEBUG_PLUGINS); + + view = GTK_TEXT_VIEW (gedit_window_get_active_view (window)); + + action = gtk_action_group_get_action (data->action_group, + "ChangeCase"); + gtk_action_set_sensitive (action, + (view != NULL) && + gtk_text_view_get_editable (view)); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + GError *error = NULL; + + gedit_debug (DEBUG_PLUGINS); + + data = g_new (WindowData, 1); + + manager = gedit_window_get_ui_manager (window); + + data->action_group = gtk_action_group_new ("GeditChangecasePluginActions"); + gtk_action_group_set_translation_domain (data->action_group, + GETTEXT_PACKAGE); + gtk_action_group_add_actions (data->action_group, + action_entries, + G_N_ELEMENTS (action_entries), + window); + + gtk_ui_manager_insert_action_group (manager, data->action_group, -1); + + data->ui_id = gtk_ui_manager_add_ui_from_string (manager, + submenu, + -1, + &error); + if (data->ui_id == 0) + { + g_warning (error->message); + return; + } + + g_object_set_data_full (G_OBJECT (window), + WINDOW_DATA_KEY, + data, + (GDestroyNotify) free_window_data); + + update_ui_real (window, data); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + manager = gedit_window_get_ui_manager (window); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + gtk_ui_manager_remove_ui (manager, data->ui_id); + gtk_ui_manager_remove_action_group (manager, data->action_group); + + g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + update_ui_real (window, data); +} + +static void +gedit_changecase_plugin_class_init (GeditChangecasePluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_changecase_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; +} diff --git a/plugins/changecase/gedit-changecase-plugin.h b/plugins/changecase/gedit-changecase-plugin.h new file mode 100644 index 00000000..9587928c --- /dev/null +++ b/plugins/changecase/gedit-changecase-plugin.h @@ -0,0 +1,72 @@ +/* + * gedit-changecase-plugin.h + * + * Copyright (C) 2004-2005 - Paolo Borelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_CHANGECASE_PLUGIN_H__ +#define __GEDIT_CHANGECASE_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_CHANGECASE_PLUGIN (gedit_changecase_plugin_get_type ()) +#define GEDIT_CHANGECASE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_CHANGECASE_PLUGIN, GeditChangecasePlugin)) +#define GEDIT_CHANGECASE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_CHANGECASE_PLUGIN, GeditChangecasePluginClass)) +#define GEDIT_IS_CHANGECASE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_CHANGECASE_PLUGIN)) +#define GEDIT_IS_CHANGECASE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_CHANGECASE_PLUGIN)) +#define GEDIT_CHANGECASE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_CHANGECASE_PLUGIN, GeditChangecasePluginClass)) + +/* + * Main object structure + */ +typedef struct _GeditChangecasePlugin GeditChangecasePlugin; + +struct _GeditChangecasePlugin +{ + GeditPlugin parent_instance; +}; + +/* + * Class definition + */ +typedef struct _GeditChangecasePluginClass GeditChangecasePluginClass; + +struct _GeditChangecasePluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_changecase_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_CHANGECASE_PLUGIN_H__ */ diff --git a/plugins/docinfo/Makefile.am b/plugins/docinfo/Makefile.am index fa368a8a..13bdd924 100644 --- a/plugins/docinfo/Makefile.am +++ b/plugins/docinfo/Makefile.am @@ -1,4 +1,4 @@ -# Document Info plugin +# docinfo plugin plugindir = $(libdir)/gedit-2/plugins INCLUDES = \ @@ -6,12 +6,16 @@ INCLUDES = \ $(GEDIT_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" plugin_LTLIBRARIES = libdocinfo.la -libdocinfo_la_SOURCES = docinfo.c +libdocinfo_la_SOURCES = \ + gedit-docinfo-plugin.h \ + gedit-docinfo-plugin.c + libdocinfo_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) gladedir = $(datadir)/gedit-2/glade @@ -26,4 +30,5 @@ plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) EXTRA_DIST = $(glade_DATA) $(plugin_in_files) CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) diff --git a/plugins/docinfo/docinfo.gedit-plugin.desktop.in b/plugins/docinfo/docinfo.gedit-plugin.desktop.in index 72dc3acf..77f2793d 100644 --- a/plugins/docinfo/docinfo.gedit-plugin.desktop.in +++ b/plugins/docinfo/docinfo.gedit-plugin.desktop.in @@ -1,7 +1,7 @@ [Gedit Plugin] -Location=docinfo +Module=docinfo +IAge=2 _Name=Document Statistics _Description=Analyzes the current document and reports the number of words, lines, characters and non-space characters in it. -Author=Paolo Maggi -Copyright=Copyright © 2002-2003 Paolo Maggi - +Authors=Paolo Maggi ;Jorge Alberto Torres +Copyright=Copyright © 2002-2005 Paolo Maggi diff --git a/plugins/docinfo/docinfo.glade2 b/plugins/docinfo/docinfo.glade2 index 74b33875..4957af76 100644 --- a/plugins/docinfo/docinfo.glade2 +++ b/plugins/docinfo/docinfo.glade2 @@ -5,13 +5,19 @@ - gedit: Document Info plugin + Document Statistics GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False False - False - True + True + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False @@ -32,7 +38,8 @@ gtk-close True GTK_RELIEF_NORMAL - 0 + True + -7 @@ -41,10 +48,73 @@ True True True - Update - True GTK_RELIEF_NORMAL - 0 + True + -5 + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-refresh + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Update + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + @@ -76,6 +146,10 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 @@ -103,6 +177,10 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 @@ -115,16 +193,16 @@ 6 True - 5 + 6 2 False 6 18 - + True - Lines + Bytes False False GTK_JUSTIFY_LEFT @@ -134,19 +212,23 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 0 - 1 + 5 + 6 fill - + True 0 False @@ -158,21 +240,25 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 1 2 - 0 - 1 + 5 + 6 fill - + True - Words + Characters (no spaces) False False GTK_JUSTIFY_LEFT @@ -182,18 +268,23 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 1 - 2 + 4 + 5 + fill - + True 0 False @@ -205,12 +296,16 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 1 2 - 1 - 2 + 4 + 5 fill @@ -229,12 +324,16 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 2 - 3 + 3 + 4 fill @@ -253,6 +352,38 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 3 + 4 + fill + + + + + + + True + 0 + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 1 @@ -265,9 +396,9 @@ - + True - Characters (no spaces) + Words False False GTK_JUSTIFY_LEFT @@ -277,19 +408,51 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 3 - 4 + 2 + 3 fill - + + True + Lines + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + True 0 False @@ -301,21 +464,67 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 1 2 - 3 - 4 + 1 + 2 fill - + True - Bytes + Document + True + True + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + 0 + True + True + + + + + + 6 + True + False + 6 + + + + True + Selection False False GTK_JUSTIFY_LEFT @@ -325,19 +534,20 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 - 0 - 1 - 4 - 5 - fill - + 0 + False + False - + True 0 False @@ -349,14 +559,115 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 - 1 - 2 - 4 - 5 - fill - + 0 + False + False + + + + + + True + 0 + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 0 + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 0 + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 0 + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False diff --git a/plugins/docinfo/gedit-docinfo-plugin.c b/plugins/docinfo/gedit-docinfo-plugin.c new file mode 100644 index 00000000..7141cc2c --- /dev/null +++ b/plugins/docinfo/gedit-docinfo-plugin.c @@ -0,0 +1,555 @@ +/* + * gedit-docinfo-plugin.c + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-docinfo-plugin.h" + +#include /* For strlen (...) */ + +#include +#include +#include + +#include +#include + +#define WINDOW_DATA_KEY "GeditDocInfoWindowData" +#define MENU_PATH "/MenuBar/ToolsMenu/ToolsOps_2" + +GEDIT_PLUGIN_REGISTER_TYPE(GeditDocInfoPlugin, gedit_docinfo_plugin) + +typedef struct +{ + GtkWidget *dialog; + GtkWidget *file_name_label; + GtkWidget *lines_label; + GtkWidget *words_label; + GtkWidget *chars_label; + GtkWidget *chars_ns_label; + GtkWidget *bytes_label; + GtkWidget *selection_vbox; + GtkWidget *selected_lines_label; + GtkWidget *selected_words_label; + GtkWidget *selected_chars_label; + GtkWidget *selected_chars_ns_label; + GtkWidget *selected_bytes_label; +} DocInfoDialog; + +typedef struct +{ + GtkActionGroup *ui_action_group; + guint ui_id; + + DocInfoDialog *dialog; +} WindowData; + +static void docinfo_dialog_response_cb (GtkDialog *widget, + gint res_id, + GeditWindow *window); + +static void +docinfo_dialog_destroy_cb (GtkObject *obj, + gpointer data_pointer) +{ + gedit_debug (DEBUG_PLUGINS); + + WindowData *data = (WindowData *) data_pointer; + + if (data != NULL) + { + g_free (data->dialog); + data->dialog = NULL; + } +} + +static DocInfoDialog * +get_docinfo_dialog (GeditWindow *window, + WindowData *data) +{ + DocInfoDialog *dialog; + GtkWidget *content; + GtkWidget *error_widget; + gboolean ret; + + gedit_debug (DEBUG_PLUGINS); + + dialog = g_new (DocInfoDialog, 1); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "docinfo.glade2", + "dialog", + &error_widget, + "dialog", &dialog->dialog, + "docinfo_dialog_content", &content, + "file_name_label", &dialog->file_name_label, + "words_label", &dialog->words_label, + "bytes_label", &dialog->bytes_label, + "lines_label", &dialog->lines_label, + "chars_label", &dialog->chars_label, + "chars_ns_label", &dialog->chars_ns_label, + "selection_vbox", &dialog->selection_vbox, + "selected_words_label", &dialog->selected_words_label, + "selected_bytes_label", &dialog->selected_bytes_label, + "selected_lines_label", &dialog->selected_lines_label, + "selected_chars_label", &dialog->selected_chars_label, + "selected_chars_ns_label", &dialog->selected_chars_ns_label, + NULL); + + if (!ret) + { + gedit_warning (GTK_WINDOW (window), + gtk_label_get_label (GTK_LABEL (error_widget))); + + g_free (dialog); + gtk_widget_destroy (error_widget); + + return NULL; + } + + gtk_dialog_set_default_response (GTK_DIALOG (dialog->dialog), + GTK_RESPONSE_OK); + gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), + GTK_WINDOW (window)); + + g_signal_connect (dialog->dialog, + "destroy", + G_CALLBACK (docinfo_dialog_destroy_cb), + data); + g_signal_connect (dialog->dialog, + "response", + G_CALLBACK (docinfo_dialog_response_cb), + window); + + return dialog; +} + + +static void +calculate_info (GeditDocument *doc, + GtkTextIter *start, + GtkTextIter *end, + gint *chars, + gint *words, + gint *white_chars, + gint *bytes) +{ + gchar *text; + PangoLogAttr *attrs; + gint i; + + text = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), + start, + end, + TRUE); + + *chars = g_utf8_strlen (text, -1); + attrs = g_new0 (PangoLogAttr, *chars + 1); + + pango_get_log_attrs (text, + -1, + 0, + pango_language_from_string ("C"), + attrs, + *chars + 1); + + for (i = 0; i < (*chars); i++) + { + if (attrs [i].is_white) + ++(*white_chars); + + if (attrs [i].is_word_start) + ++(*words); + } + + *bytes = strlen (text); + + g_free (attrs); + g_free (text); +} + +static void +docinfo_real (GeditDocument *doc, + DocInfoDialog *dialog) +{ + GtkTextIter start, end; + gint words = 0; + gint chars = 0; + gint white_chars = 0; + gint lines = 0; + gint bytes = 0; + gchar *tmp_str; + gchar *doc_name; + + gedit_debug (DEBUG_PLUGINS); + + gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc), + &start, + &end); + + lines = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (doc)); + + calculate_info (doc, + &start, &end, + &chars, &words, &white_chars, &bytes); + + if (chars == 0) + lines = 0; + + gedit_debug_message (DEBUG_PLUGINS, "Chars: %d", chars); + gedit_debug_message (DEBUG_PLUGINS, "Lines: %d", lines); + gedit_debug_message (DEBUG_PLUGINS, "Words: %d", words); + gedit_debug_message (DEBUG_PLUGINS, "Chars non-space: %d", chars - white_chars); + gedit_debug_message (DEBUG_PLUGINS, "Bytes: %d", bytes); + + doc_name = gedit_document_get_short_name_for_display (doc); + tmp_str = g_strdup_printf ("%s", doc_name); + gtk_label_set_markup (GTK_LABEL (dialog->file_name_label), tmp_str); + g_free (doc_name); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", lines); + gtk_label_set_text (GTK_LABEL (dialog->lines_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", words); + gtk_label_set_text (GTK_LABEL (dialog->words_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", chars); + gtk_label_set_text (GTK_LABEL (dialog->chars_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", chars - white_chars); + gtk_label_set_text (GTK_LABEL (dialog->chars_ns_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", bytes); + gtk_label_set_text (GTK_LABEL (dialog->bytes_label), tmp_str); + g_free (tmp_str); +} + +static void +selectioninfo_real (GeditDocument *doc, + DocInfoDialog *dialog) +{ + gboolean sel; + GtkTextIter start, end; + gint words = 0; + gint chars = 0; + gint white_chars = 0; + gint lines = 0; + gint bytes = 0; + gchar *tmp_str; + + gedit_debug (DEBUG_PLUGINS); + + sel = gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &start, + &end); + + if (sel) + { + lines = gtk_text_iter_get_line (&end) - gtk_text_iter_get_line (&start) + 1; + + calculate_info (doc, + &start, &end, + &chars, &words, &white_chars, &bytes); + + gedit_debug_message (DEBUG_PLUGINS, "Selected chars: %d", chars); + gedit_debug_message (DEBUG_PLUGINS, "Selected lines: %d", lines); + gedit_debug_message (DEBUG_PLUGINS, "Selected words: %d", words); + gedit_debug_message (DEBUG_PLUGINS, "Selected chars non-space: %d", chars - white_chars); + gedit_debug_message (DEBUG_PLUGINS, "Selected bytes: %d", bytes); + + gtk_widget_set_sensitive (dialog->selection_vbox, TRUE); + } + else + { + gtk_widget_set_sensitive (dialog->selection_vbox, FALSE); + + gedit_debug_message (DEBUG_PLUGINS, "Selection empty"); + } + + if (chars == 0) + lines = 0; + + tmp_str = g_strdup_printf("%d", lines); + gtk_label_set_text (GTK_LABEL (dialog->selected_lines_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", words); + gtk_label_set_text (GTK_LABEL (dialog->selected_words_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", chars); + gtk_label_set_text (GTK_LABEL (dialog->selected_chars_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", chars - white_chars); + gtk_label_set_text (GTK_LABEL (dialog->selected_chars_ns_label), tmp_str); + g_free (tmp_str); + + tmp_str = g_strdup_printf("%d", bytes); + gtk_label_set_text (GTK_LABEL (dialog->selected_bytes_label), tmp_str); + g_free (tmp_str); +} + +static void +docinfo_cb (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), + WINDOW_DATA_KEY); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + if (data->dialog != NULL) + { + gtk_window_present (GTK_WINDOW (data->dialog->dialog)); + gtk_widget_grab_focus (GTK_WIDGET (data->dialog->dialog)); + } + else + { + DocInfoDialog *dialog; + + dialog = get_docinfo_dialog (window, data); + g_return_if_fail (dialog != NULL); + + data->dialog = dialog; + + gtk_widget_show (GTK_WIDGET (dialog->dialog)); + } + + docinfo_real (doc, + data->dialog); + selectioninfo_real (doc, + data->dialog); +} + +static void +docinfo_dialog_response_cb (GtkDialog *widget, + gint res_id, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), + WINDOW_DATA_KEY); + + switch (res_id) + { + case GTK_RESPONSE_CLOSE: + { + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_CLOSE"); + gtk_widget_destroy (data->dialog->dialog); + + break; + } + + case GTK_RESPONSE_OK: + { + GeditDocument *doc; + + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_OK"); + + doc = gedit_window_get_active_document (window); + + if (doc == NULL) + { + gtk_widget_destroy (data->dialog->dialog); + } + else + { + docinfo_real (doc, + data->dialog); + selectioninfo_real (doc, + data->dialog); + } + + break; + } + } +} + +static const GtkActionEntry action_entries[] = +{ + { "DocumentStatistics", + NULL, + N_("_Document Statistics"), + NULL, + N_("Get statistic info on current document"), + G_CALLBACK (docinfo_cb) } +}; + +static void +free_window_data (WindowData *data) +{ + g_return_if_fail (data != NULL); + + gedit_debug (DEBUG_PLUGINS); + + g_object_unref (data->ui_action_group); + + if (data->dialog != NULL) + { + gtk_widget_destroy (data->dialog->dialog); + } + + g_free (data); +} + +static void +update_ui_real (GeditWindow *window, + WindowData *data) +{ + GeditView *view; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (window); + + gtk_action_group_set_sensitive (data->ui_action_group, + (view != NULL)); +} + +static void +gedit_docinfo_plugin_init (GeditDocInfoPlugin *plugin) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditDocInfoPlugin initializing"); +} + +static void +gedit_docinfo_plugin_finalize (GObject *object) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditDocInfoPlugin finalizing"); + + G_OBJECT_CLASS (gedit_docinfo_plugin_parent_class)->finalize (object); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = g_new (WindowData, 1); + manager = gedit_window_get_ui_manager (window); + + data->dialog = NULL; + data->ui_action_group = gtk_action_group_new ("GeditDocInfoPluginActions"); + + gtk_action_group_set_translation_domain (data->ui_action_group, + GETTEXT_PACKAGE); + gtk_action_group_add_actions (data->ui_action_group, + action_entries, + G_N_ELEMENTS (action_entries), + window); + + gtk_ui_manager_insert_action_group (manager, + data->ui_action_group, + -1); + + data->ui_id = gtk_ui_manager_new_merge_id (manager); + + g_object_set_data_full (G_OBJECT (window), + WINDOW_DATA_KEY, + data, + (GDestroyNotify) free_window_data); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "DocumentStatistics", + "DocumentStatistics", + GTK_UI_MANAGER_MENUITEM, + FALSE); + + update_ui_real (window, + data); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + manager = gedit_window_get_ui_manager (window); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), + WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + gtk_ui_manager_remove_ui (manager, + data->ui_id); + gtk_ui_manager_remove_action_group (manager, + data->ui_action_group); + + g_object_set_data (G_OBJECT (window), + WINDOW_DATA_KEY, + NULL); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), + WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + update_ui_real (window, + data); +} + +static void +gedit_docinfo_plugin_class_init (GeditDocInfoPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_docinfo_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; +} diff --git a/plugins/docinfo/gedit-docinfo-plugin.h b/plugins/docinfo/gedit-docinfo-plugin.h new file mode 100644 index 00000000..36d6bddc --- /dev/null +++ b/plugins/docinfo/gedit-docinfo-plugin.h @@ -0,0 +1,75 @@ +/* + * gedit-docinfo-plugin.h + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_DOCINFO_PLUGIN_H__ +#define __GEDIT_DOCINFO_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_DOCINFO_PLUGIN (gedit_docinfo_plugin_get_type ()) +#define GEDIT_DOCINFO_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_DOCINFO_PLUGIN, GeditDocInfoPlugin)) +#define GEDIT_DOCINFO_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_DOCINFO_PLUGIN, GeditDocInfoPluginClass)) +#define GEDIT_IS_DOCINFO_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_DOCINFO_PLUGIN)) +#define GEDIT_IS_DOCINFO_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_DOCINFO_PLUGIN)) +#define GEDIT_DOCINFO_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_DOCINFO_PLUGIN, GeditDocInfoPluginClass)) + +/* Private structure type */ +typedef struct _GeditDocInfoPluginPrivate GeditDocInfoPluginPrivate; + +/* + * Main object structure + */ +typedef struct _GeditDocInfoPlugin GeditDocInfoPlugin; + +struct _GeditDocInfoPlugin +{ + GeditPlugin parent_instance; +}; + +/* + * Class definition + */ +typedef struct _GeditDocInfoPluginClass GeditDocInfoPluginClass; + +struct _GeditDocInfoPluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_docinfo_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_DOCINFO_PLUGIN_H__ */ diff --git a/plugins/indent/Makefile.am b/plugins/indent/Makefile.am index dbc011b8..490b27fd 100644 --- a/plugins/indent/Makefile.am +++ b/plugins/indent/Makefile.am @@ -1,4 +1,4 @@ -# INDENT plugin +# indent plugin plugindir = $(libdir)/gedit-2/plugins INCLUDES = \ @@ -6,21 +6,29 @@ INCLUDES = \ $(GEDIT_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" plugin_LTLIBRARIES = libindent.la -libindent_la_SOURCES = indent.c +libindent_la_SOURCES = \ + gedit-indent-plugin.h \ + gedit-indent-plugin.c + libindent_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) +gladedir = $(datadir)/gedit-2/glade +glade_DATA = + plugin_in_files = indent.gedit-plugin.desktop.in %.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) -EXTRA_DIST = $(plugin_in_files) +EXTRA_DIST = $(glade_DATA) $(plugin_in_files) CLEANFILES = $(plugin_DATA) - +DISTCLEANFILES = $(plugin_DATA) + diff --git a/plugins/indent/gedit-indent-plugin.c b/plugins/indent/gedit-indent-plugin.c new file mode 100644 index 00000000..13f7b56e --- /dev/null +++ b/plugins/indent/gedit-indent-plugin.c @@ -0,0 +1,323 @@ +/* + * gedit-indent-plugin.h + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-indent-plugin.h" + +#include +#include + +#include +#include + +#define WINDOW_DATA_KEY "GeditIndentPluginWindowData" +#define MENU_PATH "/MenuBar/EditMenu/EditOps_5" + +#define GEDIT_INDENT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_INDENT_PLUGIN, GeditIndentPluginPrivate)) + +GEDIT_PLUGIN_REGISTER_TYPE(GeditIndentPlugin, gedit_indent_plugin) + +typedef struct +{ + GtkActionGroup *action_group; + guint ui_id; +} WindowData; + +static void indent_cb (GtkAction *action, GeditWindow *window); +static void unindent_cb (GtkAction *action, GeditWindow *window); + +/* UI actions. */ +static const GtkActionEntry action_entries[] = +{ + { "Indent", + GTK_STOCK_INDENT, + N_("_Indent"), + "T", + N_("Indent selected lines"), + G_CALLBACK (indent_cb) }, + + { "Unindent", + GTK_STOCK_UNINDENT, + N_("U_nindent"), + "T", + N_("Unindent selected lines"), + G_CALLBACK (unindent_cb) } +}; + +static void +gedit_indent_plugin_init (GeditIndentPlugin *plugin) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditIndentPlugin initializing"); +} + +static void +gedit_indent_plugin_finalize (GObject *object) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditIndentPlugin finalizing"); + + G_OBJECT_CLASS (gedit_indent_plugin_parent_class)->finalize (object); +} + +static void +indent_cb (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + GtkTextIter start, end, iter; + gint i, start_line, end_line; + gchar *tab_buffer = NULL; + + gedit_debug (DEBUG_PLUGINS); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc)); + + gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start, &end); + + start_line = gtk_text_iter_get_line (&start); + end_line = gtk_text_iter_get_line (&end); + + if ((gtk_text_iter_get_visible_line_offset (&end) == 0) && (end_line > start_line)) + end_line--; + + if (gedit_prefs_manager_get_insert_spaces ()) + { + gint tabs_size; + + tabs_size = gedit_prefs_manager_get_tabs_size (); + tab_buffer = g_strnfill (tabs_size, ' '); + } + else + { + tab_buffer = g_strdup ("\t"); + } + + for (i = start_line; i <= end_line; i++) + { + gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, i); + + /* don't add indentation on empty lines */ + if (gtk_text_iter_ends_line (&iter)) continue; + + gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &iter, tab_buffer, -1); + } + + gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc)); + + g_free (tab_buffer); +} + +static void +unindent_cb (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + GtkTextIter start, end, iter, iter2; + gint i, start_line, end_line; + + gedit_debug (DEBUG_PLUGINS); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc)); + + gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start, &end); + + start_line = gtk_text_iter_get_line (&start); + end_line = gtk_text_iter_get_line (&end); + + if ((gtk_text_iter_get_visible_line_offset (&end) == 0) && (end_line > start_line)) + end_line--; + + for (i = start_line; i <= end_line; i++) + { + gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, i); + + if (gtk_text_iter_get_char (&iter) == '\t') + { + iter2 = iter; + gtk_text_iter_forward_char (&iter2); + gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), &iter, &iter2); + } + else if (gtk_text_iter_get_char (&iter) == ' ') + { + gint spaces = 0; + + iter2 = iter; + + while (!gtk_text_iter_ends_line (&iter2)) + { + if (gtk_text_iter_get_char (&iter2) == ' ') + spaces++; + else + break; + + gtk_text_iter_forward_char (&iter2); + } + + if (spaces > 0) + { + gint tabs = 0; + gint tabs_size = gedit_prefs_manager_get_tabs_size (); + + tabs = spaces / tabs_size; + spaces = spaces - (tabs * tabs_size); + + if (spaces == 0) + spaces = tabs_size; + + iter2 = iter; + + gtk_text_iter_forward_chars (&iter2, spaces); + gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), &iter, &iter2); + } + } + } + + gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc)); +} + +static void +free_window_data (WindowData *data) +{ + g_return_if_fail (data != NULL); + + g_object_unref (data->action_group); + g_free (data); +} + +static void +update_ui_real (GeditWindow *window, + WindowData *data) +{ + GeditView *view; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (window); + + gtk_action_group_set_sensitive (data->action_group, + (view != NULL) && + gtk_text_view_get_editable (GTK_TEXT_VIEW (view))); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = g_new (WindowData, 1); + + manager = gedit_window_get_ui_manager (window); + + data->action_group = gtk_action_group_new ("GeditIndentPluginActions"); + gtk_action_group_set_translation_domain (data->action_group, + GETTEXT_PACKAGE); + gtk_action_group_add_actions (data->action_group, + action_entries, + G_N_ELEMENTS (action_entries), + window); + + gtk_ui_manager_insert_action_group (manager, data->action_group, -1); + + data->ui_id = gtk_ui_manager_new_merge_id (manager); + + g_object_set_data_full (G_OBJECT (window), + WINDOW_DATA_KEY, + data, + (GDestroyNotify) free_window_data); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "Indent", + "Indent", + GTK_UI_MANAGER_MENUITEM, + TRUE); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "Unindent", + "Unindent", + GTK_UI_MANAGER_MENUITEM, + FALSE); + + update_ui_real (window, data); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + manager = gedit_window_get_ui_manager (window); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + gtk_ui_manager_remove_ui (manager, data->ui_id); + gtk_ui_manager_remove_action_group (manager, data->action_group); + + g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + update_ui_real (window, data); +} + +static void +gedit_indent_plugin_class_init (GeditIndentPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_indent_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; +} diff --git a/plugins/indent/gedit-indent-plugin.h b/plugins/indent/gedit-indent-plugin.h new file mode 100644 index 00000000..ae518a43 --- /dev/null +++ b/plugins/indent/gedit-indent-plugin.h @@ -0,0 +1,75 @@ +/* + * gedit-indent-plugin.h + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_INDENT_PLUGIN_H__ +#define __GEDIT_INDENT_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_INDENT_PLUGIN (gedit_indent_plugin_get_type ()) +#define GEDIT_INDENT_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_INDENT_PLUGIN, GeditIndentPlugin)) +#define GEDIT_INDENT_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_INDENT_PLUGIN, GeditIndentPluginClass)) +#define GEDIT_IS_INDENT_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_INDENT_PLUGIN)) +#define GEDIT_IS_INDENT_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_INDENT_PLUGIN)) +#define GEDIT_INDENT_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_INDENT_PLUGIN, GeditIndentPluginClass)) + +/* Private structure type */ +typedef struct _GeditIndentPluginPrivate GeditIndentPluginPrivate; + +/* + * Main object structure + */ +typedef struct _GeditIndentPlugin GeditIndentPlugin; + +struct _GeditIndentPlugin +{ + GeditPlugin parent_instance; +}; + +/* + * Class definition + */ +typedef struct _GeditIndentPluginClass GeditIndentPluginClass; + +struct _GeditIndentPluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_indent_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_INDENT_PLUGIN_H__ */ diff --git a/plugins/indent/indent.gedit-plugin.desktop.in b/plugins/indent/indent.gedit-plugin.desktop.in index 8fc094e8..3491a282 100644 --- a/plugins/indent/indent.gedit-plugin.desktop.in +++ b/plugins/indent/indent.gedit-plugin.desktop.in @@ -1,6 +1,8 @@ [Gedit Plugin] -Location=indent +Module=indent +IAge=2 _Name=Indent lines _Description=Indents or un-indents selected lines. -Author=Paolo Maggi -Copyright=Copyright © 2002-2003 Paolo Maggi +Authors=Paolo Maggi +Copyright=Copyright © 2002-2005 Paolo Maggi +Website=http://www.gedit.org diff --git a/plugins/pythonconsole/.cvsignore b/plugins/pythonconsole/.cvsignore new file mode 100644 index 00000000..cac210e5 --- /dev/null +++ b/plugins/pythonconsole/.cvsignore @@ -0,0 +1,3 @@ +Makefile.in +Makefile +*.gedit-plugin diff --git a/plugins/pythonconsole/Makefile.am b/plugins/pythonconsole/Makefile.am new file mode 100644 index 00000000..50e4f9cb --- /dev/null +++ b/plugins/pythonconsole/Makefile.am @@ -0,0 +1,14 @@ +# Python Console Plugin +plugindir = $(libdir)/gedit-2/plugins +plugin_PYTHON = \ + pythonconsole.py + +plugin_in_files = pythonconsole.gedit-plugin.desktop.in +%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache + +plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) + +EXTRA_DIST = $(plugin_in_files) + +CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) diff --git a/plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in b/plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in new file mode 100644 index 00000000..93a77f2e --- /dev/null +++ b/plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in @@ -0,0 +1,9 @@ +[Gedit Plugin] +Loader=python +Module=pythonconsole +IAge=2 +_Name=Python Console +_Description=Opens an interactive python console in the bottom panel. +Authors=Raphael Slinckx +Copyright=Copyright © 2005 Raphael Slinckx, Adam Hooper +Website=http://www.gedit.org diff --git a/plugins/pythonconsole/pythonconsole.py b/plugins/pythonconsole/pythonconsole.py new file mode 100644 index 00000000..3c7b3df6 --- /dev/null +++ b/plugins/pythonconsole/pythonconsole.py @@ -0,0 +1,327 @@ +import gedit + +class ConsolePlugin(gedit.Plugin): + + def __init__(self): + gedit.Plugin.__init__(self) + + def activate(self, window): + # Build the console widget + cons = init_console(window) + + bottom = window.get_bottom_panel() + image = gtk.Image() + image.set_from_icon_name("gnome-mime-text-x-python", gtk.ICON_SIZE_BUTTON) + bottom.add_item(cons, "Python Console", image) + + # Store data in the window object + window._pythonconsole_window_data = (cons) + + def deactivate(self, window): + # Retreive the data of the window object + cons = window._pythonconsole_window_data + del window._pythonconsole_window_data + + # Shutdown the console + bottom = window.get_bottom_panel() + bottom.remove_item(cons) + + def update_ui(self, window): + pass + +def init_console(window, quit_cb=None): + console = Console(namespace={'__builtins__' : __builtins__, 'window' : window}, quit_cb=quit_cb) + console.init() + console.line.set_text("import gedit") + console.eval() + console.line.set_text("print 'You can use the window name:', window") + console.eval() + return console + +## Begin shameless code stealing from ephy's console.py extension +## Code is taken as-is and can thus be updated at will by copy/pasting +## File: epiphany-extensions/extensions/python-console/console.py + +# Interactive Python-GTK Console +# Copyright (C), 1998 James Henstridge +# Copyright (C), 2005 Adam Hooper +# +# 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, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# This module implements an interactive python session in a GTK window. To +# start the session, use the gtk_console command. Its specification is: +# gtk_console(namespace, title) +# where namespace is a dictionary representing the namespace of the session, +# title is the title on the window and +# +# As well as the starting attributes in namespace, the session will also +# have access to the list __history__, which is the command history. + +import sys, string, traceback + +import gobject +import gtk +import pango +import gtk.keysyms + +stdout = sys.stdout + +if not hasattr(sys, 'ps1'): sys.ps1 = '>>> ' +if not hasattr(sys, 'ps2'): sys.ps2 = '... ' + +# some functions to help recognise breaks between commands +def remQuotStr(s): + '''Returns s with any quoted strings removed (leaving quote marks)''' + r = '' + inq = 0 + qt = '' + prev = '_' + while len(s): + s0, s = s[0], s[1:] + if inq and (s0 != qt or prev == '\\'): + prev = s0 + continue + prev = s0 + if s0 in '\'"': + if inq: + inq = 0 + else: + inq = 1 + qt = s0 + r = r + s0 + return r + +def bracketsBalanced(s): + '''Returns true iff the brackets in s are balanced''' + b = filter(lambda x: x in '([{', s) + e = filter(lambda x: x in ')]}', s) + return len(e) >= len(b) + +class gtkoutfile: + '''A fake output file object. It sends output to a TK test widget, + and if asked for a file number, returns one set on instance creation''' + def __init__(self, w, fn, tag): + self.__fn = fn + self.__w = w + self.__tag = tag + def close(self): pass + flush = close + def fileno(self): return self.__fn + def isatty(self): return 0 + def read(self, a): return '' + def readline(self): return '' + def readlines(self): return [] + def write(self, s): + #stdout.write(str(self.__w.get_point()) + '\n') + self.__w.text_insert(self.__tag, s) + def writelines(self, l): + self.__w.text_insert(self.__tag, l) + def seek(self, a): raise IOError, (29, 'Illegal seek') + def tell(self): raise IOError, (29, 'Illegal seek') + truncate = tell + +class Console(gtk.VBox): + def __init__(self, namespace={}, quit_cb=None): + gtk.VBox.__init__(self, spacing=12) + self.set_border_width(12) + + self.quit_cb = quit_cb + + self.inp = gtk.HBox() + self.pack_start(self.inp) + self.inp.show() + + self.sw = gtk.ScrolledWindow() + self.sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC); + self.sw.set_shadow_type(gtk.SHADOW_IN) + self.inp.pack_start(self.sw, padding=1) + self.sw.show() + + self.text = gtk.TextView() + self.text.modify_font(pango.FontDescription('Monospace')) + self.text.set_editable(False) + self.text.set_wrap_mode (gtk.WRAP_WORD) + self.sw.add(self.text) + self.text.show() + + buffer = self.text.get_buffer() + self.normal = buffer.create_tag("normal") + self.error = buffer.create_tag("error") + self.error.set_property("foreground", "red") + self.command = buffer.create_tag('command') + self.command.set_property("foreground", "blue") + + self.inputbox = gtk.HBox(spacing=2) + self.pack_end(self.inputbox, expand=False) + self.inputbox.show() + + self.prompt = gtk.Label(sys.ps1) + self.prompt.set_padding(2, 0) + self.prompt.modify_font(pango.FontDescription('Monospace 10')) + self.inputbox.pack_start(self.prompt, expand=False) + self.prompt.show() + + self.line = gtk.Entry() + self.line.modify_font(pango.FontDescription('Monospace')) + self.line.connect("key_press_event", self.key_function) + self.inputbox.pack_start(self.line, padding=2) + self.line.show() + + self.namespace = namespace + + self.cmd = '' + self.cmd2 = '' + + # set up hooks for standard output. + self.stdout = gtkoutfile(self, sys.stdout.fileno(), + self.normal) + try : + # this will mostly fail on win32 ... + self.stderr = gtkoutfile(self, sys.stderr.fileno(), + self.error) + except : + # ... but gtkoutfile is not using the fileno anyway + self.stderr = gtkoutfile(self, -1, self.error) + # set up command history + self.history = [''] + self.histpos = 0 + self.namespace['__history__'] = self.history + + def scroll_to_end (self): + iter = self.text.get_buffer().get_end_iter() + self.text.scroll_to_iter(iter, 0.0) + return False # don't requeue this handler + + def text_insert(self, tag, s): + buffer = self.text.get_buffer() + iter = buffer.get_end_iter() + buffer.insert_with_tags (iter, s, tag) + gobject.idle_add(self.scroll_to_end) + + def init(self): + self.text.fg = self.text.style.fg[gtk.STATE_NORMAL] + self.text.bg = self.text.style.white + + self.line.grab_focus() + + def quit(self, *args): + #self.destroy() + if self.quit_cb: self.quit_cb() + + def key_function(self, entry, event): + if event.keyval == gtk.keysyms.Return: + self.line.emit_stop_by_name("key_press_event") + self.eval() + elif event.keyval == gtk.keysyms.Tab: + self.line.emit_stop_by_name("key_press_event") + self.line.insert_text('\t') + gobject.idle_add(self.focus_text) + elif event.keyval in (gtk.keysyms.KP_Up, gtk.keysyms.Up) \ + or (event.keyval in (gtk.keysyms.P, gtk.keysyms.p) and + event.state & gtk.gdk.CONTROL_MASK): + self.line.emit_stop_by_name("key_press_event") + self.historyUp() + gobject.idle_add(self.focus_text) + elif event.keyval in (gtk.keysyms.KP_Down, gtk.keysyms.Down) \ + or (event.keyval in (gtk.keysyms.N, gtk.keysyms.n) and + event.state & gtk.gdk.CONTROL_MASK): + self.line.emit_stop_by_name("key_press_event") + self.historyDown() + gobject.idle_add(self.focus_text) + elif event.keyval in (gtk.keysyms.L, gtk.keysyms.l) and \ + event.state & gtk.gdk.CONTROL_MASK: + self.text.get_buffer().set_text('') + elif event.keyval in (gtk.keysyms.D, gtk.keysyms.d) and \ + event.state & gtk.gdk.CONTROL_MASK: + self.line.emit_stop_by_name("key_press_event") + self.ctrld() + + def focus_text(self): + self.line.grab_focus() + return False # don't requeue this handler + + def ctrld(self): + self.quit() + pass + + def historyUp(self): + if self.histpos > 0: + l = self.line.get_text() + if len(l) > 0 and l[0] == '\n': l = l[1:] + if len(l) > 0 and l[-1] == '\n': l = l[:-1] + self.history[self.histpos] = l + self.histpos = self.histpos - 1 + self.line.set_text(self.history[self.histpos]) + + def historyDown(self): + if self.histpos < len(self.history) - 1: + l = self.line.get_text() + if len(l) > 0 and l[0] == '\n': l = l[1:] + if len(l) > 0 and l[-1] == '\n': l = l[:-1] + self.history[self.histpos] = l + self.histpos = self.histpos + 1 + self.line.set_text(self.history[self.histpos]) + + def eval(self): + l = self.line.get_text() + '\n' + if len(l) > 1 and l[0] == '\n': l = l[1:] + self.histpos = len(self.history) - 1 + if len(l) > 0 and l[-1] == '\n': + self.history[self.histpos] = l[:-1] + else: + self.history[self.histpos] = l + self.line.set_text('') + self.text_insert(self.command, self.prompt.get() + l) + if l == '\n': + self.run(self.cmd) + self.cmd = '' + self.cmd2 = '' + return + self.histpos = self.histpos + 1 + self.history.append('') + self.cmd = self.cmd + l + self.cmd2 = self.cmd2 + remQuotStr(l) + l = string.rstrip(l) + if not bracketsBalanced(self.cmd2) or l[-1] == ':' or \ + l[-1] == '\\' or l[0] in ' \11': + self.prompt.set_text(sys.ps2) + self.prompt.queue_draw() + return + self.run(self.cmd) + self.cmd = '' + self.cmd2 = '' + + def run(self, cmd): + sys.stdout, self.stdout = self.stdout, sys.stdout + sys.stderr, self.stderr = self.stderr, sys.stderr + try: + try: + r = eval(cmd, self.namespace, self.namespace) + if r is not None: + print `r` + except SyntaxError: + exec cmd in self.namespace + except: + if hasattr(sys, 'last_type') and \ + sys.last_type == SystemExit: + self.quit() + else: + traceback.print_exc() + self.prompt.set_text(sys.ps1) + self.prompt.queue_draw() + #adj = self.text.get_vadjustment() + #adj.set_value(adj.upper - adj.page_size) + sys.stdout, self.stdout = self.stdout, sys.stdout + sys.stderr, self.stderr = self.stderr, sys.stderr diff --git a/plugins/sample/Makefile.am b/plugins/sample/Makefile.am index 19dc4ad2..3f1b0a83 100644 --- a/plugins/sample/Makefile.am +++ b/plugins/sample/Makefile.am @@ -6,21 +6,30 @@ INCLUDES = \ $(GEDIT_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" plugin_LTLIBRARIES = libsample.la -libsample_la_SOURCES = sample.c +libsample_la_SOURCES = \ + gedit-sample-plugin.h \ + gedit-sample-plugin.c + libsample_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) + +gladedir = $(datadir)/gedit-2/glade +glade_DATA = + plugin_in_files = sample.gedit-plugin.desktop.in %.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) -EXTRA_DIST = $(plugin_in_files) +EXTRA_DIST = $(glade_DATA) $(plugin_in_files) CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) diff --git a/plugins/sample/gedit-sample-plugin.c b/plugins/sample/gedit-sample-plugin.c new file mode 100644 index 00000000..b27cae5c --- /dev/null +++ b/plugins/sample/gedit-sample-plugin.c @@ -0,0 +1,257 @@ +/* + * gedit-sample-plugin.h + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include /* For strlen */ + +#include "gedit-sample-plugin.h" + +#include +#include + +#include + +#include +#include + +#define WINDOW_DATA_KEY "GeditSamplePluginWindowData" +#define MENU_PATH "/MenuBar/EditMenu/EditOps_4" + +#define GEDIT_SAMPLE_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SAMPLE_PLUGIN, GeditSamplePluginPrivate)) + +struct _GeditSamplePluginPrivate +{ + gpointer dummy; +}; + +GEDIT_PLUGIN_REGISTER_TYPE(GeditSamplePlugin, gedit_sample_plugin) + +typedef struct +{ + GtkActionGroup *action_group; + guint ui_id; +} WindowData; + +static void sample_cb (GtkAction *action, GeditWindow *window); + +static const GtkActionEntry action_entries[] = +{ + { "UserName", + NULL, + N_("Insert User Na_me"), + NULL, + N_("Insert the user name at the cursor position"), + G_CALLBACK (sample_cb) }, +}; + +static void +gedit_sample_plugin_init (GeditSamplePlugin *plugin) +{ + plugin->priv = GEDIT_SAMPLE_PLUGIN_GET_PRIVATE (plugin); + + gedit_debug_message (DEBUG_PLUGINS, "GeditSamplePlugin initialising"); +} + +static void +gedit_sample_plugin_finalize (GObject *object) +{ +/* + GeditSamplePlugin *plugin = GEDIT_SAMPLE_PLUGIN (object); +*/ + gedit_debug_message (DEBUG_PLUGINS, "GeditSamplePlugin finalising"); + + G_OBJECT_CLASS (gedit_sample_plugin_parent_class)->finalize (object); +} + +static void +sample_cb (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + gchar *user_name; + gchar *user_name_utf8; + const gchar *temp; + + gedit_debug (DEBUG_PLUGINS); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + temp = g_get_real_name (); + g_return_if_fail (temp != NULL); + + if (strlen (temp) <= 0) + { + temp = g_get_user_name (); + g_return_if_fail (temp != NULL); + } + + user_name = g_strdup_printf ("%s ", temp); + g_return_if_fail (user_name != NULL); + + if (g_utf8_validate (user_name, -1, NULL)) + user_name_utf8 = user_name; + else + { + user_name_utf8 = g_locale_to_utf8 (user_name, + -1, + NULL, + NULL, + NULL); + g_free (user_name); + + if (user_name_utf8 == NULL) + user_name_utf8 = g_strdup (" "); + } + + gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc)); + + gtk_text_buffer_insert_at_cursor (GTK_TEXT_BUFFER (doc), + user_name_utf8, + -1); + + gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc)); + + g_free (user_name_utf8); +} + +static void +free_window_data (WindowData *data) +{ + g_return_if_fail (data != NULL); + + g_object_unref (data->action_group); + g_free (data); +} + +static void +update_ui_real (GeditWindow *window, + WindowData *data) +{ + GeditView *view; + GtkAction *action; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (window); + + gedit_debug_message (DEBUG_PLUGINS, "View: %p", view); + + action = gtk_action_group_get_action (data->action_group, + "UserName"); + gtk_action_set_sensitive (action, + (view != NULL) && + gtk_text_view_get_editable (GTK_TEXT_VIEW (view))); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = g_new (WindowData, 1); + + manager = gedit_window_get_ui_manager (window); + + data->action_group = gtk_action_group_new ("GeditSamplePluginActions"); + gtk_action_group_set_translation_domain (data->action_group, + GETTEXT_PACKAGE); + gtk_action_group_add_actions (data->action_group, + action_entries, + G_N_ELEMENTS (action_entries), + window); + + gtk_ui_manager_insert_action_group (manager, data->action_group, -1); + + data->ui_id = gtk_ui_manager_new_merge_id (manager); + + g_object_set_data_full (G_OBJECT (window), + WINDOW_DATA_KEY, + data, + (GDestroyNotify) free_window_data); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "UserName", + "UserName", + GTK_UI_MANAGER_MENUITEM, + TRUE); + + update_ui_real (window, data); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + manager = gedit_window_get_ui_manager (window); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + gtk_ui_manager_remove_ui (manager, data->ui_id); + gtk_ui_manager_remove_action_group (manager, data->action_group); + + g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + update_ui_real (window, data); +} + +static void +gedit_sample_plugin_class_init (GeditSamplePluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_sample_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; + + g_type_class_add_private (object_class, sizeof (GeditSamplePluginPrivate)); +} diff --git a/plugins/sample/gedit-sample-plugin.h b/plugins/sample/gedit-sample-plugin.h new file mode 100644 index 00000000..390b0744 --- /dev/null +++ b/plugins/sample/gedit-sample-plugin.h @@ -0,0 +1,78 @@ +/* + * gedit-sample-plugin.h + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_SAMPLE_PLUGIN_H__ +#define __GEDIT_SAMPLE_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_SAMPLE_PLUGIN (gedit_sample_plugin_get_type ()) +#define GEDIT_SAMPLE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_SAMPLE_PLUGIN, GeditSamplePlugin)) +#define GEDIT_SAMPLE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_SAMPLE_PLUGIN, GeditSamplePluginClass)) +#define GEDIT_IS_SAMPLE_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_SAMPLE_PLUGIN)) +#define GEDIT_IS_SAMPLE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_SAMPLE_PLUGIN)) +#define GEDIT_SAMPLE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_SAMPLE_PLUGIN, GeditSamplePluginClass)) + +/* Private structure type */ +typedef struct _GeditSamplePluginPrivate GeditSamplePluginPrivate; + +/* + * Main object structure + */ +typedef struct _GeditSamplePlugin GeditSamplePlugin; + +struct _GeditSamplePlugin +{ + GeditPlugin parent_instance; + + /*< private >*/ + GeditSamplePluginPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditSamplePluginClass GeditSamplePluginClass; + +struct _GeditSamplePluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_sample_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_SAMPLE_PLUGIN_H__ */ diff --git a/plugins/sample/sample.gedit-plugin.desktop.in b/plugins/sample/sample.gedit-plugin.desktop.in index de44d839..f528d1f6 100644 --- a/plugins/sample/sample.gedit-plugin.desktop.in +++ b/plugins/sample/sample.gedit-plugin.desktop.in @@ -1,6 +1,8 @@ [Gedit Plugin] -Location=sample +Module=sample +IAge=2 _Name=User name _Description=Inserts the user name at the cursor position. -Author=Paolo Maggi -Copyright=Copyright © 2002-2003 Paolo Maggi +Authors=Paolo Maggi +Copyright=Copyright © 2002-2005 Paolo Maggi +Website=http://www.gedit.org diff --git a/plugins/savecopy/savecopy.c b/plugins/savecopy/savecopy.c index ae4b3b0f..126583b7 100644 --- a/plugins/savecopy/savecopy.c +++ b/plugins/savecopy/savecopy.c @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -640,7 +639,7 @@ save_copy_cb (BonoboUIComponent *uic, gchar *file_uri; const GeditEncoding *encoding; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); doc = gedit_get_active_document (); g_return_if_fail (doc != NULL); @@ -685,7 +684,7 @@ update_ui (GeditPlugin *plugin, BonoboWindow *window) GeditMDI *mdi; GeditDocument *doc; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); g_return_val_if_fail (window != NULL, PLUGIN_ERROR); mdi = gedit_get_mdi (); @@ -712,7 +711,7 @@ G_MODULE_EXPORT GeditPluginState activate (GeditPlugin *plugin) { GList *top_windows; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); top_windows = gedit_get_top_windows (); g_return_val_if_fail (top_windows != NULL, PLUGIN_ERROR); @@ -743,7 +742,7 @@ deactivate (GeditPlugin *plugin) G_MODULE_EXPORT GeditPluginState init (GeditPlugin *plugin) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); return PLUGIN_OK; } @@ -751,7 +750,7 @@ init (GeditPlugin *plugin) G_MODULE_EXPORT GeditPluginState destroy (GeditPlugin *plugin) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); return PLUGIN_OK; } diff --git a/plugins/shell_output/shell_output.c b/plugins/shell_output/shell_output.c index a1f8fc51..ad95cbae 100644 --- a/plugins/shell_output/shell_output.c +++ b/plugins/shell_output/shell_output.c @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -52,6 +51,7 @@ #include #include #include +#include #define MENU_ITEM_LABEL N_("_Run Command...") #define MENU_ITEM_PATH "/menu/Tools/ToolsOps_3/" @@ -121,7 +121,7 @@ G_MODULE_EXPORT GeditPluginState init (GeditPlugin *pd); static void dialog_destroyed (GtkObject *obj, void **dialog_pointer) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); if (dialog_pointer != NULL) { @@ -173,9 +173,7 @@ dialog_destroyed (GtkObject *obj, void **dialog_pointer) static void dialog_response_handler (GtkDialog *dlg, gint res_id, ShellOutputDialog *dialog) { - GError *error = NULL; - - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); switch (res_id) { case GTK_RESPONSE_OK: @@ -183,12 +181,9 @@ dialog_response_handler (GtkDialog *dlg, gint res_id, ShellOutputDialog *dialog) break; case GTK_RESPONSE_HELP: - gnome_help_display ("gedit.xml", "gedit-shell-command-plugin", &error); - if (error != NULL) - { - g_warning (error->message); - g_error_free (error); - } + gedit_help_display (GTK_WINDOW (dlg), + "gedit.xml", + "gedit-shell-command-plugin"); break; case GEDIT_RESPONSE_STOP: @@ -198,12 +193,12 @@ dialog_response_handler (GtkDialog *dlg, gint res_id, ShellOutputDialog *dialog) gtk_widget_set_sensitive (dialog->stop_button, FALSE); - gedit_debug (DEBUG_PLUGINS, "Kill Child: %d\n", dialog->child_pid); + gedit_debug_message (DEBUG_PLUGINS, "Kill Child: %d\n", dialog->child_pid); kill (dialog->child_pid, SIGKILL); wait (NULL); - gedit_debug (DEBUG_PLUGINS, "Killed: %d\n", dialog->child_pid); + gedit_debug_message (DEBUG_PLUGINS, "Killed: %d\n", dialog->child_pid); break; @@ -310,7 +305,7 @@ get_dialog (void) GtkWidget *content; gchar *working_directory; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); window = GTK_WINDOW (gedit_get_active_window ()); @@ -427,7 +422,7 @@ run_command_cb (BonoboUIComponent *uic, gpointer user_data, const gchar* verbnam { ShellOutputDialog *dialog; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); dialog = get_dialog (); if (!dialog) @@ -441,7 +436,7 @@ handle_command_output (GIOChannel *ioc, GIOCondition condition, gpointer data) ShellOutputDialog *dialog = (ShellOutputDialog *)data; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); if ((condition & G_IO_IN) != 0) { @@ -451,12 +446,12 @@ handle_command_output (GIOChannel *ioc, GIOCondition condition, gpointer data) gsize pos = 0; gchar *line; - gedit_debug (DEBUG_PLUGINS, "1"); + gedit_debug_message (DEBUG_PLUGINS, "1"); if (!ioc->is_readable) return TRUE; - gedit_debug (DEBUG_PLUGINS, "1.1"); + gedit_debug_message (DEBUG_PLUGINS, "1.1"); do { @@ -469,7 +464,7 @@ handle_command_output (GIOChannel *ioc, GIOCondition condition, gpointer data) break; } - gedit_debug (DEBUG_PLUGINS, "1.2"); + gedit_debug_message (DEBUG_PLUGINS, "1.2"); do { @@ -503,7 +498,7 @@ handle_command_output (GIOChannel *ioc, GIOCondition condition, gpointer data) if (status != G_IO_STATUS_NORMAL) { - gedit_debug (DEBUG_PLUGINS, "1.2.1"); + gedit_debug_message (DEBUG_PLUGINS, "1.2.1"); if (error != NULL) { @@ -519,7 +514,7 @@ handle_command_output (GIOChannel *ioc, GIOCondition condition, gpointer data) if (len <= 0) continue; - gedit_debug (DEBUG_PLUGINS, "1.3"); + gedit_debug_message (DEBUG_PLUGINS, "1.3"); line = g_markup_escape_text (string, pos); @@ -562,7 +557,7 @@ handle_command_output (GIOChannel *ioc, GIOCondition condition, gpointer data) gchar *line; gboolean done = FALSE; - gedit_debug (DEBUG_PLUGINS, "2"); + gedit_debug_message (DEBUG_PLUGINS, "2"); g_io_channel_shutdown (ioc, TRUE, NULL); @@ -740,7 +735,7 @@ run_command_real (ShellOutputDialog *dialog) gboolean capture_output; GeditDocument *doc; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); g_return_val_if_fail (dialog != NULL, FALSE); @@ -928,7 +923,7 @@ run_command_real (ShellOutputDialog *dialog) G_MODULE_EXPORT GeditPluginState destroy (GeditPlugin *plugin) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); g_free (current_dir); current_dir = NULL; @@ -941,7 +936,7 @@ update_ui (GeditPlugin *plugin, BonoboWindow *window) { BonoboUIComponent *uic; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); g_return_val_if_fail (window != NULL, PLUGIN_ERROR); uic = gedit_get_ui_component_from_window (window); @@ -955,7 +950,7 @@ G_MODULE_EXPORT GeditPluginState activate (GeditPlugin *pd) { GList *top_windows; - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); top_windows = gedit_get_top_windows (); g_return_val_if_fail (top_windows != NULL, PLUGIN_ERROR); @@ -978,7 +973,7 @@ activate (GeditPlugin *pd) G_MODULE_EXPORT GeditPluginState deactivate (GeditPlugin *pd) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); gedit_menus_remove_menu_item_all (MENU_ITEM_PATH, MENU_ITEM_NAME); @@ -989,7 +984,7 @@ G_MODULE_EXPORT GeditPluginState init (GeditPlugin *pd) { /* initialize */ - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug (DEBUG_PLUGINS); pd->private_data = NULL; diff --git a/plugins/sort/Makefile.am b/plugins/sort/Makefile.am index 4600d6d5..c1eaa23c 100644 --- a/plugins/sort/Makefile.am +++ b/plugins/sort/Makefile.am @@ -1,4 +1,4 @@ -# Sort plugin +# sort plugin plugindir = $(libdir)/gedit-2/plugins INCLUDES = \ @@ -6,12 +6,16 @@ INCLUDES = \ $(GEDIT_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" plugin_LTLIBRARIES = libsort.la -libsort_la_SOURCES = sort.c +libsort_la_SOURCES = \ + gedit-sort-plugin.h \ + gedit-sort-plugin.c + libsort_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) gladedir = $(datadir)/gedit-2/glade @@ -26,4 +30,5 @@ plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) EXTRA_DIST = $(glade_DATA) $(plugin_in_files) CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) diff --git a/plugins/sort/gedit-sort-plugin.c b/plugins/sort/gedit-sort-plugin.c new file mode 100644 index 00000000..8a5ea1c5 --- /dev/null +++ b/plugins/sort/gedit-sort-plugin.c @@ -0,0 +1,545 @@ +/* + * gedit-sort-plugin.c + * + * Original author: Carlo Borreo + * Ported to Gedit2 by Lee Mallabone + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-sort-plugin.h" + +#include +#include +#include + +#include +#include +#include + +#define GEDIT_SORT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SORT_PLUGIN, GeditSortPluginPrivate)) + +/* Key in case the plugin ever needs any settings. */ +#define SORT_BASE_KEY "/apps/gedit-2/plugins/sort" + +#define WINDOW_DATA_KEY "GeditSortPluginWindowData" +#define MENU_PATH "/MenuBar/EditMenu/EditOps_6" + +GEDIT_PLUGIN_REGISTER_TYPE(GeditSortPlugin, gedit_sort_plugin) + +typedef struct +{ + GtkWidget *dialog; + GtkWidget *col_num_spinbutton; + GtkWidget *reverse_order_checkbutton; + GtkWidget *ignore_case_checkbutton; + GtkWidget *remove_dups_checkbutton; + + GeditDocument *doc; +} SortDialog; + +typedef struct +{ + GtkActionGroup *ui_action_group; + guint ui_id; +} WindowData; + +typedef struct +{ + gboolean ignore_case; + gboolean reverse_order; + gboolean remove_duplicates; + gint starting_column; +} SortInfo; + +static void sort_cb (GtkAction *action, GeditWindow *window); +static void sort_real (SortDialog *dialog); + +static const GtkActionEntry action_entries[] = +{ + { "Sort", + GTK_STOCK_SORT_ASCENDING, + N_("S_ort..."), + NULL, + N_("Sort the current document or selection"), + G_CALLBACK (sort_cb) } +}; + +static void +sort_dialog_destroy (GtkObject *obj, + gpointer dialog_pointer) +{ + gedit_debug (DEBUG_PLUGINS); + + g_free (dialog_pointer); +} + +static void +sort_dialog_response_handler (GtkDialog *widget, + gint res_id, + SortDialog *dialog) +{ + gedit_debug (DEBUG_PLUGINS); + + switch (res_id) + { + case GTK_RESPONSE_OK: + sort_real (dialog); + gtk_widget_destroy (dialog->dialog); + break; + + case GTK_RESPONSE_HELP: + gedit_help_display (GTK_WINDOW (widget), + "gedit.xml", + "gedit-sort-plugin"); + break; + + case GTK_RESPONSE_CANCEL: + gtk_widget_destroy (dialog->dialog); + break; + } +} + +static SortDialog * +get_sort_dialog (GtkWindow *parent) +{ + SortDialog *dialog; + GtkWidget *error_widget; + gboolean ret; + + gedit_debug (DEBUG_PLUGINS); + + dialog = g_new (SortDialog, 1); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "sort.glade2", + "sort_dialog", + &error_widget, + "sort_dialog", &dialog->dialog, + "reverse_order_checkbutton", &dialog->reverse_order_checkbutton, + "col_num_spinbutton", &dialog->col_num_spinbutton, + "ignore_case_checkbutton", &dialog->ignore_case_checkbutton, + "remove_dups_checkbutton", &dialog->remove_dups_checkbutton, + NULL); + + if (!ret) + { + gedit_warning (parent, + gtk_label_get_label (GTK_LABEL (error_widget))); + + g_free (dialog); + gtk_widget_destroy (error_widget); + + return NULL; + } + + gtk_dialog_set_default_response (GTK_DIALOG (dialog->dialog), + GTK_RESPONSE_OK); + + g_signal_connect (dialog->dialog, + "destroy", + G_CALLBACK (sort_dialog_destroy), + dialog); + + g_signal_connect (dialog->dialog, + "response", + G_CALLBACK (sort_dialog_response_handler), + dialog); + + return dialog; +} + +static void +sort_cb (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + GtkWindowGroup *wg; + SortDialog *dialog; + + gedit_debug (DEBUG_PLUGINS); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + dialog = get_sort_dialog (GTK_WINDOW (window)); + g_return_if_fail (dialog != NULL); + + wg = gedit_window_get_group (window); + gtk_window_group_add_window (wg, + GTK_WINDOW (dialog->dialog)); + + dialog->doc = doc; + + gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), + GTK_WINDOW (window)); + + gtk_window_set_modal (GTK_WINDOW (dialog->dialog), + TRUE); + + gtk_widget_show (GTK_WIDGET (dialog->dialog)); +} + +/* Compares two strings for the sorting algorithm. Uses the UTF-8 processing + * functions in GLib to be as correct as possible.*/ +static gint +compare_algorithm (gconstpointer s1, + gconstpointer s2, + gpointer data) +{ + gint length1, length2; + gint ret; + gchar *string1, *string2; + gchar *substring1, *substring2; + gchar *key1, *key2; + SortInfo *sort_info; + + gedit_debug (DEBUG_PLUGINS); + + sort_info = (SortInfo *) data; + g_return_val_if_fail (sort_info != NULL, -1); + + if (!sort_info->ignore_case) + { + string1 = *((gchar **) s1); + string2 = *((gchar **) s2); + } + else + { + string1 = g_utf8_casefold (*((gchar **) s1), -1); + string2 = g_utf8_casefold (*((gchar **) s2), -1); + } + + length1 = g_utf8_strlen (string1, -1); + length2 = g_utf8_strlen (string2, -1); + + if ((length1 < sort_info->starting_column) && + (length2 < sort_info->starting_column)) + { + ret = 0; + } + else if (length1 < sort_info->starting_column) + { + ret = -1; + } + else if (length2 < sort_info->starting_column) + { + ret = 1; + } + else if (sort_info->starting_column < 1) + { + key1 = g_utf8_collate_key (string1, -1); + key2 = g_utf8_collate_key (string2, -1); + ret = strcmp (key1, key2); + + g_free (key1); + g_free (key2); + } + else + { + /* A character column offset is required, so figure out + * the correct offset into the UTF-8 string. */ + substring1 = g_utf8_offset_to_pointer (string1, sort_info->starting_column); + substring2 = g_utf8_offset_to_pointer (string2, sort_info->starting_column); + + key1 = g_utf8_collate_key (substring1, -1); + key2 = g_utf8_collate_key (substring2, -1); + ret = strcmp (key1, key2); + + g_free (key1); + g_free (key2); + } + + /* Do the necessary cleanup. */ + if (sort_info->ignore_case) + { + g_free (string1); + g_free (string2); + } + + if (sort_info->reverse_order) + { + ret = -1 * ret; + } + + return ret; +} + +static void +sort_real (SortDialog *dialog) +{ + GeditDocument *doc; + GtkTextIter start, end; + gchar *buffer; + gchar *p; + gunichar c; + gchar *last_row = NULL; + gpointer *lines; + gint cont; + SortInfo *sort_info; + + gedit_debug (DEBUG_PLUGINS); + + doc = dialog->doc; + g_return_if_fail (doc != NULL); + + sort_info = g_new0 (SortInfo, 1); + sort_info->ignore_case = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->ignore_case_checkbutton)); + sort_info->reverse_order = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->reverse_order_checkbutton)); + sort_info->remove_duplicates = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->remove_dups_checkbutton)); + sort_info->starting_column = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->col_num_spinbutton)) - 1; + + if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &start, + &end)) + { + /* No selection, get the whole document. */ + gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc), + &start, + &end); + } + + buffer = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), + &start, + &end, + TRUE); + + lines = g_new0 (gpointer, gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (doc)) + 1); + + gedit_debug_message (DEBUG_PLUGINS, "Building list..."); + + cont = 0; + p = buffer; + c = g_utf8_get_char (p); + + while (c != '\0') + { + if (c == '\n') + { + gchar *old_p; + + old_p = p; + p = g_utf8_next_char (p); + + *old_p = '\0'; + + lines[cont] = p; + ++cont; + } else + { + p = g_utf8_next_char (p); + } + + c = g_utf8_get_char (p); + } + + lines[cont] = buffer; + ++cont; + + gedit_debug_message (DEBUG_PLUGINS, "Sort list..."); + + g_qsort_with_data (lines, + cont, + sizeof (gpointer), + compare_algorithm, + sort_info); + + gedit_debug_message (DEBUG_PLUGINS, "Rebuilding document..."); + + gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (doc)); + + gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), + &start, + &end); + + cont = 0; + + while (lines[cont] != NULL) + { + gchar *current_row = lines[cont]; + + /* Don't insert this row if it's the same as the last + * one and the user has specified to remove duplicates. */ + if (!sort_info->remove_duplicates || + last_row == NULL || + (strcmp (last_row, current_row) != 0)) + { + gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), + &start, + current_row, + -1); + + if (lines[cont + 1] != NULL) + { + gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), + &start, + "\n", + -1); + } + } + + last_row = current_row; + ++cont; + } + + gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (doc)); + + g_free (lines); + g_free (buffer); + g_free (sort_info); + + gedit_debug_message (DEBUG_PLUGINS, "Done."); +} + +static void +free_window_data (WindowData *data) +{ + g_return_if_fail (data != NULL); + + g_object_unref (data->ui_action_group); + g_free (data); +} + +static void +update_ui_real (GeditWindow *window, + WindowData *data) +{ + GeditView *view; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (window); + + gtk_action_group_set_sensitive (data->ui_action_group, + (view != NULL) && + gtk_text_view_get_editable (GTK_TEXT_VIEW (view))); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = g_new (WindowData, 1); + + manager = gedit_window_get_ui_manager (window); + + data->ui_action_group = gtk_action_group_new ("GeditSortPluginActions"); + gtk_action_group_set_translation_domain (data->ui_action_group, + GETTEXT_PACKAGE); + gtk_action_group_add_actions (data->ui_action_group, + action_entries, + G_N_ELEMENTS (action_entries), + window); + + gtk_ui_manager_insert_action_group (manager, + data->ui_action_group, + -1); + + data->ui_id = gtk_ui_manager_new_merge_id (manager); + + g_object_set_data_full (G_OBJECT (window), + WINDOW_DATA_KEY, + data, + (GDestroyNotify) free_window_data); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "Sort", + "Sort", + GTK_UI_MANAGER_MENUITEM, + FALSE); + + update_ui_real (window, + data); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + manager = gedit_window_get_ui_manager (window); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), + WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + gtk_ui_manager_remove_ui (manager, + data->ui_id); + gtk_ui_manager_remove_action_group (manager, + data->ui_action_group); + + g_object_set_data (G_OBJECT (window), + WINDOW_DATA_KEY, + NULL); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), + WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + update_ui_real (window, + data); +} + +static void +gedit_sort_plugin_init (GeditSortPlugin *plugin) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditSortPlugin initializing"); +} + +static void +gedit_sort_plugin_finalize (GObject *object) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditSortPlugin finalizing"); + + G_OBJECT_CLASS (gedit_sort_plugin_parent_class)->finalize (object); +} + +static void +gedit_sort_plugin_class_init (GeditSortPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_sort_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; +} diff --git a/plugins/sort/gedit-sort-plugin.h b/plugins/sort/gedit-sort-plugin.h new file mode 100644 index 00000000..c10280bf --- /dev/null +++ b/plugins/sort/gedit-sort-plugin.h @@ -0,0 +1,73 @@ +/* + * gedit-sort-plugin.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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_SORT_PLUGIN_H__ +#define __GEDIT_SORT_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_SORT_PLUGIN (gedit_sort_plugin_get_type ()) +#define GEDIT_SORT_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_SORT_PLUGIN, GeditSortPlugin)) +#define GEDIT_SORT_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_SORT_PLUGIN, GeditSortPluginClass)) +#define GEDIT_IS_SORT_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_SORT_PLUGIN)) +#define GEDIT_IS_SORT_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_SORT_PLUGIN)) +#define GEDIT_SORT_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_SORT_PLUGIN, GeditSortPluginClass)) + +/* Private structure type */ +typedef struct _GeditSortPluginPrivate GeditSortPluginPrivate; + +/* + * Main object structure + */ +typedef struct _GeditSortPlugin GeditSortPlugin; + +struct _GeditSortPlugin +{ + GeditPlugin parent_instance; +}; + +/* + * Class definition + */ +typedef struct _GeditSortPluginClass GeditSortPluginClass; + +struct _GeditSortPluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_sort_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_SORT_PLUGIN_H__ */ diff --git a/plugins/sort/sort.gedit-plugin.desktop.in b/plugins/sort/sort.gedit-plugin.desktop.in index a2b3c739..e55136d4 100644 --- a/plugins/sort/sort.gedit-plugin.desktop.in +++ b/plugins/sort/sort.gedit-plugin.desktop.in @@ -1,6 +1,8 @@ [Gedit Plugin] -Location=sort +Module=sort +IAge=2 _Name=Sort _Description=Sorts a document or selected text. -Author=Carlo Borreo , Lee Mallabone , Paolo Maggi -Copyright=Copyright © 2001 Carlo Borreo\nCopyright © 2002-2003 Lee Mallabone, Paolo Maggi +Authors=Carlo Borreo ;Lee Mallabone ;Paolo Maggi ;Jorge Alberto Torres H. +Copyright=Copyright © 2001 Carlo Borreo\nCopyright © 2002-2003 Lee Mallabone, Paolo Maggi\nCopyright © 2004-2005 Paolo Maggi +Website=http://www.gedit.org diff --git a/plugins/sort/sort.glade2 b/plugins/sort/sort.glade2 index fa574503..15f6a221 100644 --- a/plugins/sort/sort.glade2 +++ b/plugins/sort/sort.glade2 @@ -4,13 +4,18 @@ - True Sort GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE - True + False False - False + True + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True False @@ -32,6 +37,7 @@ gtk-cancel True GTK_RELIEF_NORMAL + True -6 @@ -42,6 +48,7 @@ True True GTK_RELIEF_NORMAL + True -5 @@ -51,6 +58,10 @@ 0.5 0 0 + 0 + 0 + 0 + 0 @@ -88,6 +99,10 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 @@ -110,6 +125,7 @@ gtk-help True GTK_RELIEF_NORMAL + True -11 @@ -142,6 +158,7 @@ _Reverse order True GTK_RELIEF_NORMAL + True False False True @@ -160,6 +177,7 @@ R_emove duplicates True GTK_RELIEF_NORMAL + True False False True @@ -178,6 +196,7 @@ _Ignore case True GTK_RELIEF_NORMAL + True True False True @@ -209,6 +228,10 @@ 0 0 col_num_spinbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 @@ -286,6 +309,10 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 diff --git a/plugins/spell/Makefile.am b/plugins/spell/Makefile.am index dfae0f1b..62d28d5e 100644 --- a/plugins/spell/Makefile.am +++ b/plugins/spell/Makefile.am @@ -11,12 +11,15 @@ INCLUDES = \ $(GEDIT_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" plugin_LTLIBRARIES = libspell.la -libspell_la_SOURCES = spell.c \ +libspell_la_SOURCES = \ + gedit-spell-plugin.c \ + gedit-spell-plugin.h \ gedit-spell-checker.c \ gedit-spell-checker.h \ gedit-spell-checker-dialog.c \ @@ -25,7 +28,7 @@ libspell_la_SOURCES = spell.c \ gedit-spell-language-dialog.h \ gedit-automatic-spell-checker.c \ gedit-automatic-spell-checker.h \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) libspell_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) libspell_la_LIBADD = $(PSPELL_LIBS) diff --git a/plugins/spell/gedit-automatic-spell-checker.c b/plugins/spell/gedit-automatic-spell-checker.c index cd9e0564..802b748e 100644 --- a/plugins/spell/gedit-automatic-spell-checker.c +++ b/plugins/spell/gedit-automatic-spell-checker.c @@ -382,12 +382,12 @@ replace_word (GtkWidget *menuitem, GeditAutomaticSpellChecker *spell) newword = g_object_get_qdata (G_OBJECT (menuitem), suggestion_id); g_return_if_fail (newword != NULL); - gedit_document_begin_user_action (spell->doc); + gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (spell->doc)); gtk_text_buffer_delete (GTK_TEXT_BUFFER (spell->doc), &start, &end); gtk_text_buffer_insert (GTK_TEXT_BUFFER (spell->doc), &start, newword, -1); - gedit_document_end_user_action (spell->doc); + gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (spell->doc)); gedit_spell_checker_set_correction (spell->spell_checker, oldword, strlen (oldword), @@ -880,7 +880,7 @@ gedit_automatic_spell_checker_free_internal (GeditAutomaticSpellChecker *spell) 0, 0, NULL, NULL, spell); - g_signal_handlers_disconnect_matched (G_OBJECT (gedit_view_get_gtk_text_view (view)), + g_signal_handlers_disconnect_matched (G_OBJECT (view), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, spell); @@ -900,23 +900,22 @@ gedit_automatic_spell_checker_attach_view ( { g_return_if_fail (spell != NULL); g_return_if_fail (GEDIT_IS_VIEW (view)); - g_return_if_fail (gedit_view_get_document (view) == spell->doc); - g_signal_connect (G_OBJECT (gedit_view_get_gtk_text_view (view)), + g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == + GTK_TEXT_BUFFER (spell->doc)); + + g_signal_connect (G_OBJECT (view), "button-press-event", G_CALLBACK (button_press_event), spell); - - g_signal_connect (G_OBJECT (gedit_view_get_gtk_text_view (view)), + g_signal_connect (G_OBJECT (view), "popup-menu", G_CALLBACK (popup_menu_event), spell); - g_signal_connect (G_OBJECT (view), "populate-popup", G_CALLBACK (populate_popup), spell); - g_signal_connect (G_OBJECT (view), "destroy", G_CALLBACK (view_destroy), @@ -932,7 +931,9 @@ gedit_automatic_spell_checker_detach_view ( { g_return_if_fail (spell != NULL); g_return_if_fail (GEDIT_IS_VIEW (view)); - g_return_if_fail (gedit_view_get_document (view) == spell->doc); + + g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == + GTK_TEXT_BUFFER (spell->doc)); g_return_if_fail (spell->views != NULL); g_signal_handlers_disconnect_matched (G_OBJECT (view), @@ -940,7 +941,7 @@ gedit_automatic_spell_checker_detach_view ( 0, 0, NULL, NULL, spell); - g_signal_handlers_disconnect_matched (G_OBJECT (gedit_view_get_gtk_text_view (view)), + g_signal_handlers_disconnect_matched (G_OBJECT (view), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, spell); diff --git a/plugins/spell/gedit-spell-language-dialog.c b/plugins/spell/gedit-spell-language-dialog.c index 519f7ef1..8984c386 100644 --- a/plugins/spell/gedit-spell-language-dialog.c +++ b/plugins/spell/gedit-spell-language-dialog.c @@ -37,6 +37,8 @@ #include #include +#include + #include "gedit-spell-language-dialog.h" @@ -62,7 +64,6 @@ struct _GeditSpellLanguageDialog static void ok_button_pressed (GeditSpellLanguageDialog *dialog); static GeditSpellLanguageDialog *get_languages_dialog (GeditSpellChecker *spell_checker); -static void dialog_destroyed (GtkObject *obj, void **dialog_pointer); static void dialog_destroyed (GtkObject *obj, void **dialog_pointer) @@ -75,25 +76,22 @@ dialog_destroyed (GtkObject *obj, void **dialog_pointer) } static void -dialog_response_handler (GtkDialog *dlg, gint res_id, GeditSpellLanguageDialog *dialog) +dialog_response_handler (GtkDialog *dlg, + gint res_id, + GeditSpellLanguageDialog *dialog) { GError *error = NULL; switch (res_id) { case GTK_RESPONSE_OK: ok_button_pressed (dialog); - gtk_widget_destroy (dialog->dialog); - break; - + case GTK_RESPONSE_HELP: - gnome_help_display ("gedit.xml", "gedit-spell-checker-plugin", &error); - if (error != NULL) - { - gedit_warning (GTK_WINDOW (dlg), error->message); - g_error_free (error); - } + gedit_help_display (GTK_WINDOW (dlg), + "gedit.xml", + "gedit-spell-checker-plugin"); break; default: @@ -102,7 +100,7 @@ dialog_response_handler (GtkDialog *dlg, gint res_id, GeditSpellLanguageDialog } static void -ok_button_pressed (GeditSpellLanguageDialog * dialog) +ok_button_pressed (GeditSpellLanguageDialog *dialog) { GError *error = NULL; GValue value = {0, }; @@ -132,7 +130,7 @@ ok_button_pressed (GeditSpellLanguageDialog * dialog) } } -static GtkTreeModel* +static GtkTreeModel * init_languages_treeview_model (GeditSpellLanguageDialog *dlg) { GtkListStore *store; @@ -249,17 +247,19 @@ get_languages_dialog (GeditSpellChecker *spell_checker) return NULL; } - g_signal_connect(G_OBJECT (dialog->dialog), "destroy", - G_CALLBACK (dialog_destroyed), &dialog); - - g_signal_connect(G_OBJECT (dialog->dialog), "response", - G_CALLBACK (dialog_response_handler), dialog); + g_signal_connect (dialog->dialog, + "destroy", + G_CALLBACK (dialog_destroyed), + &dialog); + g_signal_connect (dialog->dialog, + "response", + G_CALLBACK (dialog_response_handler), + dialog); dialog->model = GTK_TREE_MODEL (gtk_list_store_new (ENCODING_NUM_COLS, G_TYPE_STRING, G_TYPE_POINTER)); g_return_val_if_fail (dialog->model != NULL, FALSE); gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->languages_treeview), dialog->model); - /* Add the encoding column */ cell = gtk_cell_renderer_text_new (); @@ -273,10 +273,14 @@ get_languages_dialog (GeditSpellChecker *spell_checker) init_languages_treeview_model (dialog); - g_signal_connect (G_OBJECT (dialog->languages_treeview), "realize", - G_CALLBACK (scroll_to_selected), dialog); - g_signal_connect (G_OBJECT (dialog->languages_treeview), "row-activated", - G_CALLBACK (language_row_activated), dialog); + g_signal_connect (dialog->languages_treeview, + "realize", + G_CALLBACK (scroll_to_selected), + dialog); + g_signal_connect (dialog->languages_treeview, + "row-activated", + G_CALLBACK (language_row_activated), + dialog); g_object_unref (gui); @@ -286,7 +290,7 @@ get_languages_dialog (GeditSpellChecker *spell_checker) void gedit_spell_language_dialog_run (GeditSpellChecker *spell_checker, GtkWindow *parent) { - GeditSpellLanguageDialog* dialog; + GeditSpellLanguageDialog *dialog; g_return_if_fail (GTK_IS_WINDOW (parent)); g_return_if_fail (spell_checker != NULL); diff --git a/plugins/spell/gedit-spell-plugin.c b/plugins/spell/gedit-spell-plugin.c new file mode 100644 index 00000000..1b615f53 --- /dev/null +++ b/plugins/spell/gedit-spell-plugin.c @@ -0,0 +1,979 @@ +/* + * gedit-spell-plugin.c + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-spell-plugin.h" + +#include /* For strlen */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "gedit-spell-checker.h" +#include "gedit-spell-checker-dialog.h" +#include "gedit-spell-language-dialog.h" +#include "gedit-automatic-spell-checker.h" + +#define WINDOW_DATA_KEY "GeditSpellPluginWindowData" +#define MENU_PATH "/MenuBar/ToolsMenu/ToolsOps_1" + +#define GEDIT_SPELL_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SPELL_PLUGIN, GeditSpellPluginPrivate)) + +GEDIT_PLUGIN_REGISTER_TYPE(GeditSpellPlugin, gedit_spell_plugin) + +typedef struct +{ + GtkActionGroup *action_group; + guint ui_id; + guint message_cid; +} WindowData; + +static void spell_cb (GtkAction *action, GeditWindow *window); +static void set_language_cb (GtkAction *action, GeditWindow *window); +static void auto_spell_cb (GtkAction *action, GeditWindow *window); + +/* UI actions. */ +static const GtkActionEntry action_entries[] = +{ + { "CheckSpell", + GTK_STOCK_SPELL_CHECK, + N_("_Check Spelling"), + "F7", + N_("Check the current document for incorrect spelling"), + G_CALLBACK (spell_cb) + }, + + { "ConfigSpell", + GNOME_STOCK_BOOK_BLUE, + N_("Set _Language"), + NULL, + N_("Set the language of the current document"), + G_CALLBACK (set_language_cb) + } +}; + +static const GtkToggleActionEntry toggle_action_entries[] = +{ + { "AutoSpell", + NULL, + N_("_Autocheck Spelling"), + NULL, + N_("Automatically spell-check the current document"), + G_CALLBACK (auto_spell_cb), + FALSE + } +}; + +typedef struct _CheckRange CheckRange; + +struct _CheckRange +{ + GtkTextMark *start_mark; + GtkTextMark *end_mark; + + gint mw_start; /* misspelled word start */ + gint mw_end; /* end */ + + GtkTextMark *current_mark; +}; + +static GQuark spell_checker_id = 0; +static GQuark check_range_id = 0; + +static void +gedit_spell_plugin_init (GeditSpellPlugin *plugin) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditSpellPlugin initializing"); +} + +static void +gedit_spell_plugin_finalize (GObject *object) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditSpellPlugin finalizing"); + + G_OBJECT_CLASS (gedit_spell_plugin_parent_class)->finalize (object); +} + +static void +set_spell_language_cb (GeditSpellChecker *spell, + const GeditLanguage *lang, + GeditDocument *doc) +{ + gchar *uri; + + g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); + g_return_if_fail (lang != NULL); + + uri = gedit_document_get_uri (doc); + + if (uri != NULL) + { + gchar *key; + + key = gedit_language_to_key (lang); + g_return_if_fail (key != NULL); + + gedit_metadata_manager_set (uri, + "spell-language", + key); + + g_free (key); + g_free (uri); + } +} + +static GeditSpellChecker * +get_spell_checker_from_document (GeditDocument *doc) +{ + GeditSpellChecker *spell; + gpointer data; + + gedit_debug (DEBUG_PLUGINS); + + g_return_val_if_fail (doc != NULL, NULL); + + data = g_object_get_qdata (G_OBJECT (doc), spell_checker_id); + + if (data == NULL) + { + gchar *uri; + + spell = gedit_spell_checker_new (); + + uri = gedit_document_get_uri (doc); + + if (uri != NULL) + { + gchar *key; + const GeditLanguage *lang = NULL; + + key = gedit_metadata_manager_get (uri, + "spell-language"); + + if (key != NULL) + { + lang = gedit_language_from_key (key); + g_free (key); + } + + if (lang != NULL) + gedit_spell_checker_set_language (spell, + lang, + NULL); + + g_free (uri); + } + + g_object_set_qdata_full (G_OBJECT (doc), + spell_checker_id, + spell, + (GDestroyNotify) g_object_unref); + + g_signal_connect (G_OBJECT (spell), + "set_language", + G_CALLBACK (set_spell_language_cb), + doc); + } + else + { + g_return_val_if_fail (GEDIT_IS_SPELL_CHECKER (data), NULL); + spell = GEDIT_SPELL_CHECKER (data); + } + + return spell; +} + +static CheckRange * +get_check_range (GeditDocument *doc) +{ + CheckRange *range; + + gedit_debug (DEBUG_PLUGINS); + + g_return_val_if_fail (doc != NULL, NULL); + + range = (CheckRange *) g_object_get_qdata (G_OBJECT (doc), check_range_id); + + return range; +} + +static void +update_current (GeditDocument *doc, + gint current) +{ + CheckRange *range; + GtkTextIter iter; + GtkTextIter end_iter; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (doc != NULL); + g_return_if_fail (current >= 0); + + range = get_check_range (doc); + g_return_if_fail (range != NULL); + + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), + &iter, current); + + if (!gtk_text_iter_inside_word (&iter)) + { + /* if we're not inside a word, + * we must be in some spaces. + * skip forward to the beginning of the next word. */ + if (!gtk_text_iter_is_end (&iter)) + { + gtk_text_iter_forward_word_end (&iter); + gtk_text_iter_backward_word_start (&iter); + } + } + else + { + if (!gtk_text_iter_starts_word (&iter)) + gtk_text_iter_backward_word_start (&iter); + } + + gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), &end_iter, + range->end_mark); + + if (gtk_text_iter_compare (&end_iter, &iter) < 0) + { + gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->current_mark, + &end_iter); + } + else + { + gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->current_mark, + &iter); + } +} + +static void +set_check_range (GeditDocument *doc, + gint start, + gint end) +{ + CheckRange *range; + GtkTextIter iter; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (doc != NULL); + g_return_if_fail (start >= 0); + g_return_if_fail (start < gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (doc))); + g_return_if_fail ((end >= start) || (end < 0)); + + range = get_check_range (doc); + + if (range == NULL) + { + gedit_debug_message (DEBUG_PLUGINS, "There was not a previous check range"); + + gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); + + range = g_new0 (CheckRange, 1); + + range->start_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), + "check_range_start_mark", &iter, TRUE); + + range->end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), + "check_range_end_mark", &iter, FALSE); + + range->current_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), + "check_range_current_mark", &iter, TRUE); + + g_object_set_qdata_full (G_OBJECT (doc), + check_range_id, + range, + (GDestroyNotify)g_free); + } + + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), + &iter, start); + + gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), + range->start_mark, + &iter); + + if (end < 0) + end = gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (doc)); + g_return_if_fail (end >= start); + + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), + &iter, end); + + if (!gtk_text_iter_inside_word (&iter)) + { + /* if we're neither inside a word, + * we must be in some spaces. + * skip backward to the end of the previous word. */ + if (!gtk_text_iter_is_end (&iter)) + { + gtk_text_iter_backward_word_start (&iter); + gtk_text_iter_forward_word_end (&iter); + } + } + else + { + if (!gtk_text_iter_ends_word (&iter)) + gtk_text_iter_forward_word_end (&iter); + } + + gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->end_mark, &iter); + + range->mw_start = -1; + range->mw_end = -1; + + update_current (doc, start); +} + +static gchar * +get_current_word (GeditDocument *doc, gint *start, gint *end) +{ + const CheckRange *range; + GtkTextIter end_iter; + GtkTextIter current_iter; + gint range_end; + + gedit_debug (DEBUG_PLUGINS); + + g_return_val_if_fail (doc != NULL, NULL); + g_return_val_if_fail (start != NULL, NULL); + g_return_val_if_fail (end != NULL, NULL); + + range = get_check_range (doc); + g_return_val_if_fail (range != NULL, NULL); + + gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), + &end_iter, range->end_mark); + + range_end = gtk_text_iter_get_offset (&end_iter); + + gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), + ¤t_iter, range->current_mark); + + end_iter = current_iter; + + if (!gtk_text_iter_is_end (&end_iter)) + { + gedit_debug_message (DEBUG_PLUGINS, "Current is not end"); + + gtk_text_iter_forward_word_end (&end_iter); + } + + *start = gtk_text_iter_get_offset (¤t_iter); + *end = MIN (gtk_text_iter_get_offset (&end_iter), range_end); + + gedit_debug_message (DEBUG_PLUGINS, "Current word extends [%d, %d]", *start, *end); + + if (!(*start < *end)) + return NULL; + + return gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), + ¤t_iter, + &end_iter, + TRUE); +} + +static gboolean +goto_next_word (GeditDocument *doc) +{ + CheckRange *range; + GtkTextIter current_iter; + GtkTextIter old_current_iter; + GtkTextIter end_iter; + + gedit_debug (DEBUG_PLUGINS); + + g_return_val_if_fail (doc != NULL, FALSE); + + range = get_check_range (doc); + g_return_val_if_fail (range != NULL, FALSE); + + gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), + ¤t_iter, + range->current_mark); + gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end_iter); + + if (gtk_text_iter_compare (¤t_iter, &end_iter) >= 0) + return FALSE; + + old_current_iter = current_iter; + + gtk_text_iter_forward_word_ends (¤t_iter, 2); + gtk_text_iter_backward_word_start (¤t_iter); + + if ((gtk_text_iter_compare (&old_current_iter, ¤t_iter) < 0) && + (gtk_text_iter_compare (¤t_iter, &end_iter) < 0)) + { + update_current (doc, gtk_text_iter_get_offset (¤t_iter)); + return TRUE; + } + else + return FALSE; +} + +static gchar * +get_next_misspelled_word (GeditView *view) +{ + GeditDocument *doc; + CheckRange *range; + gint start, end; + gchar *word; + GeditSpellChecker *spell; + + g_return_val_if_fail (view != NULL, NULL); + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + g_return_val_if_fail (doc != NULL, NULL); + + range = get_check_range (doc); + g_return_val_if_fail (range != NULL, NULL); + + spell = get_spell_checker_from_document (doc); + g_return_val_if_fail (spell != NULL, NULL); + + word = get_current_word (doc, &start, &end); + if (word == NULL) + return NULL; + + gedit_debug_message (DEBUG_PLUGINS, "Word to check: %s", word); + + while (gedit_spell_checker_check_word (spell, word, -1, NULL)) + { + g_free (word); + + if (!goto_next_word (doc)) + return NULL; + + word = get_current_word (doc, &start, &end); + g_return_val_if_fail (word != NULL, NULL); + + gedit_debug_message (DEBUG_PLUGINS, "Word to check: %s", word); + } + + if (!goto_next_word (doc)) + update_current (doc, gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (doc))); + + if (word != NULL) + { + GtkTextIter s, e; + + range->mw_start = start; + range->mw_end = end; + + gedit_debug_message (DEBUG_PLUGINS, "Select [%d, %d]", start, end); + + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &s, start); + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &e, end); + + gtk_text_buffer_select_range (GTK_TEXT_BUFFER (doc), &s, &e); + + gedit_view_scroll_to_cursor (view); + } + else + { + range->mw_start = -1; + range->mw_end = -1; + } + + return word; +} + +static void +ignore_cb (GeditSpellCheckerDialog *dlg, + const gchar *w, + GeditView *view) +{ + gchar *word = NULL; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (w != NULL); + g_return_if_fail (view != NULL); + + word = get_next_misspelled_word (view); + if (word == NULL) + { + gedit_spell_checker_dialog_set_completed (dlg); + + return; + } + + gedit_spell_checker_dialog_set_misspelled_word (GEDIT_SPELL_CHECKER_DIALOG (dlg), + word, + -1); + + g_free (word); +} + +static void +change_cb (GeditSpellCheckerDialog *dlg, + const gchar *word, + const gchar *change, + GeditView *view) +{ + GeditDocument *doc; + CheckRange *range; + gchar *w = NULL; + GtkTextIter start, end; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (view != NULL); + g_return_if_fail (word != NULL); + g_return_if_fail (change != NULL); + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + g_return_if_fail (doc != NULL); + + range = get_check_range (doc); + g_return_if_fail (range != NULL); + + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &start, range->mw_start); + if (range->mw_end < 0) + gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end); + else + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &end, range->mw_end); + + w = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), &start, &end, TRUE); + g_return_if_fail (w != NULL); + + if (strcmp (w, word) != 0) + { + g_free (w); + return; + } + + g_free (w); + + gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER(doc)); + + gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), &start, &end); + gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &start, change, -1); + + gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER(doc)); + + update_current (doc, range->mw_start + g_utf8_strlen (change, -1)); + + /* go to next misspelled word */ + ignore_cb (dlg, word, view); +} + +static void +change_all_cb (GeditSpellCheckerDialog *dlg, + const gchar *word, + const gchar *change, + GeditView *view) +{ + GeditDocument *doc; + CheckRange *range; + gchar *w = NULL; + GtkTextIter start, end; + gchar *last_searched_text; + gchar *last_replaced_text; + gint flags = 0; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (view != NULL); + g_return_if_fail (word != NULL); + g_return_if_fail (change != NULL); + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + g_return_if_fail (doc != NULL); + + range = get_check_range (doc); + g_return_if_fail (range != NULL); + + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &start, range->mw_start); + if (range->mw_end < 0) + gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end); + else + gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &end, range->mw_end); + + w = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), &start, &end, TRUE); + g_return_if_fail (w != NULL); + + if (strcmp (w, word) != 0) + { + g_free (w); + return; + } + + g_free (w); + +// FIXME: save and restore search history +// last_searched_text = gedit_document_get_last_searched_text (doc); +// last_replaced_text = gedit_document_get_last_replace_text (doc); + + GEDIT_SEARCH_SET_CASE_SENSITIVE (flags, TRUE); + GEDIT_SEARCH_SET_ENTIRE_WORD (flags, TRUE); + +//CHECK: we still have to decide about this function (see gedit-document) +//beside currently the function does escaping etc + gedit_document_replace_all (doc, word, change, flags); + + update_current (doc, range->mw_start + g_utf8_strlen (change, -1)); +/* + if (last_searched_text != NULL) + { + gedit_document_set_last_searched_text (doc, last_searched_text); + + g_free (last_searched_text); + } + + if (last_replaced_text != NULL) + { + gedit_document_set_last_replace_text (doc, last_replaced_text); + + g_free (last_replaced_text); + } +*/ + /* go to next misspelled word */ + ignore_cb (dlg, word, view); +} + +static void +add_word_cb (GeditSpellCheckerDialog *dlg, + const gchar *word, + GeditView *view) +{ + g_return_if_fail (view != NULL); + g_return_if_fail (word != NULL); + + /* go to next misspelled word */ + ignore_cb (dlg, word, view); +} + +static void +set_language_cb (GtkAction *action, + GeditWindow *window) +{ + GeditDocument *doc; + GeditSpellChecker *spell; + + gedit_debug (DEBUG_PLUGINS); + + doc = gedit_window_get_active_document (window); + g_return_if_fail (doc != NULL); + + spell = get_spell_checker_from_document (doc); + g_return_if_fail (spell != NULL); + + gedit_spell_language_dialog_run (spell, GTK_WINDOW (window)); +} + +static void +spell_cb (GtkAction *action, + GeditWindow *window) +{ + GeditView *view; + GeditDocument *doc; + GeditSpellChecker *spell; + GtkWidget *dlg; + gint start, end; + GtkTextIter sel_start, sel_end; + gchar *word; + gboolean sel = FALSE; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (window); + g_return_if_fail (view != NULL); + + doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + g_return_if_fail (doc != NULL); + + spell = get_spell_checker_from_document (doc); + g_return_if_fail (spell != NULL); + + if (gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (doc)) <= 0) + { + WindowData *data; + GtkWidget *statusbar; + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + statusbar = gedit_window_get_statusbar (window); + gedit_statusbar_flash_message (GEDIT_STATUSBAR (statusbar), + data->message_cid, + _("The document is empty.")); + + return; + } + + if (gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), + &sel_start, + &sel_end)) + { + /* get selection points */ + start = gtk_text_iter_get_offset (&sel_start); + end = gtk_text_iter_get_offset (&sel_end); + set_check_range (doc, start, end); + sel = TRUE; + } + else + { + set_check_range (doc, 0, -1); + } + + word = get_next_misspelled_word (view); + if (word == NULL) + { + WindowData *data; + GtkWidget *statusbar; + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + statusbar = gedit_window_get_statusbar (window); + gedit_statusbar_flash_message (GEDIT_STATUSBAR (statusbar), + data->message_cid, + _("No misspelled words")); + + return; + } + + dlg = gedit_spell_checker_dialog_new_from_spell_checker (spell); + gtk_window_set_modal (GTK_WINDOW (dlg), TRUE); + gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (window)); + + g_signal_connect (dlg, "ignore", G_CALLBACK (ignore_cb), view); + g_signal_connect (dlg, "ignore_all", G_CALLBACK (ignore_cb), view); + + g_signal_connect (dlg, "change", G_CALLBACK (change_cb), view); + g_signal_connect (dlg, "change_all", G_CALLBACK (change_all_cb), view); + + g_signal_connect (dlg, "add_word_to_personal", G_CALLBACK (add_word_cb), view); + + gedit_spell_checker_dialog_set_misspelled_word (GEDIT_SPELL_CHECKER_DIALOG (dlg), + word, + -1); + + g_free (word); + + gtk_widget_show (dlg); +} + +static void +auto_spell_cb (GtkAction *action, + GeditWindow *window) +{ + GeditAutomaticSpellChecker *autospell; + GeditDocument *doc; + GeditSpellChecker *spell; + gboolean active; + + gedit_debug (DEBUG_PLUGINS); + + active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + + gedit_debug_message (DEBUG_PLUGINS, active ? "Auto Spell activated" : "Auto Spell deactivated"); + + doc = gedit_window_get_active_document (window); + if (doc == NULL) + return; + + spell = get_spell_checker_from_document (doc); + g_return_if_fail (spell != NULL); + + autospell = gedit_automatic_spell_checker_get_from_document (doc); + + if (active) + { + if (autospell == NULL) + { + GeditView *active_view; + + active_view = gedit_window_get_active_view (window); + g_return_if_fail (active_view != NULL); + + autospell = gedit_automatic_spell_checker_new (doc, spell); + gedit_automatic_spell_checker_attach_view (autospell, active_view); + gedit_automatic_spell_checker_recheck_all (autospell); + } + } + else + { + if (autospell != NULL) + gedit_automatic_spell_checker_free (autospell); + } +} + +static void +free_window_data (WindowData *data) +{ + g_return_if_fail (data != NULL); + + g_object_unref (data->action_group); + g_free (data); +} + +static void +update_ui_real (GeditWindow *window, + WindowData *data) +{ + GeditView *view; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (window); + + // TODO, see old plugin + + gtk_action_group_set_sensitive (data->action_group, + (view != NULL) && + gtk_text_view_get_editable (GTK_TEXT_VIEW (view))); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = g_new (WindowData, 1); + + manager = gedit_window_get_ui_manager (window); + + data->action_group = gtk_action_group_new ("GeditSpellPluginActions"); + gtk_action_group_set_translation_domain (data->action_group, + GETTEXT_PACKAGE); + gtk_action_group_add_actions (data->action_group, + action_entries, + G_N_ELEMENTS (action_entries), + window); + gtk_action_group_add_toggle_actions (data->action_group, + toggle_action_entries, + G_N_ELEMENTS (toggle_action_entries), + window); + + gtk_ui_manager_insert_action_group (manager, data->action_group, -1); + + data->ui_id = gtk_ui_manager_new_merge_id (manager); + + data->message_cid = gtk_statusbar_get_context_id + (GTK_STATUSBAR (gedit_window_get_statusbar (window)), + "spell_plugin_message"); + + g_object_set_data_full (G_OBJECT (window), + WINDOW_DATA_KEY, + data, + (GDestroyNotify) free_window_data); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "CheckSpell", + "CheckSpell", + GTK_UI_MANAGER_MENUITEM, + FALSE); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "AutoSpell", + "AutoSpell", + GTK_UI_MANAGER_MENUITEM, + FALSE); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "ConfigSpell", + "ConfigSpell", + GTK_UI_MANAGER_MENUITEM, + FALSE); + + + + update_ui_real (window, data); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + manager = gedit_window_get_ui_manager (window); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + gtk_ui_manager_remove_ui (manager, data->ui_id); + gtk_ui_manager_remove_action_group (manager, data->action_group); + + g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + update_ui_real (window, data); +} + +static void +gedit_spell_plugin_class_init (GeditSpellPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_spell_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; + + if (spell_checker_id == 0) + spell_checker_id = g_quark_from_static_string ("GeditSpellCheckerID"); + + if (check_range_id == 0) + check_range_id = g_quark_from_static_string ("CheckRangeID"); +} diff --git a/plugins/spell/gedit-spell-plugin.h b/plugins/spell/gedit-spell-plugin.h new file mode 100644 index 00000000..7de5807a --- /dev/null +++ b/plugins/spell/gedit-spell-plugin.h @@ -0,0 +1,75 @@ +/* + * gedit-spell-plugin.h + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_SPELL_PLUGIN_H__ +#define __GEDIT_SPELL_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_SPELL_PLUGIN (gedit_spell_plugin_get_type ()) +#define GEDIT_SPELL_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_SPELL_PLUGIN, GeditSpellPlugin)) +#define GEDIT_SPELL_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_SPELL_PLUGIN, GeditSpellPluginClass)) +#define GEDIT_IS_SPELL_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_SPELL_PLUGIN)) +#define GEDIT_IS_SPELL_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_SPELL_PLUGIN)) +#define GEDIT_SPELL_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_SPELL_PLUGIN, GeditSpellPluginClass)) + +/* Private structure type */ +typedef struct _GeditSpellPluginPrivate GeditSpellPluginPrivate; + +/* + * Main object structure + */ +typedef struct _GeditSpellPlugin GeditSpellPlugin; + +struct _GeditSpellPlugin +{ + GeditPlugin parent_instance; +}; + +/* + * Class definition + */ +typedef struct _GeditSpellPluginClass GeditSpellPluginClass; + +struct _GeditSpellPluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_spell_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_SPELL_PLUGIN_H__ */ diff --git a/plugins/spell/spell.gedit-plugin.desktop.in b/plugins/spell/spell.gedit-plugin.desktop.in index 5caffaf7..f4e54d94 100644 --- a/plugins/spell/spell.gedit-plugin.desktop.in +++ b/plugins/spell/spell.gedit-plugin.desktop.in @@ -1,7 +1,8 @@ [Gedit Plugin] -Location=spell +Module=spell +IAge=2 _Name=Spell checker _Description=Checks the spelling of the current document. -Author=Paolo Maggi -Copyright=Copyright © 2002-2003 Paolo Maggi - +Authors=Paolo Maggi +Copyright=Copyright © 2002-2005 Paolo Maggi +Website=http://www.gedit.org diff --git a/plugins/taglist/Makefile.am b/plugins/taglist/Makefile.am index 8e04246f..9380eea0 100644 --- a/plugins/taglist/Makefile.am +++ b/plugins/taglist/Makefile.am @@ -15,6 +15,7 @@ INCLUDES = \ $(GEDIT_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" \ -DGEDIT_TAGLIST_DIR=\""$(taglistdir)/"\" @@ -24,8 +25,8 @@ plugin_LTLIBRARIES = libtaglist.la libtaglist_la_SOURCES = \ gedit-taglist-plugin-parser.c \ gedit-taglist-plugin-parser.h \ - gedit-taglist-plugin-window.c \ - gedit-taglist-plugin-window.h \ + gedit-taglist-plugin-panel.c \ + gedit-taglist-plugin-panel.h \ gedit-taglist-plugin.c \ gedit-taglist-plugin.h @@ -44,6 +45,9 @@ EXTRA_DIST = \ $(plugin_in_files) $(plugin_DATA) CLEANFILES = \ + $(taglist_DATA) \ + $(plugin_DATA) +DISTCLEANFILES = \ $(taglist_DATA) \ $(plugin_DATA) diff --git a/plugins/taglist/gedit-taglist-plugin-panel.c b/plugins/taglist/gedit-taglist-plugin-panel.c new file mode 100644 index 00000000..178633a4 --- /dev/null +++ b/plugins/taglist/gedit-taglist-plugin-panel.c @@ -0,0 +1,578 @@ +/* + * gedit-taglist-plugin-panel.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "gedit-taglist-plugin-panel.h" +#include "gedit-taglist-plugin-parser.h" + +#include +#include + +#include +#include + +#define GEDIT_TAGLIST_PLUGIN_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_TAGLIST_PLUGIN_PANEL, GeditTaglistPluginPanelPrivate)) + +enum +{ + COLUMN_TAG_NAME, + COLUMN_TAG_INDEX_IN_GROUP, + NUM_COLUMNS +}; + +struct _GeditTaglistPluginPanelPrivate +{ + GeditWindow *window; + + GtkWidget *tag_groups_combo; + GtkWidget *tags_list; + + GtkTooltips *tooltips; + + TagGroup *selected_tag_group; +}; + +static GObjectClass *parent_class = NULL; +static GType type = 0; + +enum +{ + PROP_0, + PROP_WINDOW, +}; + +static void +set_window (GeditTaglistPluginPanel *panel, + GeditWindow *window) +{ + g_return_if_fail (panel->priv->window == NULL); + g_return_if_fail (GEDIT_IS_WINDOW (window)); + + panel->priv->window = window; + + /* TODO */ +} + +static void +gedit_taglist_plugin_panel_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeditTaglistPluginPanel *panel = GEDIT_TAGLIST_PLUGIN_PANEL (object); + + switch (prop_id) + + { + case PROP_WINDOW: + set_window (panel, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_taglist_plugin_panel_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditTaglistPluginPanel *panel = GEDIT_TAGLIST_PLUGIN_PANEL (object); + + switch (prop_id) + { + case PROP_WINDOW: + g_value_set_object (value, + GEDIT_TAGLIST_PLUGIN_PANEL_GET_PRIVATE (panel)->window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_taglist_plugin_panel_finalize (GObject *object) +{ + /* GeditTaglistPluginPanel *tab = GEDIT_TAGLIST_PLUGIN_PANEL (object); */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gedit_taglist_plugin_panel_class_init (GeditTaglistPluginPanelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gedit_taglist_plugin_panel_finalize; + object_class->get_property = gedit_taglist_plugin_panel_get_property; + object_class->set_property = gedit_taglist_plugin_panel_set_property; + + g_object_class_install_property (object_class, + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "The GeditWindow this GeditTaglistPluginPanel is associated with", + GEDIT_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof(GeditTaglistPluginPanelPrivate)); +} + +static void +insert_tag (GeditTaglistPluginPanel *panel, + Tag *tag) +{ + GeditView *view; + GtkTextBuffer *buffer; + GtkTextIter start, end; + GtkTextIter cursor; + gboolean sel = FALSE; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (panel->priv->window); + g_return_if_fail (view != NULL); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + gtk_text_buffer_begin_user_action (buffer); + + /* always insert the begin tag at the beginning of the selection + * and the end tag at the end, if there is no selection they will + * be automatically inserted at the cursor position. + */ + + if (tag->begin != NULL) + { + sel = gtk_text_buffer_get_selection_bounds (buffer, + &start, + &end); + + gtk_text_buffer_insert (buffer, + &start, + tag->begin, + -1); + + /* get iterators again since they have been invalidated and move + * the cursor after the selection */ + gtk_text_buffer_get_selection_bounds (buffer, + &start, + &cursor); + } + + if (tag->end != NULL) + { + sel = gtk_text_buffer_get_selection_bounds (buffer, + &start, + &end); + + gtk_text_buffer_insert (buffer, + &end, + tag->end, + -1); + + /* if there is no selection and we have a paired tag, move the + * cursor between the pair, otherwise move it at the end */ + if (!sel) + { + gint offset; + + offset = gtk_text_iter_get_offset (&end) - + g_utf8_strlen (tag->end, -1); + + gtk_text_buffer_get_iter_at_offset (buffer, + &end, + offset); + } + + cursor = end; + } + + gtk_text_buffer_place_cursor (buffer, &cursor); + + gtk_text_buffer_end_user_action (buffer); +} + +static void +tag_list_row_activated_cb (GtkTreeView *tag_list, + GtkTreePath *path, + GtkTreeViewColumn *column, + GeditTaglistPluginPanel *panel) +{ + GtkTreeIter iter; + GtkTreeModel *model; + gint index; + + gedit_debug (DEBUG_PLUGINS); + + model = gtk_tree_view_get_model (tag_list); + + gtk_tree_model_get_iter (model, &iter, path); + g_return_if_fail (&iter != NULL); + + gtk_tree_model_get (model, &iter, COLUMN_TAG_INDEX_IN_GROUP, &index, -1); + + gedit_debug_message (DEBUG_PLUGINS, "Index: %d", index); + + insert_tag (panel, + (Tag*)g_list_nth_data (panel->priv->selected_tag_group->tags, index)); +} + +static gboolean +tag_list_key_press_event_cb (GtkTreeView *tag_list, + GdkEventKey *event, + GeditTaglistPluginPanel *panel) +{ + if ((event->keyval == GDK_Return) && (event->state & GDK_CONTROL_MASK)) + { + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + gint index; + + gedit_debug_message (DEBUG_PLUGINS, "RETURN Pressed"); + + model = gtk_tree_view_get_model (tag_list); + + selection = gtk_tree_view_get_selection (tag_list); + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + { + gtk_tree_model_get (model, &iter, COLUMN_TAG_INDEX_IN_GROUP, &index, -1); + + gedit_debug_message (DEBUG_PLUGINS, "Index: %d", index); + + insert_tag (panel, + (Tag*)g_list_nth_data (panel->priv->selected_tag_group->tags, index)); + } + + return FALSE; + } + + return FALSE; +} + +static GtkTreeModel* +create_model (GeditTaglistPluginPanel *panel) +{ + gint i = 0; + GtkListStore *store; + GtkTreeIter iter; + GList *list; + + gedit_debug (DEBUG_PLUGINS); + + /* create list store */ + store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_INT); + + /* add data to the list store */ + list = panel->priv->selected_tag_group->tags; + + while (list != NULL) + { + const gchar* tag_name; + + tag_name = ((Tag*)list->data)->name; + + gedit_debug_message (DEBUG_PLUGINS, "%d : %s", i, tag_name); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COLUMN_TAG_NAME, tag_name, + COLUMN_TAG_INDEX_IN_GROUP, i, + -1); + ++i; + + list = g_list_next (list); + } + + gedit_debug_message (DEBUG_PLUGINS, "Rows: %d ", + gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL)); + + return GTK_TREE_MODEL (store); +} + +static void +populate_tags_list (GeditTaglistPluginPanel *panel) +{ + GtkTreeModel* model; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (taglist != NULL); + + model = create_model (panel); + + gtk_tree_view_set_model (GTK_TREE_VIEW (panel->priv->tags_list), + model); + + g_object_unref (G_OBJECT (model)); +} + +static TagGroup * +find_tag_group (const gchar *name) +{ + GList *list; + + gedit_debug (DEBUG_PLUGINS); + + g_return_val_if_fail (taglist != NULL, NULL); + + list = taglist->tag_groups; + + while (list) + { + if (strcmp (name, ((TagGroup*)list->data)->name) == 0) + return (TagGroup*)list->data; + + list = g_list_next (list); + } + + return NULL; +} + +static void +populate_tag_groups_combo (GeditTaglistPluginPanel *panel) +{ + GList *list; + GtkComboBox *combo; + + gedit_debug (DEBUG_PLUGINS); + + combo = GTK_COMBO_BOX (panel->priv->tag_groups_combo); + + if (taglist == NULL) + return; + + list = taglist->tag_groups; + + /* Build cbitems */ + while (list) + { + gtk_combo_box_append_text (combo, + ((TagGroup*)list->data)->name); + + list = g_list_next (list); + } + + gtk_combo_box_set_active (combo, 0); + + return; +} + +static void +selected_group_changed (GtkComboBox *combo, + GeditTaglistPluginPanel *panel) +{ + gchar* group_name; + + gedit_debug (DEBUG_PLUGINS); + + group_name = gtk_combo_box_get_active_text (combo); + + if ((group_name == NULL) || (strlen (group_name) <= 0)) + { + g_free (group_name); + return; + } + + if ((panel->priv->selected_tag_group == NULL) || + (strcmp (group_name, panel->priv->selected_tag_group->name) != 0)) + { + panel->priv->selected_tag_group = find_tag_group (group_name); + g_return_if_fail (panel->priv->selected_tag_group != NULL); + + gedit_debug_message (DEBUG_PLUGINS, + "New selected group: %s", + panel->priv->selected_tag_group->name); + + populate_tags_list (panel); + } + + g_free (group_name); +} + +static void +gedit_taglist_plugin_panel_init (GeditTaglistPluginPanel *panel) +{ + GtkWidget *sw; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + GList *focus_chain = NULL; + + gedit_debug (DEBUG_PLUGINS); + + panel->priv = GEDIT_TAGLIST_PLUGIN_PANEL_GET_PRIVATE (panel); + + panel->priv->tooltips = gtk_tooltips_new (); + g_object_ref (G_OBJECT (panel->priv->tooltips)); + gtk_object_sink (GTK_OBJECT (panel->priv->tooltips)); + + /* Build the window content */ + panel->priv->tag_groups_combo = gtk_combo_box_new_text (); + gtk_box_pack_start (GTK_BOX (panel), + panel->priv->tag_groups_combo, + FALSE, + TRUE, + 0); + + gtk_tooltips_set_tip (panel->priv->tooltips, + panel->priv->tag_groups_combo, + _("Select the group of tags you want to use"), + NULL); + + sw = gtk_scrolled_window_new (NULL, NULL); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), + GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (panel), sw, TRUE, TRUE, 0); + + /* Create tree view */ + panel->priv->tags_list = gtk_tree_view_new (); + + gedit_utils_set_atk_name_description (panel->priv->tag_groups_combo, + _("Available Tag Lists"), + NULL); + gedit_utils_set_atk_name_description (panel->priv->tags_list, + _("Tags"), + NULL); + gedit_utils_set_atk_relation (panel->priv->tag_groups_combo, + panel->priv->tags_list, + ATK_RELATION_CONTROLLER_FOR); + gedit_utils_set_atk_relation (panel->priv->tags_list, + panel->priv->tag_groups_combo, + ATK_RELATION_CONTROLLED_BY); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (panel->priv->tags_list), FALSE); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (panel->priv->tags_list), FALSE); + + gtk_tooltips_set_tip (panel->priv->tooltips, + panel->priv->tags_list, + _("Double-click on a tag to insert it in the current document"), + NULL); + + g_signal_connect_after (panel->priv->tags_list, + "row_activated", + G_CALLBACK (tag_list_row_activated_cb), + panel); + + g_signal_connect (panel->priv->tags_list, + "key_press_event", + G_CALLBACK (tag_list_key_press_event_cb), + panel); + + /* Add the tags column */ + cell = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (_("Tags"), + cell, + "text", + COLUMN_TAG_NAME, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (panel->priv->tags_list), + column); + + gtk_tree_view_set_search_column (GTK_TREE_VIEW (panel->priv->tags_list), + COLUMN_TAG_NAME); + + gtk_container_add (GTK_CONTAINER (sw), panel->priv->tags_list); + + g_signal_connect (panel->priv->tag_groups_combo, + "changed", + G_CALLBACK (selected_group_changed), + panel); + + focus_chain = g_list_prepend (focus_chain, panel->priv->tags_list); + focus_chain = g_list_prepend (focus_chain, panel->priv->tag_groups_combo); + + gtk_container_set_focus_chain (GTK_CONTAINER (panel), + focus_chain); + g_list_free (focus_chain); + + /* Populate combo box */ + populate_tag_groups_combo (panel); + + gtk_widget_show_all (GTK_WIDGET (panel)); +} + +GtkWidget * +gedit_taglist_plugin_panel_new (GeditWindow *window) +{ + g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL); + + return GTK_WIDGET (g_object_new (GEDIT_TYPE_TAGLIST_PLUGIN_PANEL, + "window", window, + NULL)); +} + +GType +gedit_taglist_plugin_panel_get_type (void) +{ + return type; +} + +GType +gedit_taglist_plugin_panel_register_type (GTypeModule *module) +{ + static const GTypeInfo our_info = + { + sizeof (GeditTaglistPluginPanelClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gedit_taglist_plugin_panel_class_init, + NULL, + NULL, /* class_data */ + sizeof (GeditTaglistPluginPanel), + 0, /* n_preallocs */ + (GInstanceInitFunc) gedit_taglist_plugin_panel_init + }; + + gedit_debug_message (DEBUG_PLUGINS, "Registering GeditTaglistPluginPanel"); + + type = g_type_module_register_type (module, + GTK_TYPE_VBOX, + "GeditTaglistPluginPanel", + &our_info, + 0); + return type; +} diff --git a/plugins/taglist/gedit-taglist-plugin-panel.h b/plugins/taglist/gedit-taglist-plugin-panel.h new file mode 100644 index 00000000..7270615f --- /dev/null +++ b/plugins/taglist/gedit-taglist-plugin-panel.h @@ -0,0 +1,88 @@ +/* + * gedit-taglist-plugin-panel.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + * + * $Id$ + */ + +#ifndef __GEDIT_TAGLIST_PLUGIN_PANEL_H__ +#define __GEDIT_TAGLIST_PLUGIN_PANEL_H__ + +#include + +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_TAGLIST_PLUGIN_PANEL (gedit_taglist_plugin_panel_get_type()) +#define GEDIT_TAGLIST_PLUGIN_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_TAGLIST_PLUGIN_PANEL, GeditTaglistPluginPanel)) +#define GEDIT_TAGLIST_PLUGIN_PANEL_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_TAGLIST_PLUGIN_PANEL, GeditTaglistPluginPanel const)) +#define GEDIT_TAGLIST_PLUGIN_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_TAGLIST_PLUGIN_PANEL, GeditTaglistPluginPanelClass)) +#define GEDIT_IS_TAGLIST_PLUGIN_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_TAGLIST_PLUGIN_PANEL)) +#define GEDIT_IS_TAGLIST_PLUGIN_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_TAGLIST_PLUGIN_PANEL)) +#define GEDIT_TAGLIST_PLUGIN_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_TAGLIST_PLUGIN_PANEL, GeditTaglistPluginPanelClass)) + +/* Private structure type */ +typedef struct _GeditTaglistPluginPanelPrivate GeditTaglistPluginPanelPrivate; + +/* + * Main object structure + */ +typedef struct _GeditTaglistPluginPanel GeditTaglistPluginPanel; + +struct _GeditTaglistPluginPanel +{ + GtkVBox vbox; + + /*< private > */ + GeditTaglistPluginPanelPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditTaglistPluginPanelClass GeditTaglistPluginPanelClass; + +struct _GeditTaglistPluginPanelClass +{ + GtkVBoxClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_taglist_plugin_panel_register_type (GTypeModule *module); + +GType gedit_taglist_plugin_panel_get_type (void) G_GNUC_CONST; + +GtkWidget *gedit_taglist_plugin_panel_new (GeditWindow *window); + +G_END_DECLS + +#endif /* __GEDIT_TAGLIST_PLUGIN_PANEL_H__ */ diff --git a/plugins/taglist/gedit-taglist-plugin-parser.c b/plugins/taglist/gedit-taglist-plugin-parser.c index c3888948..a4bf50fa 100644 --- a/plugins/taglist/gedit-taglist-plugin-parser.c +++ b/plugins/taglist/gedit-taglist-plugin-parser.c @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-taglist-plugin-parser.c - * This file is part of the gedit taglist plugin + * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,9 +21,11 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H @@ -45,9 +46,11 @@ #include "gedit-taglist-plugin-parser.h" +// FIXME #define USER_GEDIT_TAGLIST_PLUGIN_LOCATION ".gedit-2/plugins/taglist/" TagList *taglist = NULL; +static gint taglist_ref_count = 0; static gboolean parse_tag (Tag *tag, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur); static gboolean parse_tag_group (TagGroup *tg, const gchar *fn, @@ -66,7 +69,7 @@ static gboolean parse_tag (Tag *tag, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { /* - gedit_debug (DEBUG_PLUGINS, " Tag name: %s", tag->name); + gedit_debug_message (DEBUG_PLUGINS, " Tag name: %s", tag->name); */ /* We don't care what the top level element name is */ cur = cur->xmlChildrenNode; @@ -78,7 +81,7 @@ parse_tag (Tag *tag, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { tag->begin = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1); /* - gedit_debug (DEBUG_PLUGINS, " - Begin: %s", tag->begin); + gedit_debug_message (DEBUG_PLUGINS, " - Begin: %s", tag->begin); */ } @@ -87,7 +90,7 @@ parse_tag (Tag *tag, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { tag->end = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1); /* - gedit_debug (DEBUG_PLUGINS, " - End: %s", tag->end); + gedit_debug_message (DEBUG_PLUGINS, " - End: %s", tag->end); */ } @@ -104,7 +107,7 @@ static gboolean parse_tag_group (TagGroup *tg, const gchar* fn, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { - gedit_debug (DEBUG_PLUGINS, "Parse TagGroup: %s", tg->name); + gedit_debug_message (DEBUG_PLUGINS, "Parse TagGroup: %s", tg->name); /* We don't care what the top level element name is */ cur = cur->xmlChildrenNode; @@ -199,7 +202,7 @@ get_tag_group (const gchar* filename, xmlDocPtr doc, if (strcmp (tgn, (gchar*)tag_group->name) == 0) { - gedit_debug (DEBUG_PLUGINS, + gedit_debug_message (DEBUG_PLUGINS, "Tag group '%s' already exists.", tgn); exists = TRUE; @@ -382,7 +385,7 @@ parse_taglist_file (const gchar* filename) xmlNsPtr ns; xmlNodePtr cur; - gedit_debug (DEBUG_PLUGINS, "Parse file: %s", filename); + gedit_debug_message (DEBUG_PLUGINS, "Parse file: %s", filename); xmlKeepBlanksDefault (0); @@ -442,7 +445,7 @@ parse_taglist_file (const gchar* filename) xmlFreeDoc (doc); - gedit_debug (DEBUG_PLUGINS, "END"); + gedit_debug_message (DEBUG_PLUGINS, "END"); return taglist; } @@ -452,7 +455,7 @@ static void free_tag (Tag *tag) { /* - gedit_debug (DEBUG_PLUGINS, "Tag: %s", tag->name); + gedit_debug_message (DEBUG_PLUGINS, "Tag: %s", tag->name); */ g_return_if_fail (tag != NULL); @@ -470,7 +473,7 @@ free_tag (Tag *tag) static void free_tag_group (TagGroup *tag_group) { - gedit_debug (DEBUG_PLUGINS, "Tag group: %s", tag_group->name); + gedit_debug_message (DEBUG_PLUGINS, "Tag group: %s", tag_group->name); g_return_if_fail (tag_group != NULL); @@ -487,17 +490,23 @@ free_tag_group (TagGroup *tag_group) g_free (tag_group); - gedit_debug (DEBUG_PLUGINS, "END"); + gedit_debug_message (DEBUG_PLUGINS, "END"); } void free_taglist (void) { - gedit_debug (DEBUG_PLUGINS, ""); + gedit_debug_message (DEBUG_PLUGINS, "ref_count: %d", taglist_ref_count); + + g_return_if_fail (taglist_ref_count > 0); + --taglist_ref_count; + if (taglist_ref_count > 0) + return; + if (taglist == NULL) return; - + while (taglist->tag_groups) { free_tag_group ((TagGroup *)taglist->tag_groups->data); @@ -511,7 +520,7 @@ free_taglist (void) taglist = NULL; - gedit_debug (DEBUG_PLUGINS, "END"); + gedit_debug_message (DEBUG_PLUGINS, "Really freed"); } static TagList * @@ -520,13 +529,13 @@ parse_taglist_dir (const gchar *dir) DIR *d; struct dirent *e; - gedit_debug (DEBUG_PLUGINS, "DIR: %s", dir); + gedit_debug_message (DEBUG_PLUGINS, "DIR: %s", dir); d = opendir (dir); if (d == NULL) { - gedit_debug (DEBUG_PLUGINS, "%s", strerror (errno)); + gedit_debug_message (DEBUG_PLUGINS, "%s", strerror (errno)); return taglist; } @@ -548,10 +557,15 @@ TagList* create_taglist (void) { gchar const * const home = g_get_home_dir (); - gedit_debug (DEBUG_PLUGINS, ""); - - g_return_val_if_fail (taglist == NULL, taglist); + gedit_debug_message (DEBUG_PLUGINS, "ref_count: %d", taglist_ref_count); + if (taglist_ref_count > 0) + { + ++taglist_ref_count; + + return taglist; + } + /* load user's taglists */ if (home != NULL) { @@ -566,5 +580,8 @@ TagList* create_taglist (void) /* load system's taglists */ parse_taglist_dir (GEDIT_TAGLIST_DIR); + ++taglist_ref_count; + g_return_val_if_fail (taglist_ref_count == 1, taglist); + return taglist; } diff --git a/plugins/taglist/gedit-taglist-plugin-parser.h b/plugins/taglist/gedit-taglist-plugin-parser.h index 6d92b284..64c92998 100644 --- a/plugins/taglist/gedit-taglist-plugin-parser.h +++ b/plugins/taglist/gedit-taglist-plugin-parser.h @@ -1,9 +1,8 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * gedit-taglist-plugin-parser.c - * This file is part of the gedit taglist plugin + * gedit-taglist-plugin-parser.h + * This file is part of gedit * - * Copyright (C) 2002 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 @@ -22,20 +21,48 @@ */ /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifndef __GEDIT_TAGLIST_PLUGIN_PARSER_H__ #define __GEDIT_TAGLIST_PLUGIN_PARSER_H__ -#include "gedit-taglist-plugin.h" +#include +#include + +typedef struct _TagList TagList; +typedef struct _TagGroup TagGroup; +typedef struct _Tag Tag; + +struct _TagList +{ + GList *tag_groups; +}; + +struct _TagGroup +{ + xmlChar *name; + + GList *tags; +}; + +struct _Tag +{ + xmlChar *name; + xmlChar *begin; + xmlChar *end; +}; + +/* Note that the taglist is ref counted */ +extern TagList *taglist; TagList* create_taglist (void); void free_taglist (void); - -#endif /* __GEDIT_TAGLIST_PLUGIN_PARSER_H_ */ +#endif /* __GEDIT_TAGLIST_PLUGIN_PARSER_H__ */ diff --git a/plugins/taglist/gedit-taglist-plugin.c b/plugins/taglist/gedit-taglist-plugin.c index 03347b1d..29197d4b 100644 --- a/plugins/taglist/gedit-taglist-plugin.c +++ b/plugins/taglist/gedit-taglist-plugin.c @@ -1,14 +1,12 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * gedit-taglist-plugin.c - * This file is part of the gedit taglist plugin - * - * Copyright (C) 2002 Paolo Maggi + * gedit-taglist-plugin.h + * + * 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. + * the Free Software Foundation; either version 2, or (at your option) + * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,149 +15,189 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * */ - + /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ #ifdef HAVE_CONFIG_H #include #endif -#include - -#include - -#include -#include -#include - #include "gedit-taglist-plugin.h" -#include "gedit-taglist-plugin-window.h" +#include "gedit-taglist-plugin-panel.h" #include "gedit-taglist-plugin-parser.h" -#define MENU_ITEM_LABEL N_("Tag _List") -#define MENU_ITEM_PATH "/menu/View/ViewOps/" -/* -#define MENU_ITEM_NAME "TagList" -*/ -#define MENU_ITEM_TIP N_("Show the tag list window") +#include +#include -G_MODULE_EXPORT GeditPluginState update_ui (GeditPlugin *plugin, BonoboWindow *window); -G_MODULE_EXPORT GeditPluginState destroy (GeditPlugin *pd); -G_MODULE_EXPORT GeditPluginState activate (GeditPlugin *pd); -G_MODULE_EXPORT GeditPluginState deactivate (GeditPlugin *pd); -G_MODULE_EXPORT GeditPluginState init (GeditPlugin *pd); +#include +#define WINDOW_DATA_KEY "GeditTaglistPluginWindowData" -static void -tag_list_cb (BonoboUIComponent *ui_component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer data) +#define GEDIT_TAGLIST_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_TAGLIST_PLUGIN, GeditTaglistPluginPrivate)) + +struct _GeditTaglistPluginPrivate { - gboolean s; - - gedit_debug (DEBUG_PLUGINS, "%s toggled to '%s'", path, state); + gpointer dummy; +}; - s = (strcmp (state, "1") == 0); +static GType gedit_taglist_plugin_type = 0; - if (s) - taglist_window_show (); - else - taglist_window_close (); +GType +gedit_taglist_plugin_get_type (void) +{ + return gedit_taglist_plugin_type; } - -G_MODULE_EXPORT GeditPluginState -update_ui (GeditPlugin *plugin, BonoboWindow *window) +static void gedit_taglist_plugin_init (GeditTaglistPlugin *self); +static void gedit_taglist_plugin_class_init (GeditTaglistPluginClass *klass); +static gpointer gedit_taglist_plugin_parent_class = NULL; +static void gedit_taglist_plugin_class_intern_init (gpointer klass) { - BonoboUIComponent *uic; + gedit_taglist_plugin_parent_class = g_type_class_peek_parent (klass); + gedit_taglist_plugin_class_init ((GeditTaglistPluginClass *) klass); +} + +G_MODULE_EXPORT GType +register_gedit_plugin (GTypeModule *module) +{ + static const GTypeInfo our_info = + { + sizeof (GeditTaglistPluginClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gedit_taglist_plugin_class_intern_init, + NULL, + NULL, /* class_data */ + sizeof (GeditTaglistPlugin), + 0, /* n_preallocs */ + (GInstanceInitFunc) gedit_taglist_plugin_init + }; - gedit_debug (DEBUG_PLUGINS, ""); - - g_return_val_if_fail (window != NULL, PLUGIN_ERROR); - - uic = gedit_get_ui_component_from_window (window); + gedit_debug_message (DEBUG_PLUGINS, "Registering GeditTaglistPlugin"); + + /* Initialise the i18n stuff */ + bindtextdomain (GETTEXT_PACKAGE, GEDIT_LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + gedit_taglist_plugin_type = g_type_module_register_type (module, + GEDIT_TYPE_PLUGIN, + "GeditTaglistPlugin", + &our_info, + 0); + + gedit_taglist_plugin_panel_register_type (module); + + return gedit_taglist_plugin_type; +} - gedit_menus_set_verb_sensitive (uic, "/commands/" MENU_ITEM_NAME, TRUE); +static void +gedit_taglist_plugin_init (GeditTaglistPlugin *plugin) +{ + plugin->priv = GEDIT_TAGLIST_PLUGIN_GET_PRIVATE (plugin); - return PLUGIN_OK; + gedit_debug_message (DEBUG_PLUGINS, "GeditTaglistPlugin initializing"); + + create_taglist (); } -G_MODULE_EXPORT GeditPluginState -destroy (GeditPlugin *plugin) +static void +gedit_taglist_plugin_finalize (GObject *object) { - gedit_debug (DEBUG_PLUGINS, ""); +/* + GeditTaglistPlugin *plugin = GEDIT_TAGLIST_PLUGIN (object); +*/ + gedit_debug_message (DEBUG_PLUGINS, "GeditTaglistPlugin finalizing"); free_taglist (); - - return PLUGIN_OK; -} -G_MODULE_EXPORT GeditPluginState -activate (GeditPlugin *pd) -{ - GList *top_windows; - gedit_debug (DEBUG_PLUGINS, ""); + G_OBJECT_CLASS (gedit_taglist_plugin_parent_class)->finalize (object); +} - if (taglist == NULL) - if (create_taglist () == NULL) - return PLUGIN_ERROR; +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GeditPanel *side_panel; + GtkWidget *taglist_panel; - top_windows = gedit_get_top_windows (); - g_return_val_if_fail (top_windows != NULL, PLUGIN_ERROR); - - while (top_windows) - { - BonoboUIComponent *ui_component; - - gedit_menus_add_menu_item_toggle (BONOBO_WINDOW (top_windows->data), - MENU_ITEM_PATH, MENU_ITEM_NAME, - MENU_ITEM_LABEL, MENU_ITEM_TIP, - tag_list_cb, NULL); - - ui_component = gedit_get_ui_component_from_window ( - BONOBO_WINDOW (top_windows->data)); - - bonobo_ui_component_set_prop ( - ui_component, "/commands/" MENU_ITEM_NAME, "accel", "*Shift*F8", NULL); - - pd->update_ui (pd, BONOBO_WINDOW (top_windows->data)); - - top_windows = g_list_next (top_windows); - } - - return PLUGIN_OK; + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY) == NULL); + + side_panel = gedit_window_get_side_panel (window); + taglist_panel = gedit_taglist_plugin_panel_new (window); + + gedit_panel_add_item_with_stock_icon (side_panel, + taglist_panel, + "Tags", + GTK_STOCK_ADD); + + g_object_set_data (G_OBJECT (window), + WINDOW_DATA_KEY, + taglist_panel); } -G_MODULE_EXPORT GeditPluginState -deactivate (GeditPlugin *pd) +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) { - gedit_menus_remove_menu_item_toggle_all (MENU_ITEM_PATH, MENU_ITEM_NAME); - - taglist_window_close (); + GeditPanel *side_panel; + gpointer data; + + gedit_debug (DEBUG_PLUGINS); + + data = g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + side_panel = gedit_window_get_side_panel (window); + + gedit_panel_remove_item (side_panel, + GTK_WIDGET (data)); + + g_object_set_data (G_OBJECT (window), + WINDOW_DATA_KEY, + NULL); +} - free_taglist (); +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + gpointer data; + GeditView *view; + + gedit_debug (DEBUG_PLUGINS); + + data = g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + view = gedit_window_get_active_view (window); - return PLUGIN_OK; + gtk_widget_set_sensitive (GTK_WIDGET (data), + (view != NULL) && + gtk_text_view_get_editable (GTK_TEXT_VIEW (view))); } -G_MODULE_EXPORT GeditPluginState -init (GeditPlugin *pd) +static void +gedit_taglist_plugin_class_init (GeditTaglistPluginClass *klass) { - /* initialize */ - gedit_debug (DEBUG_PLUGINS, ""); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); - pd->private_data = NULL; - - return PLUGIN_OK; -} + object_class->finalize = gedit_taglist_plugin_finalize; + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; + g_type_class_add_private (object_class, sizeof (GeditTaglistPluginPrivate)); +} diff --git a/plugins/taglist/gedit-taglist-plugin.h b/plugins/taglist/gedit-taglist-plugin.h index affbac51..d0444e76 100644 --- a/plugins/taglist/gedit-taglist-plugin.h +++ b/plugins/taglist/gedit-taglist-plugin.h @@ -1,14 +1,12 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gedit-taglist-plugin.h - * This file is part of the gedit taglist plugin - * - * Copyright (C) 2002 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. + * the Free Software Foundation; either version 2, or (at your option) + * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,48 +15,71 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * */ - + /* - * Modified by the gedit Team, 2002. See the AUTHORS file for a + * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a * list of people on the gedit Team. * See the ChangeLog files for a list of changes. + * + * $Id$ */ - + #ifndef __GEDIT_TAGLIST_PLUGIN_H__ #define __GEDIT_TAGLIST_PLUGIN_H__ -#include -#include +#include +#include +#include -#define MENU_ITEM_NAME "TagList" +G_BEGIN_DECLS -typedef struct _TagList TagList; -typedef struct _TagGroup TagGroup; -typedef struct _Tag Tag; +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_TAGLIST_PLUGIN (gedit_taglist_plugin_get_type ()) +#define GEDIT_TAGLIST_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_TAGLIST_PLUGIN, GeditTaglistPlugin)) +#define GEDIT_TAGLIST_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_TAGLIST_PLUGIN, GeditTaglistPluginClass)) +#define GEDIT_IS_TAGLIST_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_TAGLIST_PLUGIN)) +#define GEDIT_IS_TAGLIST_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_TAGLIST_PLUGIN)) +#define GEDIT_TAGLIST_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_TAGLIST_PLUGIN, GeditTaglistPluginClass)) -struct _TagList -{ - GList *tag_groups; -}; +/* Private structure type */ +typedef struct _GeditTaglistPluginPrivate GeditTaglistPluginPrivate; -struct _TagGroup +/* + * Main object structure + */ +typedef struct _GeditTaglistPlugin GeditTaglistPlugin; + +struct _GeditTaglistPlugin { - xmlChar *name; + GeditPlugin parent_instance; - GList *tags; + /*< private >*/ + GeditTaglistPluginPrivate *priv; }; -struct _Tag +/* + * Class definition + */ +typedef struct _GeditTaglistPluginClass GeditTaglistPluginClass; + +struct _GeditTaglistPluginClass { - xmlChar *name; - xmlChar *begin; - xmlChar *end; + GeditPluginClass parent_class; }; -extern TagList *taglist; +/* + * Public methods + */ +GType gedit_taglist_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); -#endif /*__GEDIT_TAGLIST_PLUGIN_H_ */ +G_END_DECLS +#endif /* __GEDIT_TAGLIST_PLUGIN_H__ */ diff --git a/plugins/taglist/taglist.gedit-plugin.desktop.in b/plugins/taglist/taglist.gedit-plugin.desktop.in index b68fc4c2..fc52f21a 100644 --- a/plugins/taglist/taglist.gedit-plugin.desktop.in +++ b/plugins/taglist/taglist.gedit-plugin.desktop.in @@ -1,6 +1,8 @@ [Gedit Plugin] -Location=taglist +Module=taglist +IAge=2 _Name=Tag list _Description=Provides a method to easily insert into a document commonly used tags/strings without having to type them. -Author=Paolo Maggi -Copyright=Copyright © 2002-2003 Paolo Maggi +Authors=Paolo Maggi +Copyright=Copyright © 2002-2005 Paolo Maggi +Website=http://www.gedit.org diff --git a/plugins/time/Makefile.am b/plugins/time/Makefile.am index f89ec0ab..c2e2e234 100644 --- a/plugins/time/Makefile.am +++ b/plugins/time/Makefile.am @@ -1,17 +1,21 @@ -# Sample plugin +# time plugin plugindir = $(libdir)/gedit-2/plugins -INCLUDES = \ - -I$(top_srcdir) \ - $(GEDIT_CFLAGS) \ - $(WARN_CFLAGS) \ - $(DISABLE_DEPRECATED_CFLAGS) \ - -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ +INCLUDES = \ + -I$(top_srcdir) \ + $(GEDIT_CFLAGS) \ + $(WARN_CFLAGS) \ + $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" plugin_LTLIBRARIES = libtime.la -libtime_la_SOURCES = time.c +libtime_la_SOURCES = \ + gedit-time-plugin.h \ + gedit-time-plugin.c + libtime_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) gladedir = $(datadir)/gedit-2/glade @@ -26,4 +30,5 @@ plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) EXTRA_DIST = $(glade_DATA) $(plugin_in_files) CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) diff --git a/plugins/time/gedit-time-plugin.c b/plugins/time/gedit-time-plugin.c new file mode 100644 index 00000000..b386e9a7 --- /dev/null +++ b/plugins/time/gedit-time-plugin.c @@ -0,0 +1,1248 @@ +/* + * gedit-time-plugin.c + * + * 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, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +/* + * Modified by the gedit Team, 2002. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include "gedit-time-plugin.h" +#include + +#include +#include + +#include +#include + +#define GEDIT_TIME_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_TIME_PLUGIN, GeditTimePluginPrivate)) + +#define WINDOW_DATA_KEY "GeditTimePluginWindowData" +#define MENU_PATH "/MenuBar/EditMenu/EditOps_4" + +#define TIME_BASE_KEY "/apps/gedit-2/plugins/time" +#define SELECTED_FORMAT_KEY "/selected_format" +#define PROMPT_TYPE_KEY "/prompt_type" +#define CUSTOM_FORMAT_KEY "/custom_format" + +#define DIALOG_PROMPT_TYPE_KEY "gedit-2/time_plugin/prompt_type" + +#define DEFAULT_CUSTOM_FORMAT "%d/%m/%Y %H:%M:%S" + +enum +{ + COLUMN_FORMATS = 0, + COLUMN_INDEX, + NUM_COLUMNS +}; + +typedef struct _TimeConfigureDialog TimeConfigureDialog; + +struct _TimeConfigureDialog +{ + GtkWidget *dialog; + + GtkWidget *list; + + /* Radio buttons to indicate what should be done */ + GtkWidget *prompt; + GtkWidget *use_list; + GtkWidget *custom; + + GtkWidget *custom_entry; + GtkWidget *custom_format_example; + + /* Info needed for the response handler */ + GeditTimePlugin *plugin; +}; + +typedef struct _ChooseFormatDialog ChooseFormatDialog; + +struct _ChooseFormatDialog +{ + GtkWidget *dialog; + + GtkWidget *list; + + /* Radio buttons to indicate what should be done */ + GtkWidget *use_list; + GtkWidget *custom; + + GtkWidget *custom_entry; + GtkWidget *custom_format_example; + + /* Info needed for the response handler */ + GtkTextBuffer *buffer; + GeditTimePlugin *plugin; +}; + +static gchar *formats[] = +{ + "%c", + "%x", + "%X", + "%x %X", + "%Y-%m-%d %H:%M:%S", + "%a %b %d %H:%M:%S %Z %Y", + "%a %b %d %H:%M:%S %Y", + "%a %d %b %Y %H:%M:%S %Z", + "%a %d %b %Y %H:%M:%S", + "%d/%m/%Y", + "%d/%m/%y", + "%D", + "%A %d %B %Y", + "%A %B %d %Y", + "%Y-%m-%d", + "%d %B %Y", + "%B %d, %Y", + "%A %b %d", + "%H:%M:%S", + "%H:%M", + "%I:%M:%S %p", + "%I:%M %p", + "%H.%M.%S", + "%H.%M", + "%I.%M.%S %p", + "%I.%M %p", + "%d/%m/%Y %H:%M:%S", + "%d/%m/%y %H:%M:%S", +#if __GLIBC__ >= 2 + "%a, %d %b %Y %H:%M:%S %z", +#endif + NULL +}; + +typedef enum +{ + PROMPT_FOR_FORMAT = 0, + USE_SELECTED_FORMAT, + USE_CUSTOM_FORMAT +} GeditTimePluginPromptType; + +struct _GeditTimePluginPrivate +{ + GConfClient *gconf_client; + + gchar *last_custom_format; + gchar *last_selected_format; + + GeditTimePluginPromptType last_prompt_type; +}; + +GEDIT_PLUGIN_REGISTER_TYPE(GeditTimePlugin, gedit_time_plugin) + +typedef struct +{ + GtkActionGroup *action_group; + guint ui_id; +} WindowData; + +typedef struct +{ + GeditWindow *window; + GeditTimePlugin *plugin; +} ActionData; + +static void time_cb (GtkAction *action, ActionData *data); + +static const GtkActionEntry action_entries[] = +{ + { + "InsertDateAndTime", + NULL, + N_("In_sert Date and Time..."), + NULL, + N_("Insert current date and time at the cursor position"), + G_CALLBACK (time_cb) + }, +}; + +static void +gedit_time_plugin_init (GeditTimePlugin *plugin) +{ + gedit_debug_message (DEBUG_PLUGINS, "GeditTimePlugin initializing"); + + plugin->priv = GEDIT_TIME_PLUGIN_GET_PRIVATE (plugin); + + plugin->priv->gconf_client = gconf_client_get_default (); + + gconf_client_add_dir (plugin->priv->gconf_client, + TIME_BASE_KEY, + GCONF_CLIENT_PRELOAD_ONELEVEL, + NULL); + + plugin->priv->last_prompt_type = gnome_config_get_int (DIALOG_PROMPT_TYPE_KEY "=1"); +} + +static void +gedit_time_plugin_finalize (GObject *object) +{ + GeditTimePlugin *plugin = GEDIT_TIME_PLUGIN (object); + + gedit_debug_message (DEBUG_PLUGINS, "GeditTimePlugin finalizing"); + + gconf_client_suggest_sync (plugin->priv->gconf_client, NULL); + + g_object_unref (G_OBJECT (plugin->priv->gconf_client)); + + g_free (plugin->priv->last_custom_format); + g_free (plugin->priv->last_selected_format); + + gnome_config_set_int (DIALOG_PROMPT_TYPE_KEY, plugin->priv->last_prompt_type); + gnome_config_sync (); + + G_OBJECT_CLASS (gedit_time_plugin_parent_class)->finalize (object); +} + +static void +free_window_data (WindowData *data) +{ + g_return_if_fail (data != NULL); + + g_object_unref (data->action_group); + g_free (data); +} + +static void +update_ui_real (GeditWindow *window, + WindowData *data) +{ + GeditView *view; + GtkAction *action; + + gedit_debug (DEBUG_PLUGINS); + + view = gedit_window_get_active_view (window); + + gedit_debug_message (DEBUG_PLUGINS, "View: %p", view); + + action = gtk_action_group_get_action (data->action_group, + "InsertDateAndTime"); + gtk_action_set_sensitive (action, + (view != NULL) && + gtk_text_view_get_editable (GTK_TEXT_VIEW (view))); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + ActionData *action_data; + + gedit_debug (DEBUG_PLUGINS); + + data = g_new (WindowData, 1); + action_data = g_new (ActionData, 1); + + action_data->plugin = GEDIT_TIME_PLUGIN (plugin); + action_data->window = window; + + manager = gedit_window_get_ui_manager (window); + + data->action_group = gtk_action_group_new ("GeditTimePluginActions"); + gtk_action_group_set_translation_domain (data->action_group, + GETTEXT_PACKAGE); + gtk_action_group_add_actions_full (data->action_group, + action_entries, + G_N_ELEMENTS (action_entries), + action_data, + (GDestroyNotify) g_free); + + gtk_ui_manager_insert_action_group (manager, data->action_group, -1); + + data->ui_id = gtk_ui_manager_new_merge_id (manager); + + g_object_set_data_full (G_OBJECT (window), + WINDOW_DATA_KEY, + data, + (GDestroyNotify) free_window_data); + + gtk_ui_manager_add_ui (manager, + data->ui_id, + MENU_PATH, + "InsertDateAndTime", + "InsertDateAndTime", + GTK_UI_MANAGER_MENUITEM, + FALSE); + + update_ui_real (window, data); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + GtkUIManager *manager; + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + manager = gedit_window_get_ui_manager (window); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + gtk_ui_manager_remove_ui (manager, data->ui_id); + gtk_ui_manager_remove_action_group (manager, data->action_group); + + g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + WindowData *data; + + gedit_debug (DEBUG_PLUGINS); + + data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); + + update_ui_real (window, data); +} + +static GeditTimePluginPromptType +get_prompt_type (GeditTimePlugin *plugin) +{ + gchar *prompt_type; + GeditTimePluginPromptType res; + + prompt_type = gconf_client_get_string (plugin->priv->gconf_client, + TIME_BASE_KEY PROMPT_TYPE_KEY, + NULL); + + if (prompt_type == NULL) + return PROMPT_FOR_FORMAT; + + if (strcmp (prompt_type, "USE_SELECTED_FORMAT") == 0) + res = USE_SELECTED_FORMAT; + else + { + if (strcmp (prompt_type, "USE_CUSTOM_FORMAT") == 0) + res = USE_CUSTOM_FORMAT; + else + res = PROMPT_FOR_FORMAT; + } + + g_free (prompt_type); + + return res; +} + +static void +set_prompt_type (GeditTimePlugin *plugin, + GeditTimePluginPromptType prompt_type) +{ + const gchar * str; + + if (!gconf_client_key_is_writable (plugin->priv->gconf_client, + TIME_BASE_KEY PROMPT_TYPE_KEY, + NULL)) + return; + + + switch (prompt_type) + { + case USE_SELECTED_FORMAT: + str = "USE_SELECTED_FORMAT"; + break; + case USE_CUSTOM_FORMAT: + str = "USE_CUSTOM_FORMAT"; + break; + default: + str = "PROMPT_FOR_FORMAT"; + } + + gconf_client_set_string (plugin->priv->gconf_client, + TIME_BASE_KEY PROMPT_TYPE_KEY, + str, + NULL); +} + +static gchar * +get_selected_format (GeditTimePlugin *plugin) +{ + gchar *sel_format; + + sel_format = gconf_client_get_string (plugin->priv->gconf_client, + TIME_BASE_KEY SELECTED_FORMAT_KEY, + NULL); + + if (sel_format == NULL) + return g_strdup (formats [0]); + + return sel_format; +} + +static void +set_selected_format (GeditTimePlugin *plugin, + const gchar *format) +{ + g_return_if_fail (format != NULL); + + if (!gconf_client_key_is_writable (plugin->priv->gconf_client, + TIME_BASE_KEY SELECTED_FORMAT_KEY, + NULL)) + return; + + gconf_client_set_string (plugin->priv->gconf_client, + TIME_BASE_KEY SELECTED_FORMAT_KEY, + format, + NULL); +} + +static gchar * +get_custom_format (GeditTimePlugin *plugin) +{ + gchar *format; + + format = gconf_client_get_string (plugin->priv->gconf_client, + TIME_BASE_KEY CUSTOM_FORMAT_KEY, + NULL); + + if (format == NULL) + return g_strdup (DEFAULT_CUSTOM_FORMAT); + + return format; +} + +static void +set_custom_format (GeditTimePlugin *plugin, + const gchar *format) +{ + g_return_if_fail (format != NULL); + + if (!gconf_client_key_is_writable (plugin->priv->gconf_client, + TIME_BASE_KEY CUSTOM_FORMAT_KEY, + NULL)) + return; + + gconf_client_set_string (plugin->priv->gconf_client, + TIME_BASE_KEY CUSTOM_FORMAT_KEY, + format, + NULL); +} + +static gchar * +get_time (const gchar* format) +{ + gchar *out = NULL; + gchar *out_utf8 = NULL; + time_t clock; + struct tm *now; + size_t out_length = 0; + gchar *locale_format; + + gedit_debug (DEBUG_PLUGINS); + + g_return_val_if_fail (format != NULL, NULL); + + if (strlen (format) == 0) + return g_strdup (" "); + + locale_format = g_locale_from_utf8 (format, -1, NULL, NULL, NULL); + + if (locale_format == NULL) + return g_strdup (" "); + + clock = time (NULL); + now = localtime (&clock); + + do + { + out_length += 255; + out = g_realloc (out, out_length); + } + while (strftime (out, out_length, locale_format, now) == 0); + + g_free (locale_format); + + if (g_utf8_validate (out, -1, NULL)) + out_utf8 = out; + else + { + out_utf8 = g_locale_to_utf8 (out, -1, NULL, NULL, NULL); + g_free (out); + + if (out_utf8 == NULL) + out_utf8 = g_strdup (" "); + } + + return out_utf8; +} + +static void +dialog_destroyed (GtkObject *obj, gpointer dialog_pointer) +{ + gedit_debug (DEBUG_PLUGINS); + + g_free (dialog_pointer); + + gedit_debug_message (DEBUG_PLUGINS, "END"); + +} + +static GtkTreeModel * +create_model (GtkWidget *listview, + const gchar *sel_format, + GeditTimePlugin *plugin) +{ + gint i = 0; + GtkListStore *store; + GtkTreeSelection *selection; + GtkTreeIter iter; + gchar *sf; + + gedit_debug (DEBUG_PLUGINS); + + /* create list store */ + store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_INT); + + /* Set tree view model*/ + gtk_tree_view_set_model (GTK_TREE_VIEW (listview), + GTK_TREE_MODEL (store)); + + g_object_unref (G_OBJECT (store)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (listview)); + g_return_val_if_fail (selection != NULL, GTK_TREE_MODEL (store)); + + /* there should always be one line selected */ + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + + if (sel_format == NULL) + sf = get_selected_format (plugin); + else + sf = g_strdup (sel_format); + + /* add data to the list store */ + while (formats[i] != NULL) + { + gchar *str; + + str = get_time (formats[i]); + + gedit_debug_message (DEBUG_PLUGINS, "%d : %s", i, str); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COLUMN_FORMATS, str, + COLUMN_INDEX, i, + -1); + g_free (str); + + if (strncmp (formats[i], sf, strlen (sf)) == 0) + gtk_tree_selection_select_iter (selection, &iter); + + ++i; + } + + /* fall back to select the first iter */ + if (!gtk_tree_selection_get_selected (selection, NULL, NULL)) + { + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); + gtk_tree_selection_select_iter (selection, &iter); + } + + g_free (sf); + + return GTK_TREE_MODEL (store); +} + +static void +scroll_to_selected (GtkTreeView *tree_view) +{ + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + + gedit_debug (DEBUG_PLUGINS); + + model = gtk_tree_view_get_model (tree_view); + g_return_if_fail (model != NULL); + + /* Scroll to selected */ + selection = gtk_tree_view_get_selection (tree_view); + g_return_if_fail (selection != NULL); + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + { + GtkTreePath* path; + + path = gtk_tree_model_get_path (model, &iter); + g_return_if_fail (path != NULL); + + gtk_tree_view_scroll_to_cell (tree_view, + path, NULL, TRUE, 1.0, 0.0); + gtk_tree_path_free (path); + } +} + +static void +create_formats_list (GtkWidget *listview, + const gchar *sel_format, + GeditTimePlugin *plugin) +{ + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (listview != NULL); + + /* the Available formats column */ + cell = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ( + _("Available formats"), + cell, + "text", COLUMN_FORMATS, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (listview), column); + + /* Create model, it also add model to the tree view */ + create_model (listview, sel_format, plugin); + + g_signal_connect (listview, + "realize", + G_CALLBACK (scroll_to_selected), + NULL); + + gtk_widget_show (listview); +} + +static void +updated_custom_format_example (GtkEntry *format_entry, + GtkLabel *format_example) +{ + const gchar *format; + gchar *time; + gchar *str; + gchar *escaped_time; + + gedit_debug (DEBUG_PLUGINS); + + g_return_if_fail (GTK_IS_ENTRY (format_entry)); + g_return_if_fail (GTK_IS_LABEL (format_example)); + + format = gtk_entry_get_text (format_entry); + + time = get_time (format); + escaped_time = g_markup_escape_text (time, -1); + + str = g_strdup_printf ("%s", escaped_time); + + gtk_label_set_markup (format_example, str); + + g_free (escaped_time); + g_free (time); + g_free (str); +} + +static void +choose_format_dialog_button_toggled (GtkToggleButton *button, + ChooseFormatDialog *dialog) +{ + gedit_debug (DEBUG_PLUGINS); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->custom))) + { + gtk_widget_set_sensitive (dialog->list, FALSE); + gtk_widget_set_sensitive (dialog->custom_entry, TRUE); + gtk_widget_set_sensitive (dialog->custom_format_example, TRUE); + + return; + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->use_list))) + { + gtk_widget_set_sensitive (dialog->list, TRUE); + gtk_widget_set_sensitive (dialog->custom_entry, FALSE); + gtk_widget_set_sensitive (dialog->custom_format_example, FALSE); + + return; + } +} + +static void +configure_dialog_button_toggled (GtkToggleButton *button, TimeConfigureDialog *dialog) +{ + gedit_debug (DEBUG_PLUGINS); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->custom))) + { + gtk_widget_set_sensitive (dialog->list, FALSE); + gtk_widget_set_sensitive (dialog->custom_entry, TRUE); + gtk_widget_set_sensitive (dialog->custom_format_example, TRUE); + + return; + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->use_list))) + { + gtk_widget_set_sensitive (dialog->list, TRUE); + gtk_widget_set_sensitive (dialog->custom_entry, FALSE); + gtk_widget_set_sensitive (dialog->custom_format_example, FALSE); + + return; + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->prompt))) + { + gtk_widget_set_sensitive (dialog->list, FALSE); + gtk_widget_set_sensitive (dialog->custom_entry, FALSE); + gtk_widget_set_sensitive (dialog->custom_format_example, FALSE); + + return; + } +} + +static gint +get_format_from_list (GtkWidget *listview) +{ + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + gint selected_value; + + gedit_debug (DEBUG_PLUGINS); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (listview)); + g_return_val_if_fail (model != NULL, 0); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (listview)); + g_return_val_if_fail (selection != NULL, 0); + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + { + gtk_tree_model_get (model, &iter, COLUMN_INDEX, &selected_value, -1); + } + + gedit_debug_message (DEBUG_PLUGINS, "Sel value: %d", selected_value); + + return selected_value; +} + +static void +ok_button_pressed (TimeConfigureDialog *dialog) +{ + gint sel_format; + const gchar *custom_format; + + gedit_debug (DEBUG_PLUGINS); + + sel_format = get_format_from_list (dialog->list); + + custom_format = gtk_entry_get_text (GTK_ENTRY (dialog->custom_entry)); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->custom))) + { + set_prompt_type (dialog->plugin, USE_CUSTOM_FORMAT); + set_custom_format (dialog->plugin, custom_format); + } + else + { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->use_list))) + { + set_prompt_type (dialog->plugin, USE_SELECTED_FORMAT); + + set_selected_format (dialog->plugin, formats [sel_format]); + } + else + /* Default to always prompt the user */ + set_prompt_type (dialog->plugin, PROMPT_FOR_FORMAT); + } + + gedit_debug_message (DEBUG_PLUGINS, "Sel: %d", sel_format); +} + +static TimeConfigureDialog * +get_configure_dialog (GeditTimePlugin *plugin) +{ + TimeConfigureDialog *dialog = NULL; + + GtkWidget *content; + GtkWidget *viewport; + GeditTimePluginPromptType prompt_type; + gchar *sf, *cf; + GtkWidget *error_widget; + gboolean ret; + + gedit_debug (DEBUG_PLUGINS); + + dialog = g_new0 (TimeConfigureDialog, 1); + + dialog->dialog = gtk_dialog_new_with_buttons (_("Configure insert date/time plugin..."), + NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, + GTK_RESPONSE_OK, + GTK_STOCK_HELP, + GTK_RESPONSE_HELP, + NULL); + + g_return_val_if_fail (dialog->dialog != NULL, NULL); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "time.glade2", + "time_dialog_content", + &error_widget, + "time_dialog_content", &content, + "formats_viewport", &viewport, + "formats_tree", &dialog->list, + "always_prompt", &dialog->prompt, + "never_prompt", &dialog->use_list, + "use_custom", &dialog->custom, + "custom_entry", &dialog->custom_entry, + "custom_format_example", &dialog->custom_format_example, + NULL); + + if (!ret) + { + gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog->dialog)->vbox), + error_widget); + + gtk_widget_show (error_widget); + + return dialog; + } + + gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); + gtk_dialog_set_has_separator (GTK_DIALOG (dialog->dialog), FALSE); + + sf = get_selected_format (plugin); + create_formats_list (dialog->list, sf, plugin); + g_free (sf); + + prompt_type = get_prompt_type (plugin); + + cf = get_custom_format (plugin); + gtk_entry_set_text (GTK_ENTRY(dialog->custom_entry), cf); + g_free (cf); + + if (prompt_type == USE_CUSTOM_FORMAT) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->custom), TRUE); + + gtk_widget_set_sensitive (dialog->list, FALSE); + gtk_widget_set_sensitive (dialog->custom_entry, TRUE); + gtk_widget_set_sensitive (dialog->custom_format_example, TRUE); + } + else if (prompt_type == USE_SELECTED_FORMAT) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->use_list), TRUE); + + gtk_widget_set_sensitive (dialog->list, TRUE); + gtk_widget_set_sensitive (dialog->custom_entry, FALSE); + gtk_widget_set_sensitive (dialog->custom_format_example, FALSE); + } + else + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->prompt), TRUE); + + gtk_widget_set_sensitive (dialog->list, FALSE); + gtk_widget_set_sensitive (dialog->custom_entry, FALSE); + gtk_widget_set_sensitive (dialog->custom_format_example, FALSE); + } + + updated_custom_format_example (GTK_ENTRY (dialog->custom_entry), + GTK_LABEL (dialog->custom_format_example)); + + /* setup a window of a sane size. */ + gtk_widget_set_size_request (GTK_WIDGET (viewport), 10, 200); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->dialog)->vbox), + content, FALSE, FALSE, 0); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog->dialog), + GTK_RESPONSE_OK); + + g_signal_connect (dialog->custom, + "toggled", + G_CALLBACK (configure_dialog_button_toggled), + dialog); + g_signal_connect (dialog->prompt, + "toggled", + G_CALLBACK (configure_dialog_button_toggled), + dialog); + g_signal_connect (dialog->use_list, + "toggled", + G_CALLBACK (configure_dialog_button_toggled), + dialog); + g_signal_connect (dialog->dialog, + "destroy", + G_CALLBACK (dialog_destroyed), + dialog); + g_signal_connect (dialog->custom_entry, + "changed", + G_CALLBACK (updated_custom_format_example), + dialog->custom_format_example); + + return dialog; +} + +static void +real_insert_time (GtkTextBuffer *buffer, + const gchar *the_time) +{ + gedit_debug_message (DEBUG_PLUGINS, "Insert: %s", the_time); + + gtk_text_buffer_begin_user_action (buffer); + + gtk_text_buffer_insert_at_cursor (buffer, the_time, -1); + gtk_text_buffer_insert_at_cursor (buffer, " ", -1); + + gtk_text_buffer_end_user_action (buffer); +} + +static void +choose_format_dialog_row_activated (GtkTreeView *list, + GtkTreePath *path, + GtkTreeViewColumn *column, + ChooseFormatDialog *dialog) +{ + gint sel_format; + gchar *the_time; + + sel_format = get_format_from_list (dialog->list); + the_time = get_time (formats[sel_format]); + + g_free (dialog->plugin->priv->last_selected_format); + dialog->plugin->priv->last_selected_format = g_strdup (formats[sel_format]); + + dialog->plugin->priv->last_prompt_type = USE_SELECTED_FORMAT; + set_selected_format (dialog->plugin, + dialog->plugin->priv->last_selected_format); + + g_return_if_fail (the_time != NULL); + + real_insert_time (dialog->buffer, the_time); + + g_free (the_time); +} + +static ChooseFormatDialog * +get_choose_format_dialog (GtkWindow *parent, + GeditTimePlugin *plugin) +{ + ChooseFormatDialog *dialog; + GtkWidget *error_widget; + gboolean ret; + + dialog = g_new0 (ChooseFormatDialog, 1); + + ret = gedit_utils_get_glade_widgets (GEDIT_GLADEDIR "time.glade2", + "choose_format_dialog", + &error_widget, + "choose_format_dialog", &dialog->dialog, + "choice_list", &dialog->list, + "use_sel_format_radiobutton", &dialog->use_list, + "use_custom_radiobutton", &dialog->custom, + "custom_entry", &dialog->custom_entry, + "custom_format_example", &dialog->custom_format_example, + NULL); + + if (!ret) + { + gedit_warning (parent, + gtk_label_get_label (GTK_LABEL (error_widget))); + + g_free (dialog); + gtk_widget_destroy (error_widget); + + return NULL; + } + + if (plugin->priv->last_selected_format == NULL) + plugin->priv->last_selected_format = get_selected_format (plugin); + + create_formats_list (dialog->list, + plugin->priv->last_selected_format, + plugin); + + if (plugin->priv->last_custom_format == NULL) + plugin->priv->last_custom_format = get_custom_format (plugin); + + gtk_entry_set_text (GTK_ENTRY(dialog->custom_entry), + plugin->priv->last_custom_format); + updated_custom_format_example (GTK_ENTRY (dialog->custom_entry), + GTK_LABEL (dialog->custom_format_example)); + + if (plugin->priv->last_prompt_type == USE_CUSTOM_FORMAT) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->custom), TRUE); + + gtk_widget_set_sensitive (dialog->list, FALSE); + gtk_widget_set_sensitive (dialog->custom_entry, TRUE); + gtk_widget_set_sensitive (dialog->custom_format_example, TRUE); + } + else + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->use_list), TRUE); + + gtk_widget_set_sensitive (dialog->list, TRUE); + gtk_widget_set_sensitive (dialog->custom_entry, FALSE); + gtk_widget_set_sensitive (dialog->custom_format_example, FALSE); + } + + /* setup a window of a sane size. */ + gtk_widget_set_size_request (dialog->list, 10, 200); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog->dialog), + GTK_RESPONSE_OK); + + g_signal_connect (dialog->custom, + "toggled", + G_CALLBACK (choose_format_dialog_button_toggled), + dialog); + g_signal_connect (dialog->use_list, + "toggled", + G_CALLBACK (choose_format_dialog_button_toggled), + dialog); + g_signal_connect (dialog->dialog, + "destroy", + G_CALLBACK (dialog_destroyed), + dialog); + g_signal_connect (dialog->custom_entry, + "changed", + G_CALLBACK (updated_custom_format_example), + dialog->custom_format_example); + g_signal_connect (dialog->list, + "row_activated", + G_CALLBACK (choose_format_dialog_row_activated), + dialog); + + gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); + + return dialog; +} + +static void +choose_format_dialog_response_cb (GtkWidget *widget, + gint response, + ChooseFormatDialog *dialog) +{ + switch (response) + { + case GTK_RESPONSE_HELP: + { + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_HELP"); + gedit_help_display (GTK_WINDOW (widget), + "gedit.xml", + "gedit-insert-date-time-plugin"); + break; + } + case GTK_RESPONSE_OK: + { + gchar *the_time; + + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_OK"); + + /* Get the user's chosen format */ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->use_list))) + { + gint sel_format; + + sel_format = get_format_from_list (dialog->list); + the_time = get_time (formats[sel_format]); + + g_free (dialog->plugin->priv->last_selected_format); + dialog->plugin->priv->last_selected_format = g_strdup (formats[sel_format]); + + dialog->plugin->priv->last_prompt_type = USE_SELECTED_FORMAT; + set_selected_format (dialog->plugin, + dialog->plugin->priv->last_selected_format); + } + else + { + const gchar *format; + + format = gtk_entry_get_text (GTK_ENTRY (dialog->custom_entry)); + the_time = get_time (format); + + g_free (dialog->plugin->priv->last_custom_format); + dialog->plugin->priv->last_custom_format = g_strdup (format); + + dialog->plugin->priv->last_prompt_type = USE_CUSTOM_FORMAT; + set_custom_format (dialog->plugin, + dialog->plugin->priv->last_custom_format); + } + + g_return_if_fail (the_time != NULL); + + real_insert_time (dialog->buffer, the_time); + g_free (the_time); + + gtk_widget_destroy (dialog->dialog); + break; + } + case GTK_RESPONSE_CANCEL: + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_CANCEL"); + gtk_widget_destroy (dialog->dialog); + } +} + +static void +time_cb (GtkAction *action, + ActionData *data) +{ + GtkTextBuffer *buffer; + gchar *the_time = NULL; + GeditTimePluginPromptType prompt_type; + + gedit_debug (DEBUG_PLUGINS); + + buffer = GTK_TEXT_BUFFER (gedit_window_get_active_document (data->window)); + g_return_if_fail (buffer != NULL); + + prompt_type = get_prompt_type (data->plugin); + + if (prompt_type == USE_CUSTOM_FORMAT) + { + gchar *cf = get_custom_format (data->plugin); + the_time = get_time (cf); + g_free (cf); + } + else if (prompt_type == USE_SELECTED_FORMAT) + { + gchar *sf = get_selected_format (data->plugin); + the_time = get_time (sf); + g_free (sf); + } + else + { + GtkWindowGroup *wg; + ChooseFormatDialog *dialog; + + dialog = get_choose_format_dialog (GTK_WINDOW (data->window), + data->plugin); + g_return_if_fail (dialog != NULL); + + wg = gedit_window_get_group (data->window); + + gtk_window_group_add_window (wg, + GTK_WINDOW (dialog->dialog)); + + gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), + GTK_WINDOW (data->window)); + gtk_window_set_modal (GTK_WINDOW (dialog->dialog), TRUE); + + dialog->buffer = buffer; + dialog->plugin = data->plugin; + + g_signal_connect (dialog->dialog, + "response", + G_CALLBACK (choose_format_dialog_response_cb), + dialog); + + gtk_widget_show (GTK_WIDGET (dialog->dialog)); + + return; + } + + g_return_if_fail (the_time != NULL); + + real_insert_time (buffer, the_time); + + g_free (the_time); +} + +static void +configure_dialog_response_cb (GtkWidget *widget, + gint response, + TimeConfigureDialog *dialog) +{ + switch (response) + { + case GTK_RESPONSE_HELP: + { + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_HELP"); + + gedit_help_display (GTK_WINDOW (dialog), + "gedit.xml", + "gedit-date-time-configure"); + break; + } + case GTK_RESPONSE_OK: + { + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_OK"); + + ok_button_pressed (dialog); + + gtk_widget_destroy (dialog->dialog); + break; + } + case GTK_RESPONSE_CANCEL: + { + gedit_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_CANCEL"); + gtk_widget_destroy (dialog->dialog); + } + } +} + +static GtkWidget * +impl_create_configure_dialog (GeditPlugin *plugin) +{ + TimeConfigureDialog *dialog; + + dialog = get_configure_dialog (GEDIT_TIME_PLUGIN (plugin)); + + dialog->plugin = GEDIT_TIME_PLUGIN (plugin); + + g_signal_connect (dialog->dialog, + "response", + G_CALLBACK (configure_dialog_response_cb), + dialog); + + return GTK_WIDGET (dialog->dialog); +} + + +static void +gedit_time_plugin_class_init (GeditTimePluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_time_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; + + plugin_class->create_configure_dialog = impl_create_configure_dialog; + + g_type_class_add_private (object_class, sizeof (GeditTimePluginPrivate)); +} diff --git a/plugins/time/gedit-time-plugin.h b/plugins/time/gedit-time-plugin.h new file mode 100644 index 00000000..40be819f --- /dev/null +++ b/plugins/time/gedit-time-plugin.h @@ -0,0 +1,78 @@ +/* + * gedit-time-plugin.h + * + * Copyright (C) %YEAR% - %AUTHOR% + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_TIME_PLUGIN_H__ +#define __GEDIT_TIME_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_TIME_PLUGIN (gedit_time_plugin_get_type ()) +#define GEDIT_TIME_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_TIME_PLUGIN, GeditTimePlugin)) +#define GEDIT_TIME_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_TIME_PLUGIN, GeditTimePluginClass)) +#define GEDIT_IS_TIME_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_TIME_PLUGIN)) +#define GEDIT_IS_TIME_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_TIME_PLUGIN)) +#define GEDIT_TIME_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_TIME_PLUGIN, GeditTimePluginClass)) + +/* Private structure type */ +typedef struct _GeditTimePluginPrivate GeditTimePluginPrivate; + +/* + * Main object structure + */ +typedef struct _GeditTimePlugin GeditTimePlugin; + +struct _GeditTimePlugin +{ + GeditPlugin parent_instance; + + /*< private >*/ + GeditTimePluginPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditTimePluginClass GeditTimePluginClass; + +struct _GeditTimePluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_time_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_TIME_PLUGIN_H__ */ diff --git a/plugins/time/time.gedit-plugin.desktop.in b/plugins/time/time.gedit-plugin.desktop.in index a6742608..aa8776b9 100644 --- a/plugins/time/time.gedit-plugin.desktop.in +++ b/plugins/time/time.gedit-plugin.desktop.in @@ -1,6 +1,8 @@ [Gedit Plugin] -Location=time +Module=time +IAge=2 _Name=Insert Date/Time _Description=Inserts current date and time at the cursor position. -Author=Paolo Maggi , Lee Mallabone -Copyright=Copyright © 2002-2003 Paolo Maggi +Authors=Paolo Maggi ;Lee Mallabone +Copyright=Copyright © 2002-2005 Paolo Maggi +Website=http://www.gedit.org diff --git a/plugins/time/time.glade2 b/plugins/time/time.glade2 index c29ac04b..1cdb8847 100644 --- a/plugins/time/time.glade2 +++ b/plugins/time/time.glade2 @@ -346,11 +346,11 @@ - + Insert Date and Time GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE - True + False False True False diff --git a/po/ChangeLog b/po/ChangeLog index 5451cbb0..e69de29b 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,4492 +0,0 @@ -2005-11-30 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2005-11-22 Roozbeh Pournader - - * fa.po: Updated Persian translation by Meelad Zakaria and Elanz - Sarbar. - -2005-11-20 Frank Arnold - - * de.po: Fixed translation of search dialogs "Wrap around". - Closes #321874 reported by John Spray. - -2005-11-14 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2005-10-25 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-10-21 Inaki Larranaga - - * eu.po: Updated Basque translation. - -2005-10-14 Vincent van Adrighem - - * nl.po: Translation updated. - -2005-10-10 Marcel Telka - - * sk.po: Updated Slovak translation. - -==== gedit 2.12.1 ==== - -2005-10-02 Kjartan Maraas - - * nb.po: Updated Norwegian bokmål translation. - * no.po: Same - -2005-09-29 Christian Rose - - * sv.po: Reverted unauthorized changes made by - user 'kloczek'. - -2005-09-18 Christian Rose - - * sv.po: Updated Swedish translation. - -2005-09-16 Clytie Siddall - - * vi.po: Updated Vietnamese translation. - -2005-09-10 Erdal Ronahi - - * ku.po: Added Kurdish Translation - -2005-09-09 Ignacio Casal Quinteiro - - * gl.po: Updated Galician Translation. - -2005-09-09 Maxim Dziumanenko - - * uk.po: Updated Ukrainian translation. - -2005-09-07 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-09-06 Inaki Larranaga - - * eu.po: Updated Basque translation. - -2005-09-05 Rhys Jones - - * cy.po: Updated Welsh translation. - -==== gedit 2.12.0 ==== - -2005-09-05 Runa Bhattacharjee - * bn.po: Updated Bengali (bn) Translation - -2005-09-04 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2005-09-04 Frank Arnold - - * de.po: Updated German translation. - -2005-09-04 Josep Puigdemont i Casamajó - - * ca.po: Updated Catalan translation. - -2005-09-04 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-09-03 Mohammad DAMT - - * id.po: Updated Indonesian translation. - -2005-09-03 Danilo Šegan - - * sr.po, sr@Latn.po: Updated. - -2005-09-03 Christophe Merlet - - * fr.po: Updated French translation. - -2005-09-03 Gabor Kelemen - - * hu.po: Hungarian translation updated. - -2005-09-03 Christophe Merlet - - * fr.po: Updated French translation. - -2005-09-03 Mugurel Tudor - - * ro.po: Updated Romanian translation - by Dan Damian - -2005-09-03 Chao-Hsiung Liao - - * zh_TW.po: Updated Traditional Chinese translation. - -2005-09-03 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2005-09-02 Christophe Merlet - - * fr.po: Updated French translation from - Stéphane Raimbault . - -2005-09-02 Kostas Papadimas - - *el.po Updated Greek Translation - -2005-09-02 Clytie Siddall - - * vi.po: Updated Vietnamese translation. - -2005-09-02 Leonid Kanter - - * ru.po: Updated Russian translation - -2005-09-02 Rhys Jones - - * cy.po: Updated Welsh translation. - -2005-09-02 Choe Hwanjin - - * ko.po: Updated Korean translation by Young-Ho Cha. - -2005-09-02 Kostas Papadimas - - *el.po Updated Greek Translation - -2005-09-01 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-09-01 Baris Cicek - - * tr.po: Updated Turkish Translation - -2005-09-01 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2005-09-01 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2005-01-09 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-08-31 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation by Justina Klingaitė. - -2005-08-30 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2005-08-30 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Vladimir Petkov - -2005-08-30 Leonid Kanter - - * ru.po: Updated Russian translation - -2005-08-29 Miloslav Trmac - - * cs.po: Updated Czech translation. - -==== gedit 2.11.93 ==== - -2005-08-29 Telsa Gwynne - - * cy.po: Updated Welsh translation from Chris Jackson. - -2005-08-27 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2005-08-27 Clytie Siddall - - * vi.po: Updated Vietnamese translation. - -2005-08-25 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2005-08-23 Gabor Kelemen - - * hu.po: Hungarian translation updated. - -==== gedit 2.11.92 ==== - -2005-23-08 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-08-23 Ilkka Tuohela - - * fi.po: Updated Finnish translation. - -2005-08-23 Maxim Dziumanenko - - * uk.po: Updated Ukrainian translation. - -2005-08-21 Evandro Fernandes Giovanini - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2005-08-21 Kostas Papadimas - - *el.po Updated Greek Translation - -2005-08-21 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-08-20 Duarte Loreto - - * pt.po: Updated Portuguese translation and fix a typo. - -2005-08-19 Dan Damian - - * ro.po: Updated Romanian translation. - -2005-08-19 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-08-18 Chao-Hsiung Liao - - * zh_TW.po: Updated Traditional Chinese translation. - -2005-08-16 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2005-08-16 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2005-08-16 Marcel Telka - - * sk.po: Fixed invalid message translation (thanks to Sergej Chodarev). - -2005-08-14 Gabor Kelemen - - * hu.po: Hungarian translation updated. - -2005-08-13 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-08-13 Kostas Papadimas - - *el.po Updated Greek Translation - -2005-08-13 Ilkka Tuohela - - * fi.po: Updated Finnish translation. - -2005-08-11 Frank Arnold - - * de.po: Updated German translation. - -2005-08-11 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2005-08-10 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Rostislav Raykov - -2005-08-09 Marcel Telka - - * sk.po: Updated Slovak translation. - -2005-08-09 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2005-08-09 Kjartan Maraas - - * nb.po: Updated Norwegian bokmål translation. - * no.po: Same - -2005-08-09 Clytie Siddall - - * vi.po: Updated Vietnamese translation. - -2005-08-08 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -==== gedit 2.11.91 ==== - -2005-08-08 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-08-07 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2005-08-07 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2005-08-06 Josep Puigdemont - - * ca.po: Updated Catalan translation. - -2005-08-06 Clytie Siddall - - * vi.po: Updated Vietnamese translation. - -2005-08-06 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-08-06 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2005-08-05 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-08-05 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-08-05 Clytie Siddall - - * vi.po: Updated Vietnamese translation. - -2005-08-05 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2005-08-05 Kjartan Maraas - - * nb.po: Updated Norwegian bokmål translation. - * no.po: Same - -2005-08-05 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2005-08-05 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-08-04 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -==== gedit 2.10.4 ==== - -2005-08-04 Kjartan Maraas - - * nb.po: Updated Norwegian bokmål translation. - * no.po: Same - -2005-08-04 Sunil Mohan Adapa - - * te.po: Added Telugu translation done by - Prajasakti Localisation Team - - -2005-08-01 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Rostislav Raykov - -2005-08-01 Vincent van Adrighem - - * nl.po: Translation updated. - -2005-07-31 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2005-07-31 Pawan Chitrakar - - * ne.po: Updated Nepali Translation - -2005-07-31 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2005-07-28 Josep Puigdemont i Casamajó - - * ca.po: Updated translation. - -2005-07-27 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-07-27 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation by Igor - Nestorović. - -2005-07-25 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2005-07-21 Gabor Kelemen - - * hu.po: Hungarian translation updated. - -2005-07-15 Ignacio Casal Quinteiro - - * gl.po: Updated Galician Translation. - -2005-07-14 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-07-13 Yair Hershkovitz - - * he.po: Translation updated by Yair Hershkovitz - -2005-07-06 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-07-05 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-07-04 Hendrik Richter - - * de.po: Fixed German translation by - Jens Seidel . - -2005-07-03 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2005-06-27 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-06-25 Sigurd Gartmann - - * nb.po: Updated Norwegian translation. - * no.po: Updated Norwegian translation. - -2005-06-22 Abel Cheung - - * zh_TW.po: Fix language team reference. - -2005-06-21 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-06-15 Marcel Telka - - * sk.po: Updated Slovak translation. - -2005-06-15 Gabor Kelemen - - * hu.po: Hungarian translation updated. - -2005-06-14 Terance Sola - - * nb.po: Updated Norwegian Bokmal translation. - * no.po: Same. - -2005-06-12 Christophe Merlet - - * fr.po: Updated French translation from - Baptiste Mille-Mathias . - -2005-06-10 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -==== gedit 2.10.3 ==== - -2005-06-06 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Vladimir Petkov - -2005-06-01 Pauli Virtanen - - * fi.po: Improvements to the Finnish translation by Lauri Nurmi. - -2005-05-29 Pauli Virtanen - - * fi.po: Improved Finnish translation by Lauri Nurmi. - -2005-05-26 Rhys Jones - - * cy.po: Updated Welsh translation. - -2005-05-26 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2005-05-26 Kjartan Maraas - - * nb.po: Update - * no.po: Update - -2005-05-20 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2005-05-16 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-05-14 Pawan Chitrakar - - * ne.po: Updated Nepali translation - -2005-05-13 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-05-12 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Vladimir Petkov - -2005-05-11 Kostas Papadimas - - *el.po Updated Greek Translation - -2005-05-10 Rajesh Ranjan - - * hi.po: Updated Hindi translation. - -2005-05-10 Adi Attar - - * xh.po: Updated Xhosa translation. - -2005-05-10 Rajesh Ranjan - - *hi.po: Updated Hindi translation. - -2005-05-07 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2005-04-24 Clytie Siddall - - * vi.po: Updated Vietnamese translation. - -2005-04-22 Abel Cheung - - * ro.po: Mark wrong entry as fuzzy (msgfmt check failed). - -2005-04-21 Roozbeh Pournader - - * fa.po: Updated Persian translation by - Meelad Zakaria . - -2005-04-20 Pablo Saratxaga - - * wa.po: Updated Walloon file - -2005-04-15 Gabor Kelemen - - * hu.po: Hungarian translation updated. - -==== gedit 2.10.2 ==== - -2005-03-31 Steve Murphy - - * rw.po: Added Kinyarwanda translation. - -2005-03-30 Adi Attar - - * xh.po: Updated Xhosa translation. - -2005-03-28 Gabor Kelemen - - * hu.po: Hungarian translation updated. - -==== gedit 2.10.1 ==== - -2005-03-25 Ahmad Riza H Nst - - * id.po: Updated Indonesian Translation. - -2005-03-22 Adi Attar - - * xh.po: Added Xhosa translation. - -2005-03-20 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2005-03-19 Leonid Kanter - - * ru.po: Fixed Russian translation - -2005-03-19 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-03-17 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-03-13 David Lodge - - * en_GB.po: Updated British translation. - -2005-03-09 Ilkka Tuohela - - * fi.po: Updated Finnish translation. - -2005-03-08 Baris Cicek - - * tr.po: Updated Turkish Translation by Ercin Eker - -==== gedit 2.10.0 ==== - -2005-03-07 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-03-06 Vincent van Adrighem - - * nl.po: Translation updated by Tino Meinen. - -2005-03-06 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2005-03-06 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2005-03-05 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2005-03-03 Alessio Frusciante - - * it.po: Updated Italian translation by - Roberto Rosselli Del Turco . - -2005-03-03 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation from GNOME HK Team - -2005-03-03 Dan Damian - - * ro.po: Updated Romanian translation. - -2005-03-03 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2005-03-02 Dan Damian - - * ro.po: Updated Romanian translation. - -2005-03-02 Roozbeh Pournader - - * fa.po: Updated Persian translation by - Meelad Zakaria . - -2005-03-02 Danilo Šegan - - * sr.po, sr@Latn.po: Partial update of Serbian translation. - -2005-03-02 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2005-03-01 Josep Puigdemont - - * ca.po: Updated Catalan translation. - -2005-03-01 Ilkka Tuohela - - * fi.po: Updated Finnish translation. - -==== gedit 2.9.7 ==== - -2005-02-28 Alessio Frusciante - - * it.po: Updated Italian translation by - Roberto Rosselli Del Turco . - -2005-02-28 Kostas Papadimas - - * el.po: Updated Greek translation. - -2005-02-28 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Vladimir Petkov - -2005-02-27 Sami Pesonen - - * fi.po: Updated Finnish translation #2. - -2005-02-26 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2005-02-26 Sami Pesonen - - * fi.po: Updated Finnish translation #1. - -2005-02-25 Ole Laursen - - * da.po: Fixed some issues in the Danish translation based on - comments from Martin Willemoes Hansen. - -2005-02-25 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2005-02-24 Jordi Mallach - - * ca.po: Updated Catalan translation by - Josep Puigdemont . - -2005-02-23 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2005-02-21 Leonid Kanter - - * ru.po: Updated Russian translation - -2005-02-21 Priit Laes - - * et.po: Translation updated. - -2005-02-21 Ankit Patel - - * gu.po: Updated Gujarati Translation. - -2005-02-20 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2005-02-20 Ole Laursen - - * da.po: Updated Danish translation. - -2005-02-20 Kostas Papadimas - - * el.po: Updated Greek translation. - -2005-02-19 Francisco Javier F. Serrador - - * es.po: Updated Spanih translation. - -2005-02-19 Christian Rose - - * sv.po: Updated Swedish translation. - -2005-02-19 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2005-02-18 Maxim Dziumanenko - - * uk.po: Updated Ukrainian translation. - -2005-02-18 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2005-02-17 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-02-17 Frank Arnold - - * de.po: Updated German translation. - -2005-02-17 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Rostislav Raykov - -2005-02-15 Jordi Mallach - - * ca.po: Updated Catalan translation by - Josep Puigdemont . - -2005-02-14 Changwoo Ryu - - * ko.po: Updated Korean translation by Young-Ho Cha. - -2005-02-14 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2005-02-14 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2005-02-13 David Lodge - - * en_GB.po: Updated British translation. - -2005-02-13 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2005-02-13 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2005-02-12 Paolo Maggi - - * POTFILES.in: removed unused file close_all_dialog.glade2 - -2005-02-12 Priit Laes - - * et.po: Translation updated. - -2005-02-12 Marcel Telka - - * sk.po: Updated Slovak translation. - -2005-02-12 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-02-12 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-02-11 Frank Arnold - - * de.po: Updated German translation. - -2005-02-11 Christian Rose - - * sv.po: Updated Swedish translation. - -2005-02-10 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2005-02-10 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-02-10 Kjartan Maraas - - * nb.po: Update - * no.po: Update - -2005-02-09 Kostas Papadimas - - * el.po: Updated Greek translation. - -2005-02-09 Jordi Mallach - - * ca.po: Updated Catalan translation by - Josep Puigdemont . - -2005-02-08 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-02-08 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-02-08 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2005-02-08 Frank Arnold - - * de.po: Updated German translation. - -==== gedit 2.9.6 ==== - -2005-02-07 Leonid Kanter - - * ru.po: Updated Russian translation - -2005-02-07 David Lodge - - * en_GB.po: Updated British translation. - -2005-02-07 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2005-02-06 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2005-02-06 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-02-06 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-02-06 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2005-02-07 Rhys Jones - - * cy.po: Updated Welsh translation. - -2005-02-06 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2005-02-05 Frank Arnold - - * de.po: Updated German translation. - -2005-02-02 Marcel Telka - - * sk.po: Updated Slovak translation. - -2005-02-01 Kostas Papadimas - - * el.po: Updated Greek translation - -2005-01-30 David Lodge - - * en_GB.po: Updated British translation. - -2005-01-29 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2005-01-29 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2005-01-29 Marcel Telka - - * sk.po: Updated Slovak translation. - -2005-01-28 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Rostislav Raykov - -2005-01-28 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2005-01-27 Theppitak Karoonboonyanan - - * th.po: More updates on Thai translation. - -2005-01-27 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2005-01-26 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2005-01-26 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2005-01-26 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-01-26 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2005-01-25 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Rostislav Raykov - -2005-01-24 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2005-01-23 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-01-21 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-01-19 Frank Arnold - - * de.po: Updated German translation. - -2005-01-19 Marcel Telka - - * sk.po: Updated Slovak translation. - -2005-01-19 Leonid Kanter - - * ru.po: Updated Russian translation - -2005-01-18 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-01-18 Frank Arnold - - * de.po: Updated German translation. - -2005-01-17 Priit Laes - - * et.po: Translation updated by Ivar Smolin. - -2005-01-17 Rhys Jones - - * cy.po: Corrected a few new/pre-existing typos and grammar errors. - -2005-01-17 Rhys Jones - - * cy.po: Updated Welsh translation. - -2005-01-17 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2005-01-16 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-01-15 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-01-15 Kjartan Maraas - - * nb.po: Update - * no.po: Update - -2005-01-15 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-01-15 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2005-01-15 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2005-01-14 Alexander Winston - - * en_CA.po: Updated Canadian English translation. - -2005-01-13 Rhys Jones - - * cy.po: Partially updated Welsh translation. - -2005-01-13 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2005-01-12 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2005-01-11 Tomasz Kłoczko - - * kn.po: fixed format string bugs (neccessary for latest gettext). - * ms.po: added missing Plural-Forms field in header (neccessary - for latest gettext). - -==== gedit 2.9.4 ==== - -2005-01-10 Paolo Maggi - - * POTFILES.in: updated - - * POTFILES.skip: ditto - -2005-01-04 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-12-28 Kostas Papadimas - - * el.po: Updated Greek translation - -2004-12-28 Kjartan Maraas - - * nb.pok: Update - -2004-12-25 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-12-24 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2004-12-22 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2004-12-22 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2004-12-22 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-12-22 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2004-12-17 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-12-07 Tommi Vainikainen - - * fi.po: Minor consistency fixes to Finnish translation. - -2004-12-05 Paolo Borelli - - * POTFILES.in: add gedit-io-error-dialogs. - -2004-12-05 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2004-12-03 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2004-12-01 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-11-29 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-11-29 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2004-11-25 Kjartan Maraas - - * nb.po: Updated Norwegian bokmål translation. - -2004-11-23 Martin Willemoes Hansen - - * da.po: Updated Danish translation. - -2004-11-22 Martin Willemoes Hansen - - * da.po: Updated Danish translation. - -2004-11-21 David Lodge - - * en_GB.po: Updated British translation. - -2004-11-15 Meelad Zakaria - - * fa.po: Updated Persian translation. - -2004-11-14 Paolo Borelli - - * POTFILES.in: re-add the changecase plugin files, they were - added on 2004-04-05, but got lost at some point. - -2004-11-14 Paolo Maggi - - * POTFILES.*: updated - -2004-11-08 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Vladimir Petkov - -2004-11-05 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-11-04 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2004-11-01 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-11-01 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-10-31 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-10-30 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-10-29 Jordi Mallach - - * POTFILES.in: Removed nonexisting files. - * ca.po: Updated Catalan translation. - -2004-10-25 Mohammad DAMT - - * id.po: Updated Indonesian translation - -2004-10-10 Christophe Merlet - - * fr.po: Updated French translation. - -2004-10-06 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004-09-26 Roozbeh Pournader - - * fa.po: Updated Persian translation. - -2004-09-24 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-09-21 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2004-09-15 Roozbeh Pournader - - * fa.po: Updated Persian translation by Meelad Zakaria - . - -2004-09-15 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2004-09-14 Gora Mohanty - - * or.po: Updated Oriya translation. - -2004-09-12 Hasbullah Bin Pit - - * ms.po: Updated Malay translation. - -2004-09-11 Dafydd Harries - - * cy.po: Updated Welsh translation. - -2004-09-11 Christophe Merlet - - * fr.po: Updated French translation. - -2004-09-09 Baris Cicek - - * tr.po: Updated Turkish Translation by Ridvan Can - -2004-09-07 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Vladimir Petkov - -2004-09-07 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2004-09-07 David Lodge - - * en_GB.po: Fixed British translation. - -2004-09-06 David Lodge - - * en_GB.po: Updated British translation. - -2004-09-06 Mugurel Tudor - - * ro.po: Updated Romanian translation - by Misu Moldovan - -2004-09-06 Theppitak Karoonboonyanan - - * th.po: Updated Thai translation. - -2004-09-06 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2004-09-05 Kjartan Maraas - - * nb.po: Updated - * no.po: Updated - -2004-09-05 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2004-09-04 Mətin Əmirov - - * az.po: Translation updated. - -2004-09-04 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-09-03 Raphael Higino - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2004-09-02 Hendrik Richter - - * de.po: Updatet German translation - -2004-08-31 Arafat Medini - - * ar.po: Updated Arabic translation - -2004-08-31 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2004-08-30 Kostas Papadimas - - * el.po: Updated Greek translation. - -2004-08-29 Akagic Amila - - * bs.po: Added Bosnian translation. - -2004-08-25 Iñaki Larrañaga - - * eu.po: Updated Basque translation. - -2004-08-24 Francisco Javier F. Serrador - - * es.po: Updated Spanih translation. - -2004-08-24 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2004-08-23 Christian Rose - - * sv.po: Updated Swedish translation. - -2004-08-23 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2004-08-22 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004-08-21 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2004-08-21 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2004-08-21 Leonid Kanter - - * ru.po: Updated Russian translation - -2004-08-20 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-08-20 Maxim Dziumanenko - - * uk.po: Updated Ukrainian translation. - -2004-08-19 Francisco Javier F. Serrador - - * es.po: Updated Spanih translation. - -2004-08-19 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-08-19 Christian Rose - - * POTFILES.skip: Removed nonexisting entry. - * sv.po: Updated Swedish translation. - -2004-08-19 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2004-08-18 Laszlo Dvornik - - * hu.po: Updated Hungarian translation. - -2004-08-18 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2004-08-18 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-08-18 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-08-18 Martin Willemoes Hansen - - * da.po: Updated Danish translation. - -2004-08-18 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-08-17 Ankit Patel - - * gu.po: Updated Final Gujarati Translation. - -2004-08-17 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2004-08-17 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2004-08-17 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2004-08-17 Metin Amiroff - - * az.po: Translation updated. - -2004-08-16 Kjartan Maraas - - * nb.po: Added this. - -2004-08-15 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2004-08-14 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2004-08-13 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004-08-13 Gurban Tewekgeli - - * tk.po: Updated Turkmen translation. - -2004-08-12 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-08-10 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2004-08-10 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2004-08-08 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-08-08 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-08-06 Christian Neumair - - * de.po: Updated German translation. - -2004-08-06 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2004-08-06 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-08-05 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-08-05 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2004-08-05 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-08-04 Maxim Dziumanenko - - * uk.po: Updated Ukrainian translation. - -2004-08-03 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004-08-02 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-08-02 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2004-08-02 Roozbeh Pournader - - * fa.po: Updated Persian translation by Meelad Zakaria - . - -2004-08-01 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2004-07-30 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2004-07-29 Christophe Merlet - - * fr.po: Updated French translation. Close bug #148576. - -2004-07-28 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-07-28 Laszlo Dvornik - - * hu.po: Updated Hungarian translation. - -2004-07-26 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2004-07-21 Guntupalli Karunakar - - * hi.po: Updated Hindi translation. - -2004-07-19 Gareth Owen - - * en_GB.po: Updated British English translation - -2004-07-19 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-07-18 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-07-18 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2004-07-15 Christian Rose - - * sv.po: Updated Swedish translation. - -2004-07-12 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2004-07-12 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2004-07-11 Gil Osher - - * he.po: Updated Hebrew translation. - Thanks to Shoshannah Forbes. - -2004-07-10 Takeshi AIHANA - - * ja.po: Updated Japanese translation and - Fixed wrong translation reviewed by - MATSUURA Takanori . - -2004-07-08 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Rostislav Raykov - -2003-07-03 Christian Neumair - - * POTFILES.skip: Removed obsolete file. - * de.po: Updated German translation. - -2004-06-29 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2004-06-28 Laurent Dhima - - * sq.po: Translation updated. - -2004-06-22 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-06-18 Gustavo Maciel Dias Vieira - - * pt_BR.po: Updated Brazilian Portuguese translation done by João - Paulo Gomes Vanzuita . - -2004-06-17 Alexander Winston - - * en_CA.po: Updated Canadian English translation. - -2004-06-17 Alexander Shopov - - * bg.po: Updated Bulgarian translation by - Evgeni Boevski - -2004-06-16 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2004-06-14 Gareth Owen - - * en_GB.po: Updated British English translation - -2004-06-14 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-06-09 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2004-06-06 Pawan Chitrakar - - * ne.po: Upadted Nepali translation. - -2004-06-05 Dinesh Nadarajah - - * ta.po: Updated Tamil Translation - -2004-06-01 Ole Laursen - - * da.po: Updated Danish translation. - -2004-05-29 Christian Rose - - * tk.po: Added Turkmen translation by - Gurban Mühemmet Tewekgeli . - -2004-05-26 Mohammad DAMT - - * id.po: Added Indonesian translation done by Ahmad Riza H Nst - -2004-05-23 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2004-05-23 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2004-05-16 Francisco Javier F. Serrador - - * es.po: Updated Spansih translation. - -2004-05-11 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-05-04 Gustavo Maciel Dias Vieira - - * pt_BR.po: Updated Brazilian Portuguese translation done by - Raphael Higino . - -2004-05-03 Tomasz Kłoczko - - * ja.po: added missing Plural-Forms field. - -2004-04-24 Christophe Merlet - - * fr.po: Updated French translation. - -2004-04-19 Gareth Owen - - * en_GB.po: Updated British English translation - -2004-04-19 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2004-04-16 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-04-16 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-04-15 Andras Timar - - * hu.po: Updated Hungarian translation. - -2004-04-09 Guntupalli Karunakar - - * gu.po: Added Gujurati translation by - Gujarati Team . - -2004-04-08 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-04-05 Iñaki Larrañaga - - * eu.po: Updated Basque translation. - -2004-04-05 Paolo Borelli - - * POTFILES.in: add changecase plugin files. - -2004-04-05 Bastien Nocera - - * en_GB.po: fix some typos (Closes: #138999) - -2004-04-03 Samúel Jón Gunnarsson - - * is.po: Added Icelandic translation by - Helgi Þormar Þorbjörnsson - -2004-03-31 Christian Rose - - * af.po: Added Afrikaans translation by - Zuza Software Foundation . - -2004-03-30 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-03-28 Robert Sedak - - * hr.po: Updated Croatian translation. - -2004-03-24 Adam Weinberger - - * en_CA.po: Updated Canadian English translation. - -2004-03-23 Pablo Saratxaga - - * wa.po: Updated Walloon file - -2004-03-22 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2004-03-22 Baris Cicek - - * tr.po: Updated Turkish Translation. - -2004-03-21 Alastair McKinstry - - * ga.po: Updated Irish translation. - -2004-03-21 Andras Timar - - * hu.po: Added Hungarian translation. - -2004-03-20 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation from - Anthony Tang . - -2004-03-20 Abel Cheung - - * POTFILES.skip: Add gedit/recent-files/egg-recent-vfs-utils.c, - remove non-existant file. - -2004-03-19 Gareth Owen - - * en_GB.po: Added British translation - -2004-03-19 Dmitry G. Mastrukov - - * ru.po: Updated Russian translation - from Russian team . - -2004-03-18 Arafat Medini - - * ar.po: Updated Arabic translation. - -2004-03-18 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2004-03-18 Guntupalli Karunakar - - * mr.po: Added Marathi translation by - Swapnil Hajare . - -2004-03-18 Funda Wang - - * zh_CN.po: Updated Simplified Chinese to avoid bug#137329. - -2004-03-15 Dinesh Nadarajah - - * ta.po: Updated Tamil translation. - -2004-03-14 Theppitak Karoonboonyanan - - * th.po: Fixed accelerators in Thai translation. - -2004-03-13 Ales Nyakhaychyk - - * be.po: Updated Belarusian translation. - -2004-03-13 Maxim Dziumanenko - - * uk.po: some fixes to Ukrainian translation. - -2004-03-12 Arafat Medini - - * ar.po: Updated faulty Arabic translation. - -2004-03-12 Maxim Dziumanenko - - * uk.po: Updated Ukrainian translation. - -2004-03-12 Arafat Medini - - * ar.po: Updated Arabic translation. - -2004-03-11 Alessio Frusciante - - * it.po: Updated Italian translation by - Roberto Rosselli Del Turco . - -2004-03-11 Dafydd Harries - - * cy.po: Updated Welsh translation from Rhys Jones. - -2004-03-11 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-03-10 Gustavo Maciel Dias Vieira - - * pt_BR.po: Some errors fixed. - -2004-03-09 Gustavo Noronha Silva - - * pt_BR.po: translation updated by - Raphael Higino - -2004-03-10 Vincent van Adrighem - - * nl.po: Translation updated. - -2004-03-09 Duarte Loreto - - * pt.po: Fixed a bad translation (thanks to Duarte Henriques). - -2004-03-09 Sanlig Badral - - * mn.po: Updated Mongolian translation. - -2004-03-08 Francisco Javier F. Serrador - - * es.po: Updated Spansih translation. - -2004-03-08 Alastair McKinstry - - * ga.po: Updated Irish translation. - -2004-03-07 Christophe Merlet - - * fr.po: Updated French translation. - -2004-03-07 Mugurel Tudor - - * ro.po: Updated Romanian translation - -2004-03-06 Mətin Əmirov - - * az.po: Translation updated. - -2004-03-05 Albert Chin-A-Young - - * POTFILES.in: gedit/recent-files/egg-recent-vfs-utils.c - doesn't exist in the distribution - -2004-03-04 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2004-03-04 Guntupalli Karunakar - - * pa.po: Added Punjabi translation by - Amanpreet Singh Alam . - -2004-03-3 Arafat Medini - - * ar.po: Updated Arabic translation. - -2004-03-01 Funda Wang - - * zh_CN.po: Updated Simplified Chinese translation. - -2004-03-01 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation. - -2004-03-01 Alessio Frusciante - - * it.po: Updated Italian translation by - Roberto Rosselli Del Turco . - -2004-03-01 Vincent van Adrighem - - * nl.po: Translation updated by Daniel van Eeden. - -2004-02-28 Christophe Merlet - - * fr.po: Updated French translation. - -2004-02-28 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2004-02-27 Priit Laes - - * et.po: Translation updated. - -2004-02-26 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2004-02-26 Vincent van Adrighem - - * nl.po: Translation updated by Kees van den Broek. - -2004-02-25 Christophe Merlet - - * fr.po: Updated French translation. - -2004-02-24 Alastair McKinstry - - * ga.po: Updated Irish translation. - -2004-02-24 Ole Laursen - - * da.po: Updated Danish translation. - -2004-02-25 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004-02-24 Guntupalli Karunakar - - * hi.po: Updated Hindi translation. - -2004-02-24 Paolo Maggi - - [ gedit 2.5.90 released ] - -2004-02-23 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2004-02-22 Vincent van Adrighem - - * nl.po: Translation updated by Reinout van Schouwen. - -2004-02-22 Mətin Əmirov - - * az.po: Updated Azerbaijani translation. - -2004-02-22 Kostas Papadimas - - * el.po: Updated Greek translation. - -2003-02-22 Christian Neumair - - * POTFILES.skip: Added missing file. - * de.po: Updated German translation. - -2004-02-21 Paisa Seeluangsawat - - * th.po: Updated Thai translation by Supakorn Siddhichai, - Supranee Thirawatthanasuk, and Chanchai Junlouchai. - -2004-02-21 Jarkko Ranta - - * fi.po: Added plural header to Finnish translation. - -2004-02-21 Christian Rose - - * en_CA.po: Added Canadian English translation by - Adam Weinberger . - -2004-02-21 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2004-02-20 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-02-20 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-02-20 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2004-02-20 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2004-02-20 Christian Rose - - * sv.po: Updated Swedish translation. - -2004-02-20 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2004-02-19 Ole Laursen - - * da.po: Updated Danish translation. - -2004-02-19 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2004-02-17 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2004-02-15 Christian Rose - - * POTFILES.skip: Removed non-existant files. - * sv.po: Updated Swedish translation. - -2004-02-15 Mətin Əmirov - - * az.po: Translation updated. - -2004-02-15 Yukihiro Nakai - - * ja.po: Fix wrong translations. - -2004-02-13 Kostas Papadimas - - * el.po: Updated Greek translation - -2004-02-13 Kostas Papadimas - - * el.po: Updated Greek translation. - -2004-02-12 Nikos Charonitakis - - * el.po: Updated Greek translation. - -2004-02-09 Christian Rose - - * mi.po: Updated Maori translation by - John C Barstow . - -2004-02-05 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004-02-04 Robert Sedak - - * hr.po: Updated Croatian translation. - -2004-02-02 Alastair McKinstry - - * ga.po: Updated Irish translation. - -2004-02-01 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-01-31 Mətin Əmirov - - * az.po: Translation updated. - -2004-01-31 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2004-01-30 Christian Rose - - * mi.po: Updated Maori translation by - John C Barstow . - -2004-01-28 Miloslav Trmac - - * cs.po: Fixed Czech translation. - -2004-01-27 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2004-01-27 Christian Rose - - * mi.po: Added Maori translation by - John C Barstow . - -2004-01-27 Hasbullah Bin Pit - - * ms.po: Updated Malay translation. - -2004-01-26 Kostas Papadimas - - * el.po: Updated Greek translation. - -2004-01-25 Sanlig Badral - - * mn.po: Updated Mongolian translation. - -2004-01-24 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2004-01-21 Vincent van Adrighem - - * nl.po: Translation updated by Kees van den Broek. - -2004-01-21 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004-01-20 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2004-01-18 Gustavo Maciel Dias Vieira - - * pt_BR.po: Updated Brazilian Portuguese translation done by Joao - Emanuel . - -2004-01-18 Christophe Merlet - - * fr.po: Updated French translation. - -2004-01-17 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2004-01-16 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2004-01-15 Paolo Maggi - - [ gedit 2.5.3 released ] - -2004-01-15 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-01-14 Alastair McKinstry - - * ga.po: Updated Irish translation. - -2004-01-14 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-01-13 Christian Neumair - - * de.po: Updated German translation. - -2004-01-13 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2004-01-13 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2004-01-13 Vincent van Adrighem - - * nl.po: Translation updated by Kees van den Broek. - -2004-01-13 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2004-01-13 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2004-01-13 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - - * POTFILES.in: Added missing files. - -2004-01-12 Sanlig Badral - - * mn.po: Updated Mongolian translation. - -2004-01-10 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2004.01.10 Arafat Medini - - * ar.po: Updated faulty Arabic translation - -2004.01.09 Arafat Medini - - * ar.po: Updated Arabic translation - -2003-01-06 Christian Neumair - - * de.po: Updated German translation. - -2004-01-06 Åsmund Skjæveland - - * nn.po: Updated Norwegian Nynorsk translation. - -2004-01-05 Jarkko Ranta - - * fi.po: Updated Finnish Translation. - -2004-01-05 Pól Ó Dubhthaigh - - * ga.po: Updated Irish Translation. - -2004-01-04 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2004-01-03 Christophe Merlet - - * fr.po: Updated French translation from - Sebastien Bacher . - -2004-01-03 Robert Sedak - - * hr.po: Updated Croatian translation. - -2004-01-02 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2004-01-01 Duarte Loreto - - * pt.po: Updated and revised Portuguese translation. - -2004-01-01 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. Plural forms added - -2004-01-01 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-12-31 Paul Duffy - - * ga.po: Updated Irish translation - -2003-12-31 Artur Flinta - - * pl.po: Updated Polish translation by GNOME PL Team. - -2003-12-30 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-12-30 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2003-12-20 Christian Neumair - - * POTFILES.skip: Added missing file. - * de.po: Updated German translation (inter alia #127055). - -2003-12-17 Žygimantas Beručka - - * lt.po: Updated Lithuanian translation by - Vaidotas Zemlys . - -2003-12-14 Francisco Javier F. Serrador - - * es.po: Updated Spanish translation. - -2003-12-03 Sanlig Badral - - * mn.po: Updated Mongolian translation. - -2003-11-29 Danilo Šegan - - * sr.po, sr@Latn.po: More bugs fixed. - -2003-11-29 Danilo Šegan - - * sr.po, sr@Latn.po: Fixed bug #16 from Prevod.org. - -2003-11-28 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-11-20 Ole Laursen - - * da.po: Updated Danish translation. - -2003-11-12 Kostas Papadimas - - * el.po: Updated Greek translation. - -2003-11-07 Christian Rose - - * ne.po: Updated Nepali translation by - Pawan Chitrakar . - -2003-11-04 Dafydd Harries - - * cy.po: Updated Welsh translation. - -2003-10-30 Kostas Papadimas - - * el.po: Updated Greek translation - -2003-10-30 KAMAGASAKO Masatoshi - - * ja.po: Updated Japanese translation. - -2003-10-28 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2003-10-28 Andras Timar - - * hu.po: Updated Hungarian translation. - -2003-10-26 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2003-10-26 Christian Rose - - * sv.po: Fix accidental mistranslation of "Tabs". - -2003-10-25 Metin Amiroff - - * az.po: Updated Azerbaijani translation. - -2003-10-10 Laurent Dhima - - * sq.po: Updated Albanian translation. - -2003-10-04 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - - * POTFILES.skip: Removed data/GNOME_Gedit.server.in. - -2003-09-29 Gustavo Maciel Dias Vieira - - * pt_BR.po: Applied revision by Augusta Marques da Silva - . - -2003-09-23 Yogeesh MB - - * kn.po: Updated Kannada translation - -2003-09-21 Metin Amiroff - - * az.po: Updated Azerbaijani file - -2003-09-13 Alessio Frusciante - - * it.po: Updated Italian translation by - Roberto Rosselli Del Turco - -2003-09-10 Pablo Saratxaga - - * wa.po: Updated Walloon file - -2003-09-09 Paolo Maggi - - [ gedit 2.4.0 released ] - -2003-09-08 Gustavo Noronha Silva - - * pt_BR.po: updated translation. - -2003-09-07 Pablo Saratxaga - - * vi.po: Updated Vietnamese file - -2003-09-06 Mugurel Tudor - - * ro.po: Updated Romanian translation - by Mişu Moldovan - -2003-09-06 Hasbullah Bin Pit - - * ms.po: Updated Malay translation. - -2003-09-06 Laurent Dhima - - * sq.po: Added Albanian translation. - -2003-09-05 Taneem Ahmed - - * bn.po: Added Bangla translation by Santanu - of Ankur group . - -2003-09-05 Takeshi AIHANA - - * ja.po: Updated Japanese translation. - -2003-09-03 Jarkko Ranta - - * fi.po: Updated Finnish translation again. - -2003-09-03 Guntupalli Karunakar - - * hi.po: Updated Hindi translation. - -2003-09-02 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2003-08-31 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-08-30 Dafydd Harries - - * cy.po: Updated Welsh translation. - -2003-08-30 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2003-08-29 Guntupalli Karunakar - - * hi.po: Updated Hindi translations. - -2003-08-29 Alessio Frusciante - - * it.po: Updated Italian translation by - Roberto Rosselli Del Turco. - -2003-08-28 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2003-08-27 Pablo Gonzalo del Campo - - * es.po: Revision of Spanish translation by - Francisco Javier F. Serrador . - -2003-08-27 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2003-08-27 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2003-08-27 Vincent van Adrighem - - * nl.po: Dutch translation updated by Kees van den Broek. - -2003-08-27 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2003-08-24 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2003-08-24 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2003-08-24 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-08-24 Artur Flinta - - * pl.po: Updated Polish translation. - -2003-08-23 Ole Laursen - - * da.po: Updated Danish translation. - -2003-08-23 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2003-08-23 Kjartan Maraas - - * no.po: Update Norwegian translation. - -2003-08-23 Metin Amiroff - - * az.po: Updated Azerbaijani translation. - -2003-08-23 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2003-08-19 Jarkko Ranta - - * fi.po: Updated Finnish translation - -2003-08-19 Danilo Šegan - - * be.po: Updated Belarusian translation by Ales Nyakhaychyk - . - -2003-08-19 Dafydd Harries - - * cy.po: Updated Welsh translation. - -2003-08-18 Metin Amiroff - - * az.po: Updated Azerbaijani translation. - -2003-08-17 Christophe Merlet - - * fr.po: Updated French translation. - -2003-08-11 Christian Rose - - * ne.po: Added Nepali translation by Pawan . - -2003-08-08 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2003-08-08 Hasbullah Bin Pit - - * ms.po: Updated Malay translation. - -2003-08-08 Danilo Šegan - - * sr.po, sr@Latn.po: Updated Serbian translation. - -2003-08-07 Yanko Kaneti - - * bg.po: Updated Bulgarian translation by Evgeni Boevski. - -2003-08-07 Andras Timar - - * hu.po: Updated Hungarian translation. - -2003-08-06 Metin Amiroff - - * az.po: Updated Azerbaijani translation. - -2003-08-04 Andras Timar - - * hu.po: Updated Hungarian translation. - -2003-07-28 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2003-07-25 Pablo Saratxaga - - * vi.po: Updated Vietnamese file - -2003-07-24 Dafydd Harries - - * cy.po: Updated Welsh translation. - -2003-07-22 Wang Jian - - * zh_CN.po: Updated Simplified Chinese translation by - Funda Wang . - -2003-07-19 Dafydd Harries - - * cy.po: Updated Welsh translation. - -2003-07-18 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2003-07-17 Vincent van Adrighem - - * nl.po: Dutch translation updated by Kees van den Broek. - -2003-07-15 Gil "Dolfin" Osher - - * he.po: Updated Hebrew translation. - -2003-07-12 Hasbullah Bin Pit - - * ms.po: Updated Malay translation. - -2003-07-12 Artur Flinta - - * pl.po: Updated Polish translation. - -2003-07-09 Artur Flinta - - * pl.po: Updated Polish translation. - -2003-07-09 Paul Duffy - - * ga.po: Updated Irish translation. - -2003-07-08 Nikos Charonitakis - - * el.po: Updated Greek translation - -2003-07-08 Andras Timar - - * hu.po: Updated Hungarian translation. - -2003-07-07 Vincent van Adrighem - - * nl.po: Dutch translation updated by Kees van den Broek. - -2003-07-06 Kostas Papadimas - - * el.po: Updated Greek translation - -2003-07-04 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2003-07-03 Valek Filippov - - * ru.po: Updated russian translation. - -2003-07-03 Yanko Kaneti - - * bg.po: Updated Bulgarian translation by Evgeni Boevski. - -2003-06-30 Pauli Virtanen - - * fi.po: Set translator_credits. - -2003-06-28 Christian Neumair - - * POTFILES.skip: Added missing file. - * de.po: Updated German translation. - -2003-06-23 Vincent van Adrighem - - * nl.po: Dutch translation updated by Kees van den Broek. - -2003-06-20 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-06-19 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2003-06-16 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-06-16 Dmitry G. Mastrukov - - * ru.po: Updated Russian translation - from Russian team . - -2003-06-14 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-06-14 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2003-06-13 Abel Cheung - - * POTFILES.in: Added gedit/dialogs/gedit-page-setup-dialog.c, - gedit/dialogs/page-setup-dialog.glade2. - -2003-06-12 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2003-06-12 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2003-06-12 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2003-06-11 Abel Cheung - - * POTFILES.in: data/GNOME_Gedit.server.in -> .in.in - -2003-06-04 Abel Cheung - - * ta.po: Fix broken encoding. - -2003-06-04 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2003-06-04 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-06-04 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-06-04 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2003-06-03 Paolo Maggi - - * POTFILE.in: re-added indent, sort, shell_output and taglist - plugins - -2003-05-31 Dafydd Harries - - * cy.po: New translations, corrections. - -2003-05-30 Telsa Gwynne - - * cy.po: updated Welsh translations from - Dafydd Harries - -2003-05-29 Evandro Fernandes Giovanini - - * pt_BR.po: Updated Brazilian Portuguese translation - from David Barzilay . - -2003-05-29 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-05-28 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2003-05-28 Telsa Gwynne - - * cy.po: Missing accents restored ('copio' to 'cop?¯o) - -2003-05-27 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-05-27 Abel Cheung - - * POTFILES.in: Added gedit/gedit-encodings-option-menu.c - -2003-05-26 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation by - Francisco Javier F. Serrador - -2003-05-26 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2003-05-26 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2003-05-25 Kostas Papadimas - - * el.po: Updated Greek translation - -2003-05-23 Paul Duffy - - * ga.po: Updated Irish translation. - -2003-05-23 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-05-23 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-05-21 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2003-05-21 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-05-21 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-05-19 Ole Laursen - - * da.po: Updated Danish translation. - -2003-05-19 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2003-05-16 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2003-05-14 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-05-14 KAMAGASAKO Masatoshi - - * ja.po: Updated Japanese translation. - -2003-05-14 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-05-13 KAMAGASAKO Masatoshi - - * ja.po: Updated Japanese translation. - -2003-05-13 Paul Duffy - - * ga.po: Updated Irish Translation - -2003-05-13 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-05-13 Abel Cheung - - * POTFILES.skip: Remove non-existant file(s). - -2003-05-13 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - * cy.po: Fix header (msgfmt check failed). - -2003-05-12 Paolo Maggi - - * POTFILES.in: added missing files - -2003-05-11 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2003-05-11 Christophe Merlet - - * fr.po: Updated French translation. - -2003-05-09 Jordi Mallach - - * ca.po: Fixed Catalan translation by Jordi Mas. - -2003-05-08 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2003-05-07 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-05-06 Danilo ? egan - - * sr.po, sr@Latn.po: Added Serbian translation by - http://Prevod.org/. - -2003-04-29 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2003-04-16 Jordi Mallach - - * POTFILES.in: remove gedit/gedit-undo-manager.c. - -2003-04-11 Paul Duffy - - * ga.po: Updated Irish translation. - -2003-03-25 Metin Amiroff - - * az.po: Updated Azerbaijani translaion. - -2003-03-13 Christian Rose - - * ml.po: Added Malayalam translation by - FSF-India . - -2003-03-08 Dmitry G. Mastrukov - - * ru.po: updated Russian translation - from Russian team . - -2003-03-05 Dmitry G. Mastrukov - - * be.po: Updated Belarusian translation - from Belarusian team . - -2003-03-04 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2003-02-22 Roozbeh Pournader - - * fa.po: Added Persian translation. - -2003-02-21 Dmitry G. Mastrukov - - * be.po: Updated Belarusian translation - from Belarusian team . - -2003-02-09 Christian Rose - - * kn.po: Added Kannada translation by - Pramod . - -2003-02-07 Fatih Demir - - * tr.po: Committed updated Turkish translation by Erkan. - -2003-02-05 Gediminas Paulauskas - - * lt.po: Updated Lithuanian translation from Vaidotas Zemlys. - -2003-02-04 Fatih Demir - - * tr.po: Committed updated Turkish translation by Erkan. - -2003-02-03 Daniel Yacob - - * am.po: Updated Amharic translation. - -2003-01-30 Marius Andreiana - - * ro.po: updated ( thanks to Mugurel Tudor ) - -2003-01-30 Dmitry G. Mastrukov - - * ru.po: updated Russian translation - from Russian team . - -2003-01-28 Daniel Yacob - - * am.po: Updated Amharic translation. - -2003-01-28 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2003-01-27 Gil "Dolfin" Osher - - * he.po: Updated Hebrew translation. - -2003-01-26 T??µivo Leedj?€rv - - * et.po: Updated Estonian translation. - -2003-01-26 Christophe Merlet - - * fr.po: Updated French translation from - Yann Laviolette . - -2003-01-26 Kang Jeong-Hee - - * ko.po: Updated Korean translation. - -2003-01-26 Alessio Frusciante - - * it.po: Updated Italian translation by - Roberto Rosselli Del Turco. - -2003-01-26 Christian Rose - - * sv.po: Some fixes for problems catched in translation review. - -2003-01-24 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2003-01-23 He Qiangqiang - - * zh_CN.po: Fixed some translation. - -2003-01-23 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2003-01-22 Fatih Demir - - * tr.po: Committed updated Turkish translation by Barbaros. - -2003-01-22 Dmitry G. Mastrukov - - * ru.po: updated Russian translation - from Russian team . - -2003-01-22 Evandro Fernandes Giovanini - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2003-01-21 Christian Rose - - * mn.po: Added Mongolian translation by - Sanlig Badral . - -2003-01-21 Christian Neumair - - * de.po: Updated German translation. - -2003-01-21 Evandro Fernandes Giovanini - - * pt_BR.po: Updated Brazilian Portuguese translation. - -2003-01-20 Marius Andreiana - - * ro.po: updated ( thanks to Mugurel Tudor ) - -2003-01-20 Pablo Saratxaga - - * vi.po: Updated Vietnamese file - -2003-01-20 Christian Neumair - - * de.po: Updated German translation. - -2003-01-19 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2003-01-19 Fatih Demir - - * tr.po: Committed "updated" Turkish translation. - -2003-01-18 He Qiangqiang - - * zh_CN.po: Updated Simplified Chinese translation by - Funda Wang . - -2003-01-14 Daniel Yacob - - * am.po: Updated Amharic translation. - -2003-01-12 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2003-01-11 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2003-01-09 Daniel Yacob - - * am.po: Updated Amharic translation. - -2003-01-08 Kang Jeong-Hee - - * ko.po: Updated Korean translation by Young-Ho, Cha. - -2003-01-07 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2003-01-07 Daniel Yacob - - * am.po: Updated Amharic translation. - -2003-01-06 Gil 'Dolfin' Osher - - * he.po: Added Hebrew translation. - -2003-01-06 Yanko Kaneti - - * bg.po: Updated Bulgarian translation by Evgeni Boevski. - -2003-01-06 Kostas Papadimas - - * el.po: Updated Greek translation - -2003-01-05 Pablo Saratxaga - - * vi.po: Updated Vietnamese file - * am.po: enabled header - * hi.po: fixed syntax errors - -2003-01-04 Andras Timar - - * hu.po: Updated Hungarian translation. - -2003-01-04 Benjamin Greiner - - * de.po: Minor fixes and completions - -2003-01-04 Christian Neumair - - * de.po: Updated German translation. - -2003-01-03 Ole Laursen - - * da.po: Updated Danish translation. - -2003-01-03 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2003-01-02 Christian Rose - - * sv.po: Updated Swedish translation. - -2003-01-03 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2002-12-30 Artis Trops - - * lv.po: Updated Latvian translation. - -2002-12-30 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2002-12-30 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2002-12-30 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2002-12-29 Paolo Maggi - - * it.po: Updated Italian translation. - -2002-12-29 Paolo Maggi - - * POTFILES.in: updated - -2002-12-27 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2002-12-27 Artis Trops - - * lv.po: Updated Latvian translation. - -2002-12-27 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2002-12-26 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2002-12-26 Ole Laursen - - * da.po: Updated Danish translation. - -2002-12-19 Andras Timar - - * hu.po: Updated Hungarian translation. - -2002-12-19 Hasbullah Bin Pit - - * ms.po: Updated Malay translation. - -2002-12-17 Christian Neumair - - * de.po: Updated German translation. - -2002-12-17 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2002-12-17 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-12-15 Christian Neumair - - * de.po: Updated German translation. - -2002-12-15 Ole Laursen - - * da.po: Updated Danish translation. - -2002-12-13 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2002-12-11 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2002-12-10 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2002-12-07 Ole Laursen - - * da.po: Updated Danish translation. - -2002-12-07 He Qiangqiang - - * zh_CN.po: sync with gnome-2-0 branch. - -2002-12-05 Ole Laursen - - * da.po: Partial update of the Danish translation. - -2002-12-05 Miloslav Trmac - - * cs.po: Updated Czech translation. - -2002-12-04 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2002-12-04 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-12-02 Kostas Papadimas - - * el.po: Updated Greek translation. - -2002-11-30 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2002-11-29 Christian Neumair - - * de.po: Updated German translation. - -2002-11-28 Pablo Gonzalo del Campo - - * es.po: Updated Spanish translation. - -2002-11-27 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-11-27 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-11-25 Vincent van Adrighem - - * nl.po: Massive copy-paste from stable branch. - -2002-11-25 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2002-11-25 Pablo Gonzalo del Campo - - es.po: Updated Spanish translation. - -2002-11-25 Pablo Gonzalo del Campo - - es.po: Updated Spanish translation. - -2002-11-25 Yanko Kaneti - - * *.po: Convert all to UTF-8. - -2002-11-22 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2002-11-22 Fatih Demir - - * tr.po: Put back the _real_ Turkish translation... - -2002-11-21 Paolo Maggi - - * POTFILES.in: - * POTFILES.skip: updated - -2002-11-15 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2002-11-12 Dmitry G. Mastrukov - - * be.po: fixed Belarusian translation - -2002-11-12 Dmitry G. Mastrukov - - * be.po: Updated Belarusian translation - * from Belarusian team . - -2002-11-12 Kjartan Maraas - - * be.po: Change charset= to CP1251 to make it build. Please - fix this correctly by converting the file to UTF-8. - -2002-11-11 Dmitry G. Mastrukov - - * be.po: Updated Belarusian translation - * from Belarusian team . - -2002-11-09 Dmitry G. Mastrukov - - * be.po: Updated Belarusian translation - * from Belarusian team . - -2002-11-09 Dmitry G. Mastrukov - - * be.po: Updated Belarusian translation - * from Belarusian team . - -2002-11-01 Paolo Maggi - - * POTFILES.in: - * POTFILES.skip: updated - -2002-10-30 Andras Timar - - * hu.po: Terminology fix. - -2002-10-27 Andras Timar - - * hu.po: Updated Hungarian translation. - -2002-10-15 Kjartan Maraas - - * no.po: Updated Norwegian translation. - -2002-10-14 Paolo Maggi - - * POTFILES.in: added a lot of new files - -2002-10-01 jacob berkman - - * POTFILES.in: fix recent views file - -2002-09-25 Christophe Merlet - - * fr.po: Updated French translation from - Kouran . - -2002-09-20 Marius Andreiana - - * ro.po: updated ( printeaza -> tipareste ) - -2002-09-18 Marius Andreiana - - * ro.po: updated - -2002-09-01 Marius Andreiana - - * ro.po: updated ( thanks to Mugurel Tudor ) - -2002-08-29 Marius Andreiana - - * ro.po: added ( thanks to Mugurel Tudor ) - -2002-08-29 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2002-08-27 Duarte Loreto - - * pt.po: Updated Portuguese translation after typo fix. - -2002-08-26 Duarte Loreto - - * pt.po: Done Quality Review of Portuguese translation. - -2002-08-26 Pablo Saratxaga - - * wa.po: Updated Walloon file - -2002-08-23 Peteris Krisjanis - - * lv.po: Updated Latvian translation by - Artis Trops - -2002-08-21 Pablo del Campo - - * es.po: Updated Spanish Translation. - -2002-08-21 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2002-08-21 Andras Timar - - * hu.po: Updated Hungarian translation. - -2002-08-21 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-08-20 Peteris Krisjanis - - * lv.po: Updated Latvian translation. - -2002-08-19 Ole Laursen - - * da.po: Updated Danish translation. - -2002-08-19 Yanko Kaneti - - * bg.po: Updated Bulgarian translation. - -2002-08-19 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-08-19 Gustavo Noronha Silva - - * pt_BR.po: translation update - -2002-08-19 Akira TAGOH - - * ja.po: Updated Japanese translation. - -2002-08-18 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-08-18 T???µivo Leedj??¢?‚?¬rv - - * et.po: Updated Estonian translation. - -2002-08-18 He Qiangqiang - - * zh_CN.po: Merged with Sun Gl0n's translation. - -2002-08-18 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-08-17 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-08-16 Manuel Borchers - - * de.po: Updated German translation. - -2002-08-17 Changwoo Ryu - - * ko.po: Updated Korean translation by Young-Ho Cha - . - -2002-08-16 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-08-16 Dmitry G. Mastrukov - - * ru.po: updated Russian translation. - -2002-08-15 Ole Laursen - - * da.po: Updated Danish translation. - -2002-08-15 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2002-08-15 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-08-14 Christian Meyer - - * de.po: Fixed some mnemonics. - -2002-08-14 Christian Neumair - - * de.po: Updated German translation. - -2002-08-14 Andras Timar - - * hu.po: Updated Hungarian translation. - -2002-08-14 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-08-13 Andras Timar - - * hu.po: Updated Hungarian translation. - -2002-08-12 Gustavo Noronha Silva - - * pt_BR: finished updating - -2002-08-11 Christian Neumair - - * de.po: Updated German translation - by Jan Arne Petersen - -2002-08-10 Gustavo Noronha Silva - - * pt_BR: updated partially, will finish asap - -2002-08-09 Christian Meyer - - * de.po: Updated German translation, fixed typos, ... - -2002-08-08 Vincent van Adrighem - - * nl.po: Dutch translation updated by Taco Witte. - -2002-08-07 Manuel Borchers - - * de.po: Updated German translation. - -2002-08-07 Stanislav Brabec - - * cs.po: Updated Czech translation from Michal Bukovjan - . - -2002-08-06 Peteris Krisjanis - - * lv.po: Updated Latvian translation. - -2002-08-05 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-08-04 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2002-08-03 T???µivo Leedj??¢?‚?¬rv - - * et.po: Updated Estonian translation. - -2002-07-31 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-07-29 Fatih Demir - - * tr.po: Committed updated Turkish translation. - -2002-07-26 Pablo Saratxaga - - * vi.po: Updated Vietnamese file - -2002-07-26 Dmitry G. Mastrukov - - * ru.po: updated Russian translation. - -2002-07-23 Pablo del Campo - - * es.po: Updated Spanish Translation. - -2002-07-23 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-07-23 Yanko Kaneti - - * bg.po: Updated Bulgarian translation. - -2002-07-23 Ole Laursen - - * da.po: Updated Danish translation. - -2002-07-23 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-07-22 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-07-22 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2002-07-22 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2002-07-22 Changwoo Ryu - - * ko.po: Updated Korean translation from Young-Ho Cha - . - -2002-07-21 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-07-19 Pablo del Campo - - * es.po: Updated Spanish Translation. - -2002-07-19 Ole Laursen - - * da.po: Updated Danish translation. - -2002-07-19 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-07-18 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-07-18 Vincent van Adrighem - - * nl.po: Dutch translation updated (minor update). - -2002-07-17 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-07-16 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-07-16 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-07-16 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-07-16 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2002-07-15 Ole Laursen - - * da.po: Updated Danish translation. - -2002-07-15 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-07-15 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-07-15 Changwoo Ryu - - * ko.po: Updated Korean translation. - -2002-07-14 Peteris Krisjanis - - * lv.po: Updated Latvian translation. - -2002-07-13 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-07-13 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2002-07-13 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-07-12 Pablo Gonzalo del Campo - - * es.po: Updated Spanish Translation. - -2002-07-11 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2002-07-11 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-07-09 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-07-09 Christian Rose - - * POTFILES.in: Added missing file. - * sv.po: Updated Swedish translation. - -2002-07-09 Jacob Berkman - - * POTFILES.in: remove a missing file - -2002-07-09 Dmitry G. Mastrukov - - * POTFILES.in: Fixed location of .in files (now in /data), - changed gedit.shemas to gedit.schemas.in. - -2002-07-09 Akira TAGOH - - * ja.po: Updated Japanese translation. - -2002-07-08 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-07-05 Christian Rose - - * POTFILES.in: Removed non-existing file, added missing file. - * sv.po: Updated Swedish translation. - -2002-07-05 jacob berkman - - * POTFILES.in: replace gedit-prefs.c with gedit-prefs-manager.c - -2002-07-05 Christophe Fergeau - - * fr.po: Updated French translation - -2002-07-02 Manuel Borchers - - * de.po: Updated German translation after merge. - -2002-07-02 Dmitry G. Mastrukov - - * ru.po: updated Russian translation. - -2002-06-30 Manuel Borchers - - * de.po: Updated German translation - -2002-06-23 Christophe Fergeau - - * fr.po: Updated French translation - -2002-06-22 Christophe Fergeau - - * fr.po: Updated French translation - -2002-06-21 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-06-17 Daniel Yacob - - * am.po: Updated Amharic translation. - -2002-06-16 Daniel Yacob - - * am.po: New file for Amharic translation. - -2002-06-16 Akira TAGOH - - * ja.po: Updated Japanese translation. - -2002-06-10 Naba Kumar - - * hi.po: Added new hindi translation. - -2002-06-09 Dmitry G. Mastrukov - - * ru.po: updated Russian translation. - -2002-06-08 Jordi Mallach - - * ca.po: Updated Catalan translation. - -2002-06-08 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-06-05 Christian Rose - - * sv.po: Fix. - -2002-06-04 T???µivo Leedj??¢?‚?¬rv - - * et.po: Updated Estonian translation. - -2002-06-04 Vincent van Adrighem - - * nl.po: Dutch translation updated by Reinout van Schouwen. - -2002-06-04 Germ??n Poo Caama???±o - - * es.po: Updated Spanish translation. - -Mon Jun 03 15:01:20 2002 George Lebl - - * cs.po: update - -2002-06-03 Carlos Perell???³ Mar???­n - - * es.po: Small fixes. - -2002-06-03 Jarkko Ranta - - * fi.po: Updated FInnish translation. - -2002-06-03 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2002-06-02 Pablo Saratxaga - - * vi.po: Updated Vietnamese file - -2002-06-02 Christian Rose - - * sv.po: Small fix. - -2002-06-02 Christian Rose - - * sv.po: Small fix. - -2002-05-31 Pablo Gonzalo del Campo - - * es.po: Updated Spanish Translation. - -2002-05-31 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-05-29 Ole Laursen - - * da.po: Updated Danish translation. - -2002-05-29 Duarte Loreto - - * pt.po: Updated Portuguese translation - -2002-05-28 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-05-28 Yanko Kaneti - - * bg.po: Updated Bulgarian translation (100%) - by Evgeni Boevski and me. - -2002-05-27 Yanko Kaneti - - * bg.po: Updated Bulgarian translation - by Evgeni Boevski . - -2002-05-27 Jacob Berkman - - * POTFILES.in: fixup - -2002-05-27 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-05-27 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-05-27 Yanko Kaneti - - * bg.po (added): New Bulgarian translation - by Evgeni Boevski . - -2002-05-23 Pablo Gonzalo del Campo - - * es.po: Updated Spanish Translation. - -2002-05-23 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-05-22 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-05-20 Vincent van Adrighem - - * nl.po: Dutch translation updated by Sander Knopper. - -2002-05-19 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-05-17 Pablo del Campo - - * es.po: Updated Spanish Translation. - -2002-05-16 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-05-16 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-05-16 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-05-14 Fatih Demir - - * ta.po: Committed updated Tamil translation by Dinesh. - -2002-05-14 Abel Cheung - - * POTFILES.in: Synced with source tree. - * zh_TW.po: Updated traditional Chinese translation. - -2002-05-13 Pablo Saratxaga - - * ca.po: Updated Catalan file - -2002-05-11 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-05-08 Carlos Perello Marin - - * es.po: Fixed translation credits. - -2002-05-08 Pablo Saratxaga - - * eu.po,vi.po: Added Basque and Vietnamese files - * wa.po: Updated Walloon file - -2002-05-08 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-03-07 Germ??n Poo-Caama???±o - - * es.po: Updated spanish translation from - Pablo del Campo - -2002-05-07 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-05-06 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-04-30 Fatih Demir - - * ta.po: Committed updated Tamil translation by Dinesh. - -2002-04-30 Duarte Loreto - - * pt.po: Updated Portuguese translation and converted to UTF-8. - -2002-04-29 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-04-26 Changwoo Ryu - - * ko.po: Updated Korean translation by Young-Ho Cha - . - -2002-04-26 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2002-04-23 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-04-22 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2002-04-20 Paolo Maggi - - * it.po: Updated italian translation by Alessio Frusciante - -2002-04-20 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2002-04-18 Vincent van Adrighem - - * nl.po: Updated Dutch translation by Ronald Hummelink. - -2002-04-15 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-03-13 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-04-12 Abel Cheung - - * .cvsignore: Added some file(s). - * zh_TW.po: Updated traditional Chinese translation. - -2002-04-10 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-04-08 Fatih Demir - - * ta.po: Committed updated Tamil translation by Dinesh. - -2002-04-05 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-03-30 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-03-26 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-03-28 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-03-28 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation. - -2002-03-27 Jarkko Ranta - - * fi.po: Fixed broken fi.po (i hope). - -2002-03-27 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2002-03-27 Christian Rose - - * POTFILES.in: Added missing files. - * sv.po: Updated Swedish translation. - -2002-03-26 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-03-25 jacob berkman - - * fi.po: rever commit which broke the build - -2002-03-25 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2002-03-24 T???µivo Leedj??¢?‚?¬rv - - * et.po: Updated Estonian translation. - -2002-03-24 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-03-21 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-03-17 Valek Filippov - - * ru.po: Updated russian translation. - -2002-03-17 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-03-17 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-03-16 Christian Meyer - - * de.po: Updated German translation. - -2002-03-15 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-03-14 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-03-13 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2002-03-12 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-03-10 Zbigniew Chyla - - * pl.po: Updated Polish translation by - GNOME PL Team . - -2002-03-09 Matthias Warkus - - * de.po: Updated German translation. Phew. - -2002-03-06 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2002-03-06 Germ??n Poo-Caama???±o - - * es.po: Updated spanish translation from - Pablo del Campo - -2002-03-06 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-03-06 Vincent van Adrighem - - * nl.po: Updated Dutch translation (by Ronald Bultje). - -2002-03-05 Christian Rose - - * sv.po: Fixed Swedish translation. - -2002-03-05 Valek Filippov - - * ru.po: Updated russian translation. - -2002-03-05 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-03-04 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-03-04 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-03-04 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-03-04 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-03-04 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-03-03 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-02-27 Miles Lane - - * it.po: Readded it.po. D'uh. I only needed to remove - the configure.in entry. - -2002-02-27 Miles Lane - - * it.po: Removed the Italian translation. This version - is breaking the build. - -2002-02-27 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-02-27 Paolo Maggi - - * it.po: Updated Italian translation. - -2002-02-27 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-02-25 Valek Filippov - - * ru.po: Updated russian translation. - -2002-02-23 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-02-22 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-02-21 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-02-21 jacob berkman - - * POTFILES.in: it's gedit.desktop.in now - -2002-02-21 Fatih Demir - - * tr.po: Committed updated Turkish translation by Nilg???’n. - -2002-02-20 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-02-19 Christian Rose - - * sv.po: Updated Swedish translation. - -2002-02-18 Paolo Maggi - - * POTFILES.in: added *.glade2 files - -2002-02-17 Vincent van Adrighem - - * nl.po: New Dutch translation made - by Jan-Willem Harmanny. - -2002-02-14 T???µivo Leedj??¢?‚?¬rv - - * et.po: Added Estonian translation - by Ilmar Kerm . - -2002-02-14 Paolo Maggi - - * POTFILES.in: added ascii.c - * POTFILES.skip: removed ascii.c - -2002-02-10 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-02-10 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-02-08 Paolo Maggi - - * POTFILES.in: added diff.c - * POTFILES.skip: removed diff.c - -2002-02-07 Paolo Maggi - - * POTFILES.in: added files related to the new - taglist plugin - * gedit-2.0.pot: Updated - -2002-02-06 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2002-02-05 Paolo Maggi - - * gedit-2.0.pot: Updated - -2002-02-03 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-01-30 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-01-29 Jarkko Ranta - - * fi.po: Updated Finnish translation. - -2002-01-28 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-01-28 Christian Rose - - * sv.po: Updated and converted to UTF-8. - -2002-01-27 Hasbullah Bin Pit - - * ms.po: Updated Malay Translation. - -2002-01-26 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - -2002-01-24 Paolo Maggi - - * POTFILES.in: added plugins/shell_output/shell_output.c - * POTFILES.skip: removed plugins/shell_output/shell_output.c - -2002-01-23 Hasbullah Bin Pit - - * ms.po: Updated Malay translation. - -2002-01-22 Paolo Maggi - - * POTFILES.in: added plugins/cvschangelog/cvschangelog.c, - plugins/time/time.c and src/dialogs/gedit-dialog-plugin-manager.c - * POTFILES.skip: removed plugins/cvschangelog/cvschangelog.c - and plugins/time/time.c - -2002-01-22 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-01-18 Paolo Maggi - - * POTFILES.in: added plugins/docinfo/docinfo.c - - * POTFILES.skip: removed plugins/docinfo/docinfo.c - -2002-01-18 Paolo Maggi - - * POTFILES.in: added plugins/sample/sample.c - * POTFILES.skip: removed plugins/sample/sample.c - -2002-01-17 Hasbullah Bin Pit - - * ms.po: Added Malay translation. - -2002-01-17 Christian Rose - - * POTFILES.in: Added a missing file. - * sv.po: Updated Swedish translation. - -2002-01-16 Peteris Krisjanis - - * lv.po: Added Latvian translation. - -2002-01-15 Paolo Maggi - - * POTFILES.skip: created - -2002-01-14 Paolo Maggi - - * POTFILES.in: Removed unused files (i.e. plugins/*) - * it.po: Updated Italian translation. - -2002-01-13 Kjartan Maraas - - * no.po: Updated Norwegian (bokm???¥l) translation. - * POTFILES.in: Removed a missing file. - -2002-01-13 Christian Rose - - * POTFILES.in: Sorted and added LOTS of missing files. - * sv.po: Updated Swedish translation. - -2002-01-11 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2002-01-04 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2001-12-31 Valek Filippov - - * ru.po: Updated russian translation. - -2001-12-29 Duarte Loreto - - * pt.po: Updated Portuguese translation. - -2001-12-27 Jesus Bravo Alvarez - - * gl.po: Updated Galician translation from - Manuel A. Fernandez Montecelo - -2001-12-19 Christian Rose - - * sv.po: Updated Swedish translation. - -2001-12-15 Christian Rose - - * sv.po: Updated Swedish translation. - -2001-12-13 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2001-12-11 Stanislav Visnovsky - - * sk.po: Updated Slovak translation. - -2001-12-09 Abel Cheung - - * zh_TW.po: Updated traditional Chinese translation, and - converted to UTF-8. - -2001-12-08 Christian Rose - - * sv.po: Updated Swedish translation. - -2001-12-04 Yuriy Syrota - - * uk.po: Updated Ukrainian translation. - -2001-12-03 Christian Rose - - * sv.po: Updated Swedish translation. - -2001-11-27 Pablo Saratxaga - - * az.po: Updated Azeri file - * ja.po: corrected syntax error - -2001-11-18 Valek Filippov - - * ru.po: Updated russian translation. - -2001-11-16 Carlos Perell???³ Mar???­n - - * POTFILES.in: Updated. - -2001-11-16 Carlos Perell???³ Mar???­n - - * ChangeLog: rolled over to ChangeLog-20011116. - -2001-11-16 Kostas Papadimas - - * el.po: Updated Greek translation diff --git a/po/ChangeLog-20051212 b/po/ChangeLog-20051212 new file mode 100644 index 00000000..5451cbb0 --- /dev/null +++ b/po/ChangeLog-20051212 @@ -0,0 +1,4492 @@ +2005-11-30 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2005-11-22 Roozbeh Pournader + + * fa.po: Updated Persian translation by Meelad Zakaria and Elanz + Sarbar. + +2005-11-20 Frank Arnold + + * de.po: Fixed translation of search dialogs "Wrap around". + Closes #321874 reported by John Spray. + +2005-11-14 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-10-25 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-10-21 Inaki Larranaga + + * eu.po: Updated Basque translation. + +2005-10-14 Vincent van Adrighem + + * nl.po: Translation updated. + +2005-10-10 Marcel Telka + + * sk.po: Updated Slovak translation. + +==== gedit 2.12.1 ==== + +2005-10-02 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same + +2005-09-29 Christian Rose + + * sv.po: Reverted unauthorized changes made by + user 'kloczek'. + +2005-09-18 Christian Rose + + * sv.po: Updated Swedish translation. + +2005-09-16 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-09-10 Erdal Ronahi + + * ku.po: Added Kurdish Translation + +2005-09-09 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2005-09-09 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2005-09-07 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-09-06 Inaki Larranaga + + * eu.po: Updated Basque translation. + +2005-09-05 Rhys Jones + + * cy.po: Updated Welsh translation. + +==== gedit 2.12.0 ==== + +2005-09-05 Runa Bhattacharjee + * bn.po: Updated Bengali (bn) Translation + +2005-09-04 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-09-04 Frank Arnold + + * de.po: Updated German translation. + +2005-09-04 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation. + +2005-09-04 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-09-03 Mohammad DAMT + + * id.po: Updated Indonesian translation. + +2005-09-03 Danilo Šegan + + * sr.po, sr@Latn.po: Updated. + +2005-09-03 Christophe Merlet + + * fr.po: Updated French translation. + +2005-09-03 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +2005-09-03 Christophe Merlet + + * fr.po: Updated French translation. + +2005-09-03 Mugurel Tudor + + * ro.po: Updated Romanian translation + by Dan Damian + +2005-09-03 Chao-Hsiung Liao + + * zh_TW.po: Updated Traditional Chinese translation. + +2005-09-03 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2005-09-02 Christophe Merlet + + * fr.po: Updated French translation from + Stéphane Raimbault . + +2005-09-02 Kostas Papadimas + + *el.po Updated Greek Translation + +2005-09-02 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-09-02 Leonid Kanter + + * ru.po: Updated Russian translation + +2005-09-02 Rhys Jones + + * cy.po: Updated Welsh translation. + +2005-09-02 Choe Hwanjin + + * ko.po: Updated Korean translation by Young-Ho Cha. + +2005-09-02 Kostas Papadimas + + *el.po Updated Greek Translation + +2005-09-01 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-09-01 Baris Cicek + + * tr.po: Updated Turkish Translation + +2005-09-01 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-09-01 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2005-01-09 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-08-31 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation by Justina Klingaitė. + +2005-08-30 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2005-08-30 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2005-08-30 Leonid Kanter + + * ru.po: Updated Russian translation + +2005-08-29 Miloslav Trmac + + * cs.po: Updated Czech translation. + +==== gedit 2.11.93 ==== + +2005-08-29 Telsa Gwynne + + * cy.po: Updated Welsh translation from Chris Jackson. + +2005-08-27 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2005-08-27 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-08-25 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2005-08-23 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +==== gedit 2.11.92 ==== + +2005-23-08 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-08-23 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2005-08-23 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2005-08-21 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-08-21 Kostas Papadimas + + *el.po Updated Greek Translation + +2005-08-21 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-08-20 Duarte Loreto + + * pt.po: Updated Portuguese translation and fix a typo. + +2005-08-19 Dan Damian + + * ro.po: Updated Romanian translation. + +2005-08-19 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-08-18 Chao-Hsiung Liao + + * zh_TW.po: Updated Traditional Chinese translation. + +2005-08-16 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2005-08-16 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2005-08-16 Marcel Telka + + * sk.po: Fixed invalid message translation (thanks to Sergej Chodarev). + +2005-08-14 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +2005-08-13 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-08-13 Kostas Papadimas + + *el.po Updated Greek Translation + +2005-08-13 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2005-08-11 Frank Arnold + + * de.po: Updated German translation. + +2005-08-11 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-08-10 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav Raykov + +2005-08-09 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-08-09 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-08-09 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same + +2005-08-09 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-08-08 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +==== gedit 2.11.91 ==== + +2005-08-08 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-08-07 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-08-07 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-08-06 Josep Puigdemont + + * ca.po: Updated Catalan translation. + +2005-08-06 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-08-06 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-08-06 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-08-05 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-08-05 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-08-05 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-08-05 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-08-05 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same + +2005-08-05 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-08-05 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-08-04 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +==== gedit 2.10.4 ==== + +2005-08-04 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same + +2005-08-04 Sunil Mohan Adapa + + * te.po: Added Telugu translation done by + Prajasakti Localisation Team + + +2005-08-01 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav Raykov + +2005-08-01 Vincent van Adrighem + + * nl.po: Translation updated. + +2005-07-31 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-07-31 Pawan Chitrakar + + * ne.po: Updated Nepali Translation + +2005-07-31 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-07-28 Josep Puigdemont i Casamajó + + * ca.po: Updated translation. + +2005-07-27 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-07-27 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation by Igor + Nestorović. + +2005-07-25 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-07-21 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +2005-07-15 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2005-07-14 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-07-13 Yair Hershkovitz + + * he.po: Translation updated by Yair Hershkovitz + +2005-07-06 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-07-05 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-07-04 Hendrik Richter + + * de.po: Fixed German translation by + Jens Seidel . + +2005-07-03 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-06-27 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-06-25 Sigurd Gartmann + + * nb.po: Updated Norwegian translation. + * no.po: Updated Norwegian translation. + +2005-06-22 Abel Cheung + + * zh_TW.po: Fix language team reference. + +2005-06-21 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-06-15 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-06-15 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +2005-06-14 Terance Sola + + * nb.po: Updated Norwegian Bokmal translation. + * no.po: Same. + +2005-06-12 Christophe Merlet + + * fr.po: Updated French translation from + Baptiste Mille-Mathias . + +2005-06-10 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +==== gedit 2.10.3 ==== + +2005-06-06 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2005-06-01 Pauli Virtanen + + * fi.po: Improvements to the Finnish translation by Lauri Nurmi. + +2005-05-29 Pauli Virtanen + + * fi.po: Improved Finnish translation by Lauri Nurmi. + +2005-05-26 Rhys Jones + + * cy.po: Updated Welsh translation. + +2005-05-26 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2005-05-26 Kjartan Maraas + + * nb.po: Update + * no.po: Update + +2005-05-20 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2005-05-16 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-05-14 Pawan Chitrakar + + * ne.po: Updated Nepali translation + +2005-05-13 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-05-12 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2005-05-11 Kostas Papadimas + + *el.po Updated Greek Translation + +2005-05-10 Rajesh Ranjan + + * hi.po: Updated Hindi translation. + +2005-05-10 Adi Attar + + * xh.po: Updated Xhosa translation. + +2005-05-10 Rajesh Ranjan + + *hi.po: Updated Hindi translation. + +2005-05-07 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-04-24 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-04-22 Abel Cheung + + * ro.po: Mark wrong entry as fuzzy (msgfmt check failed). + +2005-04-21 Roozbeh Pournader + + * fa.po: Updated Persian translation by + Meelad Zakaria . + +2005-04-20 Pablo Saratxaga + + * wa.po: Updated Walloon file + +2005-04-15 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +==== gedit 2.10.2 ==== + +2005-03-31 Steve Murphy + + * rw.po: Added Kinyarwanda translation. + +2005-03-30 Adi Attar + + * xh.po: Updated Xhosa translation. + +2005-03-28 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +==== gedit 2.10.1 ==== + +2005-03-25 Ahmad Riza H Nst + + * id.po: Updated Indonesian Translation. + +2005-03-22 Adi Attar + + * xh.po: Added Xhosa translation. + +2005-03-20 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2005-03-19 Leonid Kanter + + * ru.po: Fixed Russian translation + +2005-03-19 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-03-17 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-03-13 David Lodge + + * en_GB.po: Updated British translation. + +2005-03-09 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2005-03-08 Baris Cicek + + * tr.po: Updated Turkish Translation by Ercin Eker + +==== gedit 2.10.0 ==== + +2005-03-07 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-03-06 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2005-03-06 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2005-03-06 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-03-05 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-03-03 Alessio Frusciante + + * it.po: Updated Italian translation by + Roberto Rosselli Del Turco . + +2005-03-03 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation from GNOME HK Team + +2005-03-03 Dan Damian + + * ro.po: Updated Romanian translation. + +2005-03-03 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2005-03-02 Dan Damian + + * ro.po: Updated Romanian translation. + +2005-03-02 Roozbeh Pournader + + * fa.po: Updated Persian translation by + Meelad Zakaria . + +2005-03-02 Danilo Šegan + + * sr.po, sr@Latn.po: Partial update of Serbian translation. + +2005-03-02 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-03-01 Josep Puigdemont + + * ca.po: Updated Catalan translation. + +2005-03-01 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +==== gedit 2.9.7 ==== + +2005-02-28 Alessio Frusciante + + * it.po: Updated Italian translation by + Roberto Rosselli Del Turco . + +2005-02-28 Kostas Papadimas + + * el.po: Updated Greek translation. + +2005-02-28 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2005-02-27 Sami Pesonen + + * fi.po: Updated Finnish translation #2. + +2005-02-26 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-02-26 Sami Pesonen + + * fi.po: Updated Finnish translation #1. + +2005-02-25 Ole Laursen + + * da.po: Fixed some issues in the Danish translation based on + comments from Martin Willemoes Hansen. + +2005-02-25 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2005-02-24 Jordi Mallach + + * ca.po: Updated Catalan translation by + Josep Puigdemont . + +2005-02-23 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-02-21 Leonid Kanter + + * ru.po: Updated Russian translation + +2005-02-21 Priit Laes + + * et.po: Translation updated. + +2005-02-21 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-02-20 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2005-02-20 Ole Laursen + + * da.po: Updated Danish translation. + +2005-02-20 Kostas Papadimas + + * el.po: Updated Greek translation. + +2005-02-19 Francisco Javier F. Serrador + + * es.po: Updated Spanih translation. + +2005-02-19 Christian Rose + + * sv.po: Updated Swedish translation. + +2005-02-19 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2005-02-18 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2005-02-18 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2005-02-17 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-02-17 Frank Arnold + + * de.po: Updated German translation. + +2005-02-17 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav Raykov + +2005-02-15 Jordi Mallach + + * ca.po: Updated Catalan translation by + Josep Puigdemont . + +2005-02-14 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha. + +2005-02-14 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-02-14 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-02-13 David Lodge + + * en_GB.po: Updated British translation. + +2005-02-13 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2005-02-13 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-02-12 Paolo Maggi + + * POTFILES.in: removed unused file close_all_dialog.glade2 + +2005-02-12 Priit Laes + + * et.po: Translation updated. + +2005-02-12 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-02-12 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-02-12 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-02-11 Frank Arnold + + * de.po: Updated German translation. + +2005-02-11 Christian Rose + + * sv.po: Updated Swedish translation. + +2005-02-10 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-02-10 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-02-10 Kjartan Maraas + + * nb.po: Update + * no.po: Update + +2005-02-09 Kostas Papadimas + + * el.po: Updated Greek translation. + +2005-02-09 Jordi Mallach + + * ca.po: Updated Catalan translation by + Josep Puigdemont . + +2005-02-08 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-02-08 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-02-08 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-02-08 Frank Arnold + + * de.po: Updated German translation. + +==== gedit 2.9.6 ==== + +2005-02-07 Leonid Kanter + + * ru.po: Updated Russian translation + +2005-02-07 David Lodge + + * en_GB.po: Updated British translation. + +2005-02-07 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2005-02-06 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2005-02-06 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-02-06 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-02-06 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-02-07 Rhys Jones + + * cy.po: Updated Welsh translation. + +2005-02-06 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-02-05 Frank Arnold + + * de.po: Updated German translation. + +2005-02-02 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-02-01 Kostas Papadimas + + * el.po: Updated Greek translation + +2005-01-30 David Lodge + + * en_GB.po: Updated British translation. + +2005-01-29 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-01-29 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-01-29 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-01-28 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav Raykov + +2005-01-28 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-01-27 Theppitak Karoonboonyanan + + * th.po: More updates on Thai translation. + +2005-01-27 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-01-26 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2005-01-26 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-01-26 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-01-26 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-01-25 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav Raykov + +2005-01-24 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-01-23 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-01-21 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-01-19 Frank Arnold + + * de.po: Updated German translation. + +2005-01-19 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-01-19 Leonid Kanter + + * ru.po: Updated Russian translation + +2005-01-18 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-01-18 Frank Arnold + + * de.po: Updated German translation. + +2005-01-17 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-01-17 Rhys Jones + + * cy.po: Corrected a few new/pre-existing typos and grammar errors. + +2005-01-17 Rhys Jones + + * cy.po: Updated Welsh translation. + +2005-01-17 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2005-01-16 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-01-15 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-01-15 Kjartan Maraas + + * nb.po: Update + * no.po: Update + +2005-01-15 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-01-15 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-01-15 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-01-14 Alexander Winston + + * en_CA.po: Updated Canadian English translation. + +2005-01-13 Rhys Jones + + * cy.po: Partially updated Welsh translation. + +2005-01-13 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-01-12 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-01-11 Tomasz Kłoczko + + * kn.po: fixed format string bugs (neccessary for latest gettext). + * ms.po: added missing Plural-Forms field in header (neccessary + for latest gettext). + +==== gedit 2.9.4 ==== + +2005-01-10 Paolo Maggi + + * POTFILES.in: updated + + * POTFILES.skip: ditto + +2005-01-04 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-12-28 Kostas Papadimas + + * el.po: Updated Greek translation + +2004-12-28 Kjartan Maraas + + * nb.pok: Update + +2004-12-25 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-12-24 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2004-12-22 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-12-22 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2004-12-22 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-12-22 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-12-17 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-12-07 Tommi Vainikainen + + * fi.po: Minor consistency fixes to Finnish translation. + +2004-12-05 Paolo Borelli + + * POTFILES.in: add gedit-io-error-dialogs. + +2004-12-05 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-12-03 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2004-12-01 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-11-29 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-11-29 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-11-25 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2004-11-23 Martin Willemoes Hansen + + * da.po: Updated Danish translation. + +2004-11-22 Martin Willemoes Hansen + + * da.po: Updated Danish translation. + +2004-11-21 David Lodge + + * en_GB.po: Updated British translation. + +2004-11-15 Meelad Zakaria + + * fa.po: Updated Persian translation. + +2004-11-14 Paolo Borelli + + * POTFILES.in: re-add the changecase plugin files, they were + added on 2004-04-05, but got lost at some point. + +2004-11-14 Paolo Maggi + + * POTFILES.*: updated + +2004-11-08 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2004-11-05 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-11-04 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-11-01 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-11-01 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-10-31 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-10-30 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-10-29 Jordi Mallach + + * POTFILES.in: Removed nonexisting files. + * ca.po: Updated Catalan translation. + +2004-10-25 Mohammad DAMT + + * id.po: Updated Indonesian translation + +2004-10-10 Christophe Merlet + + * fr.po: Updated French translation. + +2004-10-06 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-09-26 Roozbeh Pournader + + * fa.po: Updated Persian translation. + +2004-09-24 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-09-21 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2004-09-15 Roozbeh Pournader + + * fa.po: Updated Persian translation by Meelad Zakaria + . + +2004-09-15 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2004-09-14 Gora Mohanty + + * or.po: Updated Oriya translation. + +2004-09-12 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2004-09-11 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2004-09-11 Christophe Merlet + + * fr.po: Updated French translation. + +2004-09-09 Baris Cicek + + * tr.po: Updated Turkish Translation by Ridvan Can + +2004-09-07 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2004-09-07 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2004-09-07 David Lodge + + * en_GB.po: Fixed British translation. + +2004-09-06 David Lodge + + * en_GB.po: Updated British translation. + +2004-09-06 Mugurel Tudor + + * ro.po: Updated Romanian translation + by Misu Moldovan + +2004-09-06 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2004-09-06 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2004-09-05 Kjartan Maraas + + * nb.po: Updated + * no.po: Updated + +2004-09-05 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2004-09-04 Mətin Əmirov + + * az.po: Translation updated. + +2004-09-04 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-09-03 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2004-09-02 Hendrik Richter + + * de.po: Updatet German translation + +2004-08-31 Arafat Medini + + * ar.po: Updated Arabic translation + +2004-08-31 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-08-30 Kostas Papadimas + + * el.po: Updated Greek translation. + +2004-08-29 Akagic Amila + + * bs.po: Added Bosnian translation. + +2004-08-25 Iñaki Larrañaga + + * eu.po: Updated Basque translation. + +2004-08-24 Francisco Javier F. Serrador + + * es.po: Updated Spanih translation. + +2004-08-24 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2004-08-23 Christian Rose + + * sv.po: Updated Swedish translation. + +2004-08-23 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2004-08-22 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-08-21 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2004-08-21 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2004-08-21 Leonid Kanter + + * ru.po: Updated Russian translation + +2004-08-20 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-08-20 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2004-08-19 Francisco Javier F. Serrador + + * es.po: Updated Spanih translation. + +2004-08-19 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-08-19 Christian Rose + + * POTFILES.skip: Removed nonexisting entry. + * sv.po: Updated Swedish translation. + +2004-08-19 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-08-18 Laszlo Dvornik + + * hu.po: Updated Hungarian translation. + +2004-08-18 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-08-18 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-08-18 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-08-18 Martin Willemoes Hansen + + * da.po: Updated Danish translation. + +2004-08-18 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-08-17 Ankit Patel + + * gu.po: Updated Final Gujarati Translation. + +2004-08-17 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-08-17 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2004-08-17 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-08-17 Metin Amiroff + + * az.po: Translation updated. + +2004-08-16 Kjartan Maraas + + * nb.po: Added this. + +2004-08-15 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-08-14 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2004-08-13 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-08-13 Gurban Tewekgeli + + * tk.po: Updated Turkmen translation. + +2004-08-12 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-08-10 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-08-10 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-08-08 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-08-08 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-08-06 Christian Neumair + + * de.po: Updated German translation. + +2004-08-06 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-08-06 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-08-05 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-08-05 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-08-05 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-08-04 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2004-08-03 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-08-02 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-08-02 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-08-02 Roozbeh Pournader + + * fa.po: Updated Persian translation by Meelad Zakaria + . + +2004-08-01 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-07-30 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2004-07-29 Christophe Merlet + + * fr.po: Updated French translation. Close bug #148576. + +2004-07-28 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-07-28 Laszlo Dvornik + + * hu.po: Updated Hungarian translation. + +2004-07-26 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2004-07-21 Guntupalli Karunakar + + * hi.po: Updated Hindi translation. + +2004-07-19 Gareth Owen + + * en_GB.po: Updated British English translation + +2004-07-19 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-07-18 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-07-18 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-07-15 Christian Rose + + * sv.po: Updated Swedish translation. + +2004-07-12 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2004-07-12 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-07-11 Gil Osher + + * he.po: Updated Hebrew translation. + Thanks to Shoshannah Forbes. + +2004-07-10 Takeshi AIHANA + + * ja.po: Updated Japanese translation and + Fixed wrong translation reviewed by + MATSUURA Takanori . + +2004-07-08 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav Raykov + +2003-07-03 Christian Neumair + + * POTFILES.skip: Removed obsolete file. + * de.po: Updated German translation. + +2004-06-29 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2004-06-28 Laurent Dhima + + * sq.po: Translation updated. + +2004-06-22 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-06-18 Gustavo Maciel Dias Vieira + + * pt_BR.po: Updated Brazilian Portuguese translation done by João + Paulo Gomes Vanzuita . + +2004-06-17 Alexander Winston + + * en_CA.po: Updated Canadian English translation. + +2004-06-17 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Evgeni Boevski + +2004-06-16 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-06-14 Gareth Owen + + * en_GB.po: Updated British English translation + +2004-06-14 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-06-09 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2004-06-06 Pawan Chitrakar + + * ne.po: Upadted Nepali translation. + +2004-06-05 Dinesh Nadarajah + + * ta.po: Updated Tamil Translation + +2004-06-01 Ole Laursen + + * da.po: Updated Danish translation. + +2004-05-29 Christian Rose + + * tk.po: Added Turkmen translation by + Gurban Mühemmet Tewekgeli . + +2004-05-26 Mohammad DAMT + + * id.po: Added Indonesian translation done by Ahmad Riza H Nst + +2004-05-23 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-05-23 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2004-05-16 Francisco Javier F. Serrador + + * es.po: Updated Spansih translation. + +2004-05-11 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-05-04 Gustavo Maciel Dias Vieira + + * pt_BR.po: Updated Brazilian Portuguese translation done by + Raphael Higino . + +2004-05-03 Tomasz Kłoczko + + * ja.po: added missing Plural-Forms field. + +2004-04-24 Christophe Merlet + + * fr.po: Updated French translation. + +2004-04-19 Gareth Owen + + * en_GB.po: Updated British English translation + +2004-04-19 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2004-04-16 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-04-16 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-04-15 Andras Timar + + * hu.po: Updated Hungarian translation. + +2004-04-09 Guntupalli Karunakar + + * gu.po: Added Gujurati translation by + Gujarati Team . + +2004-04-08 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-04-05 Iñaki Larrañaga + + * eu.po: Updated Basque translation. + +2004-04-05 Paolo Borelli + + * POTFILES.in: add changecase plugin files. + +2004-04-05 Bastien Nocera + + * en_GB.po: fix some typos (Closes: #138999) + +2004-04-03 Samúel Jón Gunnarsson + + * is.po: Added Icelandic translation by + Helgi Þormar Þorbjörnsson + +2004-03-31 Christian Rose + + * af.po: Added Afrikaans translation by + Zuza Software Foundation . + +2004-03-30 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-03-28 Robert Sedak + + * hr.po: Updated Croatian translation. + +2004-03-24 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-03-23 Pablo Saratxaga + + * wa.po: Updated Walloon file + +2004-03-22 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-03-22 Baris Cicek + + * tr.po: Updated Turkish Translation. + +2004-03-21 Alastair McKinstry + + * ga.po: Updated Irish translation. + +2004-03-21 Andras Timar + + * hu.po: Added Hungarian translation. + +2004-03-20 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation from + Anthony Tang . + +2004-03-20 Abel Cheung + + * POTFILES.skip: Add gedit/recent-files/egg-recent-vfs-utils.c, + remove non-existant file. + +2004-03-19 Gareth Owen + + * en_GB.po: Added British translation + +2004-03-19 Dmitry G. Mastrukov + + * ru.po: Updated Russian translation + from Russian team . + +2004-03-18 Arafat Medini + + * ar.po: Updated Arabic translation. + +2004-03-18 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2004-03-18 Guntupalli Karunakar + + * mr.po: Added Marathi translation by + Swapnil Hajare . + +2004-03-18 Funda Wang + + * zh_CN.po: Updated Simplified Chinese to avoid bug#137329. + +2004-03-15 Dinesh Nadarajah + + * ta.po: Updated Tamil translation. + +2004-03-14 Theppitak Karoonboonyanan + + * th.po: Fixed accelerators in Thai translation. + +2004-03-13 Ales Nyakhaychyk + + * be.po: Updated Belarusian translation. + +2004-03-13 Maxim Dziumanenko + + * uk.po: some fixes to Ukrainian translation. + +2004-03-12 Arafat Medini + + * ar.po: Updated faulty Arabic translation. + +2004-03-12 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2004-03-12 Arafat Medini + + * ar.po: Updated Arabic translation. + +2004-03-11 Alessio Frusciante + + * it.po: Updated Italian translation by + Roberto Rosselli Del Turco . + +2004-03-11 Dafydd Harries + + * cy.po: Updated Welsh translation from Rhys Jones. + +2004-03-11 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-03-10 Gustavo Maciel Dias Vieira + + * pt_BR.po: Some errors fixed. + +2004-03-09 Gustavo Noronha Silva + + * pt_BR.po: translation updated by + Raphael Higino + +2004-03-10 Vincent van Adrighem + + * nl.po: Translation updated. + +2004-03-09 Duarte Loreto + + * pt.po: Fixed a bad translation (thanks to Duarte Henriques). + +2004-03-09 Sanlig Badral + + * mn.po: Updated Mongolian translation. + +2004-03-08 Francisco Javier F. Serrador + + * es.po: Updated Spansih translation. + +2004-03-08 Alastair McKinstry + + * ga.po: Updated Irish translation. + +2004-03-07 Christophe Merlet + + * fr.po: Updated French translation. + +2004-03-07 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2004-03-06 Mətin Əmirov + + * az.po: Translation updated. + +2004-03-05 Albert Chin-A-Young + + * POTFILES.in: gedit/recent-files/egg-recent-vfs-utils.c + doesn't exist in the distribution + +2004-03-04 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2004-03-04 Guntupalli Karunakar + + * pa.po: Added Punjabi translation by + Amanpreet Singh Alam . + +2004-03-3 Arafat Medini + + * ar.po: Updated Arabic translation. + +2004-03-01 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-03-01 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2004-03-01 Alessio Frusciante + + * it.po: Updated Italian translation by + Roberto Rosselli Del Turco . + +2004-03-01 Vincent van Adrighem + + * nl.po: Translation updated by Daniel van Eeden. + +2004-02-28 Christophe Merlet + + * fr.po: Updated French translation. + +2004-02-28 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2004-02-27 Priit Laes + + * et.po: Translation updated. + +2004-02-26 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-02-26 Vincent van Adrighem + + * nl.po: Translation updated by Kees van den Broek. + +2004-02-25 Christophe Merlet + + * fr.po: Updated French translation. + +2004-02-24 Alastair McKinstry + + * ga.po: Updated Irish translation. + +2004-02-24 Ole Laursen + + * da.po: Updated Danish translation. + +2004-02-25 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-02-24 Guntupalli Karunakar + + * hi.po: Updated Hindi translation. + +2004-02-24 Paolo Maggi + + [ gedit 2.5.90 released ] + +2004-02-23 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-02-22 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2004-02-22 Mətin Əmirov + + * az.po: Updated Azerbaijani translation. + +2004-02-22 Kostas Papadimas + + * el.po: Updated Greek translation. + +2003-02-22 Christian Neumair + + * POTFILES.skip: Added missing file. + * de.po: Updated German translation. + +2004-02-21 Paisa Seeluangsawat + + * th.po: Updated Thai translation by Supakorn Siddhichai, + Supranee Thirawatthanasuk, and Chanchai Junlouchai. + +2004-02-21 Jarkko Ranta + + * fi.po: Added plural header to Finnish translation. + +2004-02-21 Christian Rose + + * en_CA.po: Added Canadian English translation by + Adam Weinberger . + +2004-02-21 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2004-02-20 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-02-20 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-02-20 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-02-20 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2004-02-20 Christian Rose + + * sv.po: Updated Swedish translation. + +2004-02-20 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-02-19 Ole Laursen + + * da.po: Updated Danish translation. + +2004-02-19 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-02-17 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2004-02-15 Christian Rose + + * POTFILES.skip: Removed non-existant files. + * sv.po: Updated Swedish translation. + +2004-02-15 Mətin Əmirov + + * az.po: Translation updated. + +2004-02-15 Yukihiro Nakai + + * ja.po: Fix wrong translations. + +2004-02-13 Kostas Papadimas + + * el.po: Updated Greek translation + +2004-02-13 Kostas Papadimas + + * el.po: Updated Greek translation. + +2004-02-12 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2004-02-09 Christian Rose + + * mi.po: Updated Maori translation by + John C Barstow . + +2004-02-05 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-02-04 Robert Sedak + + * hr.po: Updated Croatian translation. + +2004-02-02 Alastair McKinstry + + * ga.po: Updated Irish translation. + +2004-02-01 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-01-31 Mətin Əmirov + + * az.po: Translation updated. + +2004-01-31 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-01-30 Christian Rose + + * mi.po: Updated Maori translation by + John C Barstow . + +2004-01-28 Miloslav Trmac + + * cs.po: Fixed Czech translation. + +2004-01-27 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-01-27 Christian Rose + + * mi.po: Added Maori translation by + John C Barstow . + +2004-01-27 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2004-01-26 Kostas Papadimas + + * el.po: Updated Greek translation. + +2004-01-25 Sanlig Badral + + * mn.po: Updated Mongolian translation. + +2004-01-24 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-01-21 Vincent van Adrighem + + * nl.po: Translation updated by Kees van den Broek. + +2004-01-21 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-01-20 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-01-18 Gustavo Maciel Dias Vieira + + * pt_BR.po: Updated Brazilian Portuguese translation done by Joao + Emanuel . + +2004-01-18 Christophe Merlet + + * fr.po: Updated French translation. + +2004-01-17 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-01-16 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-01-15 Paolo Maggi + + [ gedit 2.5.3 released ] + +2004-01-15 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-01-14 Alastair McKinstry + + * ga.po: Updated Irish translation. + +2004-01-14 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-01-13 Christian Neumair + + * de.po: Updated German translation. + +2004-01-13 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2004-01-13 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-01-13 Vincent van Adrighem + + * nl.po: Translation updated by Kees van den Broek. + +2004-01-13 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-01-13 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-01-13 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + + * POTFILES.in: Added missing files. + +2004-01-12 Sanlig Badral + + * mn.po: Updated Mongolian translation. + +2004-01-10 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004.01.10 Arafat Medini + + * ar.po: Updated faulty Arabic translation + +2004.01.09 Arafat Medini + + * ar.po: Updated Arabic translation + +2003-01-06 Christian Neumair + + * de.po: Updated German translation. + +2004-01-06 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-01-05 Jarkko Ranta + + * fi.po: Updated Finnish Translation. + +2004-01-05 Pól Ó Dubhthaigh + + * ga.po: Updated Irish Translation. + +2004-01-04 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-01-03 Christophe Merlet + + * fr.po: Updated French translation from + Sebastien Bacher . + +2004-01-03 Robert Sedak + + * hr.po: Updated Croatian translation. + +2004-01-02 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2004-01-01 Duarte Loreto + + * pt.po: Updated and revised Portuguese translation. + +2004-01-01 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. Plural forms added + +2004-01-01 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-12-31 Paul Duffy + + * ga.po: Updated Irish translation + +2003-12-31 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2003-12-30 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-12-30 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-12-20 Christian Neumair + + * POTFILES.skip: Added missing file. + * de.po: Updated German translation (inter alia #127055). + +2003-12-17 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation by + Vaidotas Zemlys . + +2003-12-14 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2003-12-03 Sanlig Badral + + * mn.po: Updated Mongolian translation. + +2003-11-29 Danilo Šegan + + * sr.po, sr@Latn.po: More bugs fixed. + +2003-11-29 Danilo Šegan + + * sr.po, sr@Latn.po: Fixed bug #16 from Prevod.org. + +2003-11-28 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-11-20 Ole Laursen + + * da.po: Updated Danish translation. + +2003-11-12 Kostas Papadimas + + * el.po: Updated Greek translation. + +2003-11-07 Christian Rose + + * ne.po: Updated Nepali translation by + Pawan Chitrakar . + +2003-11-04 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-10-30 Kostas Papadimas + + * el.po: Updated Greek translation + +2003-10-30 KAMAGASAKO Masatoshi + + * ja.po: Updated Japanese translation. + +2003-10-28 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2003-10-28 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-10-26 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-10-26 Christian Rose + + * sv.po: Fix accidental mistranslation of "Tabs". + +2003-10-25 Metin Amiroff + + * az.po: Updated Azerbaijani translation. + +2003-10-10 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2003-10-04 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + + * POTFILES.skip: Removed data/GNOME_Gedit.server.in. + +2003-09-29 Gustavo Maciel Dias Vieira + + * pt_BR.po: Applied revision by Augusta Marques da Silva + . + +2003-09-23 Yogeesh MB + + * kn.po: Updated Kannada translation + +2003-09-21 Metin Amiroff + + * az.po: Updated Azerbaijani file + +2003-09-13 Alessio Frusciante + + * it.po: Updated Italian translation by + Roberto Rosselli Del Turco + +2003-09-10 Pablo Saratxaga + + * wa.po: Updated Walloon file + +2003-09-09 Paolo Maggi + + [ gedit 2.4.0 released ] + +2003-09-08 Gustavo Noronha Silva + + * pt_BR.po: updated translation. + +2003-09-07 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2003-09-06 Mugurel Tudor + + * ro.po: Updated Romanian translation + by Mişu Moldovan + +2003-09-06 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2003-09-06 Laurent Dhima + + * sq.po: Added Albanian translation. + +2003-09-05 Taneem Ahmed + + * bn.po: Added Bangla translation by Santanu + of Ankur group . + +2003-09-05 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2003-09-03 Jarkko Ranta + + * fi.po: Updated Finnish translation again. + +2003-09-03 Guntupalli Karunakar + + * hi.po: Updated Hindi translation. + +2003-09-02 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2003-08-31 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-08-30 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-08-30 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-08-29 Guntupalli Karunakar + + * hi.po: Updated Hindi translations. + +2003-08-29 Alessio Frusciante + + * it.po: Updated Italian translation by + Roberto Rosselli Del Turco. + +2003-08-28 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2003-08-27 Pablo Gonzalo del Campo + + * es.po: Revision of Spanish translation by + Francisco Javier F. Serrador . + +2003-08-27 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2003-08-27 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2003-08-27 Vincent van Adrighem + + * nl.po: Dutch translation updated by Kees van den Broek. + +2003-08-27 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2003-08-24 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-08-24 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2003-08-24 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-08-24 Artur Flinta + + * pl.po: Updated Polish translation. + +2003-08-23 Ole Laursen + + * da.po: Updated Danish translation. + +2003-08-23 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-08-23 Kjartan Maraas + + * no.po: Update Norwegian translation. + +2003-08-23 Metin Amiroff + + * az.po: Updated Azerbaijani translation. + +2003-08-23 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2003-08-19 Jarkko Ranta + + * fi.po: Updated Finnish translation + +2003-08-19 Danilo Šegan + + * be.po: Updated Belarusian translation by Ales Nyakhaychyk + . + +2003-08-19 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-08-18 Metin Amiroff + + * az.po: Updated Azerbaijani translation. + +2003-08-17 Christophe Merlet + + * fr.po: Updated French translation. + +2003-08-11 Christian Rose + + * ne.po: Added Nepali translation by Pawan . + +2003-08-08 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-08-08 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2003-08-08 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-08-07 Yanko Kaneti + + * bg.po: Updated Bulgarian translation by Evgeni Boevski. + +2003-08-07 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-08-06 Metin Amiroff + + * az.po: Updated Azerbaijani translation. + +2003-08-04 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-07-28 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2003-07-25 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2003-07-24 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-07-22 Wang Jian + + * zh_CN.po: Updated Simplified Chinese translation by + Funda Wang . + +2003-07-19 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-07-18 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2003-07-17 Vincent van Adrighem + + * nl.po: Dutch translation updated by Kees van den Broek. + +2003-07-15 Gil "Dolfin" Osher + + * he.po: Updated Hebrew translation. + +2003-07-12 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2003-07-12 Artur Flinta + + * pl.po: Updated Polish translation. + +2003-07-09 Artur Flinta + + * pl.po: Updated Polish translation. + +2003-07-09 Paul Duffy + + * ga.po: Updated Irish translation. + +2003-07-08 Nikos Charonitakis + + * el.po: Updated Greek translation + +2003-07-08 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-07-07 Vincent van Adrighem + + * nl.po: Dutch translation updated by Kees van den Broek. + +2003-07-06 Kostas Papadimas + + * el.po: Updated Greek translation + +2003-07-04 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2003-07-03 Valek Filippov + + * ru.po: Updated russian translation. + +2003-07-03 Yanko Kaneti + + * bg.po: Updated Bulgarian translation by Evgeni Boevski. + +2003-06-30 Pauli Virtanen + + * fi.po: Set translator_credits. + +2003-06-28 Christian Neumair + + * POTFILES.skip: Added missing file. + * de.po: Updated German translation. + +2003-06-23 Vincent van Adrighem + + * nl.po: Dutch translation updated by Kees van den Broek. + +2003-06-20 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-06-19 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2003-06-16 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-06-16 Dmitry G. Mastrukov + + * ru.po: Updated Russian translation + from Russian team . + +2003-06-14 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-06-14 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-06-13 Abel Cheung + + * POTFILES.in: Added gedit/dialogs/gedit-page-setup-dialog.c, + gedit/dialogs/page-setup-dialog.glade2. + +2003-06-12 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2003-06-12 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-06-12 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-06-11 Abel Cheung + + * POTFILES.in: data/GNOME_Gedit.server.in -> .in.in + +2003-06-04 Abel Cheung + + * ta.po: Fix broken encoding. + +2003-06-04 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-06-04 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-06-04 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-06-04 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-06-03 Paolo Maggi + + * POTFILE.in: re-added indent, sort, shell_output and taglist + plugins + +2003-05-31 Dafydd Harries + + * cy.po: New translations, corrections. + +2003-05-30 Telsa Gwynne + + * cy.po: updated Welsh translations from + Dafydd Harries + +2003-05-29 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation + from David Barzilay . + +2003-05-29 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-05-28 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2003-05-28 Telsa Gwynne + + * cy.po: Missing accents restored ('copio' to 'cop?¯o) + +2003-05-27 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-05-27 Abel Cheung + + * POTFILES.in: Added gedit/gedit-encodings-option-menu.c + +2003-05-26 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation by + Francisco Javier F. Serrador + +2003-05-26 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2003-05-26 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2003-05-25 Kostas Papadimas + + * el.po: Updated Greek translation + +2003-05-23 Paul Duffy + + * ga.po: Updated Irish translation. + +2003-05-23 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-05-23 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-05-21 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-05-21 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-05-21 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-05-19 Ole Laursen + + * da.po: Updated Danish translation. + +2003-05-19 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2003-05-16 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2003-05-14 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-05-14 KAMAGASAKO Masatoshi + + * ja.po: Updated Japanese translation. + +2003-05-14 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-05-13 KAMAGASAKO Masatoshi + + * ja.po: Updated Japanese translation. + +2003-05-13 Paul Duffy + + * ga.po: Updated Irish Translation + +2003-05-13 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-05-13 Abel Cheung + + * POTFILES.skip: Remove non-existant file(s). + +2003-05-13 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + * cy.po: Fix header (msgfmt check failed). + +2003-05-12 Paolo Maggi + + * POTFILES.in: added missing files + +2003-05-11 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2003-05-11 Christophe Merlet + + * fr.po: Updated French translation. + +2003-05-09 Jordi Mallach + + * ca.po: Fixed Catalan translation by Jordi Mas. + +2003-05-08 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-05-07 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-05-06 Danilo ? egan + + * sr.po, sr@Latn.po: Added Serbian translation by + http://Prevod.org/. + +2003-04-29 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-04-16 Jordi Mallach + + * POTFILES.in: remove gedit/gedit-undo-manager.c. + +2003-04-11 Paul Duffy + + * ga.po: Updated Irish translation. + +2003-03-25 Metin Amiroff + + * az.po: Updated Azerbaijani translaion. + +2003-03-13 Christian Rose + + * ml.po: Added Malayalam translation by + FSF-India . + +2003-03-08 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-03-05 Dmitry G. Mastrukov + + * be.po: Updated Belarusian translation + from Belarusian team . + +2003-03-04 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2003-02-22 Roozbeh Pournader + + * fa.po: Added Persian translation. + +2003-02-21 Dmitry G. Mastrukov + + * be.po: Updated Belarusian translation + from Belarusian team . + +2003-02-09 Christian Rose + + * kn.po: Added Kannada translation by + Pramod . + +2003-02-07 Fatih Demir + + * tr.po: Committed updated Turkish translation by Erkan. + +2003-02-05 Gediminas Paulauskas + + * lt.po: Updated Lithuanian translation from Vaidotas Zemlys. + +2003-02-04 Fatih Demir + + * tr.po: Committed updated Turkish translation by Erkan. + +2003-02-03 Daniel Yacob + + * am.po: Updated Amharic translation. + +2003-01-30 Marius Andreiana + + * ro.po: updated ( thanks to Mugurel Tudor ) + +2003-01-30 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-01-28 Daniel Yacob + + * am.po: Updated Amharic translation. + +2003-01-28 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2003-01-27 Gil "Dolfin" Osher + + * he.po: Updated Hebrew translation. + +2003-01-26 T??µivo Leedj?€rv + + * et.po: Updated Estonian translation. + +2003-01-26 Christophe Merlet + + * fr.po: Updated French translation from + Yann Laviolette . + +2003-01-26 Kang Jeong-Hee + + * ko.po: Updated Korean translation. + +2003-01-26 Alessio Frusciante + + * it.po: Updated Italian translation by + Roberto Rosselli Del Turco. + +2003-01-26 Christian Rose + + * sv.po: Some fixes for problems catched in translation review. + +2003-01-24 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2003-01-23 He Qiangqiang + + * zh_CN.po: Fixed some translation. + +2003-01-23 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-01-22 Fatih Demir + + * tr.po: Committed updated Turkish translation by Barbaros. + +2003-01-22 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-01-22 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2003-01-21 Christian Rose + + * mn.po: Added Mongolian translation by + Sanlig Badral . + +2003-01-21 Christian Neumair + + * de.po: Updated German translation. + +2003-01-21 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2003-01-20 Marius Andreiana + + * ro.po: updated ( thanks to Mugurel Tudor ) + +2003-01-20 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2003-01-20 Christian Neumair + + * de.po: Updated German translation. + +2003-01-19 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2003-01-19 Fatih Demir + + * tr.po: Committed "updated" Turkish translation. + +2003-01-18 He Qiangqiang + + * zh_CN.po: Updated Simplified Chinese translation by + Funda Wang . + +2003-01-14 Daniel Yacob + + * am.po: Updated Amharic translation. + +2003-01-12 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2003-01-11 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2003-01-09 Daniel Yacob + + * am.po: Updated Amharic translation. + +2003-01-08 Kang Jeong-Hee + + * ko.po: Updated Korean translation by Young-Ho, Cha. + +2003-01-07 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2003-01-07 Daniel Yacob + + * am.po: Updated Amharic translation. + +2003-01-06 Gil 'Dolfin' Osher + + * he.po: Added Hebrew translation. + +2003-01-06 Yanko Kaneti + + * bg.po: Updated Bulgarian translation by Evgeni Boevski. + +2003-01-06 Kostas Papadimas + + * el.po: Updated Greek translation + +2003-01-05 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + * am.po: enabled header + * hi.po: fixed syntax errors + +2003-01-04 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-01-04 Benjamin Greiner + + * de.po: Minor fixes and completions + +2003-01-04 Christian Neumair + + * de.po: Updated German translation. + +2003-01-03 Ole Laursen + + * da.po: Updated Danish translation. + +2003-01-03 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-01-02 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-01-03 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2002-12-30 Artis Trops + + * lv.po: Updated Latvian translation. + +2002-12-30 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-30 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2002-12-30 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-12-29 Paolo Maggi + + * it.po: Updated Italian translation. + +2002-12-29 Paolo Maggi + + * POTFILES.in: updated + +2002-12-27 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2002-12-27 Artis Trops + + * lv.po: Updated Latvian translation. + +2002-12-27 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-12-26 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-12-26 Ole Laursen + + * da.po: Updated Danish translation. + +2002-12-19 Andras Timar + + * hu.po: Updated Hungarian translation. + +2002-12-19 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2002-12-17 Christian Neumair + + * de.po: Updated German translation. + +2002-12-17 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-17 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-12-15 Christian Neumair + + * de.po: Updated German translation. + +2002-12-15 Ole Laursen + + * da.po: Updated Danish translation. + +2002-12-13 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-11 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-12-10 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-12-07 Ole Laursen + + * da.po: Updated Danish translation. + +2002-12-07 He Qiangqiang + + * zh_CN.po: sync with gnome-2-0 branch. + +2002-12-05 Ole Laursen + + * da.po: Partial update of the Danish translation. + +2002-12-05 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-04 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2002-12-04 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-12-02 Kostas Papadimas + + * el.po: Updated Greek translation. + +2002-11-30 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2002-11-29 Christian Neumair + + * de.po: Updated German translation. + +2002-11-28 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-11-27 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-11-27 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-11-25 Vincent van Adrighem + + * nl.po: Massive copy-paste from stable branch. + +2002-11-25 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2002-11-25 Pablo Gonzalo del Campo + + es.po: Updated Spanish translation. + +2002-11-25 Pablo Gonzalo del Campo + + es.po: Updated Spanish translation. + +2002-11-25 Yanko Kaneti + + * *.po: Convert all to UTF-8. + +2002-11-22 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2002-11-22 Fatih Demir + + * tr.po: Put back the _real_ Turkish translation... + +2002-11-21 Paolo Maggi + + * POTFILES.in: + * POTFILES.skip: updated + +2002-11-15 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2002-11-12 Dmitry G. Mastrukov + + * be.po: fixed Belarusian translation + +2002-11-12 Dmitry G. Mastrukov + + * be.po: Updated Belarusian translation + * from Belarusian team . + +2002-11-12 Kjartan Maraas + + * be.po: Change charset= to CP1251 to make it build. Please + fix this correctly by converting the file to UTF-8. + +2002-11-11 Dmitry G. Mastrukov + + * be.po: Updated Belarusian translation + * from Belarusian team . + +2002-11-09 Dmitry G. Mastrukov + + * be.po: Updated Belarusian translation + * from Belarusian team . + +2002-11-09 Dmitry G. Mastrukov + + * be.po: Updated Belarusian translation + * from Belarusian team . + +2002-11-01 Paolo Maggi + + * POTFILES.in: + * POTFILES.skip: updated + +2002-10-30 Andras Timar + + * hu.po: Terminology fix. + +2002-10-27 Andras Timar + + * hu.po: Updated Hungarian translation. + +2002-10-15 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2002-10-14 Paolo Maggi + + * POTFILES.in: added a lot of new files + +2002-10-01 jacob berkman + + * POTFILES.in: fix recent views file + +2002-09-25 Christophe Merlet + + * fr.po: Updated French translation from + Kouran . + +2002-09-20 Marius Andreiana + + * ro.po: updated ( printeaza -> tipareste ) + +2002-09-18 Marius Andreiana + + * ro.po: updated + +2002-09-01 Marius Andreiana + + * ro.po: updated ( thanks to Mugurel Tudor ) + +2002-08-29 Marius Andreiana + + * ro.po: added ( thanks to Mugurel Tudor ) + +2002-08-29 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2002-08-27 Duarte Loreto + + * pt.po: Updated Portuguese translation after typo fix. + +2002-08-26 Duarte Loreto + + * pt.po: Done Quality Review of Portuguese translation. + +2002-08-26 Pablo Saratxaga + + * wa.po: Updated Walloon file + +2002-08-23 Peteris Krisjanis + + * lv.po: Updated Latvian translation by + Artis Trops + +2002-08-21 Pablo del Campo + + * es.po: Updated Spanish Translation. + +2002-08-21 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2002-08-21 Andras Timar + + * hu.po: Updated Hungarian translation. + +2002-08-21 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-08-20 Peteris Krisjanis + + * lv.po: Updated Latvian translation. + +2002-08-19 Ole Laursen + + * da.po: Updated Danish translation. + +2002-08-19 Yanko Kaneti + + * bg.po: Updated Bulgarian translation. + +2002-08-19 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-08-19 Gustavo Noronha Silva + + * pt_BR.po: translation update + +2002-08-19 Akira TAGOH + + * ja.po: Updated Japanese translation. + +2002-08-18 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-08-18 T???µivo Leedj??¢?‚?¬rv + + * et.po: Updated Estonian translation. + +2002-08-18 He Qiangqiang + + * zh_CN.po: Merged with Sun Gl0n's translation. + +2002-08-18 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-08-17 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-08-16 Manuel Borchers + + * de.po: Updated German translation. + +2002-08-17 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha + . + +2002-08-16 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-08-16 Dmitry G. Mastrukov + + * ru.po: updated Russian translation. + +2002-08-15 Ole Laursen + + * da.po: Updated Danish translation. + +2002-08-15 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2002-08-15 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-08-14 Christian Meyer + + * de.po: Fixed some mnemonics. + +2002-08-14 Christian Neumair + + * de.po: Updated German translation. + +2002-08-14 Andras Timar + + * hu.po: Updated Hungarian translation. + +2002-08-14 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-08-13 Andras Timar + + * hu.po: Updated Hungarian translation. + +2002-08-12 Gustavo Noronha Silva + + * pt_BR: finished updating + +2002-08-11 Christian Neumair + + * de.po: Updated German translation + by Jan Arne Petersen + +2002-08-10 Gustavo Noronha Silva + + * pt_BR: updated partially, will finish asap + +2002-08-09 Christian Meyer + + * de.po: Updated German translation, fixed typos, ... + +2002-08-08 Vincent van Adrighem + + * nl.po: Dutch translation updated by Taco Witte. + +2002-08-07 Manuel Borchers + + * de.po: Updated German translation. + +2002-08-07 Stanislav Brabec + + * cs.po: Updated Czech translation from Michal Bukovjan + . + +2002-08-06 Peteris Krisjanis + + * lv.po: Updated Latvian translation. + +2002-08-05 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-08-04 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2002-08-03 T???µivo Leedj??¢?‚?¬rv + + * et.po: Updated Estonian translation. + +2002-07-31 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-07-29 Fatih Demir + + * tr.po: Committed updated Turkish translation. + +2002-07-26 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2002-07-26 Dmitry G. Mastrukov + + * ru.po: updated Russian translation. + +2002-07-23 Pablo del Campo + + * es.po: Updated Spanish Translation. + +2002-07-23 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-07-23 Yanko Kaneti + + * bg.po: Updated Bulgarian translation. + +2002-07-23 Ole Laursen + + * da.po: Updated Danish translation. + +2002-07-23 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-07-22 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-22 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2002-07-22 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2002-07-22 Changwoo Ryu + + * ko.po: Updated Korean translation from Young-Ho Cha + . + +2002-07-21 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-07-19 Pablo del Campo + + * es.po: Updated Spanish Translation. + +2002-07-19 Ole Laursen + + * da.po: Updated Danish translation. + +2002-07-19 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-07-18 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-07-18 Vincent van Adrighem + + * nl.po: Dutch translation updated (minor update). + +2002-07-17 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-16 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-16 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-16 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-07-16 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2002-07-15 Ole Laursen + + * da.po: Updated Danish translation. + +2002-07-15 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-15 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-07-15 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2002-07-14 Peteris Krisjanis + + * lv.po: Updated Latvian translation. + +2002-07-13 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-13 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2002-07-13 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-07-12 Pablo Gonzalo del Campo + + * es.po: Updated Spanish Translation. + +2002-07-11 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2002-07-11 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-09 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-07-09 Christian Rose + + * POTFILES.in: Added missing file. + * sv.po: Updated Swedish translation. + +2002-07-09 Jacob Berkman + + * POTFILES.in: remove a missing file + +2002-07-09 Dmitry G. Mastrukov + + * POTFILES.in: Fixed location of .in files (now in /data), + changed gedit.shemas to gedit.schemas.in. + +2002-07-09 Akira TAGOH + + * ja.po: Updated Japanese translation. + +2002-07-08 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-07-05 Christian Rose + + * POTFILES.in: Removed non-existing file, added missing file. + * sv.po: Updated Swedish translation. + +2002-07-05 jacob berkman + + * POTFILES.in: replace gedit-prefs.c with gedit-prefs-manager.c + +2002-07-05 Christophe Fergeau + + * fr.po: Updated French translation + +2002-07-02 Manuel Borchers + + * de.po: Updated German translation after merge. + +2002-07-02 Dmitry G. Mastrukov + + * ru.po: updated Russian translation. + +2002-06-30 Manuel Borchers + + * de.po: Updated German translation + +2002-06-23 Christophe Fergeau + + * fr.po: Updated French translation + +2002-06-22 Christophe Fergeau + + * fr.po: Updated French translation + +2002-06-21 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-06-17 Daniel Yacob + + * am.po: Updated Amharic translation. + +2002-06-16 Daniel Yacob + + * am.po: New file for Amharic translation. + +2002-06-16 Akira TAGOH + + * ja.po: Updated Japanese translation. + +2002-06-10 Naba Kumar + + * hi.po: Added new hindi translation. + +2002-06-09 Dmitry G. Mastrukov + + * ru.po: updated Russian translation. + +2002-06-08 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2002-06-08 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-06-05 Christian Rose + + * sv.po: Fix. + +2002-06-04 T???µivo Leedj??¢?‚?¬rv + + * et.po: Updated Estonian translation. + +2002-06-04 Vincent van Adrighem + + * nl.po: Dutch translation updated by Reinout van Schouwen. + +2002-06-04 Germ??n Poo Caama???±o + + * es.po: Updated Spanish translation. + +Mon Jun 03 15:01:20 2002 George Lebl + + * cs.po: update + +2002-06-03 Carlos Perell???³ Mar???­n + + * es.po: Small fixes. + +2002-06-03 Jarkko Ranta + + * fi.po: Updated FInnish translation. + +2002-06-03 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2002-06-02 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2002-06-02 Christian Rose + + * sv.po: Small fix. + +2002-06-02 Christian Rose + + * sv.po: Small fix. + +2002-05-31 Pablo Gonzalo del Campo + + * es.po: Updated Spanish Translation. + +2002-05-31 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-05-29 Ole Laursen + + * da.po: Updated Danish translation. + +2002-05-29 Duarte Loreto + + * pt.po: Updated Portuguese translation + +2002-05-28 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-05-28 Yanko Kaneti + + * bg.po: Updated Bulgarian translation (100%) + by Evgeni Boevski and me. + +2002-05-27 Yanko Kaneti + + * bg.po: Updated Bulgarian translation + by Evgeni Boevski . + +2002-05-27 Jacob Berkman + + * POTFILES.in: fixup + +2002-05-27 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-05-27 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-05-27 Yanko Kaneti + + * bg.po (added): New Bulgarian translation + by Evgeni Boevski . + +2002-05-23 Pablo Gonzalo del Campo + + * es.po: Updated Spanish Translation. + +2002-05-23 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-05-22 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-05-20 Vincent van Adrighem + + * nl.po: Dutch translation updated by Sander Knopper. + +2002-05-19 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-05-17 Pablo del Campo + + * es.po: Updated Spanish Translation. + +2002-05-16 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-05-16 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-05-16 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-05-14 Fatih Demir + + * ta.po: Committed updated Tamil translation by Dinesh. + +2002-05-14 Abel Cheung + + * POTFILES.in: Synced with source tree. + * zh_TW.po: Updated traditional Chinese translation. + +2002-05-13 Pablo Saratxaga + + * ca.po: Updated Catalan file + +2002-05-11 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-05-08 Carlos Perello Marin + + * es.po: Fixed translation credits. + +2002-05-08 Pablo Saratxaga + + * eu.po,vi.po: Added Basque and Vietnamese files + * wa.po: Updated Walloon file + +2002-05-08 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-03-07 Germ??n Poo-Caama???±o + + * es.po: Updated spanish translation from + Pablo del Campo + +2002-05-07 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-05-06 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-04-30 Fatih Demir + + * ta.po: Committed updated Tamil translation by Dinesh. + +2002-04-30 Duarte Loreto + + * pt.po: Updated Portuguese translation and converted to UTF-8. + +2002-04-29 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-04-26 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha + . + +2002-04-26 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2002-04-23 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-04-22 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2002-04-20 Paolo Maggi + + * it.po: Updated italian translation by Alessio Frusciante + +2002-04-20 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2002-04-18 Vincent van Adrighem + + * nl.po: Updated Dutch translation by Ronald Hummelink. + +2002-04-15 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-03-13 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-04-12 Abel Cheung + + * .cvsignore: Added some file(s). + * zh_TW.po: Updated traditional Chinese translation. + +2002-04-10 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-04-08 Fatih Demir + + * ta.po: Committed updated Tamil translation by Dinesh. + +2002-04-05 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-03-30 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-03-26 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-03-28 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-03-28 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2002-03-27 Jarkko Ranta + + * fi.po: Fixed broken fi.po (i hope). + +2002-03-27 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2002-03-27 Christian Rose + + * POTFILES.in: Added missing files. + * sv.po: Updated Swedish translation. + +2002-03-26 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-03-25 jacob berkman + + * fi.po: rever commit which broke the build + +2002-03-25 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2002-03-24 T???µivo Leedj??¢?‚?¬rv + + * et.po: Updated Estonian translation. + +2002-03-24 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-03-21 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-03-17 Valek Filippov + + * ru.po: Updated russian translation. + +2002-03-17 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-03-17 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-03-16 Christian Meyer + + * de.po: Updated German translation. + +2002-03-15 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-03-14 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-03-13 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2002-03-12 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-03-10 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-03-09 Matthias Warkus + + * de.po: Updated German translation. Phew. + +2002-03-06 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2002-03-06 Germ??n Poo-Caama???±o + + * es.po: Updated spanish translation from + Pablo del Campo + +2002-03-06 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-03-06 Vincent van Adrighem + + * nl.po: Updated Dutch translation (by Ronald Bultje). + +2002-03-05 Christian Rose + + * sv.po: Fixed Swedish translation. + +2002-03-05 Valek Filippov + + * ru.po: Updated russian translation. + +2002-03-05 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-03-04 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-03-04 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-03-04 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-03-04 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-03-04 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-03-03 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-02-27 Miles Lane + + * it.po: Readded it.po. D'uh. I only needed to remove + the configure.in entry. + +2002-02-27 Miles Lane + + * it.po: Removed the Italian translation. This version + is breaking the build. + +2002-02-27 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-02-27 Paolo Maggi + + * it.po: Updated Italian translation. + +2002-02-27 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-02-25 Valek Filippov + + * ru.po: Updated russian translation. + +2002-02-23 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-02-22 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-02-21 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-02-21 jacob berkman + + * POTFILES.in: it's gedit.desktop.in now + +2002-02-21 Fatih Demir + + * tr.po: Committed updated Turkish translation by Nilg???’n. + +2002-02-20 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-02-19 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-02-18 Paolo Maggi + + * POTFILES.in: added *.glade2 files + +2002-02-17 Vincent van Adrighem + + * nl.po: New Dutch translation made + by Jan-Willem Harmanny. + +2002-02-14 T???µivo Leedj??¢?‚?¬rv + + * et.po: Added Estonian translation + by Ilmar Kerm . + +2002-02-14 Paolo Maggi + + * POTFILES.in: added ascii.c + * POTFILES.skip: removed ascii.c + +2002-02-10 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-02-10 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-02-08 Paolo Maggi + + * POTFILES.in: added diff.c + * POTFILES.skip: removed diff.c + +2002-02-07 Paolo Maggi + + * POTFILES.in: added files related to the new + taglist plugin + * gedit-2.0.pot: Updated + +2002-02-06 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-02-05 Paolo Maggi + + * gedit-2.0.pot: Updated + +2002-02-03 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-01-30 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-01-29 Jarkko Ranta + + * fi.po: Updated Finnish translation. + +2002-01-28 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-01-28 Christian Rose + + * sv.po: Updated and converted to UTF-8. + +2002-01-27 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-01-26 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + +2002-01-24 Paolo Maggi + + * POTFILES.in: added plugins/shell_output/shell_output.c + * POTFILES.skip: removed plugins/shell_output/shell_output.c + +2002-01-23 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2002-01-22 Paolo Maggi + + * POTFILES.in: added plugins/cvschangelog/cvschangelog.c, + plugins/time/time.c and src/dialogs/gedit-dialog-plugin-manager.c + * POTFILES.skip: removed plugins/cvschangelog/cvschangelog.c + and plugins/time/time.c + +2002-01-22 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-01-18 Paolo Maggi + + * POTFILES.in: added plugins/docinfo/docinfo.c + + * POTFILES.skip: removed plugins/docinfo/docinfo.c + +2002-01-18 Paolo Maggi + + * POTFILES.in: added plugins/sample/sample.c + * POTFILES.skip: removed plugins/sample/sample.c + +2002-01-17 Hasbullah Bin Pit + + * ms.po: Added Malay translation. + +2002-01-17 Christian Rose + + * POTFILES.in: Added a missing file. + * sv.po: Updated Swedish translation. + +2002-01-16 Peteris Krisjanis + + * lv.po: Added Latvian translation. + +2002-01-15 Paolo Maggi + + * POTFILES.skip: created + +2002-01-14 Paolo Maggi + + * POTFILES.in: Removed unused files (i.e. plugins/*) + * it.po: Updated Italian translation. + +2002-01-13 Kjartan Maraas + + * no.po: Updated Norwegian (bokm???¥l) translation. + * POTFILES.in: Removed a missing file. + +2002-01-13 Christian Rose + + * POTFILES.in: Sorted and added LOTS of missing files. + * sv.po: Updated Swedish translation. + +2002-01-11 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-01-04 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2001-12-31 Valek Filippov + + * ru.po: Updated russian translation. + +2001-12-29 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2001-12-27 Jesus Bravo Alvarez + + * gl.po: Updated Galician translation from + Manuel A. Fernandez Montecelo + +2001-12-19 Christian Rose + + * sv.po: Updated Swedish translation. + +2001-12-15 Christian Rose + + * sv.po: Updated Swedish translation. + +2001-12-13 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2001-12-11 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2001-12-09 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation, and + converted to UTF-8. + +2001-12-08 Christian Rose + + * sv.po: Updated Swedish translation. + +2001-12-04 Yuriy Syrota + + * uk.po: Updated Ukrainian translation. + +2001-12-03 Christian Rose + + * sv.po: Updated Swedish translation. + +2001-11-27 Pablo Saratxaga + + * az.po: Updated Azeri file + * ja.po: corrected syntax error + +2001-11-18 Valek Filippov + + * ru.po: Updated russian translation. + +2001-11-16 Carlos Perell???³ Mar???­n + + * POTFILES.in: Updated. + +2001-11-16 Carlos Perell???³ Mar???­n + + * ChangeLog: rolled over to ChangeLog-20011116. + +2001-11-16 Kostas Papadimas + + * el.po: Updated Greek translation diff --git a/po/POTFILES.in b/po/POTFILES.in index 8526faf4..c8a7b702 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,83 +1,78 @@ # List of source files containing translatable strings. # Please keep this file sorted alphabetically. -data/GNOME_Gedit.server.in.in +[encoding: UTF-8] data/gedit.desktop.in.in data/gedit.keys.in data/gedit.schemas.in -gedit/bonobo-mdi-child.c -gedit/bonobo-mdi.c gedit/dialogs/gedit-close-confirmation-dialog.c -gedit/dialogs/gedit-dialog-goto-line.c -gedit/dialogs/gedit-dialog-replace.c -gedit/dialogs/gedit-dialog-uri.c gedit/dialogs/gedit-encodings-dialog.c -gedit/dialogs/gedit-encodings-dialog.glade2 +gedit/dialogs/gedit-encodings-dialog.glade +gedit/dialogs/gedit-open-location-dialog.c +gedit/dialogs/gedit-open-location-dialog.glade gedit/dialogs/gedit-page-setup-dialog.c -gedit/dialogs/gedit-plugin-manager.c -gedit/dialogs/gedit-plugin-program-location-dialog.c +gedit/dialogs/gedit-page-setup-dialog.glade gedit/dialogs/gedit-preferences-dialog.c -gedit/dialogs/gedit-preferences.glade2 -gedit/dialogs/goto-line.glade2 -gedit/dialogs/page-setup-dialog.glade2 -gedit/dialogs/plugin-manager.glade2 -gedit/dialogs/program-location-dialog.glade2 -gedit/dialogs/replace.glade2 -gedit/dialogs/uri.glade2 -gedit/gedit-commands.c +gedit/dialogs/gedit-preferences-dialog.glade +gedit/dialogs/gedit-search-dialog.c +gedit/dialogs/gedit-search-dialog.glade +gedit/gedit.c +gedit/gedit-commands-file.c +gedit/gedit-commands-help.c +gedit/gedit-commands-search.c +gedit/gedit-convert.c gedit/gedit-debug.c gedit/gedit-document.c -gedit/gedit-encodings-option-menu.c +gedit/gedit-document-saver.c +gedit/gedit-documents-panel.c gedit/gedit-encodings.c -gedit/gedit-file-selector-util.c -gedit/gedit-file.c -gedit/gedit-io-error-dialogs.c -gedit/gedit-mdi-child.c -gedit/gedit-mdi.c -gedit/gedit-menus.c -gedit/gedit-output-window.c +gedit/gedit-encodings-option-menu.c +gedit/gedit-file-chooser-dialog.c +gedit/gedit-help.c +gedit/gedit-io-error-message-area.c +gedit/gedit-notebook.c +gedit/gedit-panel.c +gedit/gedit-plugin-manager.c gedit/gedit-plugins-engine.c gedit/gedit-prefs-manager.c gedit/gedit-print.c +gedit/gedit-print-job-preview.c gedit/gedit-recent.c +gedit/gedit-statusbar.c +gedit/gedit-tab.c +gedit/gedit-ui.h gedit/gedit-ui.xml gedit/gedit-utils.c gedit/gedit-view.c -gedit/gedit2.c -gedit/gedit-convert.c -gedit/recent-files/egg-recent-view-bonobo.c -plugins/changecase/changecase.c +gedit/gedit-window.c +gedit/recent-files/egg-recent-view-gtk.c +gedit/recent-files/egg-recent-view-uimanager.c plugins/changecase/changecase.gedit-plugin.desktop.in -plugins/docinfo/docinfo.c +plugins/changecase/gedit-changecase-plugin.c plugins/docinfo/docinfo.gedit-plugin.desktop.in plugins/docinfo/docinfo.glade2 -plugins/indent/indent.c +plugins/docinfo/gedit-docinfo-plugin.c +plugins/indent/gedit-indent-plugin.c plugins/indent/indent.gedit-plugin.desktop.in -plugins/sample/sample.c +plugins/sample/gedit-sample-plugin.c plugins/sample/sample.gedit-plugin.desktop.in -plugins/savecopy/savecopy.c -plugins/savecopy/savecopy.gedit-plugin.desktop.in -plugins/shell_output/shell_output.c -plugins/shell_output/shell_output.gedit-plugin.desktop.in -plugins/shell_output/shell_output.glade2 -plugins/sort/sort.c +plugins/sort/gedit-sort-plugin.c plugins/sort/sort.gedit-plugin.desktop.in plugins/sort/sort.glade2 plugins/spell/gedit-automatic-spell-checker.c -plugins/spell/gedit-spell-checker-dialog.c plugins/spell/gedit-spell-checker.c +plugins/spell/gedit-spell-checker-dialog.c plugins/spell/gedit-spell-language-dialog.c +plugins/spell/gedit-spell-plugin.c plugins/spell/languages-dialog.glade2 plugins/spell/spell-checker.glade2 -plugins/spell/spell.c plugins/spell/spell.gedit-plugin.desktop.in +plugins/taglist/gedit-taglist-plugin.c +plugins/taglist/gedit-taglist-plugin-panel.c +plugins/taglist/gedit-taglist-plugin-parser.c plugins/taglist/HTML.tags.xml.in plugins/taglist/Latex.tags.xml.in -plugins/taglist/XSLT.tags.xml.in -plugins/taglist/gedit-taglist-plugin-parser.c -plugins/taglist/gedit-taglist-plugin-window.c -plugins/taglist/gedit-taglist-plugin.c plugins/taglist/taglist.gedit-plugin.desktop.in -plugins/time/time.c +plugins/taglist/XSLT.tags.xml.in +plugins/time/gedit-time-plugin.c plugins/time/time.gedit-plugin.desktop.in plugins/time/time.glade2 - diff --git a/tools/generate-plugin.py b/tools/generate-plugin.py new file mode 100755 index 00000000..0a02cff7 --- /dev/null +++ b/tools/generate-plugin.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +import os +import sys +import getopt + +usage = """usage: generate-plugin.py [ options ] plugin-name (words must be separated by '-' )""" + +help = """generate scheleton sources for a gedit plugin. + +Options: + -i, --internal adds the plugin to gedit's configure.ac (TODO) + -t, --type=TYPE specify which kind of plugin generate (defauly barebone) + +types + barebone - generate code for a simple plugin + with-ui - generate code for a plugin which adds menu items and toolbuttons + sidepane - generate code for a plugin which adds a sidepane page (TODO) + +""" + + +# template info + +tmpl_dir = 'plugin_template' + +common_tmpl_files = ( + 'gedit-xyz-plugin.h', + 'xyz.gedit-plugin.desktop.in', + 'Makefile.am', +) + +barebone_tmpl = 'gedit-xyz-plugin.c' +with_ui_tmpl = 'gedit-xyz-plugin.c' +sidepane_tmpl = 'gedit-xyz-plugin.c' + + +def copy_template_file(tmpl_file, replacements): + dest_file = tmpl_file + + for (a, b) in replacements: + dest_file = dest_file.replace(a, b) + + print "generating " + dest_file + " from " + tmpl_file + + dest_dir = os.path.dirname(dest_file) + + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + + r = open(tmpl_file, 'r') + w = open(dest_file, 'w') + + for line in r: + for (a, b) in replacements: + line = line.replace(a, b) + w.write(line) + + r.close() + w.close() + +# --- main --- + +plugin_types = { + 'barebone': barebone_tmpl, + 'with-ui': with_ui_tmpl, + 'sidepane': sidepane_tmpl, +} + +#defaults +internal = False +tmpl_type = barebone_tmpl + +try: + opts, args = getopt.getopt(sys.argv[1:], 'i:t:', ['internal', 'type=', 'help']) +except getopt.error, exc: + sys.stderr.write('gen-plugin: %s\n' % str(exc)) + sys.stderr.write(usage + '\n') + sys.exit(1) + +for opt, arg in opts: + if opt == '--help': + print usage + print help + sys.exit(0) + elif opt in ('-i', '--internal'): + internal = True + elif opt in ('-t', '--type'): + if arg in plugin_types.keys(): + tmpl_type = plugin_types[arg] + else: + sys.stderr.write('invalid type, using barebone\n\n') + +if len(args) != 1: + sys.stderr.write(usage + '\n') + sys.exit(1) + +new_name = args[0] + +replacements = [('plugin_template', new_name.replace('-', '')), + ('libxyz', 'lib' + new_name.replace('-', '')), + ('xyz_', new_name.replace('-', '_') + '_'), + ('Xyz', new_name.title().replace('-', '')), + ('XYZ', new_name.upper().replace('-', '_')), + ('xyz', new_name), +] + +root_path = os.path.dirname(__file__) + +tmpl_paths = [] + +for f in common_tmpl_files: + tmpl_paths.append(os.path.join(root_path, tmpl_dir, f)) + +tmpl_paths.append(os.path.join(root_path, tmpl_dir, tmpl_type)) + +#if internal: +# TODO: edit configure.in +#else +# tmpl_paths.append(os.path.join(root, "configure.in")) + +for f in tmpl_paths: + copy_template_file(f, replacements) + diff --git a/tools/plugin_template/Makefile.am b/tools/plugin_template/Makefile.am new file mode 100644 index 00000000..198fb52c --- /dev/null +++ b/tools/plugin_template/Makefile.am @@ -0,0 +1,34 @@ +# xyz plugin +plugindir = $(libdir)/gedit-2/plugins + +INCLUDES = \ + -I$(top_srcdir) \ + $(GEDIT_CFLAGS) \ + $(WARN_CFLAGS) \ + $(DISABLE_DEPRECATED_CFLAGS) \ + -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" \ + -DGEDIT_GLADEDIR=\""$(datadir)/gedit-2/glade/"\" + +plugin_LTLIBRARIES = libxyz.la + +libxyz_la_SOURCES = \ + gedit-xyz-plugin.h \ + gedit-xyz-plugin.c + +libxyz_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) + +gladedir = $(datadir)/gedit-2/glade +glade_DATA = + +plugin_in_files = xyz.gedit-plugin.desktop.in + +%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache + +plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) + +EXTRA_DIST = $(glade_DATA) $(plugin_in_files) + +CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) + diff --git a/tools/plugin_template/gedit-xyz-plugin.c b/tools/plugin_template/gedit-xyz-plugin.c new file mode 100644 index 00000000..42a34d0d --- /dev/null +++ b/tools/plugin_template/gedit-xyz-plugin.c @@ -0,0 +1,108 @@ +/* + * gedit-xyz-plugin.c + * + * Copyright (C) %YEAR% - %AUTHOR% + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gedit-xyz-plugin.h" + +#include +#include + +#include + +#define GEDIT_XYZ_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_XYZ_PLUGIN, GeditXyzPluginPrivate)) + +struct _GeditXyzPluginPrivate +{ + gpointer dummy; +}; + +GEDIT_PLUGIN_REGISTER_TYPE(GeditXyzPlugin, gedit_xyz_plugin) + +static void +gedit_xyz_plugin_init (GeditXyzPlugin *plugin) +{ + plugin->priv = GEDIT_XYZ_PLUGIN_GET_PRIVATE (plugin); + + gedit_debug_message (DEBUG_PLUGINS, "GeditXyzPlugin initializing"); +} + +static void +gedit_xyz_plugin_finalize (GObject *object) +{ +/* + GeditXyzPlugin *plugin = GEDIT_XYZ_PLUGIN (object); +*/ + gedit_debug_message (DEBUG_PLUGINS, "GeditXyzPlugin finalizing"); + + G_OBJECT_CLASS (gedit_xyz_plugin_parent_class)->finalize (object); +} + +static void +impl_activate (GeditPlugin *plugin, + GeditWindow *window) +{ + gedit_debug (DEBUG_PLUGINS); +} + +static void +impl_deactivate (GeditPlugin *plugin, + GeditWindow *window) +{ + gedit_debug (DEBUG_PLUGINS); +} + +static void +impl_update_ui (GeditPlugin *plugin, + GeditWindow *window) +{ + gedit_debug (DEBUG_PLUGINS); +} + +/* +static GtkWidget * +impl_create_configure_dialog (GeditPlugin *plugin) +{ + * Implements this function only and only if the plugin + * is configurable. Otherwise you can safely remove it. * +} +*/ + +static void +gedit_xyz_plugin_class_init (GeditXyzPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass); + + object_class->finalize = gedit_xyz_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + plugin_class->update_ui = impl_update_ui; + + /* Only if the plugin is configurable */ + /* plugin_class->create_configure_dialog = impl_create_configure_dialog; */ + + g_type_class_add_private (object_class, sizeof (GeditXyzPluginPrivate)); +} diff --git a/tools/plugin_template/gedit-xyz-plugin.h b/tools/plugin_template/gedit-xyz-plugin.h new file mode 100644 index 00000000..7100d6a1 --- /dev/null +++ b/tools/plugin_template/gedit-xyz-plugin.h @@ -0,0 +1,78 @@ +/* + * gedit-xyz-plugin.h + * + * Copyright (C) %YEAR% - %AUTHOR% + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifndef __GEDIT_XYZ_PLUGIN_H__ +#define __GEDIT_XYZ_PLUGIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GEDIT_TYPE_XYZ_PLUGIN (gedit_xyz_plugin_get_type ()) +#define GEDIT_XYZ_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GEDIT_TYPE_XYZ_PLUGIN, GeditXyzPlugin)) +#define GEDIT_XYZ_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GEDIT_TYPE_XYZ_PLUGIN, GeditXyzPluginClass)) +#define GEDIT_IS_XYZ_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GEDIT_TYPE_XYZ_PLUGIN)) +#define GEDIT_IS_XYZ_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_XYZ_PLUGIN)) +#define GEDIT_XYZ_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_XYZ_PLUGIN, GeditXyzPluginClass)) + +/* Private structure type */ +typedef struct _GeditXyzPluginPrivate GeditXyzPluginPrivate; + +/* + * Main object structure + */ +typedef struct _GeditXyzPlugin GeditXyzPlugin; + +struct _GeditXyzPlugin +{ + GeditPlugin parent_instance; + + /*< private >*/ + GeditXyzPluginPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GeditXyzPluginClass GeditXyzPluginClass; + +struct _GeditXyzPluginClass +{ + GeditPluginClass parent_class; +}; + +/* + * Public methods + */ +GType gedit_xyz_plugin_get_type (void) G_GNUC_CONST; + +/* All plugins must implement this function */ +G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GEDIT_XYZ_PLUGIN_H__ */ diff --git a/tools/plugin_template/xyz.gedit-plugin.desktop.in b/tools/plugin_template/xyz.gedit-plugin.desktop.in new file mode 100644 index 00000000..b7ab70f4 --- /dev/null +++ b/tools/plugin_template/xyz.gedit-plugin.desktop.in @@ -0,0 +1,8 @@ +[Gedit Plugin] +Module=xyz +IAge=2 +_Name=Name of xyz +_Description=Description of xyz +Authors=%AUTHOR1% <%MAIL1%>;%AUTHOR2% <%MAIL2%> +Copyright=Copyright © %YEAR% %AUTHORS% +Website=http://www.gedit.org