summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am352
-rw-r--r--src/Makefile.in2446
-rw-r--r--src/eggshell.c112
-rw-r--r--src/eggshell.h38
-rw-r--r--src/gnome-terminal-search-provider.ini20
-rw-r--r--src/nautilus.symbols3
-rw-r--r--src/org.gnome.Terminal.gschema.xml724
-rw-r--r--src/org.gnome.Terminal.xml43
-rw-r--r--src/preferences.ui2453
-rw-r--r--src/profile-editor.c1444
-rw-r--r--src/profile-editor.h37
-rw-r--r--src/search-popover.ui251
-rw-r--r--src/server.c191
-rw-r--r--src/terminal-accels.c614
-rw-r--r--src/terminal-accels.h37
-rw-r--r--src/terminal-app.c1278
-rw-r--r--src/terminal-app.h117
-rw-r--r--src/terminal-client-utils.c252
-rw-r--r--src/terminal-client-utils.h54
-rw-r--r--src/terminal-debug.c48
-rw-r--r--src/terminal-debug.h76
-rw-r--r--src/terminal-defines.h48
-rw-r--r--src/terminal-enums.h69
-rw-r--r--src/terminal-gdbus.c566
-rw-r--r--src/terminal-gdbus.h90
-rw-r--r--src/terminal-headerbar.c170
-rw-r--r--src/terminal-headerbar.h40
-rw-r--r--src/terminal-headerbar.ui111
-rw-r--r--src/terminal-headermenu.ui119
-rw-r--r--src/terminal-i18n.c31
-rw-r--r--src/terminal-i18n.h29
-rw-r--r--src/terminal-icon-button.c50
-rw-r--r--src/terminal-icon-button.h33
-rw-r--r--src/terminal-info-bar.c119
-rw-r--r--src/terminal-info-bar.h61
-rw-r--r--src/terminal-intl.h29
-rw-r--r--src/terminal-libgsystem.h258
-rw-r--r--src/terminal-marshal.list1
-rw-r--r--src/terminal-mdi-container.c208
-rw-r--r--src/terminal-mdi-container.h104
-rw-r--r--src/terminal-menu-button.c147
-rw-r--r--src/terminal-menu-button.h57
-rw-r--r--src/terminal-menubar.ui.in248
-rw-r--r--src/terminal-nautilus.c770
-rw-r--r--src/terminal-notebook-menu.ui49
-rw-r--r--src/terminal-notebook.c593
-rw-r--r--src/terminal-notebook.h62
-rw-r--r--src/terminal-options.c1696
-rw-r--r--src/terminal-options.h193
-rw-r--r--src/terminal-pcre2.h25
-rw-r--r--src/terminal-prefs.c922
-rw-r--r--src/terminal-prefs.h55
-rw-r--r--src/terminal-profiles-list.c267
-rw-r--r--src/terminal-profiles-list.h53
-rw-r--r--src/terminal-regex.c374
-rw-r--r--src/terminal-regex.h162
-rw-r--r--src/terminal-schemas.h101
-rw-r--r--src/terminal-screen-container.c391
-rw-r--r--src/terminal-screen-container.h64
-rw-r--r--src/terminal-screen.c2324
-rw-r--r--src/terminal-screen.h164
-rw-r--r--src/terminal-search-popover.c580
-rw-r--r--src/terminal-search-popover.h49
-rw-r--r--src/terminal-search-provider.c379
-rw-r--r--src/terminal-search-provider.h51
-rw-r--r--src/terminal-settings-list.c938
-rw-r--r--src/terminal-settings-list.h89
-rw-r--r--src/terminal-tab-label.c391
-rw-r--r--src/terminal-tab-label.h66
-rw-r--r--src/terminal-type-builtins.c.template45
-rw-r--r--src/terminal-type-builtins.h.template25
-rw-r--r--src/terminal-util.c1580
-rw-r--r--src/terminal-util.h117
-rw-r--r--src/terminal-version.h34
-rw-r--r--src/terminal-version.h.in34
-rw-r--r--src/terminal-window.c3259
-rw-r--r--src/terminal-window.h97
-rw-r--r--src/terminal-window.ui17
-rw-r--r--src/terminal.about5
-rw-r--r--src/terminal.c601
-rw-r--r--src/terminal.common.css22
-rw-r--r--src/terminal.gresource.xml31
82 files changed, 29853 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..2ea3d93
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,352 @@
+NULL =
+
+BUILT_SOURCES =
+
+bin_PROGRAMS = gnome-terminal
+libexec_PROGRAMS = gnome-terminal-server
+noinst_PROGRAMS =
+
+check_PROGRAMS = terminal-regex
+
+if WITH_NAUTILUS_EXTENSION
+nautilusextension_LTLIBRARIES = libterminal-nautilus.la
+endif # WITH_NAUTILUS_EXTENSION
+
+# Terminal server
+
+dbusservice_DATA = org.gnome.Terminal.service
+
+# It is correct for this to be in ${prefix}/lib, even on systems where that
+# does not match ${libdir}. This is what systemd uses on such platforms.
+systemduserdir = $(prefix)/lib/systemd/user
+nodist_systemduser_DATA = gnome-terminal-server.service
+
+gnome_terminal_server_built = \
+ terminal-marshal.c \
+ terminal-marshal.h \
+ terminal-type-builtins.c \
+ terminal-type-builtins.h \
+ terminal-gdbus-generated.c \
+ terminal-gdbus-generated.h \
+ terminal-resources.c \
+ terminal-resources.h \
+ terminal-menubar-with-mnemonics.ui \
+ terminal-menubar-without-mnemonics.ui \
+ $(NULL)
+BUILT_SOURCES += $(gnome_terminal_server_built)
+
+gnome_terminal_server_SOURCES = \
+ eggshell.c \
+ eggshell.h \
+ profile-editor.c \
+ profile-editor.h \
+ server.c \
+ terminal-accels.c \
+ terminal-accels.h \
+ terminal-app.c \
+ terminal-app.h \
+ terminal-debug.c \
+ terminal-debug.h \
+ terminal-defines.h \
+ terminal-enums.h \
+ terminal-gdbus.c \
+ terminal-gdbus.h \
+ terminal-headerbar.c \
+ terminal-headerbar.h \
+ terminal-icon-button.h \
+ terminal-icon-button.c \
+ terminal-info-bar.c \
+ terminal-info-bar.h \
+ terminal-intl.h \
+ terminal-i18n.c \
+ terminal-i18n.h \
+ terminal-libgsystem.h \
+ terminal-mdi-container.c \
+ terminal-mdi-container.h \
+ terminal-menu-button.h \
+ terminal-menu-button.c \
+ terminal-notebook.c \
+ terminal-notebook.h \
+ terminal-pcre2.h \
+ terminal-prefs.c \
+ terminal-prefs.h \
+ terminal-profiles-list.c \
+ terminal-profiles-list.h \
+ terminal-regex.h \
+ terminal-schemas.h \
+ terminal-settings-list.c \
+ terminal-settings-list.h \
+ terminal-screen.c \
+ terminal-screen.h \
+ terminal-screen-container.c \
+ terminal-screen-container.h \
+ terminal-search-popover.c \
+ terminal-search-popover.h \
+ terminal-tab-label.c \
+ terminal-tab-label.h \
+ terminal-util.c \
+ terminal-util.h \
+ terminal-version.h \
+ terminal-window.c \
+ terminal-window.h \
+ $(NULL)
+
+nodist_gnome_terminal_server_SOURCES = $(gnome_terminal_server_built)
+
+gnome_terminal_server_CPPFLAGS = \
+ -DTERMINAL_COMPILATION \
+ -DVTE_DISABLE_DEPRECATION_WARNINGS \
+ -DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+ $(AM_CPPFLAGS)
+
+gnome_terminal_server_CFLAGS = \
+ $(TERM_CFLAGS) \
+ $(PTHREAD_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+
+gnome_terminal_server_LDFLAGS = \
+ $(AM_LDFLAGS)
+
+gnome_terminal_server_LDADD = \
+ $(TERM_LIBS) \
+ $(PTHREAD_LIBS) \
+ $(NULL)
+
+TYPES_H_FILES = \
+ terminal-enums.h \
+ $(NULL)
+
+terminal-type-builtins.h: stamp-terminal-type-builtins.h
+ @true
+
+stamp-terminal-type-builtins.h: terminal-type-builtins.h.template $(TYPES_H_FILES)
+ $(AM_V_GEN) $(GLIB_MKENUMS) --template $< $(filter-out $<,$^) > xgen-ttbh \
+ && (cmp -s xgen-ttbh terminal-type-builtins.h || cp xgen-ttbh terminal-type-builtins.h ) \
+ && rm -f xgen-ttbh \
+ && echo timestamp > $(@F)
+
+terminal-type-builtins.c: terminal-type-builtins.c.template $(TYPES_H_FILES)
+ $(AM_V_GEN) $(GLIB_MKENUMS) --template $< $(filter-out $<,$^) > xgen-ttbc \
+ && (cmp -s xgen-ttbc terminal-type-builtins.c || cp xgen-ttbc terminal-type-builtins.c ) \
+ && rm -f xgen-ttbc
+
+terminal-marshal.h: $(srcdir)/terminal-marshal.list
+ $(AM_V_GEN) ( $(GLIB_GENMARSHAL) --prefix=_terminal_marshal $(srcdir)/terminal-marshal.list \
+ --header \
+ --internal > terminal-marshal.h.tmp \
+ && mv terminal-marshal.h.tmp terminal-marshal.h ) \
+ || ( rm -f terminal-marshal.h.tmp && exit 1 )
+
+terminal-marshal.c: $(srcdir)/terminal-marshal.list
+ $(AM_V_GEN) ( echo '#include "terminal-marshal.h"' > terminal-marshal.c.tmp && \
+ $(GLIB_GENMARSHAL) --prefix=_terminal_marshal $(srcdir)/terminal-marshal.list \
+ --body \
+ --internal >> terminal-marshal.c.tmp \
+ && mv terminal-marshal.c.tmp terminal-marshal.c ) \
+ || ( rm -f terminal-marshal.c.tmp && exit 1 )
+
+org.gnome.Terminal.service: Makefile
+ $(AM_V_GEN) ( echo "[D-BUS Service]"; \
+ echo "Name=org.gnome.Terminal"; \
+ echo "SystemdService=gnome-terminal-server.service"; \
+ echo "Exec=${libexecdir}/gnome-terminal-server") > $@
+
+gnome-terminal-server.service: Makefile
+ $(AM_V_GEN) ( echo "[Unit]"; \
+ echo "Description=GNOME Terminal Server"; \
+ echo "PartOf=graphical-session.target"; \
+ echo "[Service]"; \
+ echo "Slice=app-org.gnome.Terminal.slice"; \
+ echo "Type=dbus"; \
+ echo "BusName=org.gnome.Terminal"; \
+ echo "ExecStart=${libexecdir}/gnome-terminal-server"; \
+ echo "TimeoutStopSec=5s"; \
+ echo "KillMode=process") > $@
+
+terminal-gdbus-generated.c terminal-gdbus-generated.h: org.gnome.Terminal.xml Makefile
+ $(AM_V_GEN) $(GDBUS_CODEGEN) \
+ --interface-prefix=org.gnome.Terminal \
+ --c-namespace=Terminal \
+ --c-generate-object-manager \
+ --generate-c-code terminal-gdbus-generated \
+ $<
+
+terminal-menubar-with-mnemonics.ui: terminal-menubar.ui.in
+ $(AM_V_GEN)$(SED) -e 's|<WITH_MNEMONIC>||g' -e 's|</WITH_MNEMONIC>||g' -e 's|<WITHOUT_MNEMONIC>|<!-- |g' -e 's|</WITHOUT_MNEMONIC>| -->|g' $< > $@
+
+terminal-menubar-without-mnemonics.ui: terminal-menubar.ui.in
+ $(AM_V_GEN)$(SED) -e 's|<WITH_MNEMONIC>|<!-- |g' -e 's|</WITH_MNEMONIC>| -->|g' -e 's|<WITHOUT_MNEMONIC>||g' -e 's|</WITHOUT_MNEMONIC>||g' $< > $@
+
+terminal-resources.h terminal-resources.c: terminal.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies --sourcedir $(srcdir) --sourcedir $(builddir) $(srcdir)/terminal.gresource.xml)
+ $(AM_V_GEN) XMLLINT=$(XMLLINT) $(GLIB_COMPILE_RESOURCES) --target $@ --sourcedir $(builddir) --sourcedir $(srcdir) --generate --c-name terminal $<
+
+# Checks
+
+TESTS = \
+ terminal-regex \
+ $(NULL)
+
+# Check programmes
+
+terminal_regex_CPPFLAGS = \
+ $(AM_CPPFLAGS)
+terminal_regex_SOURCES = \
+ terminal-regex.c \
+ terminal-regex.h \
+ $(NULL)
+terminal_regex_CFLAGS = \
+ -DTERMINAL_REGEX_MAIN \
+ $(TERM_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+terminal_regex_LDFLAGS = \
+ $(AM_LDFLAGS)
+terminal_regex_LDADD = \
+ $(TERM_LIBS)
+
+# Legacy terminal client
+
+gnome_terminal_SOURCES = \
+ terminal.c \
+ terminal-client-utils.c \
+ terminal-client-utils.h \
+ terminal-debug.c \
+ terminal-debug.h \
+ terminal-defines.h \
+ terminal-i18n.c \
+ terminal-i18n.h \
+ terminal-libgsystem.h \
+ terminal-options.c \
+ terminal-options.h \
+ terminal-profiles-list.c \
+ terminal-profiles-list.h \
+ terminal-schemas.h \
+ terminal-settings-list.c \
+ terminal-settings-list.h \
+ $(NULL)
+
+nodist_gnome_terminal_SOURCES = \
+ terminal-gdbus-generated.c \
+ terminal-gdbus-generated.h \
+ terminal-type-builtins.c \
+ terminal-type-builtins.h \
+ $(NULL)
+
+gnome_terminal_CPPFLAGS = \
+ -DTERMINAL_COMPILATION \
+ -DTERMINAL_CLIENT \
+ -DTERM_DATADIR="\"$(datadir)\"" \
+ -DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+ -DTERM_PKGDATADIR="\"$(pkgdatadir)\"" \
+ $(AM_CPPFLAGS)
+
+gnome_terminal_CFLAGS = \
+ $(TERM_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+
+gnome_terminal_LDFLAGS = \
+ $(AM_LDFLAGS)
+
+gnome_terminal_LDADD = \
+ $(TERM_LIBS)
+
+# Nautilus extension
+
+libterminal_nautilus_la_SOURCES = \
+ terminal-client-utils.c \
+ terminal-client-utils.h \
+ terminal-defines.h \
+ terminal-i18n.c \
+ terminal-i18n.h \
+ terminal-libgsystem.h \
+ terminal-nautilus.c \
+ $(NULL)
+
+nodist_libterminal_nautilus_la_SOURCES = \
+ terminal-gdbus-generated.c \
+ terminal-gdbus-generated.h \
+ terminal-type-builtins.c \
+ terminal-type-builtins.h \
+ $(NULL)
+
+libterminal_nautilus_la_CPPFLAGS = \
+ -DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+ $(AM_CPPFLAGS)
+
+libterminal_nautilus_la_CFLAGS = \
+ $(NAUTILUS_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libterminal_nautilus_la_LDFLAGS = \
+ -module -avoid-version \
+ -export-symbols $(srcdir)/nautilus.symbols \
+ $(AM_LDFLAGS)
+
+libterminal_nautilus_la_LIBADD = \
+ $(NAUTILUS_LIBS)
+
+# GNOME Shell search provider
+
+if ENABLE_SEARCH_PROVIDER
+
+searchproviderdir = $(datadir)/gnome-shell/search-providers
+dist_searchprovider_DATA = gnome-terminal-search-provider.ini
+
+gnome_terminal_server_built += \
+ terminal-search-provider-gdbus-generated.c \
+ terminal-search-provider-gdbus-generated.h \
+ $(NULL)
+
+gnome_terminal_server_SOURCES += \
+ terminal-search-provider.c \
+ terminal-search-provider.h \
+ $(NULL)
+
+terminal-search-provider-gdbus-generated.c terminal-search-provider-gdbus-generated.h: $(dbusinterfacedir)/org.gnome.ShellSearchProvider2.xml Makefile
+ $(AM_V_GEN) $(GDBUS_CODEGEN) \
+ --interface-prefix=org.gnome.Shell \
+ --c-namespace=Terminal \
+ --generate-c-code terminal-search-provider-gdbus-generated \
+ $<
+
+endif # ENABLE_SEARCH_PROVIDER
+
+gsettings_SCHEMAS = \
+ org.gnome.Terminal.gschema.xml \
+ $(NULL)
+
+CLEANFILES = \
+ stamp-terminal-type-builtins.h \
+ gnome-terminal.schemas \
+ stamp-terminal-type-builtins.h \
+ org.gnome.Terminal.service \
+ gnome-terminal-server.service \
+ $(BUILT_SOURCES)
+
+EXTRA_DIST = \
+ terminal.about \
+ terminal-headerbar.ui \
+ terminal-headermenu.ui \
+ terminal-menubar.ui.in \
+ terminal-notebook-menu.ui \
+ terminal-window.ui \
+ terminal.gresource.xml \
+ terminal-marshal.list \
+ terminal-type-builtins.c.template \
+ terminal-type-builtins.h.template \
+ org.gnome.Terminal.xml \
+ nautilus.symbols \
+ search-popover.ui \
+ preferences.ui \
+ terminal.common.css \
+ $(about_DATA) \
+ $(builder_DATA) \
+ $(gsettings_SCHEMAS) \
+ $(NULL)
+
+@GSETTINGS_RULES@
+
+-include $(top_srcdir)/git.mk
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..d38c7d2
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,2446 @@
+# Makefile.in generated by automake 1.16.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = gnome-terminal$(EXEEXT)
+libexec_PROGRAMS = gnome-terminal-server$(EXEEXT)
+noinst_PROGRAMS =
+check_PROGRAMS = terminal-regex$(EXEEXT)
+TESTS = terminal-regex$(EXEEXT) $(am__EXEEXT_1)
+@ENABLE_SEARCH_PROVIDER_TRUE@am__append_1 = \
+@ENABLE_SEARCH_PROVIDER_TRUE@ terminal-search-provider-gdbus-generated.c \
+@ENABLE_SEARCH_PROVIDER_TRUE@ terminal-search-provider-gdbus-generated.h \
+@ENABLE_SEARCH_PROVIDER_TRUE@ $(NULL)
+
+@ENABLE_SEARCH_PROVIDER_TRUE@am__append_2 = \
+@ENABLE_SEARCH_PROVIDER_TRUE@ terminal-search-provider.c \
+@ENABLE_SEARCH_PROVIDER_TRUE@ terminal-search-provider.h \
+@ENABLE_SEARCH_PROVIDER_TRUE@ $(NULL)
+
+subdir = src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am \
+ $(am__dist_searchprovider_DATA_DIST) $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = terminal-version.h
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \
+ "$(DESTDIR)$(nautilusextensiondir)" \
+ "$(DESTDIR)$(dbusservicedir)" "$(DESTDIR)$(searchproviderdir)" \
+ "$(DESTDIR)$(systemduserdir)"
+PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+LTLIBRARIES = $(nautilusextension_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libterminal_nautilus_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libterminal_nautilus_la_OBJECTS = \
+ libterminal_nautilus_la-terminal-client-utils.lo \
+ libterminal_nautilus_la-terminal-i18n.lo \
+ libterminal_nautilus_la-terminal-nautilus.lo $(am__objects_1)
+nodist_libterminal_nautilus_la_OBJECTS = \
+ libterminal_nautilus_la-terminal-gdbus-generated.lo \
+ libterminal_nautilus_la-terminal-type-builtins.lo \
+ $(am__objects_1)
+libterminal_nautilus_la_OBJECTS = \
+ $(am_libterminal_nautilus_la_OBJECTS) \
+ $(nodist_libterminal_nautilus_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libterminal_nautilus_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) \
+ $(libterminal_nautilus_la_LDFLAGS) $(LDFLAGS) -o $@
+@WITH_NAUTILUS_EXTENSION_TRUE@am_libterminal_nautilus_la_rpath = \
+@WITH_NAUTILUS_EXTENSION_TRUE@ -rpath $(nautilusextensiondir)
+am_gnome_terminal_OBJECTS = gnome_terminal-terminal.$(OBJEXT) \
+ gnome_terminal-terminal-client-utils.$(OBJEXT) \
+ gnome_terminal-terminal-debug.$(OBJEXT) \
+ gnome_terminal-terminal-i18n.$(OBJEXT) \
+ gnome_terminal-terminal-options.$(OBJEXT) \
+ gnome_terminal-terminal-profiles-list.$(OBJEXT) \
+ gnome_terminal-terminal-settings-list.$(OBJEXT) \
+ $(am__objects_1)
+nodist_gnome_terminal_OBJECTS = \
+ gnome_terminal-terminal-gdbus-generated.$(OBJEXT) \
+ gnome_terminal-terminal-type-builtins.$(OBJEXT) \
+ $(am__objects_1)
+gnome_terminal_OBJECTS = $(am_gnome_terminal_OBJECTS) \
+ $(nodist_gnome_terminal_OBJECTS)
+gnome_terminal_DEPENDENCIES = $(am__DEPENDENCIES_1)
+gnome_terminal_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(gnome_terminal_CFLAGS) $(CFLAGS) $(gnome_terminal_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am__gnome_terminal_server_SOURCES_DIST = eggshell.c eggshell.h \
+ profile-editor.c profile-editor.h server.c terminal-accels.c \
+ terminal-accels.h terminal-app.c terminal-app.h \
+ terminal-debug.c terminal-debug.h terminal-defines.h \
+ terminal-enums.h terminal-gdbus.c terminal-gdbus.h \
+ terminal-headerbar.c terminal-headerbar.h \
+ terminal-icon-button.h terminal-icon-button.c \
+ terminal-info-bar.c terminal-info-bar.h terminal-intl.h \
+ terminal-i18n.c terminal-i18n.h terminal-libgsystem.h \
+ terminal-mdi-container.c terminal-mdi-container.h \
+ terminal-menu-button.h terminal-menu-button.c \
+ terminal-notebook.c terminal-notebook.h terminal-pcre2.h \
+ terminal-prefs.c terminal-prefs.h terminal-profiles-list.c \
+ terminal-profiles-list.h terminal-regex.h terminal-schemas.h \
+ terminal-settings-list.c terminal-settings-list.h \
+ terminal-screen.c terminal-screen.h \
+ terminal-screen-container.c terminal-screen-container.h \
+ terminal-search-popover.c terminal-search-popover.h \
+ terminal-tab-label.c terminal-tab-label.h terminal-util.c \
+ terminal-util.h terminal-version.h terminal-window.c \
+ terminal-window.h terminal-search-provider.c \
+ terminal-search-provider.h
+@ENABLE_SEARCH_PROVIDER_TRUE@am__objects_2 = gnome_terminal_server-terminal-search-provider.$(OBJEXT) \
+@ENABLE_SEARCH_PROVIDER_TRUE@ $(am__objects_1)
+am_gnome_terminal_server_OBJECTS = \
+ gnome_terminal_server-eggshell.$(OBJEXT) \
+ gnome_terminal_server-profile-editor.$(OBJEXT) \
+ gnome_terminal_server-server.$(OBJEXT) \
+ gnome_terminal_server-terminal-accels.$(OBJEXT) \
+ gnome_terminal_server-terminal-app.$(OBJEXT) \
+ gnome_terminal_server-terminal-debug.$(OBJEXT) \
+ gnome_terminal_server-terminal-gdbus.$(OBJEXT) \
+ gnome_terminal_server-terminal-headerbar.$(OBJEXT) \
+ gnome_terminal_server-terminal-icon-button.$(OBJEXT) \
+ gnome_terminal_server-terminal-info-bar.$(OBJEXT) \
+ gnome_terminal_server-terminal-i18n.$(OBJEXT) \
+ gnome_terminal_server-terminal-mdi-container.$(OBJEXT) \
+ gnome_terminal_server-terminal-menu-button.$(OBJEXT) \
+ gnome_terminal_server-terminal-notebook.$(OBJEXT) \
+ gnome_terminal_server-terminal-prefs.$(OBJEXT) \
+ gnome_terminal_server-terminal-profiles-list.$(OBJEXT) \
+ gnome_terminal_server-terminal-settings-list.$(OBJEXT) \
+ gnome_terminal_server-terminal-screen.$(OBJEXT) \
+ gnome_terminal_server-terminal-screen-container.$(OBJEXT) \
+ gnome_terminal_server-terminal-search-popover.$(OBJEXT) \
+ gnome_terminal_server-terminal-tab-label.$(OBJEXT) \
+ gnome_terminal_server-terminal-util.$(OBJEXT) \
+ gnome_terminal_server-terminal-window.$(OBJEXT) \
+ $(am__objects_1) $(am__objects_2)
+@ENABLE_SEARCH_PROVIDER_TRUE@am__objects_3 = gnome_terminal_server-terminal-search-provider-gdbus-generated.$(OBJEXT) \
+@ENABLE_SEARCH_PROVIDER_TRUE@ $(am__objects_1)
+am__objects_4 = gnome_terminal_server-terminal-marshal.$(OBJEXT) \
+ gnome_terminal_server-terminal-type-builtins.$(OBJEXT) \
+ gnome_terminal_server-terminal-gdbus-generated.$(OBJEXT) \
+ gnome_terminal_server-terminal-resources.$(OBJEXT) \
+ $(am__objects_1) $(am__objects_3)
+nodist_gnome_terminal_server_OBJECTS = $(am__objects_4)
+gnome_terminal_server_OBJECTS = $(am_gnome_terminal_server_OBJECTS) \
+ $(nodist_gnome_terminal_server_OBJECTS)
+gnome_terminal_server_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+gnome_terminal_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(gnome_terminal_server_CFLAGS) $(CFLAGS) \
+ $(gnome_terminal_server_LDFLAGS) $(LDFLAGS) -o $@
+am_terminal_regex_OBJECTS = terminal_regex-terminal-regex.$(OBJEXT) \
+ $(am__objects_1)
+terminal_regex_OBJECTS = $(am_terminal_regex_OBJECTS)
+terminal_regex_DEPENDENCIES = $(am__DEPENDENCIES_1)
+terminal_regex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(terminal_regex_CFLAGS) $(CFLAGS) $(terminal_regex_LDFLAGS) \
+ $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/gnome_terminal-terminal-client-utils.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal-debug.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal-i18n.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal-options.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal-profiles-list.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal-settings-list.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal-type-builtins.Po \
+ ./$(DEPDIR)/gnome_terminal-terminal.Po \
+ ./$(DEPDIR)/gnome_terminal_server-eggshell.Po \
+ ./$(DEPDIR)/gnome_terminal_server-profile-editor.Po \
+ ./$(DEPDIR)/gnome_terminal_server-server.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-accels.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-app.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-debug.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-gdbus.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-headerbar.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-i18n.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-icon-button.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-info-bar.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-marshal.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-menu-button.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-notebook.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-prefs.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-resources.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-screen-container.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-screen.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-search-popover.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-search-provider.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-settings-list.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-tab-label.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-util.Po \
+ ./$(DEPDIR)/gnome_terminal_server-terminal-window.Po \
+ ./$(DEPDIR)/libterminal_nautilus_la-terminal-client-utils.Plo \
+ ./$(DEPDIR)/libterminal_nautilus_la-terminal-gdbus-generated.Plo \
+ ./$(DEPDIR)/libterminal_nautilus_la-terminal-i18n.Plo \
+ ./$(DEPDIR)/libterminal_nautilus_la-terminal-nautilus.Plo \
+ ./$(DEPDIR)/libterminal_nautilus_la-terminal-type-builtins.Plo \
+ ./$(DEPDIR)/terminal_regex-terminal-regex.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libterminal_nautilus_la_SOURCES) \
+ $(nodist_libterminal_nautilus_la_SOURCES) \
+ $(gnome_terminal_SOURCES) $(nodist_gnome_terminal_SOURCES) \
+ $(gnome_terminal_server_SOURCES) \
+ $(nodist_gnome_terminal_server_SOURCES) \
+ $(terminal_regex_SOURCES)
+DIST_SOURCES = $(libterminal_nautilus_la_SOURCES) \
+ $(gnome_terminal_SOURCES) \
+ $(am__gnome_terminal_server_SOURCES_DIST) \
+ $(terminal_regex_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__dist_searchprovider_DATA_DIST = \
+ gnome-terminal-search-provider.ini
+DATA = $(dbusservice_DATA) $(dist_searchprovider_DATA) \
+ $(nodist_systemduser_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+am__EXEEXT_1 =
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(srcdir)/terminal-version.h.in $(top_srcdir)/depcomp \
+ $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GDBUS_CODEGEN = @GDBUS_CODEGEN@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@
+GTK_API_VERSION = @GTK_API_VERSION@
+HELP_DIR = @HELP_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+ITSTOOL = @ITSTOOL@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NAUTILUS_CFLAGS = @NAUTILUS_CFLAGS@
+NAUTILUS_LIBS = @NAUTILUS_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TERMINAL_API_VERSION = @TERMINAL_API_VERSION@
+TERMINAL_MAJOR_VERSION = @TERMINAL_MAJOR_VERSION@
+TERMINAL_MICRO_VERSION = @TERMINAL_MICRO_VERSION@
+TERMINAL_MINOR_VERSION = @TERMINAL_MINOR_VERSION@
+TERM_CFLAGS = @TERM_CFLAGS@
+TERM_LIBS = @TERM_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMLLINT = @XMLLINT@
+XSLTPROC = @XSLTPROC@
+YELP_LC_DIST = @YELP_LC_DIST@
+YELP_LC_MEDIA_LINKS = @YELP_LC_MEDIA_LINKS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusinterfacedir = @dbusinterfacedir@
+dbusservicedir = @dbusservicedir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gsettingsschemadir = @gsettingsschemadir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nautilusextensiondir = @nautilusextensiondir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+BUILT_SOURCES = $(gnome_terminal_server_built)
+@WITH_NAUTILUS_EXTENSION_TRUE@nautilusextension_LTLIBRARIES = libterminal-nautilus.la
+
+# Terminal server
+dbusservice_DATA = org.gnome.Terminal.service
+
+# It is correct for this to be in ${prefix}/lib, even on systems where that
+# does not match ${libdir}. This is what systemd uses on such platforms.
+systemduserdir = $(prefix)/lib/systemd/user
+nodist_systemduser_DATA = gnome-terminal-server.service
+gnome_terminal_server_built = terminal-marshal.c terminal-marshal.h \
+ terminal-type-builtins.c terminal-type-builtins.h \
+ terminal-gdbus-generated.c terminal-gdbus-generated.h \
+ terminal-resources.c terminal-resources.h \
+ terminal-menubar-with-mnemonics.ui \
+ terminal-menubar-without-mnemonics.ui $(NULL) $(am__append_1)
+gnome_terminal_server_SOURCES = eggshell.c eggshell.h profile-editor.c \
+ profile-editor.h server.c terminal-accels.c terminal-accels.h \
+ terminal-app.c terminal-app.h terminal-debug.c \
+ terminal-debug.h terminal-defines.h terminal-enums.h \
+ terminal-gdbus.c terminal-gdbus.h terminal-headerbar.c \
+ terminal-headerbar.h terminal-icon-button.h \
+ terminal-icon-button.c terminal-info-bar.c terminal-info-bar.h \
+ terminal-intl.h terminal-i18n.c terminal-i18n.h \
+ terminal-libgsystem.h terminal-mdi-container.c \
+ terminal-mdi-container.h terminal-menu-button.h \
+ terminal-menu-button.c terminal-notebook.c terminal-notebook.h \
+ terminal-pcre2.h terminal-prefs.c terminal-prefs.h \
+ terminal-profiles-list.c terminal-profiles-list.h \
+ terminal-regex.h terminal-schemas.h terminal-settings-list.c \
+ terminal-settings-list.h terminal-screen.c terminal-screen.h \
+ terminal-screen-container.c terminal-screen-container.h \
+ terminal-search-popover.c terminal-search-popover.h \
+ terminal-tab-label.c terminal-tab-label.h terminal-util.c \
+ terminal-util.h terminal-version.h terminal-window.c \
+ terminal-window.h $(NULL) $(am__append_2)
+nodist_gnome_terminal_server_SOURCES = $(gnome_terminal_server_built)
+gnome_terminal_server_CPPFLAGS = \
+ -DTERMINAL_COMPILATION \
+ -DVTE_DISABLE_DEPRECATION_WARNINGS \
+ -DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+ $(AM_CPPFLAGS)
+
+gnome_terminal_server_CFLAGS = \
+ $(TERM_CFLAGS) \
+ $(PTHREAD_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+
+gnome_terminal_server_LDFLAGS = \
+ $(AM_LDFLAGS)
+
+gnome_terminal_server_LDADD = \
+ $(TERM_LIBS) \
+ $(PTHREAD_LIBS) \
+ $(NULL)
+
+TYPES_H_FILES = \
+ terminal-enums.h \
+ $(NULL)
+
+
+# Check programmes
+terminal_regex_CPPFLAGS = \
+ $(AM_CPPFLAGS)
+
+terminal_regex_SOURCES = \
+ terminal-regex.c \
+ terminal-regex.h \
+ $(NULL)
+
+terminal_regex_CFLAGS = \
+ -DTERMINAL_REGEX_MAIN \
+ $(TERM_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+
+terminal_regex_LDFLAGS = \
+ $(AM_LDFLAGS)
+
+terminal_regex_LDADD = \
+ $(TERM_LIBS)
+
+
+# Legacy terminal client
+gnome_terminal_SOURCES = \
+ terminal.c \
+ terminal-client-utils.c \
+ terminal-client-utils.h \
+ terminal-debug.c \
+ terminal-debug.h \
+ terminal-defines.h \
+ terminal-i18n.c \
+ terminal-i18n.h \
+ terminal-libgsystem.h \
+ terminal-options.c \
+ terminal-options.h \
+ terminal-profiles-list.c \
+ terminal-profiles-list.h \
+ terminal-schemas.h \
+ terminal-settings-list.c \
+ terminal-settings-list.h \
+ $(NULL)
+
+nodist_gnome_terminal_SOURCES = \
+ terminal-gdbus-generated.c \
+ terminal-gdbus-generated.h \
+ terminal-type-builtins.c \
+ terminal-type-builtins.h \
+ $(NULL)
+
+gnome_terminal_CPPFLAGS = \
+ -DTERMINAL_COMPILATION \
+ -DTERMINAL_CLIENT \
+ -DTERM_DATADIR="\"$(datadir)\"" \
+ -DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+ -DTERM_PKGDATADIR="\"$(pkgdatadir)\"" \
+ $(AM_CPPFLAGS)
+
+gnome_terminal_CFLAGS = \
+ $(TERM_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+
+gnome_terminal_LDFLAGS = \
+ $(AM_LDFLAGS)
+
+gnome_terminal_LDADD = \
+ $(TERM_LIBS)
+
+
+# Nautilus extension
+libterminal_nautilus_la_SOURCES = \
+ terminal-client-utils.c \
+ terminal-client-utils.h \
+ terminal-defines.h \
+ terminal-i18n.c \
+ terminal-i18n.h \
+ terminal-libgsystem.h \
+ terminal-nautilus.c \
+ $(NULL)
+
+nodist_libterminal_nautilus_la_SOURCES = \
+ terminal-gdbus-generated.c \
+ terminal-gdbus-generated.h \
+ terminal-type-builtins.c \
+ terminal-type-builtins.h \
+ $(NULL)
+
+libterminal_nautilus_la_CPPFLAGS = \
+ -DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+ $(AM_CPPFLAGS)
+
+libterminal_nautilus_la_CFLAGS = \
+ $(NAUTILUS_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(AM_CFLAGS)
+
+libterminal_nautilus_la_LDFLAGS = \
+ -module -avoid-version \
+ -export-symbols $(srcdir)/nautilus.symbols \
+ $(AM_LDFLAGS)
+
+libterminal_nautilus_la_LIBADD = \
+ $(NAUTILUS_LIBS)
+
+
+# GNOME Shell search provider
+@ENABLE_SEARCH_PROVIDER_TRUE@searchproviderdir = $(datadir)/gnome-shell/search-providers
+@ENABLE_SEARCH_PROVIDER_TRUE@dist_searchprovider_DATA = gnome-terminal-search-provider.ini
+gsettings_SCHEMAS = \
+ org.gnome.Terminal.gschema.xml \
+ $(NULL)
+
+CLEANFILES = \
+ stamp-terminal-type-builtins.h \
+ gnome-terminal.schemas \
+ stamp-terminal-type-builtins.h \
+ org.gnome.Terminal.service \
+ gnome-terminal-server.service \
+ $(BUILT_SOURCES)
+
+EXTRA_DIST = \
+ terminal.about \
+ terminal-headerbar.ui \
+ terminal-headermenu.ui \
+ terminal-menubar.ui.in \
+ terminal-notebook-menu.ui \
+ terminal-window.ui \
+ terminal.gresource.xml \
+ terminal-marshal.list \
+ terminal-type-builtins.c.template \
+ terminal-type-builtins.h.template \
+ org.gnome.Terminal.xml \
+ nautilus.symbols \
+ search-popover.ui \
+ preferences.ui \
+ terminal.common.css \
+ $(about_DATA) \
+ $(builder_DATA) \
+ $(gsettings_SCHEMAS) \
+ $(NULL)
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+terminal-version.h: $(top_builddir)/config.status $(srcdir)/terminal-version.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+install-libexecPROGRAMS: $(libexec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-libexecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files
+
+clean-libexecPROGRAMS:
+ @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+install-nautilusextensionLTLIBRARIES: $(nautilusextension_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(nautilusextension_LTLIBRARIES)'; test -n "$(nautilusextensiondir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(nautilusextensiondir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(nautilusextensiondir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(nautilusextensiondir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(nautilusextensiondir)"; \
+ }
+
+uninstall-nautilusextensionLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nautilusextension_LTLIBRARIES)'; test -n "$(nautilusextensiondir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(nautilusextensiondir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(nautilusextensiondir)/$$f"; \
+ done
+
+clean-nautilusextensionLTLIBRARIES:
+ -test -z "$(nautilusextension_LTLIBRARIES)" || rm -f $(nautilusextension_LTLIBRARIES)
+ @list='$(nautilusextension_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libterminal-nautilus.la: $(libterminal_nautilus_la_OBJECTS) $(libterminal_nautilus_la_DEPENDENCIES) $(EXTRA_libterminal_nautilus_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libterminal_nautilus_la_LINK) $(am_libterminal_nautilus_la_rpath) $(libterminal_nautilus_la_OBJECTS) $(libterminal_nautilus_la_LIBADD) $(LIBS)
+
+gnome-terminal$(EXEEXT): $(gnome_terminal_OBJECTS) $(gnome_terminal_DEPENDENCIES) $(EXTRA_gnome_terminal_DEPENDENCIES)
+ @rm -f gnome-terminal$(EXEEXT)
+ $(AM_V_CCLD)$(gnome_terminal_LINK) $(gnome_terminal_OBJECTS) $(gnome_terminal_LDADD) $(LIBS)
+
+gnome-terminal-server$(EXEEXT): $(gnome_terminal_server_OBJECTS) $(gnome_terminal_server_DEPENDENCIES) $(EXTRA_gnome_terminal_server_DEPENDENCIES)
+ @rm -f gnome-terminal-server$(EXEEXT)
+ $(AM_V_CCLD)$(gnome_terminal_server_LINK) $(gnome_terminal_server_OBJECTS) $(gnome_terminal_server_LDADD) $(LIBS)
+
+terminal-regex$(EXEEXT): $(terminal_regex_OBJECTS) $(terminal_regex_DEPENDENCIES) $(EXTRA_terminal_regex_DEPENDENCIES)
+ @rm -f terminal-regex$(EXEEXT)
+ $(AM_V_CCLD)$(terminal_regex_LINK) $(terminal_regex_OBJECTS) $(terminal_regex_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-client-utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-debug.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-i18n.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-options.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-profiles-list.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-settings-list.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal-type-builtins.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal-terminal.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-eggshell.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-profile-editor.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-accels.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-app.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-debug.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-gdbus.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-headerbar.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-i18n.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-icon-button.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-info-bar.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-marshal.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-menu-button.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-notebook.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-prefs.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-resources.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-screen-container.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-screen.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-search-popover.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-search-provider.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-settings-list.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-tab-label.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnome_terminal_server-terminal-window.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libterminal_nautilus_la-terminal-client-utils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libterminal_nautilus_la-terminal-gdbus-generated.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libterminal_nautilus_la-terminal-i18n.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libterminal_nautilus_la-terminal-nautilus.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libterminal_nautilus_la-terminal-type-builtins.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/terminal_regex-terminal-regex.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libterminal_nautilus_la-terminal-client-utils.lo: terminal-client-utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -MT libterminal_nautilus_la-terminal-client-utils.lo -MD -MP -MF $(DEPDIR)/libterminal_nautilus_la-terminal-client-utils.Tpo -c -o libterminal_nautilus_la-terminal-client-utils.lo `test -f 'terminal-client-utils.c' || echo '$(srcdir)/'`terminal-client-utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libterminal_nautilus_la-terminal-client-utils.Tpo $(DEPDIR)/libterminal_nautilus_la-terminal-client-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-client-utils.c' object='libterminal_nautilus_la-terminal-client-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -c -o libterminal_nautilus_la-terminal-client-utils.lo `test -f 'terminal-client-utils.c' || echo '$(srcdir)/'`terminal-client-utils.c
+
+libterminal_nautilus_la-terminal-i18n.lo: terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -MT libterminal_nautilus_la-terminal-i18n.lo -MD -MP -MF $(DEPDIR)/libterminal_nautilus_la-terminal-i18n.Tpo -c -o libterminal_nautilus_la-terminal-i18n.lo `test -f 'terminal-i18n.c' || echo '$(srcdir)/'`terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libterminal_nautilus_la-terminal-i18n.Tpo $(DEPDIR)/libterminal_nautilus_la-terminal-i18n.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-i18n.c' object='libterminal_nautilus_la-terminal-i18n.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -c -o libterminal_nautilus_la-terminal-i18n.lo `test -f 'terminal-i18n.c' || echo '$(srcdir)/'`terminal-i18n.c
+
+libterminal_nautilus_la-terminal-nautilus.lo: terminal-nautilus.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -MT libterminal_nautilus_la-terminal-nautilus.lo -MD -MP -MF $(DEPDIR)/libterminal_nautilus_la-terminal-nautilus.Tpo -c -o libterminal_nautilus_la-terminal-nautilus.lo `test -f 'terminal-nautilus.c' || echo '$(srcdir)/'`terminal-nautilus.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libterminal_nautilus_la-terminal-nautilus.Tpo $(DEPDIR)/libterminal_nautilus_la-terminal-nautilus.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-nautilus.c' object='libterminal_nautilus_la-terminal-nautilus.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -c -o libterminal_nautilus_la-terminal-nautilus.lo `test -f 'terminal-nautilus.c' || echo '$(srcdir)/'`terminal-nautilus.c
+
+libterminal_nautilus_la-terminal-gdbus-generated.lo: terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -MT libterminal_nautilus_la-terminal-gdbus-generated.lo -MD -MP -MF $(DEPDIR)/libterminal_nautilus_la-terminal-gdbus-generated.Tpo -c -o libterminal_nautilus_la-terminal-gdbus-generated.lo `test -f 'terminal-gdbus-generated.c' || echo '$(srcdir)/'`terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libterminal_nautilus_la-terminal-gdbus-generated.Tpo $(DEPDIR)/libterminal_nautilus_la-terminal-gdbus-generated.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-gdbus-generated.c' object='libterminal_nautilus_la-terminal-gdbus-generated.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -c -o libterminal_nautilus_la-terminal-gdbus-generated.lo `test -f 'terminal-gdbus-generated.c' || echo '$(srcdir)/'`terminal-gdbus-generated.c
+
+libterminal_nautilus_la-terminal-type-builtins.lo: terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -MT libterminal_nautilus_la-terminal-type-builtins.lo -MD -MP -MF $(DEPDIR)/libterminal_nautilus_la-terminal-type-builtins.Tpo -c -o libterminal_nautilus_la-terminal-type-builtins.lo `test -f 'terminal-type-builtins.c' || echo '$(srcdir)/'`terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libterminal_nautilus_la-terminal-type-builtins.Tpo $(DEPDIR)/libterminal_nautilus_la-terminal-type-builtins.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-type-builtins.c' object='libterminal_nautilus_la-terminal-type-builtins.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libterminal_nautilus_la_CPPFLAGS) $(CPPFLAGS) $(libterminal_nautilus_la_CFLAGS) $(CFLAGS) -c -o libterminal_nautilus_la-terminal-type-builtins.lo `test -f 'terminal-type-builtins.c' || echo '$(srcdir)/'`terminal-type-builtins.c
+
+gnome_terminal-terminal.o: terminal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal.Tpo -c -o gnome_terminal-terminal.o `test -f 'terminal.c' || echo '$(srcdir)/'`terminal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal.Tpo $(DEPDIR)/gnome_terminal-terminal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal.c' object='gnome_terminal-terminal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal.o `test -f 'terminal.c' || echo '$(srcdir)/'`terminal.c
+
+gnome_terminal-terminal.obj: terminal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal.Tpo -c -o gnome_terminal-terminal.obj `if test -f 'terminal.c'; then $(CYGPATH_W) 'terminal.c'; else $(CYGPATH_W) '$(srcdir)/terminal.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal.Tpo $(DEPDIR)/gnome_terminal-terminal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal.c' object='gnome_terminal-terminal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal.obj `if test -f 'terminal.c'; then $(CYGPATH_W) 'terminal.c'; else $(CYGPATH_W) '$(srcdir)/terminal.c'; fi`
+
+gnome_terminal-terminal-client-utils.o: terminal-client-utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-client-utils.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-client-utils.Tpo -c -o gnome_terminal-terminal-client-utils.o `test -f 'terminal-client-utils.c' || echo '$(srcdir)/'`terminal-client-utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-client-utils.Tpo $(DEPDIR)/gnome_terminal-terminal-client-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-client-utils.c' object='gnome_terminal-terminal-client-utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-client-utils.o `test -f 'terminal-client-utils.c' || echo '$(srcdir)/'`terminal-client-utils.c
+
+gnome_terminal-terminal-client-utils.obj: terminal-client-utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-client-utils.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-client-utils.Tpo -c -o gnome_terminal-terminal-client-utils.obj `if test -f 'terminal-client-utils.c'; then $(CYGPATH_W) 'terminal-client-utils.c'; else $(CYGPATH_W) '$(srcdir)/terminal-client-utils.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-client-utils.Tpo $(DEPDIR)/gnome_terminal-terminal-client-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-client-utils.c' object='gnome_terminal-terminal-client-utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-client-utils.obj `if test -f 'terminal-client-utils.c'; then $(CYGPATH_W) 'terminal-client-utils.c'; else $(CYGPATH_W) '$(srcdir)/terminal-client-utils.c'; fi`
+
+gnome_terminal-terminal-debug.o: terminal-debug.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-debug.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-debug.Tpo -c -o gnome_terminal-terminal-debug.o `test -f 'terminal-debug.c' || echo '$(srcdir)/'`terminal-debug.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-debug.Tpo $(DEPDIR)/gnome_terminal-terminal-debug.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-debug.c' object='gnome_terminal-terminal-debug.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-debug.o `test -f 'terminal-debug.c' || echo '$(srcdir)/'`terminal-debug.c
+
+gnome_terminal-terminal-debug.obj: terminal-debug.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-debug.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-debug.Tpo -c -o gnome_terminal-terminal-debug.obj `if test -f 'terminal-debug.c'; then $(CYGPATH_W) 'terminal-debug.c'; else $(CYGPATH_W) '$(srcdir)/terminal-debug.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-debug.Tpo $(DEPDIR)/gnome_terminal-terminal-debug.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-debug.c' object='gnome_terminal-terminal-debug.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-debug.obj `if test -f 'terminal-debug.c'; then $(CYGPATH_W) 'terminal-debug.c'; else $(CYGPATH_W) '$(srcdir)/terminal-debug.c'; fi`
+
+gnome_terminal-terminal-i18n.o: terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-i18n.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-i18n.Tpo -c -o gnome_terminal-terminal-i18n.o `test -f 'terminal-i18n.c' || echo '$(srcdir)/'`terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-i18n.Tpo $(DEPDIR)/gnome_terminal-terminal-i18n.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-i18n.c' object='gnome_terminal-terminal-i18n.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-i18n.o `test -f 'terminal-i18n.c' || echo '$(srcdir)/'`terminal-i18n.c
+
+gnome_terminal-terminal-i18n.obj: terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-i18n.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-i18n.Tpo -c -o gnome_terminal-terminal-i18n.obj `if test -f 'terminal-i18n.c'; then $(CYGPATH_W) 'terminal-i18n.c'; else $(CYGPATH_W) '$(srcdir)/terminal-i18n.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-i18n.Tpo $(DEPDIR)/gnome_terminal-terminal-i18n.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-i18n.c' object='gnome_terminal-terminal-i18n.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-i18n.obj `if test -f 'terminal-i18n.c'; then $(CYGPATH_W) 'terminal-i18n.c'; else $(CYGPATH_W) '$(srcdir)/terminal-i18n.c'; fi`
+
+gnome_terminal-terminal-options.o: terminal-options.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-options.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-options.Tpo -c -o gnome_terminal-terminal-options.o `test -f 'terminal-options.c' || echo '$(srcdir)/'`terminal-options.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-options.Tpo $(DEPDIR)/gnome_terminal-terminal-options.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-options.c' object='gnome_terminal-terminal-options.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-options.o `test -f 'terminal-options.c' || echo '$(srcdir)/'`terminal-options.c
+
+gnome_terminal-terminal-options.obj: terminal-options.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-options.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-options.Tpo -c -o gnome_terminal-terminal-options.obj `if test -f 'terminal-options.c'; then $(CYGPATH_W) 'terminal-options.c'; else $(CYGPATH_W) '$(srcdir)/terminal-options.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-options.Tpo $(DEPDIR)/gnome_terminal-terminal-options.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-options.c' object='gnome_terminal-terminal-options.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-options.obj `if test -f 'terminal-options.c'; then $(CYGPATH_W) 'terminal-options.c'; else $(CYGPATH_W) '$(srcdir)/terminal-options.c'; fi`
+
+gnome_terminal-terminal-profiles-list.o: terminal-profiles-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-profiles-list.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-profiles-list.Tpo -c -o gnome_terminal-terminal-profiles-list.o `test -f 'terminal-profiles-list.c' || echo '$(srcdir)/'`terminal-profiles-list.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-profiles-list.Tpo $(DEPDIR)/gnome_terminal-terminal-profiles-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-profiles-list.c' object='gnome_terminal-terminal-profiles-list.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-profiles-list.o `test -f 'terminal-profiles-list.c' || echo '$(srcdir)/'`terminal-profiles-list.c
+
+gnome_terminal-terminal-profiles-list.obj: terminal-profiles-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-profiles-list.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-profiles-list.Tpo -c -o gnome_terminal-terminal-profiles-list.obj `if test -f 'terminal-profiles-list.c'; then $(CYGPATH_W) 'terminal-profiles-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-profiles-list.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-profiles-list.Tpo $(DEPDIR)/gnome_terminal-terminal-profiles-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-profiles-list.c' object='gnome_terminal-terminal-profiles-list.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-profiles-list.obj `if test -f 'terminal-profiles-list.c'; then $(CYGPATH_W) 'terminal-profiles-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-profiles-list.c'; fi`
+
+gnome_terminal-terminal-settings-list.o: terminal-settings-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-settings-list.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-settings-list.Tpo -c -o gnome_terminal-terminal-settings-list.o `test -f 'terminal-settings-list.c' || echo '$(srcdir)/'`terminal-settings-list.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-settings-list.Tpo $(DEPDIR)/gnome_terminal-terminal-settings-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-settings-list.c' object='gnome_terminal-terminal-settings-list.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-settings-list.o `test -f 'terminal-settings-list.c' || echo '$(srcdir)/'`terminal-settings-list.c
+
+gnome_terminal-terminal-settings-list.obj: terminal-settings-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-settings-list.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-settings-list.Tpo -c -o gnome_terminal-terminal-settings-list.obj `if test -f 'terminal-settings-list.c'; then $(CYGPATH_W) 'terminal-settings-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-settings-list.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-settings-list.Tpo $(DEPDIR)/gnome_terminal-terminal-settings-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-settings-list.c' object='gnome_terminal-terminal-settings-list.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-settings-list.obj `if test -f 'terminal-settings-list.c'; then $(CYGPATH_W) 'terminal-settings-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-settings-list.c'; fi`
+
+gnome_terminal-terminal-gdbus-generated.o: terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-gdbus-generated.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Tpo -c -o gnome_terminal-terminal-gdbus-generated.o `test -f 'terminal-gdbus-generated.c' || echo '$(srcdir)/'`terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Tpo $(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-gdbus-generated.c' object='gnome_terminal-terminal-gdbus-generated.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-gdbus-generated.o `test -f 'terminal-gdbus-generated.c' || echo '$(srcdir)/'`terminal-gdbus-generated.c
+
+gnome_terminal-terminal-gdbus-generated.obj: terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-gdbus-generated.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Tpo -c -o gnome_terminal-terminal-gdbus-generated.obj `if test -f 'terminal-gdbus-generated.c'; then $(CYGPATH_W) 'terminal-gdbus-generated.c'; else $(CYGPATH_W) '$(srcdir)/terminal-gdbus-generated.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Tpo $(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-gdbus-generated.c' object='gnome_terminal-terminal-gdbus-generated.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-gdbus-generated.obj `if test -f 'terminal-gdbus-generated.c'; then $(CYGPATH_W) 'terminal-gdbus-generated.c'; else $(CYGPATH_W) '$(srcdir)/terminal-gdbus-generated.c'; fi`
+
+gnome_terminal-terminal-type-builtins.o: terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-type-builtins.o -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-type-builtins.Tpo -c -o gnome_terminal-terminal-type-builtins.o `test -f 'terminal-type-builtins.c' || echo '$(srcdir)/'`terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-type-builtins.Tpo $(DEPDIR)/gnome_terminal-terminal-type-builtins.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-type-builtins.c' object='gnome_terminal-terminal-type-builtins.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-type-builtins.o `test -f 'terminal-type-builtins.c' || echo '$(srcdir)/'`terminal-type-builtins.c
+
+gnome_terminal-terminal-type-builtins.obj: terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -MT gnome_terminal-terminal-type-builtins.obj -MD -MP -MF $(DEPDIR)/gnome_terminal-terminal-type-builtins.Tpo -c -o gnome_terminal-terminal-type-builtins.obj `if test -f 'terminal-type-builtins.c'; then $(CYGPATH_W) 'terminal-type-builtins.c'; else $(CYGPATH_W) '$(srcdir)/terminal-type-builtins.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal-terminal-type-builtins.Tpo $(DEPDIR)/gnome_terminal-terminal-type-builtins.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-type-builtins.c' object='gnome_terminal-terminal-type-builtins.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_CFLAGS) $(CFLAGS) -c -o gnome_terminal-terminal-type-builtins.obj `if test -f 'terminal-type-builtins.c'; then $(CYGPATH_W) 'terminal-type-builtins.c'; else $(CYGPATH_W) '$(srcdir)/terminal-type-builtins.c'; fi`
+
+gnome_terminal_server-eggshell.o: eggshell.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-eggshell.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-eggshell.Tpo -c -o gnome_terminal_server-eggshell.o `test -f 'eggshell.c' || echo '$(srcdir)/'`eggshell.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-eggshell.Tpo $(DEPDIR)/gnome_terminal_server-eggshell.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='eggshell.c' object='gnome_terminal_server-eggshell.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-eggshell.o `test -f 'eggshell.c' || echo '$(srcdir)/'`eggshell.c
+
+gnome_terminal_server-eggshell.obj: eggshell.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-eggshell.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-eggshell.Tpo -c -o gnome_terminal_server-eggshell.obj `if test -f 'eggshell.c'; then $(CYGPATH_W) 'eggshell.c'; else $(CYGPATH_W) '$(srcdir)/eggshell.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-eggshell.Tpo $(DEPDIR)/gnome_terminal_server-eggshell.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='eggshell.c' object='gnome_terminal_server-eggshell.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-eggshell.obj `if test -f 'eggshell.c'; then $(CYGPATH_W) 'eggshell.c'; else $(CYGPATH_W) '$(srcdir)/eggshell.c'; fi`
+
+gnome_terminal_server-profile-editor.o: profile-editor.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-profile-editor.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-profile-editor.Tpo -c -o gnome_terminal_server-profile-editor.o `test -f 'profile-editor.c' || echo '$(srcdir)/'`profile-editor.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-profile-editor.Tpo $(DEPDIR)/gnome_terminal_server-profile-editor.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile-editor.c' object='gnome_terminal_server-profile-editor.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-profile-editor.o `test -f 'profile-editor.c' || echo '$(srcdir)/'`profile-editor.c
+
+gnome_terminal_server-profile-editor.obj: profile-editor.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-profile-editor.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-profile-editor.Tpo -c -o gnome_terminal_server-profile-editor.obj `if test -f 'profile-editor.c'; then $(CYGPATH_W) 'profile-editor.c'; else $(CYGPATH_W) '$(srcdir)/profile-editor.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-profile-editor.Tpo $(DEPDIR)/gnome_terminal_server-profile-editor.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile-editor.c' object='gnome_terminal_server-profile-editor.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-profile-editor.obj `if test -f 'profile-editor.c'; then $(CYGPATH_W) 'profile-editor.c'; else $(CYGPATH_W) '$(srcdir)/profile-editor.c'; fi`
+
+gnome_terminal_server-server.o: server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-server.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-server.Tpo -c -o gnome_terminal_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-server.Tpo $(DEPDIR)/gnome_terminal_server-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='gnome_terminal_server-server.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c
+
+gnome_terminal_server-server.obj: server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-server.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-server.Tpo -c -o gnome_terminal_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-server.Tpo $(DEPDIR)/gnome_terminal_server-server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='gnome_terminal_server-server.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi`
+
+gnome_terminal_server-terminal-accels.o: terminal-accels.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-accels.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-accels.Tpo -c -o gnome_terminal_server-terminal-accels.o `test -f 'terminal-accels.c' || echo '$(srcdir)/'`terminal-accels.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-accels.Tpo $(DEPDIR)/gnome_terminal_server-terminal-accels.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-accels.c' object='gnome_terminal_server-terminal-accels.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-accels.o `test -f 'terminal-accels.c' || echo '$(srcdir)/'`terminal-accels.c
+
+gnome_terminal_server-terminal-accels.obj: terminal-accels.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-accels.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-accels.Tpo -c -o gnome_terminal_server-terminal-accels.obj `if test -f 'terminal-accels.c'; then $(CYGPATH_W) 'terminal-accels.c'; else $(CYGPATH_W) '$(srcdir)/terminal-accels.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-accels.Tpo $(DEPDIR)/gnome_terminal_server-terminal-accels.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-accels.c' object='gnome_terminal_server-terminal-accels.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-accels.obj `if test -f 'terminal-accels.c'; then $(CYGPATH_W) 'terminal-accels.c'; else $(CYGPATH_W) '$(srcdir)/terminal-accels.c'; fi`
+
+gnome_terminal_server-terminal-app.o: terminal-app.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-app.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-app.Tpo -c -o gnome_terminal_server-terminal-app.o `test -f 'terminal-app.c' || echo '$(srcdir)/'`terminal-app.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-app.Tpo $(DEPDIR)/gnome_terminal_server-terminal-app.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-app.c' object='gnome_terminal_server-terminal-app.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-app.o `test -f 'terminal-app.c' || echo '$(srcdir)/'`terminal-app.c
+
+gnome_terminal_server-terminal-app.obj: terminal-app.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-app.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-app.Tpo -c -o gnome_terminal_server-terminal-app.obj `if test -f 'terminal-app.c'; then $(CYGPATH_W) 'terminal-app.c'; else $(CYGPATH_W) '$(srcdir)/terminal-app.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-app.Tpo $(DEPDIR)/gnome_terminal_server-terminal-app.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-app.c' object='gnome_terminal_server-terminal-app.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-app.obj `if test -f 'terminal-app.c'; then $(CYGPATH_W) 'terminal-app.c'; else $(CYGPATH_W) '$(srcdir)/terminal-app.c'; fi`
+
+gnome_terminal_server-terminal-debug.o: terminal-debug.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-debug.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-debug.Tpo -c -o gnome_terminal_server-terminal-debug.o `test -f 'terminal-debug.c' || echo '$(srcdir)/'`terminal-debug.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-debug.Tpo $(DEPDIR)/gnome_terminal_server-terminal-debug.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-debug.c' object='gnome_terminal_server-terminal-debug.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-debug.o `test -f 'terminal-debug.c' || echo '$(srcdir)/'`terminal-debug.c
+
+gnome_terminal_server-terminal-debug.obj: terminal-debug.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-debug.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-debug.Tpo -c -o gnome_terminal_server-terminal-debug.obj `if test -f 'terminal-debug.c'; then $(CYGPATH_W) 'terminal-debug.c'; else $(CYGPATH_W) '$(srcdir)/terminal-debug.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-debug.Tpo $(DEPDIR)/gnome_terminal_server-terminal-debug.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-debug.c' object='gnome_terminal_server-terminal-debug.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-debug.obj `if test -f 'terminal-debug.c'; then $(CYGPATH_W) 'terminal-debug.c'; else $(CYGPATH_W) '$(srcdir)/terminal-debug.c'; fi`
+
+gnome_terminal_server-terminal-gdbus.o: terminal-gdbus.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-gdbus.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-gdbus.Tpo -c -o gnome_terminal_server-terminal-gdbus.o `test -f 'terminal-gdbus.c' || echo '$(srcdir)/'`terminal-gdbus.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-gdbus.Tpo $(DEPDIR)/gnome_terminal_server-terminal-gdbus.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-gdbus.c' object='gnome_terminal_server-terminal-gdbus.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-gdbus.o `test -f 'terminal-gdbus.c' || echo '$(srcdir)/'`terminal-gdbus.c
+
+gnome_terminal_server-terminal-gdbus.obj: terminal-gdbus.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-gdbus.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-gdbus.Tpo -c -o gnome_terminal_server-terminal-gdbus.obj `if test -f 'terminal-gdbus.c'; then $(CYGPATH_W) 'terminal-gdbus.c'; else $(CYGPATH_W) '$(srcdir)/terminal-gdbus.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-gdbus.Tpo $(DEPDIR)/gnome_terminal_server-terminal-gdbus.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-gdbus.c' object='gnome_terminal_server-terminal-gdbus.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-gdbus.obj `if test -f 'terminal-gdbus.c'; then $(CYGPATH_W) 'terminal-gdbus.c'; else $(CYGPATH_W) '$(srcdir)/terminal-gdbus.c'; fi`
+
+gnome_terminal_server-terminal-headerbar.o: terminal-headerbar.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-headerbar.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-headerbar.Tpo -c -o gnome_terminal_server-terminal-headerbar.o `test -f 'terminal-headerbar.c' || echo '$(srcdir)/'`terminal-headerbar.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-headerbar.Tpo $(DEPDIR)/gnome_terminal_server-terminal-headerbar.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-headerbar.c' object='gnome_terminal_server-terminal-headerbar.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-headerbar.o `test -f 'terminal-headerbar.c' || echo '$(srcdir)/'`terminal-headerbar.c
+
+gnome_terminal_server-terminal-headerbar.obj: terminal-headerbar.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-headerbar.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-headerbar.Tpo -c -o gnome_terminal_server-terminal-headerbar.obj `if test -f 'terminal-headerbar.c'; then $(CYGPATH_W) 'terminal-headerbar.c'; else $(CYGPATH_W) '$(srcdir)/terminal-headerbar.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-headerbar.Tpo $(DEPDIR)/gnome_terminal_server-terminal-headerbar.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-headerbar.c' object='gnome_terminal_server-terminal-headerbar.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-headerbar.obj `if test -f 'terminal-headerbar.c'; then $(CYGPATH_W) 'terminal-headerbar.c'; else $(CYGPATH_W) '$(srcdir)/terminal-headerbar.c'; fi`
+
+gnome_terminal_server-terminal-icon-button.o: terminal-icon-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-icon-button.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-icon-button.Tpo -c -o gnome_terminal_server-terminal-icon-button.o `test -f 'terminal-icon-button.c' || echo '$(srcdir)/'`terminal-icon-button.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-icon-button.Tpo $(DEPDIR)/gnome_terminal_server-terminal-icon-button.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-icon-button.c' object='gnome_terminal_server-terminal-icon-button.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-icon-button.o `test -f 'terminal-icon-button.c' || echo '$(srcdir)/'`terminal-icon-button.c
+
+gnome_terminal_server-terminal-icon-button.obj: terminal-icon-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-icon-button.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-icon-button.Tpo -c -o gnome_terminal_server-terminal-icon-button.obj `if test -f 'terminal-icon-button.c'; then $(CYGPATH_W) 'terminal-icon-button.c'; else $(CYGPATH_W) '$(srcdir)/terminal-icon-button.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-icon-button.Tpo $(DEPDIR)/gnome_terminal_server-terminal-icon-button.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-icon-button.c' object='gnome_terminal_server-terminal-icon-button.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-icon-button.obj `if test -f 'terminal-icon-button.c'; then $(CYGPATH_W) 'terminal-icon-button.c'; else $(CYGPATH_W) '$(srcdir)/terminal-icon-button.c'; fi`
+
+gnome_terminal_server-terminal-info-bar.o: terminal-info-bar.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-info-bar.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-info-bar.Tpo -c -o gnome_terminal_server-terminal-info-bar.o `test -f 'terminal-info-bar.c' || echo '$(srcdir)/'`terminal-info-bar.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-info-bar.Tpo $(DEPDIR)/gnome_terminal_server-terminal-info-bar.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-info-bar.c' object='gnome_terminal_server-terminal-info-bar.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-info-bar.o `test -f 'terminal-info-bar.c' || echo '$(srcdir)/'`terminal-info-bar.c
+
+gnome_terminal_server-terminal-info-bar.obj: terminal-info-bar.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-info-bar.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-info-bar.Tpo -c -o gnome_terminal_server-terminal-info-bar.obj `if test -f 'terminal-info-bar.c'; then $(CYGPATH_W) 'terminal-info-bar.c'; else $(CYGPATH_W) '$(srcdir)/terminal-info-bar.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-info-bar.Tpo $(DEPDIR)/gnome_terminal_server-terminal-info-bar.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-info-bar.c' object='gnome_terminal_server-terminal-info-bar.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-info-bar.obj `if test -f 'terminal-info-bar.c'; then $(CYGPATH_W) 'terminal-info-bar.c'; else $(CYGPATH_W) '$(srcdir)/terminal-info-bar.c'; fi`
+
+gnome_terminal_server-terminal-i18n.o: terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-i18n.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-i18n.Tpo -c -o gnome_terminal_server-terminal-i18n.o `test -f 'terminal-i18n.c' || echo '$(srcdir)/'`terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-i18n.Tpo $(DEPDIR)/gnome_terminal_server-terminal-i18n.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-i18n.c' object='gnome_terminal_server-terminal-i18n.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-i18n.o `test -f 'terminal-i18n.c' || echo '$(srcdir)/'`terminal-i18n.c
+
+gnome_terminal_server-terminal-i18n.obj: terminal-i18n.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-i18n.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-i18n.Tpo -c -o gnome_terminal_server-terminal-i18n.obj `if test -f 'terminal-i18n.c'; then $(CYGPATH_W) 'terminal-i18n.c'; else $(CYGPATH_W) '$(srcdir)/terminal-i18n.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-i18n.Tpo $(DEPDIR)/gnome_terminal_server-terminal-i18n.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-i18n.c' object='gnome_terminal_server-terminal-i18n.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-i18n.obj `if test -f 'terminal-i18n.c'; then $(CYGPATH_W) 'terminal-i18n.c'; else $(CYGPATH_W) '$(srcdir)/terminal-i18n.c'; fi`
+
+gnome_terminal_server-terminal-mdi-container.o: terminal-mdi-container.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-mdi-container.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Tpo -c -o gnome_terminal_server-terminal-mdi-container.o `test -f 'terminal-mdi-container.c' || echo '$(srcdir)/'`terminal-mdi-container.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Tpo $(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-mdi-container.c' object='gnome_terminal_server-terminal-mdi-container.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-mdi-container.o `test -f 'terminal-mdi-container.c' || echo '$(srcdir)/'`terminal-mdi-container.c
+
+gnome_terminal_server-terminal-mdi-container.obj: terminal-mdi-container.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-mdi-container.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Tpo -c -o gnome_terminal_server-terminal-mdi-container.obj `if test -f 'terminal-mdi-container.c'; then $(CYGPATH_W) 'terminal-mdi-container.c'; else $(CYGPATH_W) '$(srcdir)/terminal-mdi-container.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Tpo $(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-mdi-container.c' object='gnome_terminal_server-terminal-mdi-container.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-mdi-container.obj `if test -f 'terminal-mdi-container.c'; then $(CYGPATH_W) 'terminal-mdi-container.c'; else $(CYGPATH_W) '$(srcdir)/terminal-mdi-container.c'; fi`
+
+gnome_terminal_server-terminal-menu-button.o: terminal-menu-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-menu-button.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-menu-button.Tpo -c -o gnome_terminal_server-terminal-menu-button.o `test -f 'terminal-menu-button.c' || echo '$(srcdir)/'`terminal-menu-button.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-menu-button.Tpo $(DEPDIR)/gnome_terminal_server-terminal-menu-button.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-menu-button.c' object='gnome_terminal_server-terminal-menu-button.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-menu-button.o `test -f 'terminal-menu-button.c' || echo '$(srcdir)/'`terminal-menu-button.c
+
+gnome_terminal_server-terminal-menu-button.obj: terminal-menu-button.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-menu-button.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-menu-button.Tpo -c -o gnome_terminal_server-terminal-menu-button.obj `if test -f 'terminal-menu-button.c'; then $(CYGPATH_W) 'terminal-menu-button.c'; else $(CYGPATH_W) '$(srcdir)/terminal-menu-button.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-menu-button.Tpo $(DEPDIR)/gnome_terminal_server-terminal-menu-button.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-menu-button.c' object='gnome_terminal_server-terminal-menu-button.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-menu-button.obj `if test -f 'terminal-menu-button.c'; then $(CYGPATH_W) 'terminal-menu-button.c'; else $(CYGPATH_W) '$(srcdir)/terminal-menu-button.c'; fi`
+
+gnome_terminal_server-terminal-notebook.o: terminal-notebook.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-notebook.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-notebook.Tpo -c -o gnome_terminal_server-terminal-notebook.o `test -f 'terminal-notebook.c' || echo '$(srcdir)/'`terminal-notebook.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-notebook.Tpo $(DEPDIR)/gnome_terminal_server-terminal-notebook.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-notebook.c' object='gnome_terminal_server-terminal-notebook.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-notebook.o `test -f 'terminal-notebook.c' || echo '$(srcdir)/'`terminal-notebook.c
+
+gnome_terminal_server-terminal-notebook.obj: terminal-notebook.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-notebook.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-notebook.Tpo -c -o gnome_terminal_server-terminal-notebook.obj `if test -f 'terminal-notebook.c'; then $(CYGPATH_W) 'terminal-notebook.c'; else $(CYGPATH_W) '$(srcdir)/terminal-notebook.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-notebook.Tpo $(DEPDIR)/gnome_terminal_server-terminal-notebook.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-notebook.c' object='gnome_terminal_server-terminal-notebook.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-notebook.obj `if test -f 'terminal-notebook.c'; then $(CYGPATH_W) 'terminal-notebook.c'; else $(CYGPATH_W) '$(srcdir)/terminal-notebook.c'; fi`
+
+gnome_terminal_server-terminal-prefs.o: terminal-prefs.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-prefs.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-prefs.Tpo -c -o gnome_terminal_server-terminal-prefs.o `test -f 'terminal-prefs.c' || echo '$(srcdir)/'`terminal-prefs.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-prefs.Tpo $(DEPDIR)/gnome_terminal_server-terminal-prefs.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-prefs.c' object='gnome_terminal_server-terminal-prefs.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-prefs.o `test -f 'terminal-prefs.c' || echo '$(srcdir)/'`terminal-prefs.c
+
+gnome_terminal_server-terminal-prefs.obj: terminal-prefs.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-prefs.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-prefs.Tpo -c -o gnome_terminal_server-terminal-prefs.obj `if test -f 'terminal-prefs.c'; then $(CYGPATH_W) 'terminal-prefs.c'; else $(CYGPATH_W) '$(srcdir)/terminal-prefs.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-prefs.Tpo $(DEPDIR)/gnome_terminal_server-terminal-prefs.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-prefs.c' object='gnome_terminal_server-terminal-prefs.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-prefs.obj `if test -f 'terminal-prefs.c'; then $(CYGPATH_W) 'terminal-prefs.c'; else $(CYGPATH_W) '$(srcdir)/terminal-prefs.c'; fi`
+
+gnome_terminal_server-terminal-profiles-list.o: terminal-profiles-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-profiles-list.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Tpo -c -o gnome_terminal_server-terminal-profiles-list.o `test -f 'terminal-profiles-list.c' || echo '$(srcdir)/'`terminal-profiles-list.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Tpo $(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-profiles-list.c' object='gnome_terminal_server-terminal-profiles-list.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-profiles-list.o `test -f 'terminal-profiles-list.c' || echo '$(srcdir)/'`terminal-profiles-list.c
+
+gnome_terminal_server-terminal-profiles-list.obj: terminal-profiles-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-profiles-list.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Tpo -c -o gnome_terminal_server-terminal-profiles-list.obj `if test -f 'terminal-profiles-list.c'; then $(CYGPATH_W) 'terminal-profiles-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-profiles-list.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Tpo $(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-profiles-list.c' object='gnome_terminal_server-terminal-profiles-list.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-profiles-list.obj `if test -f 'terminal-profiles-list.c'; then $(CYGPATH_W) 'terminal-profiles-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-profiles-list.c'; fi`
+
+gnome_terminal_server-terminal-settings-list.o: terminal-settings-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-settings-list.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-settings-list.Tpo -c -o gnome_terminal_server-terminal-settings-list.o `test -f 'terminal-settings-list.c' || echo '$(srcdir)/'`terminal-settings-list.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-settings-list.Tpo $(DEPDIR)/gnome_terminal_server-terminal-settings-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-settings-list.c' object='gnome_terminal_server-terminal-settings-list.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-settings-list.o `test -f 'terminal-settings-list.c' || echo '$(srcdir)/'`terminal-settings-list.c
+
+gnome_terminal_server-terminal-settings-list.obj: terminal-settings-list.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-settings-list.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-settings-list.Tpo -c -o gnome_terminal_server-terminal-settings-list.obj `if test -f 'terminal-settings-list.c'; then $(CYGPATH_W) 'terminal-settings-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-settings-list.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-settings-list.Tpo $(DEPDIR)/gnome_terminal_server-terminal-settings-list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-settings-list.c' object='gnome_terminal_server-terminal-settings-list.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-settings-list.obj `if test -f 'terminal-settings-list.c'; then $(CYGPATH_W) 'terminal-settings-list.c'; else $(CYGPATH_W) '$(srcdir)/terminal-settings-list.c'; fi`
+
+gnome_terminal_server-terminal-screen.o: terminal-screen.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-screen.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-screen.Tpo -c -o gnome_terminal_server-terminal-screen.o `test -f 'terminal-screen.c' || echo '$(srcdir)/'`terminal-screen.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-screen.Tpo $(DEPDIR)/gnome_terminal_server-terminal-screen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-screen.c' object='gnome_terminal_server-terminal-screen.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-screen.o `test -f 'terminal-screen.c' || echo '$(srcdir)/'`terminal-screen.c
+
+gnome_terminal_server-terminal-screen.obj: terminal-screen.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-screen.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-screen.Tpo -c -o gnome_terminal_server-terminal-screen.obj `if test -f 'terminal-screen.c'; then $(CYGPATH_W) 'terminal-screen.c'; else $(CYGPATH_W) '$(srcdir)/terminal-screen.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-screen.Tpo $(DEPDIR)/gnome_terminal_server-terminal-screen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-screen.c' object='gnome_terminal_server-terminal-screen.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-screen.obj `if test -f 'terminal-screen.c'; then $(CYGPATH_W) 'terminal-screen.c'; else $(CYGPATH_W) '$(srcdir)/terminal-screen.c'; fi`
+
+gnome_terminal_server-terminal-screen-container.o: terminal-screen-container.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-screen-container.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-screen-container.Tpo -c -o gnome_terminal_server-terminal-screen-container.o `test -f 'terminal-screen-container.c' || echo '$(srcdir)/'`terminal-screen-container.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-screen-container.Tpo $(DEPDIR)/gnome_terminal_server-terminal-screen-container.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-screen-container.c' object='gnome_terminal_server-terminal-screen-container.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-screen-container.o `test -f 'terminal-screen-container.c' || echo '$(srcdir)/'`terminal-screen-container.c
+
+gnome_terminal_server-terminal-screen-container.obj: terminal-screen-container.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-screen-container.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-screen-container.Tpo -c -o gnome_terminal_server-terminal-screen-container.obj `if test -f 'terminal-screen-container.c'; then $(CYGPATH_W) 'terminal-screen-container.c'; else $(CYGPATH_W) '$(srcdir)/terminal-screen-container.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-screen-container.Tpo $(DEPDIR)/gnome_terminal_server-terminal-screen-container.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-screen-container.c' object='gnome_terminal_server-terminal-screen-container.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-screen-container.obj `if test -f 'terminal-screen-container.c'; then $(CYGPATH_W) 'terminal-screen-container.c'; else $(CYGPATH_W) '$(srcdir)/terminal-screen-container.c'; fi`
+
+gnome_terminal_server-terminal-search-popover.o: terminal-search-popover.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-search-popover.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-search-popover.Tpo -c -o gnome_terminal_server-terminal-search-popover.o `test -f 'terminal-search-popover.c' || echo '$(srcdir)/'`terminal-search-popover.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-search-popover.Tpo $(DEPDIR)/gnome_terminal_server-terminal-search-popover.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-search-popover.c' object='gnome_terminal_server-terminal-search-popover.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-search-popover.o `test -f 'terminal-search-popover.c' || echo '$(srcdir)/'`terminal-search-popover.c
+
+gnome_terminal_server-terminal-search-popover.obj: terminal-search-popover.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-search-popover.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-search-popover.Tpo -c -o gnome_terminal_server-terminal-search-popover.obj `if test -f 'terminal-search-popover.c'; then $(CYGPATH_W) 'terminal-search-popover.c'; else $(CYGPATH_W) '$(srcdir)/terminal-search-popover.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-search-popover.Tpo $(DEPDIR)/gnome_terminal_server-terminal-search-popover.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-search-popover.c' object='gnome_terminal_server-terminal-search-popover.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-search-popover.obj `if test -f 'terminal-search-popover.c'; then $(CYGPATH_W) 'terminal-search-popover.c'; else $(CYGPATH_W) '$(srcdir)/terminal-search-popover.c'; fi`
+
+gnome_terminal_server-terminal-tab-label.o: terminal-tab-label.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-tab-label.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-tab-label.Tpo -c -o gnome_terminal_server-terminal-tab-label.o `test -f 'terminal-tab-label.c' || echo '$(srcdir)/'`terminal-tab-label.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-tab-label.Tpo $(DEPDIR)/gnome_terminal_server-terminal-tab-label.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-tab-label.c' object='gnome_terminal_server-terminal-tab-label.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-tab-label.o `test -f 'terminal-tab-label.c' || echo '$(srcdir)/'`terminal-tab-label.c
+
+gnome_terminal_server-terminal-tab-label.obj: terminal-tab-label.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-tab-label.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-tab-label.Tpo -c -o gnome_terminal_server-terminal-tab-label.obj `if test -f 'terminal-tab-label.c'; then $(CYGPATH_W) 'terminal-tab-label.c'; else $(CYGPATH_W) '$(srcdir)/terminal-tab-label.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-tab-label.Tpo $(DEPDIR)/gnome_terminal_server-terminal-tab-label.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-tab-label.c' object='gnome_terminal_server-terminal-tab-label.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-tab-label.obj `if test -f 'terminal-tab-label.c'; then $(CYGPATH_W) 'terminal-tab-label.c'; else $(CYGPATH_W) '$(srcdir)/terminal-tab-label.c'; fi`
+
+gnome_terminal_server-terminal-util.o: terminal-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-util.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-util.Tpo -c -o gnome_terminal_server-terminal-util.o `test -f 'terminal-util.c' || echo '$(srcdir)/'`terminal-util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-util.Tpo $(DEPDIR)/gnome_terminal_server-terminal-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-util.c' object='gnome_terminal_server-terminal-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-util.o `test -f 'terminal-util.c' || echo '$(srcdir)/'`terminal-util.c
+
+gnome_terminal_server-terminal-util.obj: terminal-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-util.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-util.Tpo -c -o gnome_terminal_server-terminal-util.obj `if test -f 'terminal-util.c'; then $(CYGPATH_W) 'terminal-util.c'; else $(CYGPATH_W) '$(srcdir)/terminal-util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-util.Tpo $(DEPDIR)/gnome_terminal_server-terminal-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-util.c' object='gnome_terminal_server-terminal-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-util.obj `if test -f 'terminal-util.c'; then $(CYGPATH_W) 'terminal-util.c'; else $(CYGPATH_W) '$(srcdir)/terminal-util.c'; fi`
+
+gnome_terminal_server-terminal-window.o: terminal-window.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-window.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-window.Tpo -c -o gnome_terminal_server-terminal-window.o `test -f 'terminal-window.c' || echo '$(srcdir)/'`terminal-window.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-window.Tpo $(DEPDIR)/gnome_terminal_server-terminal-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-window.c' object='gnome_terminal_server-terminal-window.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-window.o `test -f 'terminal-window.c' || echo '$(srcdir)/'`terminal-window.c
+
+gnome_terminal_server-terminal-window.obj: terminal-window.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-window.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-window.Tpo -c -o gnome_terminal_server-terminal-window.obj `if test -f 'terminal-window.c'; then $(CYGPATH_W) 'terminal-window.c'; else $(CYGPATH_W) '$(srcdir)/terminal-window.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-window.Tpo $(DEPDIR)/gnome_terminal_server-terminal-window.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-window.c' object='gnome_terminal_server-terminal-window.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-window.obj `if test -f 'terminal-window.c'; then $(CYGPATH_W) 'terminal-window.c'; else $(CYGPATH_W) '$(srcdir)/terminal-window.c'; fi`
+
+gnome_terminal_server-terminal-search-provider.o: terminal-search-provider.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-search-provider.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-search-provider.Tpo -c -o gnome_terminal_server-terminal-search-provider.o `test -f 'terminal-search-provider.c' || echo '$(srcdir)/'`terminal-search-provider.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-search-provider.Tpo $(DEPDIR)/gnome_terminal_server-terminal-search-provider.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-search-provider.c' object='gnome_terminal_server-terminal-search-provider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-search-provider.o `test -f 'terminal-search-provider.c' || echo '$(srcdir)/'`terminal-search-provider.c
+
+gnome_terminal_server-terminal-search-provider.obj: terminal-search-provider.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-search-provider.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-search-provider.Tpo -c -o gnome_terminal_server-terminal-search-provider.obj `if test -f 'terminal-search-provider.c'; then $(CYGPATH_W) 'terminal-search-provider.c'; else $(CYGPATH_W) '$(srcdir)/terminal-search-provider.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-search-provider.Tpo $(DEPDIR)/gnome_terminal_server-terminal-search-provider.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-search-provider.c' object='gnome_terminal_server-terminal-search-provider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-search-provider.obj `if test -f 'terminal-search-provider.c'; then $(CYGPATH_W) 'terminal-search-provider.c'; else $(CYGPATH_W) '$(srcdir)/terminal-search-provider.c'; fi`
+
+gnome_terminal_server-terminal-marshal.o: terminal-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-marshal.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-marshal.Tpo -c -o gnome_terminal_server-terminal-marshal.o `test -f 'terminal-marshal.c' || echo '$(srcdir)/'`terminal-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-marshal.Tpo $(DEPDIR)/gnome_terminal_server-terminal-marshal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-marshal.c' object='gnome_terminal_server-terminal-marshal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-marshal.o `test -f 'terminal-marshal.c' || echo '$(srcdir)/'`terminal-marshal.c
+
+gnome_terminal_server-terminal-marshal.obj: terminal-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-marshal.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-marshal.Tpo -c -o gnome_terminal_server-terminal-marshal.obj `if test -f 'terminal-marshal.c'; then $(CYGPATH_W) 'terminal-marshal.c'; else $(CYGPATH_W) '$(srcdir)/terminal-marshal.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-marshal.Tpo $(DEPDIR)/gnome_terminal_server-terminal-marshal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-marshal.c' object='gnome_terminal_server-terminal-marshal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-marshal.obj `if test -f 'terminal-marshal.c'; then $(CYGPATH_W) 'terminal-marshal.c'; else $(CYGPATH_W) '$(srcdir)/terminal-marshal.c'; fi`
+
+gnome_terminal_server-terminal-type-builtins.o: terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-type-builtins.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Tpo -c -o gnome_terminal_server-terminal-type-builtins.o `test -f 'terminal-type-builtins.c' || echo '$(srcdir)/'`terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Tpo $(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-type-builtins.c' object='gnome_terminal_server-terminal-type-builtins.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-type-builtins.o `test -f 'terminal-type-builtins.c' || echo '$(srcdir)/'`terminal-type-builtins.c
+
+gnome_terminal_server-terminal-type-builtins.obj: terminal-type-builtins.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-type-builtins.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Tpo -c -o gnome_terminal_server-terminal-type-builtins.obj `if test -f 'terminal-type-builtins.c'; then $(CYGPATH_W) 'terminal-type-builtins.c'; else $(CYGPATH_W) '$(srcdir)/terminal-type-builtins.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Tpo $(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-type-builtins.c' object='gnome_terminal_server-terminal-type-builtins.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-type-builtins.obj `if test -f 'terminal-type-builtins.c'; then $(CYGPATH_W) 'terminal-type-builtins.c'; else $(CYGPATH_W) '$(srcdir)/terminal-type-builtins.c'; fi`
+
+gnome_terminal_server-terminal-gdbus-generated.o: terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-gdbus-generated.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Tpo -c -o gnome_terminal_server-terminal-gdbus-generated.o `test -f 'terminal-gdbus-generated.c' || echo '$(srcdir)/'`terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Tpo $(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-gdbus-generated.c' object='gnome_terminal_server-terminal-gdbus-generated.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-gdbus-generated.o `test -f 'terminal-gdbus-generated.c' || echo '$(srcdir)/'`terminal-gdbus-generated.c
+
+gnome_terminal_server-terminal-gdbus-generated.obj: terminal-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-gdbus-generated.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Tpo -c -o gnome_terminal_server-terminal-gdbus-generated.obj `if test -f 'terminal-gdbus-generated.c'; then $(CYGPATH_W) 'terminal-gdbus-generated.c'; else $(CYGPATH_W) '$(srcdir)/terminal-gdbus-generated.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Tpo $(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-gdbus-generated.c' object='gnome_terminal_server-terminal-gdbus-generated.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-gdbus-generated.obj `if test -f 'terminal-gdbus-generated.c'; then $(CYGPATH_W) 'terminal-gdbus-generated.c'; else $(CYGPATH_W) '$(srcdir)/terminal-gdbus-generated.c'; fi`
+
+gnome_terminal_server-terminal-resources.o: terminal-resources.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-resources.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-resources.Tpo -c -o gnome_terminal_server-terminal-resources.o `test -f 'terminal-resources.c' || echo '$(srcdir)/'`terminal-resources.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-resources.Tpo $(DEPDIR)/gnome_terminal_server-terminal-resources.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-resources.c' object='gnome_terminal_server-terminal-resources.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-resources.o `test -f 'terminal-resources.c' || echo '$(srcdir)/'`terminal-resources.c
+
+gnome_terminal_server-terminal-resources.obj: terminal-resources.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-resources.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-resources.Tpo -c -o gnome_terminal_server-terminal-resources.obj `if test -f 'terminal-resources.c'; then $(CYGPATH_W) 'terminal-resources.c'; else $(CYGPATH_W) '$(srcdir)/terminal-resources.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-resources.Tpo $(DEPDIR)/gnome_terminal_server-terminal-resources.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-resources.c' object='gnome_terminal_server-terminal-resources.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-resources.obj `if test -f 'terminal-resources.c'; then $(CYGPATH_W) 'terminal-resources.c'; else $(CYGPATH_W) '$(srcdir)/terminal-resources.c'; fi`
+
+gnome_terminal_server-terminal-search-provider-gdbus-generated.o: terminal-search-provider-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-search-provider-gdbus-generated.o -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Tpo -c -o gnome_terminal_server-terminal-search-provider-gdbus-generated.o `test -f 'terminal-search-provider-gdbus-generated.c' || echo '$(srcdir)/'`terminal-search-provider-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Tpo $(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-search-provider-gdbus-generated.c' object='gnome_terminal_server-terminal-search-provider-gdbus-generated.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-search-provider-gdbus-generated.o `test -f 'terminal-search-provider-gdbus-generated.c' || echo '$(srcdir)/'`terminal-search-provider-gdbus-generated.c
+
+gnome_terminal_server-terminal-search-provider-gdbus-generated.obj: terminal-search-provider-gdbus-generated.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -MT gnome_terminal_server-terminal-search-provider-gdbus-generated.obj -MD -MP -MF $(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Tpo -c -o gnome_terminal_server-terminal-search-provider-gdbus-generated.obj `if test -f 'terminal-search-provider-gdbus-generated.c'; then $(CYGPATH_W) 'terminal-search-provider-gdbus-generated.c'; else $(CYGPATH_W) '$(srcdir)/terminal-search-provider-gdbus-generated.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Tpo $(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-search-provider-gdbus-generated.c' object='gnome_terminal_server-terminal-search-provider-gdbus-generated.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnome_terminal_server_CPPFLAGS) $(CPPFLAGS) $(gnome_terminal_server_CFLAGS) $(CFLAGS) -c -o gnome_terminal_server-terminal-search-provider-gdbus-generated.obj `if test -f 'terminal-search-provider-gdbus-generated.c'; then $(CYGPATH_W) 'terminal-search-provider-gdbus-generated.c'; else $(CYGPATH_W) '$(srcdir)/terminal-search-provider-gdbus-generated.c'; fi`
+
+terminal_regex-terminal-regex.o: terminal-regex.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(terminal_regex_CPPFLAGS) $(CPPFLAGS) $(terminal_regex_CFLAGS) $(CFLAGS) -MT terminal_regex-terminal-regex.o -MD -MP -MF $(DEPDIR)/terminal_regex-terminal-regex.Tpo -c -o terminal_regex-terminal-regex.o `test -f 'terminal-regex.c' || echo '$(srcdir)/'`terminal-regex.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/terminal_regex-terminal-regex.Tpo $(DEPDIR)/terminal_regex-terminal-regex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-regex.c' object='terminal_regex-terminal-regex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(terminal_regex_CPPFLAGS) $(CPPFLAGS) $(terminal_regex_CFLAGS) $(CFLAGS) -c -o terminal_regex-terminal-regex.o `test -f 'terminal-regex.c' || echo '$(srcdir)/'`terminal-regex.c
+
+terminal_regex-terminal-regex.obj: terminal-regex.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(terminal_regex_CPPFLAGS) $(CPPFLAGS) $(terminal_regex_CFLAGS) $(CFLAGS) -MT terminal_regex-terminal-regex.obj -MD -MP -MF $(DEPDIR)/terminal_regex-terminal-regex.Tpo -c -o terminal_regex-terminal-regex.obj `if test -f 'terminal-regex.c'; then $(CYGPATH_W) 'terminal-regex.c'; else $(CYGPATH_W) '$(srcdir)/terminal-regex.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/terminal_regex-terminal-regex.Tpo $(DEPDIR)/terminal_regex-terminal-regex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-regex.c' object='terminal_regex-terminal-regex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(terminal_regex_CPPFLAGS) $(CPPFLAGS) $(terminal_regex_CFLAGS) $(CFLAGS) -c -o terminal_regex-terminal-regex.obj `if test -f 'terminal-regex.c'; then $(CYGPATH_W) 'terminal-regex.c'; else $(CYGPATH_W) '$(srcdir)/terminal-regex.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-dbusserviceDATA: $(dbusservice_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(dbusservicedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(dbusservicedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbusservicedir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(dbusservicedir)" || exit $$?; \
+ done
+
+uninstall-dbusserviceDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(dbusservicedir)'; $(am__uninstall_files_from_dir)
+install-dist_searchproviderDATA: $(dist_searchprovider_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_searchprovider_DATA)'; test -n "$(searchproviderdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(searchproviderdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(searchproviderdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(searchproviderdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(searchproviderdir)" || exit $$?; \
+ done
+
+uninstall-dist_searchproviderDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_searchprovider_DATA)'; test -n "$(searchproviderdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(searchproviderdir)'; $(am__uninstall_files_from_dir)
+install-nodist_systemduserDATA: $(nodist_systemduser_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(nodist_systemduser_DATA)'; test -n "$(systemduserdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(systemduserdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(systemduserdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemduserdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(systemduserdir)" || exit $$?; \
+ done
+
+uninstall-nodist_systemduserDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_systemduser_DATA)'; test -n "$(systemduserdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(systemduserdir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS: $(check_PROGRAMS)
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all $(check_PROGRAMS)
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+terminal-regex.log: terminal-regex$(EXEEXT)
+ @p='terminal-regex$(EXEEXT)'; \
+ b='terminal-regex'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(nautilusextensiondir)" "$(DESTDIR)$(dbusservicedir)" "$(DESTDIR)$(searchproviderdir)" "$(DESTDIR)$(systemduserdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
+ clean-libexecPROGRAMS clean-libtool \
+ clean-nautilusextensionLTLIBRARIES clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-client-utils.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-debug.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-i18n.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-options.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-profiles-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-settings-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-type-builtins.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-eggshell.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-profile-editor.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-server.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-accels.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-app.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-debug.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-gdbus.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-headerbar.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-i18n.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-icon-button.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-info-bar.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-marshal.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-menu-button.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-notebook.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-prefs.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-resources.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-screen-container.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-screen.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-search-popover.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-search-provider.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-settings-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-tab-label.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-util.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-window.Po
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-client-utils.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-gdbus-generated.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-i18n.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-nautilus.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-type-builtins.Plo
+ -rm -f ./$(DEPDIR)/terminal_regex-terminal-regex.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dbusserviceDATA \
+ install-dist_searchproviderDATA \
+ install-nautilusextensionLTLIBRARIES \
+ install-nodist_systemduserDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-libexecPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-client-utils.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-debug.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-gdbus-generated.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-i18n.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-options.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-profiles-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-settings-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal-type-builtins.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal-terminal.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-eggshell.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-profile-editor.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-server.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-accels.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-app.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-debug.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-gdbus-generated.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-gdbus.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-headerbar.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-i18n.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-icon-button.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-info-bar.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-marshal.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-mdi-container.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-menu-button.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-notebook.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-prefs.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-profiles-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-resources.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-screen-container.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-screen.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-search-popover.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-search-provider-gdbus-generated.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-search-provider.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-settings-list.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-tab-label.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-type-builtins.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-util.Po
+ -rm -f ./$(DEPDIR)/gnome_terminal_server-terminal-window.Po
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-client-utils.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-gdbus-generated.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-i18n.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-nautilus.Plo
+ -rm -f ./$(DEPDIR)/libterminal_nautilus_la-terminal-type-builtins.Plo
+ -rm -f ./$(DEPDIR)/terminal_regex-terminal-regex.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-dbusserviceDATA \
+ uninstall-dist_searchproviderDATA uninstall-libexecPROGRAMS \
+ uninstall-nautilusextensionLTLIBRARIES \
+ uninstall-nodist_systemduserDATA
+
+.MAKE: all check check-am install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
+ check-am clean clean-binPROGRAMS clean-checkPROGRAMS \
+ clean-generic clean-libexecPROGRAMS clean-libtool \
+ clean-nautilusextensionLTLIBRARIES clean-noinstPROGRAMS \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am \
+ install-dbusserviceDATA install-dist_searchproviderDATA \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-info install-info-am \
+ install-libexecPROGRAMS install-man \
+ install-nautilusextensionLTLIBRARIES \
+ install-nodist_systemduserDATA install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ recheck tags tags-am uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-dbusserviceDATA \
+ uninstall-dist_searchproviderDATA uninstall-libexecPROGRAMS \
+ uninstall-nautilusextensionLTLIBRARIES \
+ uninstall-nodist_systemduserDATA
+
+.PRECIOUS: Makefile
+
+
+terminal-type-builtins.h: stamp-terminal-type-builtins.h
+ @true
+
+stamp-terminal-type-builtins.h: terminal-type-builtins.h.template $(TYPES_H_FILES)
+ $(AM_V_GEN) $(GLIB_MKENUMS) --template $< $(filter-out $<,$^) > xgen-ttbh \
+ && (cmp -s xgen-ttbh terminal-type-builtins.h || cp xgen-ttbh terminal-type-builtins.h ) \
+ && rm -f xgen-ttbh \
+ && echo timestamp > $(@F)
+
+terminal-type-builtins.c: terminal-type-builtins.c.template $(TYPES_H_FILES)
+ $(AM_V_GEN) $(GLIB_MKENUMS) --template $< $(filter-out $<,$^) > xgen-ttbc \
+ && (cmp -s xgen-ttbc terminal-type-builtins.c || cp xgen-ttbc terminal-type-builtins.c ) \
+ && rm -f xgen-ttbc
+
+terminal-marshal.h: $(srcdir)/terminal-marshal.list
+ $(AM_V_GEN) ( $(GLIB_GENMARSHAL) --prefix=_terminal_marshal $(srcdir)/terminal-marshal.list \
+ --header \
+ --internal > terminal-marshal.h.tmp \
+ && mv terminal-marshal.h.tmp terminal-marshal.h ) \
+ || ( rm -f terminal-marshal.h.tmp && exit 1 )
+
+terminal-marshal.c: $(srcdir)/terminal-marshal.list
+ $(AM_V_GEN) ( echo '#include "terminal-marshal.h"' > terminal-marshal.c.tmp && \
+ $(GLIB_GENMARSHAL) --prefix=_terminal_marshal $(srcdir)/terminal-marshal.list \
+ --body \
+ --internal >> terminal-marshal.c.tmp \
+ && mv terminal-marshal.c.tmp terminal-marshal.c ) \
+ || ( rm -f terminal-marshal.c.tmp && exit 1 )
+
+org.gnome.Terminal.service: Makefile
+ $(AM_V_GEN) ( echo "[D-BUS Service]"; \
+ echo "Name=org.gnome.Terminal"; \
+ echo "SystemdService=gnome-terminal-server.service"; \
+ echo "Exec=${libexecdir}/gnome-terminal-server") > $@
+
+gnome-terminal-server.service: Makefile
+ $(AM_V_GEN) ( echo "[Unit]"; \
+ echo "Description=GNOME Terminal Server"; \
+ echo "PartOf=graphical-session.target"; \
+ echo "[Service]"; \
+ echo "Slice=app-org.gnome.Terminal.slice"; \
+ echo "Type=dbus"; \
+ echo "BusName=org.gnome.Terminal"; \
+ echo "ExecStart=${libexecdir}/gnome-terminal-server"; \
+ echo "TimeoutStopSec=5s"; \
+ echo "KillMode=process") > $@
+
+terminal-gdbus-generated.c terminal-gdbus-generated.h: org.gnome.Terminal.xml Makefile
+ $(AM_V_GEN) $(GDBUS_CODEGEN) \
+ --interface-prefix=org.gnome.Terminal \
+ --c-namespace=Terminal \
+ --c-generate-object-manager \
+ --generate-c-code terminal-gdbus-generated \
+ $<
+
+terminal-menubar-with-mnemonics.ui: terminal-menubar.ui.in
+ $(AM_V_GEN)$(SED) -e 's|<WITH_MNEMONIC>||g' -e 's|</WITH_MNEMONIC>||g' -e 's|<WITHOUT_MNEMONIC>|<!-- |g' -e 's|</WITHOUT_MNEMONIC>| -->|g' $< > $@
+
+terminal-menubar-without-mnemonics.ui: terminal-menubar.ui.in
+ $(AM_V_GEN)$(SED) -e 's|<WITH_MNEMONIC>|<!-- |g' -e 's|</WITH_MNEMONIC>| -->|g' -e 's|<WITHOUT_MNEMONIC>||g' -e 's|</WITHOUT_MNEMONIC>||g' $< > $@
+
+terminal-resources.h terminal-resources.c: terminal.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies --sourcedir $(srcdir) --sourcedir $(builddir) $(srcdir)/terminal.gresource.xml)
+ $(AM_V_GEN) XMLLINT=$(XMLLINT) $(GLIB_COMPILE_RESOURCES) --target $@ --sourcedir $(builddir) --sourcedir $(srcdir) --generate --c-name terminal $<
+
+@ENABLE_SEARCH_PROVIDER_TRUE@terminal-search-provider-gdbus-generated.c terminal-search-provider-gdbus-generated.h: $(dbusinterfacedir)/org.gnome.ShellSearchProvider2.xml Makefile
+@ENABLE_SEARCH_PROVIDER_TRUE@ $(AM_V_GEN) $(GDBUS_CODEGEN) \
+@ENABLE_SEARCH_PROVIDER_TRUE@ --interface-prefix=org.gnome.Shell \
+@ENABLE_SEARCH_PROVIDER_TRUE@ --c-namespace=Terminal \
+@ENABLE_SEARCH_PROVIDER_TRUE@ --generate-c-code terminal-search-provider-gdbus-generated \
+@ENABLE_SEARCH_PROVIDER_TRUE@ $<
+
+@GSETTINGS_RULES@
+
+-include $(top_srcdir)/git.mk
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/eggshell.c b/src/eggshell.c
new file mode 100644
index 0000000..ed4f3b5
--- /dev/null
+++ b/src/eggshell.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
+ * Copyright (C) 1999, 2000 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ @NOTATION@
+ */
+
+/*
+ *
+ * Gnome utility routines.
+ * (C) 1997, 1998, 1999 the Free Software Foundation.
+ *
+ * Author: Miguel de Icaza,
+ */
+
+#include <config.h>
+
+#include "eggshell.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#ifndef G_OS_WIN32
+#include <pwd.h>
+#endif
+
+#include <glib.h>
+
+/**
+ * egg_shell:
+ * @shell: the value of the SHELL env variable
+ *
+ * Retrieves the user's preferred shell.
+ *
+ * Returns: A newly allocated string that is the path to the shell.
+ */
+char *
+egg_shell (const char *shell)
+{
+#ifndef G_OS_WIN32
+ struct passwd *pw;
+ int i;
+ static const char shells [][14] = {
+ /* Note that on some systems shells can also
+ * be installed in /usr/bin */
+ "/bin/bash", "/usr/bin/bash",
+ "/bin/zsh", "/usr/bin/zsh",
+ "/bin/tcsh", "/usr/bin/tcsh",
+ "/bin/ksh", "/usr/bin/ksh",
+ "/bin/csh", "/bin/sh"
+ };
+
+ if (geteuid () == getuid () &&
+ getegid () == getgid ()) {
+ /* only in non-setuid */
+ if (shell != NULL) {
+ if (access (shell, X_OK) == 0) {
+ return g_strdup (shell);
+ }
+ }
+ }
+ pw = getpwuid(getuid());
+ if (pw && pw->pw_shell) {
+ if (access (pw->pw_shell, X_OK) == 0) {
+ return g_strdup (pw->pw_shell);
+ }
+ }
+
+ for (i = 0; i != G_N_ELEMENTS (shells); i++) {
+ if (access (shells [i], X_OK) == 0) {
+ return g_strdup (shells[i]);
+ }
+ }
+
+ /* If /bin/sh doesn't exist, your system is truly broken. */
+ g_assert_not_reached ();
+
+ /* Placate compiler. */
+ return NULL;
+#else
+ /* g_find_program_in_path() always looks also in the Windows
+ * and System32 directories, so it should always find either cmd.exe
+ * or command.com.
+ */
+ char *retval = g_find_program_in_path ("cmd.exe");
+
+ if (retval == NULL)
+ retval = g_find_program_in_path ("command.com");
+
+ g_assert (retval != NULL);
+
+ return retval;
+#endif
+}
diff --git a/src/eggshell.h b/src/eggshell.h
new file mode 100644
index 0000000..2312777
--- /dev/null
+++ b/src/eggshell.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
+ * Copyright (C) 1999, 2000 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ @NOTATION@
+ */
+
+#ifndef __EGG_USER_SHELL_H__
+#define __EGG_USER_SHELL_H__
+
+#include <stdlib.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/* Find the name of the user's shell. */
+char *egg_shell (const char *shell);
+
+G_END_DECLS
+
+#endif
diff --git a/src/gnome-terminal-search-provider.ini b/src/gnome-terminal-search-provider.ini
new file mode 100644
index 0000000..1b9f81c
--- /dev/null
+++ b/src/gnome-terminal-search-provider.ini
@@ -0,0 +1,20 @@
+# Copyright © 2013 Red Hat, 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+[Shell Search Provider]
+DesktopId=org.gnome.Terminal.desktop
+BusName=org.gnome.Terminal
+ObjectPath=/org/gnome/Terminal/SearchProvider
+Version=2
diff --git a/src/nautilus.symbols b/src/nautilus.symbols
new file mode 100644
index 0000000..7f58bf8
--- /dev/null
+++ b/src/nautilus.symbols
@@ -0,0 +1,3 @@
+nautilus_module_initialize
+nautilus_module_shutdown
+nautilus_module_list_types
diff --git a/src/org.gnome.Terminal.gschema.xml b/src/org.gnome.Terminal.gschema.xml
new file mode 100644
index 0000000..be00aa2
--- /dev/null
+++ b/src/org.gnome.Terminal.gschema.xml
@@ -0,0 +1,724 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2002 Havoc Pennington
+ Copyright © 2002 Jonathan Blandford
+ Copyright © 2003, 2004 Mariano Suárez-Alvarez
+ Copyright © 2005 Kjartan Maraas
+ Copyright © 2005 Tony Tsui
+ Copyright © 2006 Guilherme de S. Pastore
+ Copyright © 2009, 2010 Behdad Esfahbod
+ Copyright © 2008, 2010 Christian Persch
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<schemalist gettext-domain="gnome-terminal">
+
+ <enum id='org.gnome.Terminal.NewTerminalMode'>
+ <value nick='window' value='0'/>
+ <value nick='tab' value='1'/>
+ </enum>
+
+ <enum id='org.gnome.Terminal.NewTabPosition'>
+ <value nick='last' value='0'/>
+ <value nick='next' value='1'/>
+ </enum>
+
+ <enum id='org.gnome.Terminal.ScrollbarPolicy'>
+ <value nick='always' value='0'/>
+ <!-- <value nick='automatic' value='1'/> -->
+ <value nick='never' value='2'/>
+ </enum>
+
+ <enum id='org.gnome.Terminal.TabsbarPolicy'>
+ <value nick='always' value='0'/>
+ <value nick='automatic' value='1'/>
+ <!-- <value nick='never' value='2'/> -->
+ </enum>
+
+ <enum id='org.gnome.Terminal.ThemeVariant'>
+ <value nick='system' value='0'/>
+ <value nick='light' value='1'/>
+ <value nick='dark' value='2'/>
+ </enum>
+
+ <enum id='org.gnome.Terminal.ExitAction'>
+ <value nick='close' value='0'/>
+ <value nick='restart' value='1'/>
+ <value nick='hold' value='2'/>
+ </enum>
+
+ <enum id='org.gnome.Terminal.CJKWidth'>
+ <value nick='narrow' value='1'/>
+ <value nick='wide' value='2'/>
+ </enum>
+
+ <enum id="org.gnome.Terminal.PreserveWorkingDirectory">
+ <value nick="never" value='0'/>
+ <value nick="safe" value='1'/>
+ <value nick="always" value='2'/>
+ </enum>
+
+ <!-- From gtk+ -->
+ <enum id="org.gnome.Terminal.TabPosition">
+ <!-- <value nick="left" value="0" /> -->
+ <!-- <value nick="right" value="1" /> -->
+ <value nick="top" value="2" />
+ <value nick="bottom" value="3" />
+ </enum>
+
+ <!-- These really belong into some vte-built enums file, but
+ using enums from other modules still has some
+ problems. Just include a copy here for now.
+ -->
+ <enum id='org.gnome.Terminal.EraseBinding'>
+ <value nick='auto' value='0'/>
+ <value nick='ascii-backspace' value='1'/>
+ <value nick='ascii-delete' value='2'/>
+ <value nick='delete-sequence' value='3'/>
+ <value nick='tty' value='4'/>
+ </enum>
+ <enum id='org.gnome.Terminal.Cursor.BlinkMode'>
+ <value nick='system' value='0'/>
+ <value nick='on' value='1'/>
+ <value nick='off' value='2'/>
+ </enum>
+ <enum id='org.gnome.Terminal.Cursor.Shape'>
+ <value nick='block' value='0'/>
+ <value nick='ibeam' value='1'/>
+ <value nick='underline' value='2'/>
+ </enum>
+ <enum id='org.gnome.Terminal.TextBlinkMode'>
+ <value nick='never' value='0'/>
+ <value nick='focused' value='1'/>
+ <value nick='unfocused' value='2'/>
+ <value nick='always' value='3'/>
+ </enum>
+
+ <!-- SettingsList base schema -->
+
+ <schema id="org.gnome.Terminal.SettingsList">
+ <key name="list" type="as">
+ <default>[]</default>
+ </key>
+ <key name="default" type="s">
+ <default>''</default>
+ </key>
+ </schema>
+
+ <!-- Profiles list schema -->
+
+ <schema id="org.gnome.Terminal.ProfilesList"
+ extends="org.gnome.Terminal.SettingsList"
+ path="/org/gnome/terminal/legacy/profiles:/">
+ <override name="list">['b1dcc9dd-5262-4d8d-a863-c897e6d979b9']</override>
+ <override name="default">'b1dcc9dd-5262-4d8d-a863-c897e6d979b9'</override>
+ </schema>
+
+ <!-- A terminal profile -->
+
+ <schema id="org.gnome.Terminal.Legacy.Profile">
+ <key name="visible-name" type="s">
+ <!-- Translators: Keep single quote please! -->
+ <default l10n="messages" context="visible-name">'Unnamed'</default>
+ <summary>Human-readable name of the profile</summary>
+ <description>Human-readable name of the profile.</description>
+ </key>
+ <key name="foreground-color" type="s">
+ <default>'#171421'</default>
+ <summary>Default color of text in the terminal</summary>
+ <description>Default color of text in the terminal, as a color specification (can be HTML-style hex digits, or a color name such as “red”).</description>
+ </key>
+ <key name="background-color" type="s">
+ <default>'#ffffff'</default>
+ <summary>Default color of terminal background</summary>
+ <description>Default color of terminal background, as a color specification (can be HTML-style hex digits, or a color name such as “red”).</description>
+ </key>
+ <key name="bold-color" type="s">
+ <default>'#000000'</default>
+ <summary>Default color of bold text in the terminal</summary>
+ <description>Default color of bold text in the terminal, as a color specification (can be HTML-style hex digits, or a color name such as “red”). This is ignored if bold-color-same-as-fg is true.</description>
+ </key>
+ <key name="bold-color-same-as-fg" type="b">
+ <default>true</default>
+ <summary>Whether bold text should use the same color as normal text</summary>
+ <description>If true, boldface text will be rendered using the same color as normal text.</description>
+ </key>
+ <key name="cell-height-scale" type="d">
+ <range min="1.0" max="2.0" />
+ <default>1.0</default>
+ <summary>Scale factor for the cell height to increase line spacing. (Does not increase the font’s height.)</summary>
+ </key>
+ <key name="cell-width-scale" type="d">
+ <range min="1.0" max="2.0" />
+ <default>1.0</default>
+ <summary>Scale factor for the cell width to increase letter spacing. (Does not increase the font’s width.)</summary>
+ </key>
+ <key name="cursor-colors-set" type="b">
+ <default>false</default>
+ <summary>Whether to use custom cursor colors</summary>
+ <description>If true, use the cursor colors from the profile.</description>
+ </key>
+ <key name="cursor-background-color" type="s">
+ <default>'#000000'</default>
+ <summary>Cursor background color</summary>
+ <description>Custom color of the background of the terminal’s cursor, as a color specification (can be HTML-style hex digits, or a color name such as “red”). This is ignored if cursor-colors-set is false.</description>
+ </key>
+ <key name="cursor-foreground-color" type="s">
+ <default>'#ffffff'</default>
+ <summary>Cursor foreground colour</summary>
+ <description>Custom color for the foreground of the text character at the terminal’s cursor position, as a color specification (can be HTML-style hex digits, or a color name such as “red”). This is ignored if cursor-colors-set is false.</description>
+ </key>
+ <key name="highlight-colors-set" type="b">
+ <default>false</default>
+ <summary>Whether to use custom highlight colors</summary>
+ <description>If true, use the highlight colors from the profile.</description>
+ </key>
+ <key name="highlight-background-color" type="s">
+ <default>'#000000'</default>
+ <summary>Highlight background color</summary>
+ <description>Custom color of the background of the terminal’s highlight, as a color specification (can be HTML-style hex digits, or a color name such as “red”). This is ignored if highlight-colors-set is false.</description>
+ </key>
+ <key name="highlight-foreground-color" type="s">
+ <default>'#ffffff'</default>
+ <summary>Highlight foreground colour</summary>
+ <description>Custom color for the foreground of the text character at the terminal’s highlight position, as a color specification (can be HTML-style hex digits, or a color name such as “red”). This is ignored if highlight-colors-set is false.</description>
+ </key>
+ <key name="enable-bidi" type="b">
+ <default>true</default>
+ <summary>Whether to perform bidirectional text rendering</summary>
+ <description>If true, perform bidirectional text rendering (“BiDi”).</description>
+ </key>
+ <key name="enable-shaping" type="b">
+ <default>true</default>
+ <summary>Whether to perform Arabic shaping</summary>
+ <description>If true, shape Arabic text.</description>
+ </key>
+ <key name="enable-sixel" type="b">
+ <default>false</default>
+ <summary>Whether to enable SIXEL images</summary>
+ <description>If true, SIXEL sequences are parsed and images are rendered.</description>
+ </key>
+ <key name="bold-is-bright" type="b">
+ <default>false</default>
+ <summary>Whether bold is also bright</summary>
+ <description>If true, setting bold on the first 8 colors also switches to their bright variants.</description>
+ </key>
+ <key name="audible-bell" type="b">
+ <default>true</default>
+ <summary>Whether to ring the terminal bell</summary>
+ </key>
+ <key name="word-char-exceptions" type="ms">
+ <default>nothing</default>
+ <summary>List of ASCII punctuation characters that are not to be treated as part of a word when doing word-wise selection</summary>
+ </key>
+ <key name="default-size-columns" type="i">
+ <range min="16" max="511" />
+ <default>80</default>
+ <summary>Default number of columns</summary>
+ <description>Number of columns in newly created terminal windows. Has no effect if use_custom_default_size is not enabled.</description>
+ </key>
+ <key name="default-size-rows" type="i">
+ <range min="4" max="511" />
+ <default>24</default>
+ <summary>Default number of rows</summary>
+ <description>Number of rows in newly created terminal windows. Has no effect if use_custom_default_size is not enabled.</description>
+ </key>
+ <key name="scrollbar-policy" enum="org.gnome.Terminal.ScrollbarPolicy">
+ <default>'always'</default>
+ <summary>When to show the scrollbar</summary>
+ </key>
+ <key name="scrollback-lines" type="i">
+ <default>10000</default>
+ <summary>Number of lines to keep in scrollback</summary>
+ <description>Number of scrollback lines to keep around. You can scroll back in the terminal by this number of lines; lines that don’t fit in the scrollback are discarded. If scrollback_unlimited is true, this value is ignored.</description>
+ </key>
+ <key name="scrollback-unlimited" type="b">
+ <default>false</default>
+ <summary>Whether an unlimited number of lines should be kept in scrollback</summary>
+ <description>If true, scrollback lines will never be discarded. The scrollback history is stored on disk temporarily, so this may cause the system to run out of disk space if there is a lot of output to the terminal.</description>
+ </key>
+ <key name="scroll-on-keystroke" type="b">
+ <default>true</default>
+ <summary>Whether to scroll to the bottom when a key is pressed</summary>
+ <description>If true, pressing a key jumps the scrollbar to the bottom.</description>
+ </key>
+ <key name="scroll-on-output" type="b">
+ <default>false</default>
+ <summary>Whether to scroll to the bottom when there’s new output</summary>
+ <description>If true, whenever there’s new output the terminal will scroll to the bottom.</description>
+ </key>
+ <key name="exit-action" enum="org.gnome.Terminal.ExitAction">
+ <default>'close'</default>
+ <summary>What to do with the terminal when the child command exits</summary>
+ <description>Possible values are “close” to close the terminal, “restart” to restart the command, and “hold” to keep the terminal open with no command running inside.</description>
+ </key>
+ <key name="login-shell" type="b">
+ <default>false</default>
+ <summary>Whether to launch the command in the terminal as a login shell</summary>
+ <description>If true, the command inside the terminal will be launched as a login shell (argv[0] will have a hyphen in front of it).</description>
+ </key>
+ <key name="preserve-working-directory" enum="org.gnome.Terminal.PreserveWorkingDirectory">
+ <default>'safe'</default>
+ <summary>Whether to preserve the working directory when opening a new terminal</summary>
+ <description>
+ Controls when opening a new terminal from a previous one carries over the working directory of the opening terminal to the new one.
+ </description>
+ </key>
+ <key name="use-custom-command" type="b">
+ <default>false</default>
+ <summary>Whether to run a custom command instead of the shell</summary>
+ <description>If true, the value of the custom_command setting will be used in place of running a shell.</description>
+ </key>
+ <key name="cursor-blink-mode" enum="org.gnome.Terminal.Cursor.BlinkMode">
+ <default>'system'</default>
+ <summary>Whether to blink the cursor</summary>
+ <description>The possible values are “system” to use the global cursor blinking settings, or “on” or “off” to set the mode explicitly.</description>
+ </key>
+ <key name="cursor-shape" enum="org.gnome.Terminal.Cursor.Shape">
+ <default>'block'</default>
+ <summary>The cursor appearance</summary>
+ </key>
+ <key name="text-blink-mode" enum="org.gnome.Terminal.TextBlinkMode">
+ <default>'always'</default>
+ <summary>Possible values are “always” or “never” allow blinking text, or only when the terminal is “focused” or “unfocused”.</summary>
+ </key>
+ <key name="custom-command" type="s">
+ <default>''</default>
+ <summary>Custom command to use instead of the shell</summary>
+ <description>Run this command in place of the shell, if use_custom_command is true.</description>
+ </key>
+ <key name="palette" type="as">
+ <default>['#171421',
+ '#c01c28',
+ '#26a269',
+ '#a2734c',
+ '#12488b',
+ '#a347ba',
+ '#2aa1b3',
+ '#d0cfcc',
+ '#5e5c64',
+ '#f66151',
+ '#33da7a',
+ '#e9ad0c',
+ '#2a7bde',
+ '#c061cb',
+ '#33c7de',
+ '#ffffff']</default>
+ <summary>Palette for terminal applications</summary>
+ </key>
+ <key name="font" type="s">
+ <default>'Monospace 12'</default>
+ <summary>A Pango font name and size</summary>
+ </key>
+ <key name="backspace-binding" enum="org.gnome.Terminal.EraseBinding">
+ <default>'ascii-delete'</default>
+ <summary>The code sequence the Backspace key generates</summary>
+ </key>
+ <key name="delete-binding" enum="org.gnome.Terminal.EraseBinding">
+ <default>'delete-sequence'</default>
+ <summary>The code sequence the Delete key generates</summary>
+ </key>
+ <key name="use-theme-colors" type="b">
+ <default>true</default>
+ <summary>Whether to use the colors from the theme for the terminal widget</summary>
+ </key>
+ <key name="use-system-font" type="b">
+ <default>true</default>
+ <summary>Whether to use the system monospace font</summary>
+ </key>
+ <key name="rewrap-on-resize" type="b">
+ <default>true</default>
+ <summary>Whether to rewrap the terminal contents on window resize</summary>
+ </key>
+ <key name="encoding" type="s">
+ <default>'UTF-8'</default>
+ <summary>Which encoding to use</summary>
+ </key>
+ <key name="cjk-utf8-ambiguous-width" enum="org.gnome.Terminal.CJKWidth">
+ <default>'narrow'</default>
+ <summary>Whether ambiguous-width characters are narrow or wide when using UTF-8 encoding</summary>
+ </key>
+ </schema>
+
+ <!-- Keybinding settings -->
+
+ <schema id="org.gnome.Terminal.Legacy.Keybindings">
+ <key name="new-tab" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;t'</default>
+ <summary>Keyboard shortcut to open a new tab</summary>
+ </key>
+ <key name="new-window" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;n'</default>
+ <summary>Keyboard shortcut to open a new window</summary>
+ </key>
+ <key name="save-contents" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to save the current tab contents to file</summary>
+ </key>
+ <key name="export" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to export the current tab contents to file in various formats</summary>
+ </key>
+ <key name="print" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to print the current tab contents to printer or file</summary>
+ </key>
+ <key name="close-tab" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;w'</default>
+ <summary>Keyboard shortcut to close a tab</summary>
+ </key>
+ <key name="close-window" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;q'</default>
+ <summary>Keyboard shortcut to close a window</summary>
+ </key>
+ <key name="copy" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;c'</default>
+ <summary>Keyboard shortcut to copy text</summary>
+ </key>
+ <key name="copy-html" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to copy text as HTML</summary>
+ </key>
+ <key name="paste" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;v'</default>
+ <summary>Keyboard shortcut to paste text</summary>
+ </key>
+ <key name="select-all" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to select all text</summary>
+ </key>
+ <key name="preferences" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to open the Preferences dialog</summary>
+ </key>
+ <key name="full-screen" type="s">
+ <default>'F11'</default>
+ <summary>Keyboard shortcut to toggle full screen mode</summary>
+ </key>
+ <key name="toggle-menubar" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to toggle the visibility of the menubar</summary>
+ </key>
+ <key name="read-only" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to toggle the read-only state</summary>
+ </key>
+ <key name="reset" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to reset the terminal</summary>
+ </key>
+ <key name="reset-and-clear" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to reset and clear the terminal</summary>
+ </key>
+ <key name="find" type="s">
+ <default>'&lt;Control&gt;&lt;Shift&gt;F'</default>
+ <summary>Keyboard shortcut to open the search dialog</summary>
+ </key>
+ <key name="find-next" type="s">
+ <default>'&lt;Control&gt;&lt;Shift&gt;G'</default>
+ <summary>Keyboard shortcut to find the next occurrence of the search term</summary>
+ </key>
+ <key name="find-previous" type="s">
+ <default>'&lt;Control&gt;&lt;Shift&gt;H'</default>
+ <summary>Keyboard shortcut to find the previous occurrence of the search term</summary>
+ </key>
+ <key name="find-clear" type="s">
+ <default>'&lt;Control&gt;&lt;Shift&gt;J'</default>
+ <summary>Keyboard shortcut to clear the find highlighting</summary>
+ </key>
+ <key name="prev-tab" type="s">
+ <default>'&lt;Control&gt;Page_Up'</default>
+ <summary>Keyboard shortcut to switch to the previous tab</summary>
+ </key>
+ <key name="next-tab" type="s">
+ <default>'&lt;Control&gt;Page_Down'</default>
+ <summary>Keyboard shortcut to switch to the next tab</summary>
+ </key>
+ <key name="move-tab-left" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;Page_Up'</default>
+ <summary>Keyboard shortcut to move the current tab to the left</summary>
+ </key>
+ <key name="move-tab-right" type="s">
+ <default>'&lt;Ctrl&gt;&lt;Shift&gt;Page_Down'</default>
+ <summary>Keyboard shortcut to move the current tab to the right</summary>
+ </key>
+ <key name="detach-tab" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to detach current tab</summary>
+ </key>
+ <key name="switch-to-tab-1" type="s">
+ <default>'&lt;Alt&gt;1'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-2" type="s">
+ <default>'&lt;Alt&gt;2'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-3" type="s">
+ <default>'&lt;Alt&gt;3'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-4" type="s">
+ <default>'&lt;Alt&gt;4'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-5" type="s">
+ <default>'&lt;Alt&gt;5'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-6" type="s">
+ <default>'&lt;Alt&gt;6'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-7" type="s">
+ <default>'&lt;Alt&gt;7'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-8" type="s">
+ <default>'&lt;Alt&gt;8'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-9" type="s">
+ <default>'&lt;Alt&gt;9'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-10" type="s">
+ <default>'&lt;Alt&gt;0'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-11" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-12" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-13" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-14" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-15" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-16" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-17" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-18" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-19" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-20" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-21" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-22" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-23" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-24" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-25" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-26" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-27" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-28" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-29" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-30" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-31" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-32" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-33" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-34" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-35" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the numbered tab</summary>
+ </key>
+ <key name="switch-to-tab-last" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the last tab</summary>
+ </key>
+ <key name="help" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to launch help</summary>
+ </key>
+ <key name="zoom-in" type="s">
+ <default>'&lt;Ctrl&gt;plus'</default>
+ <summary>Keyboard shortcut to make font larger</summary>
+ </key>
+ <key name="zoom-out" type="s">
+ <default>'&lt;Ctrl&gt;minus'</default>
+ <summary>Keyboard shortcut to make font smaller</summary>
+ </key>
+ <key name="zoom-normal" type="s">
+ <default>'&lt;Ctrl&gt;0'</default>
+ <summary>Keyboard shortcut to make font normal-size</summary>
+ </key>
+ <key name="header-menu" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to show the primary menu</summary>
+ </key>
+ </schema>
+
+ <!-- Global settings -->
+
+ <schema id="org.gnome.Terminal.Legacy.Settings" path="/org/gnome/terminal/legacy/">
+
+ <key name="mnemonics-enabled" type="b">
+ <default>false</default>
+ <summary>Whether the menubar has access keys</summary>
+ <description>
+ Whether to have Alt+letter access keys for the menubar.
+ They may interfere with some applications run inside the terminal
+ so it’s possible to turn them off.
+ </description>
+ </key>
+
+ <key name="shortcuts-enabled" type="b">
+ <default>true</default>
+ <summary>Whether shortcuts are enabled</summary>
+ <description>
+ Whether shortcuts are enabled.
+ They may interfere with some applications run inside the terminal
+ so it’s possible to turn them off.
+ </description>
+ </key>
+
+ <key name="menu-accelerator-enabled" type="b">
+ <default>true</default>
+ <summary>Whether the standard GTK shortcut for menubar access is enabled</summary>
+ <description>
+ Normally you can access the menubar with F10. This can also
+ be customized via gtkrc (gtk-menu-bar-accel =
+ "whatever"). This option allows the standard menubar
+ accelerator to be disabled.
+ </description>
+ </key>
+
+ <key name="shell-integration-enabled" type="b">
+ <default>true</default>
+ <summary>Whether the shell integration is enabled</summary>
+ </key>
+
+ <key name="confirm-close" type="b">
+ <default>true</default>
+ <summary>Whether to ask for confirmation before closing a terminal</summary>
+ </key>
+
+ <key name="default-show-menubar" type="b">
+ <default>true</default>
+ <summary>Whether to show the menubar in new windows</summary>
+ </key>
+
+ <key name="new-terminal-mode" enum="org.gnome.Terminal.NewTerminalMode">
+ <default>'window'</default>
+ <summary>Whether to open new terminals as windows or tabs</summary>
+ </key>
+
+ <key name="tab-policy" enum="org.gnome.Terminal.TabsbarPolicy">
+ <default>'automatic'</default>
+ <summary>When to show the tabs bar</summary>
+ </key>
+
+ <key name="tab-position" enum="org.gnome.Terminal.TabPosition">
+ <default>'top'</default>
+ <summary>The position of the tab bar</summary>
+ </key>
+
+ <key name="theme-variant" enum="org.gnome.Terminal.ThemeVariant">
+ <default>'system'</default>
+ <summary>Which theme variant to use</summary>
+ </key>
+
+ <key name="new-tab-position" enum="org.gnome.Terminal.NewTabPosition">
+ <default>'last'</default>
+ <summary>Whether new tabs should open next to the current one or at the last position</summary>
+ </key>
+
+ <!-- Note that changing the following settings will only take effect
+ when gnome-terminal-server is restarted.
+ -->
+
+ <key name="headerbar" type="mb">
+ <default>nothing</default>
+ </key>
+
+ <key name="unified-menu" type="b">
+ <default>true</default>
+ </key>
+
+ <!-- <child name="profiles" schema="org.gnome.Terminal.ProfilesList" /> -->
+
+ <child name="keybindings" schema="org.gnome.Terminal.Legacy.Keybindings" />
+
+ <key name="schema-version" type="u">
+ <default>3</default>
+ </key>
+
+ </schema>
+
+</schemalist>
diff --git a/src/org.gnome.Terminal.xml b/src/org.gnome.Terminal.xml
new file mode 100644
index 0000000..a6ada0e
--- /dev/null
+++ b/src/org.gnome.Terminal.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Introspection 0.1//EN"
+ "http://www.freedesktop.org/software/dbus/introspection.dtd">
+<!--
+ Copyright © 2011 Christian Persch
+
+ 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 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope conf it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<node>
+ <interface name="org.gnome.Terminal.Factory0">
+ <annotation name="org.gtk.GDBus.C.Name" value="Factory" />
+ <method name="CreateInstance">
+ <arg type="a{sv}" name="options" direction="in" />
+ <arg type="o" name="receiver" direction="out" />
+ </method>
+ </interface>
+
+ <interface name="org.gnome.Terminal.Terminal0">
+ <annotation name="org.gtk.GDBus.C.Name" value="Receiver" />
+ <method name="Exec">
+ <annotation name="org.gtk.GDBus.C.UnixFD" value="true" />
+ <arg type="a{sv}" name="options" direction="in" />
+ <arg type="aay" name="arguments" direction="in">
+ <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true" />
+ </arg>
+ </method>
+
+ <signal name="ChildExited">
+ <arg type="i" name="exit_code" direction="in" />
+ </signal>
+ </interface>
+</node>
diff --git a/src/preferences.ui b/src/preferences.ui
new file mode 100644
index 0000000..d1aca7b
--- /dev/null
+++ b/src/preferences.ui
@@ -0,0 +1,2453 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.19.0 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkListStore" id="new-terminal-mode-liststore">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="Open new terminal in new window">Window</col>
+ <col id="1">window</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Open new terminal in new tab">Tab</col>
+ <col id="1">tab</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="new-tab-position-liststore">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="New tab opens at the last position">Last</col>
+ <col id="1">last</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="New tab opens next to current tab">Next</col>
+ <col id="1">next</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="theme-variant-liststore">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" context="theme variant">Default</col>
+ <col id="1">system</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="theme variant">Light</col>
+ <col id="1">light</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="theme variant">Dark</col>
+ <col id="1">dark</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">16</property>
+ <property name="upper">511</property>
+ <property name="value">80</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="lower">4</property>
+ <property name="upper">511</property>
+ <property name="value">24</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment4">
+ <property name="lower">0</property>
+ <property name="upper">2147483647</property>
+ <property name="value">10000</property>
+ <property name="step_increment">1000</property>
+ <property name="page_increment">10000</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment5">
+ <property name="lower">1.0</property>
+ <property name="upper">2.0</property>
+ <property name="value">1.0</property>
+ <property name="step_increment">0.05</property>
+ <property name="page_increment">0.25</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment6">
+ <property name="lower">1.0</property>
+ <property name="upper">2.0</property>
+ <property name="value">1.0</property>
+ <property name="step_increment">0.05</property>
+ <property name="page_increment">0.25</property>
+ </object>
+ <object class="GtkListStore" id="cjk-ambiguous-width-model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="ambiguous-width characers are">Narrow</col>
+ <col id="1">narrow</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="ambiguous-width characers are">Wide</col>
+ <col id="1">wide</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model1">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="Cursor shape">Block</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Cursor shape">I-Beam</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Cursor shape">Underline</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model7">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="Cursor blink mode">Default</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Cursor blink mode">Enabled</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Cursor blink mode">Disabled</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model5">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="Text blink mode">Never</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Text blink mode">When focused</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Text blink mode">When unfocused</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Text blink mode">Always</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model2">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="When terminal commands set their own titles">Replace initial title</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="When terminal commands set their own titles">Append initial title</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="When terminal commands set their own titles">Prepend initial title</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="When terminal commands set their own titles">Keep initial title</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model3">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="When command exits">Exit the terminal</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="When command exits">Restart the command</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="When command exits">Hold the terminal open</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model4">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="This is the name of a colour scheme">GNOME</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This is the name of a colour scheme">Tango</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This is the name of a colour scheme">Linux console</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This is the name of a colour scheme">XTerm</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This is the name of a colour scheme">Rxvt</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This is the name of a colour scheme">Solarized</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This is the name of a colour scheme">Custom</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model6">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="This refers to the Delete keybinding option">Automatic</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This refers to the Delete keybinding option">Control-H</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This refers to the Delete keybinding option">ASCII DEL</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This refers to the Delete keybinding option">Escape sequence</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="This refers to the Delete keybinding option">TTY Erase</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="preserve-working-directory-model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" comments="Preserve working directory">Never</col>
+ <col id="1">never</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Preserve working directory">Shell only</col>
+ <col id="1">safe</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" comments="Preserve working directory">Always</col>
+ <col id="1">always</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkApplicationWindow" id="preferences-dialog">
+ <property name="can_focus">False</property>
+ <property name="show_menubar">False</property>
+ <property name="role">gnome-terminal-preferences</property>
+ <property name="resizable">False</property>
+ <child>
+ <object class="GtkBox" id="dialogue-content-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="main-hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkFrame">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkListBox" id="the-listbox">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="the-stack">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkEventBox" id="bug722114-comment25-1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkFrame" id="general-frame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="default-show-menubar-checkbutton">
+ <property name="label" translatable="yes">_Show menubar by default in new terminals</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="disable-mnemonics-checkbutton">
+ <property name="label" translatable="yes">_Enable mnemonics (such as Alt+F to open the File menu)</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="disable-menu-accel-checkbutton">
+ <property name="label" translatable="yes">Enable the _menu accelerator key (F10 by default)</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="theme-variant-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Theme _variant:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">theme-variant-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="theme-variant-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">theme-variant-liststore</property>
+ <property name="id_column">1</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer1a"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="new-terminal-mode-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Open _new terminals in:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">new-terminal-mode-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="new-terminal-mode-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">new-terminal-mode-liststore</property>
+ <property name="id_column">1</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer2a"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="new-tab-position-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">New tab _position:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">new-tab-position-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="new-tab-position-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">new-tab-position-liststore</property>
+ <property name="id_column">1</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer3a"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">general-prefs</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox" id="bug722114-comment25-2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkFrame" id="keybindings-frame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="disable-shortcuts-checkbutton">
+ <property name="label" translatable="yes">_Enable shortcuts</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkTreeView" id="accelerators-treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="rules_hint">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">shortcut-prefs</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox" id="bug722114-comment25-3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkNotebook" id="profile-editor-notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkGrid" id="general-table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Text Appearance</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="default-size-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="label" translatable="yes">Initial terminal si_ze:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">default-size-columns-spinbutton</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="default-size-columns-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSpinButton" id="default-size-columns-spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="numeric">True</property>
+ <property name="input_hints">GTK_INPUT_HINT_NO_EMOJI</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="default-size-columns-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">columns</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="default-size-rows-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSpinButton" id="default-size-rows-spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment2</property>
+ <property name="numeric">True</property>
+ <property name="input_hints">GTK_INPUT_HINT_NO_EMOJI</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="default-size-rows-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">rows</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="default-size-reset-button">
+ <property name="label" translatable="yes">Rese_t</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="focus_on_click">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="custom-font-checkbutton">
+ <property name="label" translatable="yes">Custom _font:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_start">12</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFontButton" id="font-selector">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="focus_on_click">False</property>
+ <property name="font">Sans 12</property>
+ <property name="title" translatable="yes">Choose A Terminal Font</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">1</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="label" translatable="yes">Cell spaci_ng:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">cell-width-scale-spinbutton</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSpinButton" id="cell-width-scale-spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment5</property>
+ <property name="digits">2</property>
+ <property name="numeric">True</property>
+ <property name="input_hints">GTK_INPUT_HINT_NO_EMOJI</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="cell-width-scale-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSpinButton" id="cell-height-scale-spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment6</property>
+ <property name="digits">2</property>
+ <property name="numeric">True</property>
+ <property name="input_hints">GTK_INPUT_HINT_NO_EMOJI</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="cell-height-scale-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cell-scale-reset-button">
+ <property name="label" translatable="yes">Rese_t</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="focus_on_click">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label481">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="label" translatable="yes">Allow b_linking text:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">text-blink-mode-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="text-blink-mode-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model5</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer2"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">1</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">12</property>
+ <property name="label" translatable="yes">Cursor</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="left_attach">0</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label480">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="label" translatable="yes">Cursor _shape:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">cursor-shape-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">6</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="cursor-shape-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model1</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">6</property>
+ <property name="left_attach">1</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="label" translatable="yes">Cursor blin_king:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">cursor-blink-mode-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">7</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="cursor-blink-mode-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model7</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer5"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">7</property>
+ <property name="left_attach">1</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">12</property>
+ <property name="label" translatable="yes">Sound</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="top_attach">8</property>
+ <property name="left_attach">0</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="bell-checkbutton">
+ <property name="label" translatable="yes">Terminal _bell</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_start">12</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">9</property>
+ <property name="left_attach">0</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="valign">end</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkLabel" id="profile-uuid-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Profile ID:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="profile-uuid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="selectable">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">100</property>
+ <property name="left_attach">0</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Text</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox90">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkVBox" id="vbox82">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label39">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Text and Background Color</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment10105">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox94">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="use-theme-colors-checkbutton">
+ <property name="label" translatable="yes">_Use colors from system theme</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="colors-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="builtin-color-schemes-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="color-scheme-combobox-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Built-in sche_mes:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">color-scheme-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="color-scheme-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="focus_on_click">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Text</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Background</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="foreground-colorpicker-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">_Default color:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">foreground-colorpicker</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="foreground-colorpicker">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Text Color</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="background-colorpicker">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Background Color</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="bold-color-checkbutton">
+ <property name="label" translatable="yes">Bo_ld color:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="bold-colorpicker">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Bold Text Color</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="underline-color-checkbutton">
+ <property name="label" translatable="yes">_Underline color:</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="underline-colorpicker">
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Underlined Text Color</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="cursor-colors-checkbutton">
+ <property name="label" translatable="yes">Cu_rsor color:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="cursor-foreground-colorpicker">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Cursor Foreground Color</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="cursor-background-colorpicker">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Cursor Background Color</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="highlight-colors-checkbutton">
+ <property name="label" translatable="yes">_Highlight color:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="highlight-foreground-colorpicker">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Highlight Foreground Color</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="highlight-background-colorpicker">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="title" translatable="yes">Choose Terminal Highlight Background Color</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="palette-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label42">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Palette</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment10106">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkGrid" id="table25">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="palette-optionmenu-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Built-in _schemes:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">palette-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="palette-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model4</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label43">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Color p_alette:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">palette-colorpicker-0</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="palette-table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-0">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-4">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-5">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-6">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-7">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-8">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-9">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-10">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-11">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-12">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-13">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-14">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="palette-colorpicker-15">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text">dummy</property>
+ <property name="show-editor">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">7</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="bold-is-bright-checkbutton">
+ <property name="label" translatable="yes">Show _bold text in bright colors</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label45">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Colors</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="table27">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="scrollbar-checkbutton">
+ <property name="label" translatable="yes">_Show scrollbar</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="scroll-on-output-checkbutton">
+ <property name="label" translatable="yes">Scroll on _output</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="scroll-on-keystroke-checkbutton">
+ <property name="label" translatable="yes">Scroll on _keystroke</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="scrollback-limited-checkbutton">
+ <property name="label" translatable="yes">_Limit scrollback to:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ <property name="hexpand">False</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="scrollback-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkSpinButton" id="scrollback-lines-spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment4</property>
+ <property name="numeric">True</property>
+ <property name="input_hints">GTK_INPUT_HINT_NO_EMOJI</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="scrollback-lines-spinbutton-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">lines</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">scrollback-lines-spinbutton</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label60">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Scrolling</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="login-shell-checkbutton">
+ <property name="label" translatable="yes">_Run command as a login shell</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="use-custom-command-checkbutton">
+ <property name="label" translatable="yes">Ru_n a custom command instead of my shell</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="custom-command-entry-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Custom co_mmand:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">custom-command-entry</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="custom-command-entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="input_hints">GTK_INPUT_HINT_NO_EMOJI</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="preserve-working-directory-checkbutton-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Preserve working directory:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">preserve-working-directory-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="preserve-working-directory-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">preserve-working-directory-model</property>
+ <property name="focus_on_click">False</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkCellRendererText" id="preserve-working-directory-renderer"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="exit-action-combobox-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">When command _exits:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">exit-action-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="exit-action-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model3</property>
+ <property name="focus_on_click">False</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer3"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label38">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Command</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="table30">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="backspace-binding-combobox-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Backspace key generates:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">backspace-binding-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="backspace-binding-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model6</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer6"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="delete-binding-combobox-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Delete key generates:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">delete-binding-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="delete-binding-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model6</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer7"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="encoding-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Encoding:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">encoding-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="encoding-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="focus_on_click">False</property>
+ <property name="id_column">0</property>
+ <child>
+ <object class="GtkCellRendererText" id="encoding-combobox-renderer"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="cjk-ambiguous-width-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Ambiguous-_width characters:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">cjk-ambiguous-width-combobox</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="cjk-ambiguous-width-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">cjk-ambiguous-width-model</property>
+ <property name="focus_on_click">False</property>
+ <property name="id_column">1</property>
+ <child>
+ <object class="GtkCellRendererText" id="cjk-ambiguous-width-renderer"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="enable-sixel-checkbutton">
+ <property name="label" translatable="yes">Enable _SIXEL images</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="left_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="reset-compat-defaults-button">
+ <property name="label" translatable="yes">_Reset Compatibility Options to Defaults</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="halign">start</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="left_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label54">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Compatibility</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">profile-prefs</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="dialogue-buttonbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkButton" id="help-button">
+ <property name="label">gtk-help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <property name="focus_on_click">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close-button">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <property name="focus_on_click">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkPopoverMenu" id="popover-menu">
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="margin">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="action-name">win.clone</property>
+ <property name="text" translatable="yes">Clone…</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="action-name">win.rename</property>
+ <property name="text" translatable="yes">Rename…</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="action-name">win.delete</property>
+ <property name="text" translatable="yes">Delete…</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="orientation">horizontal</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="action-name">win.set-as-default</property>
+ <property name="text" translatable="yes">Set as default</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkPopover" id="popover-dialog">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="border_width">12</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="popover-dialog-label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="margin_bottom">6</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="popover-dialog-label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="popover-dialog-entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">start</property>
+ <property name="margin_top">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="popover-dialog-cancel">
+ <property name="label" translatable="yes">Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="popover-dialog-ok">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="sensitive">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/src/profile-editor.c b/src/profile-editor.c
new file mode 100644
index 0000000..4098f90
--- /dev/null
+++ b/src/profile-editor.c
@@ -0,0 +1,1444 @@
+/*
+ * Copyright © 2002 Havoc Pennington
+ * Copyright © 2002 Mathias Hasselmann
+ * Copyright © 2008, 2011, 2017 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <math.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "terminal-app.h"
+#include "terminal-enums.h"
+#include "profile-editor.h"
+#include "terminal-prefs.h"
+#include "terminal-schemas.h"
+#include "terminal-type-builtins.h"
+#include "terminal-util.h"
+#include "terminal-profiles-list.h"
+#include "terminal-libgsystem.h"
+
+
+/* Wrapper around g_signal_connect that maintains a list of the
+ * handlers installed, and can disconnect them all. */
+typedef struct {
+ gpointer instance;
+ gulong handler_id;
+} ProfilePrefsSignal;
+
+static void
+profile_prefs_register_signal_handler (gpointer instance,
+ gulong handler_id)
+{
+ ProfilePrefsSignal sig;
+ sig.instance = instance;
+ sig.handler_id = handler_id;
+ g_array_append_val (the_pref_data->profile_signals, sig);
+}
+
+static gulong
+profile_prefs_signal_connect (gpointer instance,
+ const gchar *detailed_signal,
+ GCallback c_handler,
+ gpointer data)
+{
+ gulong handler_id = g_signal_connect(instance, detailed_signal, c_handler, data);
+ profile_prefs_register_signal_handler (instance, handler_id);
+ return handler_id;
+}
+
+static void
+profile_prefs_signal_handlers_disconnect_all (void)
+{
+ for (guint i = 0; i < the_pref_data->profile_signals->len; i++) {
+ ProfilePrefsSignal *sig = &g_array_index (the_pref_data->profile_signals, ProfilePrefsSignal, i);
+ g_signal_handler_disconnect (sig->instance, sig->handler_id);
+ }
+ g_array_set_size (the_pref_data->profile_signals, 0);
+}
+
+
+/* Wrappers around g_settings_bind and friends that maintain a list of the
+ * bindings installed, and can unbind them all. */
+typedef struct {
+ gpointer object;
+ char *property;
+} ProfilePrefsBinding;
+
+static void
+profile_prefs_register_settings_binding (gpointer object,
+ const char *property)
+{
+ ProfilePrefsBinding bind;
+ bind.object = object;
+ bind.property = g_strdup (property);
+ g_array_append_val (the_pref_data->profile_bindings, bind);
+}
+
+static void
+profile_prefs_settings_bind (GSettings *settings,
+ const gchar *key,
+ gpointer object,
+ const gchar *property,
+ GSettingsBindFlags flags)
+{
+ profile_prefs_register_settings_binding (object, property);
+ g_settings_bind (settings, key, object, property, flags);
+}
+
+static void
+profile_prefs_settings_bind_with_mapping (GSettings *settings,
+ const gchar *key,
+ gpointer object,
+ const gchar *property,
+ GSettingsBindFlags flags,
+ GSettingsBindGetMapping get_mapping,
+ GSettingsBindSetMapping set_mapping,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ profile_prefs_register_settings_binding (object, property);
+ g_settings_bind_with_mapping (settings, key, object, property, flags, get_mapping, set_mapping, user_data, destroy);
+}
+
+static void
+profile_prefs_settings_bind_writable (GSettings *settings,
+ const gchar *key,
+ gpointer object,
+ const gchar *property,
+ gboolean inverted)
+{
+ profile_prefs_register_settings_binding (object, property);
+ g_settings_bind_writable (settings, key, object, property, inverted);
+}
+
+static void
+profile_prefs_settings_unbind_all (void)
+{
+ for (guint i = 0; i < the_pref_data->profile_bindings->len; i++) {
+ ProfilePrefsBinding *bind = &g_array_index (the_pref_data->profile_bindings, ProfilePrefsBinding, i);
+ g_settings_unbind (bind->object, bind->property);
+ g_free (bind->property);
+ }
+ g_array_set_size (the_pref_data->profile_bindings, 0);
+}
+
+
+typedef struct _TerminalColorScheme TerminalColorScheme;
+
+struct _TerminalColorScheme
+{
+ const char *name;
+ const GdkRGBA foreground;
+ const GdkRGBA background;
+};
+
+#define COLOR(r, g, b) { .red = (r) / 255.0, .green = (g) / 255.0, .blue = (b) / 255.0, .alpha = 1.0 }
+
+static const TerminalColorScheme color_schemes[] = {
+ { N_("Black on light yellow"),
+ COLOR (0x00, 0x00, 0x00),
+ COLOR (0xff, 0xff, 0xdd)
+ },
+ { N_("Black on white"),
+ COLOR (0x00, 0x00, 0x00),
+ COLOR (0xff, 0xff, 0xff)
+ },
+ { N_("Gray on black"),
+ COLOR (0xaa, 0xaa, 0xaa),
+ COLOR (0x00, 0x00, 0x00)
+ },
+ { N_("Green on black"),
+ COLOR (0x00, 0xff, 0x00),
+ COLOR (0x00, 0x00, 0x00)
+ },
+ { N_("White on black"),
+ COLOR (0xff, 0xff, 0xff),
+ COLOR (0x00, 0x00, 0x00)
+ },
+ /* Translators: "GNOME" is the name of a colour scheme, "light" can be translated */
+ { N_("GNOME light"),
+ COLOR (0x17, 0x14, 0x21), /* Palette entry 0 */
+ COLOR (0xff, 0xff, 0xff) /* Palette entry 15 */
+ },
+ /* Translators: "GNOME" is the name of a colour scheme, "dark" can be translated */
+ { N_("GNOME dark"),
+ COLOR (0xd0, 0xcf, 0xcc), /* Palette entry 7 */
+ COLOR (0x17, 0x14, 0x21) /* Palette entry 0 */
+ },
+ /* Translators: "Tango" is the name of a colour scheme, "light" can be translated */
+ { N_("Tango light"),
+ COLOR (0x2e, 0x34, 0x36),
+ COLOR (0xee, 0xee, 0xec)
+ },
+ /* Translators: "Tango" is the name of a colour scheme, "dark" can be translated */
+ { N_("Tango dark"),
+ COLOR (0xd3, 0xd7, 0xcf),
+ COLOR (0x2e, 0x34, 0x36)
+ },
+ /* Translators: "Solarized" is the name of a colour scheme, "light" can be translated */
+ { N_("Solarized light"),
+ COLOR (0x65, 0x7b, 0x83), /* 11: base00 */
+ COLOR (0xfd, 0xf6, 0xe3) /* 15: base3 */
+ },
+ /* Translators: "Solarized" is the name of a colour scheme, "dark" can be translated */
+ { N_("Solarized dark"),
+ COLOR (0x83, 0x94, 0x96), /* 12: base0 */
+ COLOR (0x00, 0x2b, 0x36) /* 8: base03 */
+ },
+};
+
+#define TERMINAL_PALETTE_SIZE (16)
+
+enum
+{
+ TERMINAL_PALETTE_GNOME = 0,
+ TERMINAL_PALETTE_TANGO = 1,
+ TERMINAL_PALETTE_LINUX = 2,
+ TERMINAL_PALETTE_XTERM = 3,
+ TERMINAL_PALETTE_RXVT = 4,
+ TERMINAL_PALETTE_SOLARIZED = 5,
+ TERMINAL_PALETTE_N_BUILTINS
+};
+
+static const GdkRGBA terminal_palettes[TERMINAL_PALETTE_N_BUILTINS][TERMINAL_PALETTE_SIZE] =
+{
+ /* Based on GNOME 3.32 palette: https://developer.gnome.org/hig/stable/icon-design.html.en#palette */
+ {
+ COLOR (0x17, 0x14, 0x21), /* Blend of Dark 4 and Black */
+ COLOR (0xc0, 0x1c, 0x28), /* Red 4 */
+ COLOR (0x26, 0xa2, 0x69), /* Green 5 */
+ COLOR (0xa2, 0x73, 0x4c), /* Blend of Brown 2 and Brown 3 */
+ COLOR (0x12, 0x48, 0x8b), /* Blend of Blue 5 and Dark 4 */
+ COLOR (0xa3, 0x47, 0xba), /* Purple 3 */
+ COLOR (0x2a, 0xa1, 0xb3), /* Linear addition Blue 5 + Green 5, darkened slightly */
+ COLOR (0xd0, 0xcf, 0xcc), /* Blend of Light 3 and Light 4 */
+ COLOR (0x5e, 0x5c, 0x64), /* Dark 2 */
+ COLOR (0xf6, 0x61, 0x51), /* Red 1 */
+ COLOR (0x33, 0xd1, 0x7a), /* Green 3 */
+ COLOR (0xe9, 0xad, 0x0c), /* Blend of Yellow 4 and Yellow 5 */
+ COLOR (0x2a, 0x7b, 0xde), /* Blend of Blue 3 and Blue 4 */
+ COLOR (0xc0, 0x61, 0xcb), /* Purple 2 */
+ COLOR (0x33, 0xc7, 0xde), /* Linear addition Blue 4 + Green 4, darkened slightly */
+ COLOR (0xff, 0xff, 0xff) /* Light 1 */
+ },
+
+ /* Tango palette */
+ {
+ COLOR (0x2e, 0x34, 0x36),
+ COLOR (0xcc, 0x00, 0x00),
+ COLOR (0x4e, 0x9a, 0x06),
+ COLOR (0xc4, 0xa0, 0x00),
+ COLOR (0x34, 0x65, 0xa4),
+ COLOR (0x75, 0x50, 0x7b),
+ COLOR (0x06, 0x98, 0x9a),
+ COLOR (0xd3, 0xd7, 0xcf),
+ COLOR (0x55, 0x57, 0x53),
+ COLOR (0xef, 0x29, 0x29),
+ COLOR (0x8a, 0xe2, 0x34),
+ COLOR (0xfc, 0xe9, 0x4f),
+ COLOR (0x72, 0x9f, 0xcf),
+ COLOR (0xad, 0x7f, 0xa8),
+ COLOR (0x34, 0xe2, 0xe2),
+ COLOR (0xee, 0xee, 0xec)
+ },
+
+ /* Linux palette */
+ {
+ COLOR (0x00, 0x00, 0x00),
+ COLOR (0xaa, 0x00, 0x00),
+ COLOR (0x00, 0xaa, 0x00),
+ COLOR (0xaa, 0x55, 0x00),
+ COLOR (0x00, 0x00, 0xaa),
+ COLOR (0xaa, 0x00, 0xaa),
+ COLOR (0x00, 0xaa, 0xaa),
+ COLOR (0xaa, 0xaa, 0xaa),
+ COLOR (0x55, 0x55, 0x55),
+ COLOR (0xff, 0x55, 0x55),
+ COLOR (0x55, 0xff, 0x55),
+ COLOR (0xff, 0xff, 0x55),
+ COLOR (0x55, 0x55, 0xff),
+ COLOR (0xff, 0x55, 0xff),
+ COLOR (0x55, 0xff, 0xff),
+ COLOR (0xff, 0xff, 0xff)
+ },
+
+ /* XTerm palette */
+ {
+ COLOR (0x00, 0x00, 0x00),
+ COLOR (0xcd, 0x00, 0x00),
+ COLOR (0x00, 0xcd, 0x00),
+ COLOR (0xcd, 0xcd, 0x00),
+ COLOR (0x00, 0x00, 0xee),
+ COLOR (0xcd, 0x00, 0xcd),
+ COLOR (0x00, 0xcd, 0xcd),
+ COLOR (0xe5, 0xe5, 0xe5),
+ COLOR (0x7f, 0x7f, 0x7f),
+ COLOR (0xff, 0x00, 0x00),
+ COLOR (0x00, 0xff, 0x00),
+ COLOR (0xff, 0xff, 0x00),
+ COLOR (0x5c, 0x5c, 0xff),
+ COLOR (0xff, 0x00, 0xff),
+ COLOR (0x00, 0xff, 0xff),
+ COLOR (0xff, 0xff, 0xff)
+ },
+
+ /* RXVT palette */
+ {
+ COLOR (0x00, 0x00, 0x00),
+ COLOR (0xcd, 0x00, 0x00),
+ COLOR (0x00, 0xcd, 0x00),
+ COLOR (0xcd, 0xcd, 0x00),
+ COLOR (0x00, 0x00, 0xcd),
+ COLOR (0xcd, 0x00, 0xcd),
+ COLOR (0x00, 0xcd, 0xcd),
+ COLOR (0xfa, 0xeb, 0xd7),
+ COLOR (0x40, 0x40, 0x40),
+ COLOR (0xff, 0x00, 0x00),
+ COLOR (0x00, 0xff, 0x00),
+ COLOR (0xff, 0xff, 0x00),
+ COLOR (0x00, 0x00, 0xff),
+ COLOR (0xff, 0x00, 0xff),
+ COLOR (0x00, 0xff, 0xff),
+ COLOR (0xff, 0xff, 0xff)
+ },
+
+ /* Solarized palette (1.0.0beta2): http://ethanschoonover.com/solarized */
+ {
+ COLOR (0x07, 0x36, 0x42), /* 0: base02 */
+ COLOR (0xdc, 0x32, 0x2f), /* 1: red */
+ COLOR (0x85, 0x99, 0x00), /* 2: green */
+ COLOR (0xb5, 0x89, 0x00), /* 3: yellow */
+ COLOR (0x26, 0x8b, 0xd2), /* 4: blue */
+ COLOR (0xd3, 0x36, 0x82), /* 5: magenta */
+ COLOR (0x2a, 0xa1, 0x98), /* 6: cyan */
+ COLOR (0xee, 0xe8, 0xd5), /* 7: base2 */
+ COLOR (0x00, 0x2b, 0x36), /* 8: base03 */
+ COLOR (0xcb, 0x4b, 0x16), /* 9: orange */
+ COLOR (0x58, 0x6e, 0x75), /* 10: base01 */
+ COLOR (0x65, 0x7b, 0x83), /* 11: base00 */
+ COLOR (0x83, 0x94, 0x96), /* 12: base0 */
+ COLOR (0x6c, 0x71, 0xc4), /* 13: violet */
+ COLOR (0x93, 0xa1, 0xa1), /* 14: base1 */
+ COLOR (0xfd, 0xf6, 0xe3) /* 15: base3 */
+ },
+};
+
+#undef COLOR
+
+static void profile_colors_notify_scheme_combo_cb (GSettings *profile,
+ const char *key,
+ GtkComboBox *combo);
+
+static void profile_palette_notify_scheme_combo_cb (GSettings *profile,
+ const char *key,
+ GtkComboBox *combo);
+
+static void profile_palette_notify_colorpickers_cb (GSettings *profile,
+ const char *key,
+ gpointer user_data);
+
+static void profile_notify_encoding_combo_cb (GSettings *profile,
+ const char *key,
+ GtkComboBox *combo);
+
+enum {
+ ENCODINGS_COL_ID,
+ ENCODINGS_COL_TEXT
+};
+
+/* gdk_rgba_equal is too strict! */
+static gboolean
+rgba_equal (const GdkRGBA *a,
+ const GdkRGBA *b)
+{
+ gdouble dr, dg, db;
+
+ dr = a->red - b->red;
+ dg = a->green - b->green;
+ db = a->blue - b->blue;
+
+ return (dr * dr + dg * dg + db * db) < 1e-4;
+}
+
+static gboolean
+palette_cmp (const GdkRGBA *ca,
+ const GdkRGBA *cb)
+{
+ guint i;
+
+ for (i = 0; i < TERMINAL_PALETTE_SIZE; ++i)
+ if (!rgba_equal (&ca[i], &cb[i]))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+palette_is_builtin (const GdkRGBA *colors,
+ gsize n_colors,
+ guint *n)
+{
+ guint i;
+
+ if (n_colors != TERMINAL_PALETTE_SIZE)
+ return FALSE;
+
+ for (i = 0; i < TERMINAL_PALETTE_N_BUILTINS; ++i)
+ {
+ if (palette_cmp (colors, terminal_palettes[i]))
+ {
+ *n = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+modify_palette_entry (GSettings *profile,
+ guint i,
+ const GdkRGBA *color)
+{
+ gs_free GdkRGBA *colors;
+ gsize n_colors;
+
+ /* FIXMEchpe: this can be optimised, don't really need to parse the colours! */
+
+ colors = terminal_g_settings_get_rgba_palette (profile, TERMINAL_PROFILE_PALETTE_KEY, &n_colors);
+
+ if (i < n_colors)
+ {
+ colors[i] = *color;
+ terminal_g_settings_set_rgba_palette (profile, TERMINAL_PROFILE_PALETTE_KEY,
+ colors, n_colors);
+ }
+}
+
+static void
+color_scheme_combo_changed_cb (GtkWidget *combo,
+ GParamSpec *pspec,
+ GSettings *profile)
+{
+ guint i;
+
+ i = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+ if (i < G_N_ELEMENTS (color_schemes))
+ {
+ g_signal_handlers_block_by_func (profile, G_CALLBACK (profile_colors_notify_scheme_combo_cb), combo);
+ terminal_g_settings_set_rgba (profile, TERMINAL_PROFILE_FOREGROUND_COLOR_KEY, &color_schemes[i].foreground);
+ terminal_g_settings_set_rgba (profile, TERMINAL_PROFILE_BACKGROUND_COLOR_KEY, &color_schemes[i].background);
+ g_signal_handlers_unblock_by_func (profile, G_CALLBACK (profile_colors_notify_scheme_combo_cb), combo);
+ }
+ else
+ {
+ /* "custom" selected, no change */
+ }
+}
+
+static void
+profile_colors_notify_scheme_combo_cb (GSettings *profile,
+ const char *key,
+ GtkComboBox *combo)
+{
+ GdkRGBA fg, bg;
+ guint i;
+
+ terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_FOREGROUND_COLOR_KEY, &fg);
+ terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_BACKGROUND_COLOR_KEY, &bg);
+
+ for (i = 0; i < G_N_ELEMENTS (color_schemes); ++i)
+ {
+ if (rgba_equal (&fg, &color_schemes[i].foreground) &&
+ rgba_equal (&bg, &color_schemes[i].background))
+ break;
+ }
+ /* If we didn't find a match, then we get the last combo box item which is "custom" */
+
+ g_signal_handlers_block_by_func (combo, G_CALLBACK (color_scheme_combo_changed_cb), profile);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i);
+ g_signal_handlers_unblock_by_func (combo, G_CALLBACK (color_scheme_combo_changed_cb), profile);
+}
+
+static void
+palette_scheme_combo_changed_cb (GtkComboBox *combo,
+ GParamSpec *pspec,
+ GSettings *profile)
+{
+ int i;
+
+ i = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+ g_signal_handlers_block_by_func (profile, G_CALLBACK (profile_colors_notify_scheme_combo_cb), combo);
+ if (i < TERMINAL_PALETTE_N_BUILTINS)
+ terminal_g_settings_set_rgba_palette (profile, TERMINAL_PROFILE_PALETTE_KEY,
+ terminal_palettes[i], TERMINAL_PALETTE_SIZE);
+ else
+ {
+ /* "custom" selected, no change */
+ }
+ g_signal_handlers_unblock_by_func (profile, G_CALLBACK (profile_colors_notify_scheme_combo_cb), combo);
+}
+
+static void
+profile_palette_notify_scheme_combo_cb (GSettings *profile,
+ const char *key,
+ GtkComboBox *combo)
+{
+ gs_free GdkRGBA *colors;
+ gsize n_colors;
+ guint i;
+
+ colors = terminal_g_settings_get_rgba_palette (profile, TERMINAL_PROFILE_PALETTE_KEY, &n_colors);
+ if (!palette_is_builtin (colors, n_colors, &i))
+ /* If we didn't find a match, then we want the last combo
+ * box item which is "custom"
+ */
+ i = TERMINAL_PALETTE_N_BUILTINS;
+
+ g_signal_handlers_block_by_func (combo, G_CALLBACK (palette_scheme_combo_changed_cb), profile);
+ gtk_combo_box_set_active (combo, i);
+ g_signal_handlers_unblock_by_func (combo, G_CALLBACK (palette_scheme_combo_changed_cb), profile);
+}
+
+static void
+palette_color_notify_cb (GtkColorButton *button,
+ GParamSpec *pspec,
+ GSettings *profile)
+{
+ GdkRGBA color;
+ guint i;
+
+ gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (button), &color);
+ i = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "palette-entry-index"));
+
+ g_signal_handlers_block_by_func (profile, G_CALLBACK (profile_palette_notify_colorpickers_cb), NULL);
+ modify_palette_entry (profile, i, &color);
+ g_signal_handlers_unblock_by_func (profile, G_CALLBACK (profile_palette_notify_colorpickers_cb), NULL);
+}
+
+static void
+profile_palette_notify_colorpickers_cb (GSettings *profile,
+ const char *key,
+ gpointer user_data)
+{
+ GtkWidget *w;
+ GtkBuilder *builder = the_pref_data->builder;
+ gs_free GdkRGBA *colors;
+ gsize n_colors, i;
+
+ g_assert (strcmp (key, TERMINAL_PROFILE_PALETTE_KEY) == 0);
+
+ colors = terminal_g_settings_get_rgba_palette (profile, TERMINAL_PROFILE_PALETTE_KEY, &n_colors);
+
+ n_colors = MIN (n_colors, TERMINAL_PALETTE_SIZE);
+ for (i = 0; i < n_colors; i++)
+ {
+ char name[32];
+
+ g_snprintf (name, sizeof (name), "palette-colorpicker-%" G_GSIZE_FORMAT, i);
+ w = (GtkWidget *) gtk_builder_get_object (builder, name);
+
+ g_signal_handlers_block_by_func (w, G_CALLBACK (palette_color_notify_cb), profile);
+ gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (w), &colors[i]);
+ g_signal_handlers_unblock_by_func (w, G_CALLBACK (palette_color_notify_cb), profile);
+ }
+}
+
+static void
+custom_command_entry_changed_cb (GtkEntry *entry)
+{
+ const char *command;
+ gs_free_error GError *error = NULL;
+
+ command = gtk_entry_get_text (entry);
+
+ if (command[0] == '\0' ||
+ g_shell_parse_argv (command, NULL, NULL, &error))
+ {
+ gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
+ }
+ else
+ {
+ gs_free char *tooltip;
+
+ gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, "dialog-warning");
+
+ tooltip = g_strdup_printf (_("Error parsing command: %s"), error->message);
+ gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, tooltip);
+ }
+}
+
+static void
+default_size_reset_cb (GtkWidget *button,
+ GSettings *profile)
+{
+ g_settings_reset (profile, TERMINAL_PROFILE_DEFAULT_SIZE_COLUMNS_KEY);
+ g_settings_reset (profile, TERMINAL_PROFILE_DEFAULT_SIZE_ROWS_KEY);
+}
+
+static void
+cell_scale_reset_cb (GtkWidget *button,
+ GSettings *profile)
+{
+ g_settings_reset (profile, TERMINAL_PROFILE_CELL_HEIGHT_SCALE_KEY);
+ g_settings_reset (profile, TERMINAL_PROFILE_CELL_WIDTH_SCALE_KEY);
+}
+
+static void
+reset_compat_defaults_cb (GtkWidget *button,
+ GSettings *profile)
+{
+ g_settings_reset (profile, TERMINAL_PROFILE_DELETE_BINDING_KEY);
+ g_settings_reset (profile, TERMINAL_PROFILE_BACKSPACE_BINDING_KEY);
+ g_settings_reset (profile, TERMINAL_PROFILE_ENCODING_KEY);
+ g_settings_reset (profile, TERMINAL_PROFILE_CJK_UTF8_AMBIGUOUS_WIDTH_KEY);
+ g_settings_reset (profile, TERMINAL_PROFILE_ENABLE_SIXEL_KEY);
+}
+
+static gboolean
+tree_model_id_to_iter_recurse (GtkTreeModel *model,
+ int id_column,
+ const char *active_id,
+ GtkTreeIter *iter,
+ GtkTreeIter *result_iter)
+{
+ do {
+ /* Descend the tree */
+ GtkTreeIter child_iter;
+ if (gtk_tree_model_iter_children(model, &child_iter, iter) &&
+ tree_model_id_to_iter_recurse (model, id_column, active_id, &child_iter, result_iter))
+ return TRUE;
+
+ gs_free char *id = NULL;
+ gtk_tree_model_get (model, iter, id_column, &id, -1);
+ if (g_strcmp0 (id, active_id) == 0) {
+ *result_iter = *iter;
+ return TRUE;
+ }
+ } while (gtk_tree_model_iter_next (model, iter));
+
+ return FALSE;
+}
+
+static gboolean
+tree_model_id_to_iter (GtkTreeModel *model,
+ int id_column,
+ const char *active_id,
+ GtkTreeIter *iter)
+{
+ GtkTreeIter first_iter;
+
+ return gtk_tree_model_get_iter_first(model, &first_iter) &&
+ tree_model_id_to_iter_recurse(model, id_column, active_id, &first_iter, iter);
+}
+
+static void
+profile_encoding_combo_changed_cb (GtkComboBox *combo,
+ GSettings *profile)
+{
+ GtkTreeIter iter;
+
+ if (!gtk_combo_box_get_active_iter(combo, &iter))
+ return;
+
+ gs_free char *encoding = NULL;
+ gtk_tree_model_get(gtk_combo_box_get_model(combo),
+ &iter,
+ ENCODINGS_COL_ID, &encoding,
+ -1);
+ if (encoding == NULL)
+ return;
+
+ g_signal_handlers_block_by_func (profile, G_CALLBACK (profile_notify_encoding_combo_cb), combo);
+ g_settings_set_string(profile, TERMINAL_PROFILE_ENCODING_KEY, encoding);
+ g_signal_handlers_unblock_by_func (profile, G_CALLBACK (profile_notify_encoding_combo_cb), combo);
+}
+
+static void
+profile_notify_encoding_combo_cb (GSettings *profile,
+ const char *key,
+ GtkComboBox *combo)
+{
+ gs_free char *encoding = NULL;
+ g_settings_get(profile, key, "s", &encoding);
+
+ g_signal_handlers_block_by_func (combo, G_CALLBACK (profile_encoding_combo_changed_cb), profile);
+
+ GtkTreeIter iter;
+ if (tree_model_id_to_iter(gtk_combo_box_get_model(combo),
+ ENCODINGS_COL_ID,
+ encoding,
+ &iter)) {
+ gtk_combo_box_set_active_iter(combo, &iter);
+ } else {
+ gtk_combo_box_set_active(combo, -1);
+ }
+
+ g_signal_handlers_unblock_by_func (combo, G_CALLBACK (profile_encoding_combo_changed_cb), profile);
+}
+
+/*
+ * initialize widgets
+ */
+
+static void
+init_color_scheme_menu (GtkWidget *widget)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeIter iter;
+ gs_unref_object GtkListStore *store;
+ guint i;
+
+ store = gtk_list_store_new (1, G_TYPE_STRING);
+ for (i = 0; i < G_N_ELEMENTS (color_schemes); ++i)
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ 0, _(color_schemes[i].name),
+ -1);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ 0, _("Custom"),
+ -1);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), renderer, "text", 0, NULL);
+}
+
+typedef enum {
+ GROUP_UTF8,
+ GROUP_CJKV,
+ GROUP_OBSOLETE,
+ LAST_GROUP
+} EncodingGroup;
+
+typedef struct {
+ const char *charset;
+ const char *name;
+ EncodingGroup group;
+} EncodingEntry;
+
+/* These MUST be sorted by charset so that bsearch can work! */
+static const EncodingEntry encodings[] = {
+ { "ARMSCII-8", N_("Armenian"), GROUP_OBSOLETE },
+ { "BIG5", N_("Chinese Traditional"), GROUP_CJKV },
+ { "BIG5-HKSCS", N_("Chinese Traditional"), GROUP_CJKV },
+ { "CP866", N_("Cyrillic/Russian"), GROUP_OBSOLETE },
+ { "EUC-JP", N_("Japanese"), GROUP_CJKV },
+ { "EUC-KR", N_("Korean"), GROUP_CJKV },
+ { "EUC-TW", N_("Chinese Traditional"), GROUP_CJKV },
+ { "GB18030", N_("Chinese Simplified"), GROUP_CJKV },
+ { "GB2312", N_("Chinese Simplified"), GROUP_CJKV },
+ { "GBK", N_("Chinese Simplified"), GROUP_CJKV },
+ { "GEORGIAN-PS", N_("Georgian"), GROUP_OBSOLETE },
+ { "IBM850", N_("Western"), GROUP_OBSOLETE },
+ { "IBM852", N_("Central European"), GROUP_OBSOLETE },
+ { "IBM855", N_("Cyrillic"), GROUP_OBSOLETE },
+ { "IBM857", N_("Turkish"), GROUP_OBSOLETE },
+ { "IBM862", N_("Hebrew"), GROUP_OBSOLETE },
+ { "IBM864", N_("Arabic"), GROUP_OBSOLETE },
+ { "ISO-2022-JP", N_("Japanese"), GROUP_CJKV },
+ { "ISO-2022-KR", N_("Korean"), GROUP_CJKV },
+ { "ISO-8859-1", N_("Western"), GROUP_OBSOLETE },
+ { "ISO-8859-10", N_("Nordic"), GROUP_OBSOLETE },
+ { "ISO-8859-13", N_("Baltic"), GROUP_OBSOLETE },
+ { "ISO-8859-14", N_("Celtic"), GROUP_OBSOLETE },
+ { "ISO-8859-15", N_("Western"), GROUP_OBSOLETE },
+ { "ISO-8859-16", N_("Romanian"), GROUP_OBSOLETE },
+ { "ISO-8859-2", N_("Central European"), GROUP_OBSOLETE },
+ { "ISO-8859-3", N_("South European"), GROUP_OBSOLETE },
+ { "ISO-8859-4", N_("Baltic"), GROUP_OBSOLETE },
+ { "ISO-8859-5", N_("Cyrillic"), GROUP_OBSOLETE },
+ { "ISO-8859-6", N_("Arabic"), GROUP_OBSOLETE },
+ { "ISO-8859-7", N_("Greek"), GROUP_OBSOLETE },
+ { "ISO-8859-8", N_("Hebrew Visual"), GROUP_OBSOLETE },
+ { "ISO-8859-8-I", N_("Hebrew"), GROUP_OBSOLETE },
+ { "ISO-8859-9", N_("Turkish"), GROUP_OBSOLETE },
+ { "ISO-IR-111", N_("Cyrillic"), GROUP_OBSOLETE },
+ { "KOI8-R", N_("Cyrillic"), GROUP_OBSOLETE },
+ { "KOI8-U", N_("Cyrillic/Ukrainian"), GROUP_OBSOLETE },
+ { "MAC-CYRILLIC", N_("Cyrillic"), GROUP_OBSOLETE },
+ { "MAC_ARABIC", N_("Arabic"), GROUP_OBSOLETE },
+ { "MAC_CE", N_("Central European"), GROUP_OBSOLETE },
+ { "MAC_CROATIAN", N_("Croatian"), GROUP_OBSOLETE },
+ { "MAC_GREEK", N_("Greek"), GROUP_OBSOLETE },
+ { "MAC_HEBREW", N_("Hebrew"), GROUP_OBSOLETE },
+ { "MAC_ROMAN", N_("Western"), GROUP_OBSOLETE },
+ { "MAC_ROMANIAN", N_("Romanian"), GROUP_OBSOLETE },
+ { "MAC_TURKISH", N_("Turkish"), GROUP_OBSOLETE },
+ { "MAC_UKRAINIAN", N_("Cyrillic/Ukrainian"), GROUP_OBSOLETE },
+ { "SHIFT_JIS", N_("Japanese"), GROUP_CJKV },
+ { "TIS-620", N_("Thai"), GROUP_OBSOLETE },
+ { "UHC", N_("Korean"), GROUP_CJKV },
+ { "UTF-8", N_("Unicode"), GROUP_UTF8 },
+ { "WINDOWS-1250", N_("Central European"), GROUP_OBSOLETE },
+ { "WINDOWS-1251", N_("Cyrillic"), GROUP_OBSOLETE },
+ { "WINDOWS-1252", N_("Western"), GROUP_OBSOLETE },
+ { "WINDOWS-1253", N_("Greek"), GROUP_OBSOLETE },
+ { "WINDOWS-1254", N_("Turkish"), GROUP_OBSOLETE },
+ { "WINDOWS-1255", N_("Hebrew"), GROUP_OBSOLETE},
+ { "WINDOWS-1256", N_("Arabic"), GROUP_OBSOLETE },
+ { "WINDOWS-1257", N_("Baltic"), GROUP_OBSOLETE },
+ { "WINDOWS-1258", N_("Vietnamese"), GROUP_OBSOLETE },
+};
+
+static const struct {
+ EncodingGroup group;
+ const char *name;
+} encodings_group_names[] = {
+ { GROUP_UTF8, N_("Unicode") },
+ { GROUP_CJKV, N_("Legacy CJK Encodings") },
+ { GROUP_OBSOLETE, N_("Obsolete Encodings") },
+};
+
+#define EM_DASH "—"
+
+static void
+append_encodings_for_group (GtkTreeStore *store,
+ EncodingGroup group,
+ gboolean submenu)
+{
+ GtkTreeIter parent_iter;
+
+ if (submenu) {
+ gtk_tree_store_insert_with_values (store,
+ &parent_iter,
+ NULL,
+ -1,
+ ENCODINGS_COL_ID, NULL,
+ ENCODINGS_COL_TEXT, _(encodings_group_names[group].name),
+ -1);
+ }
+
+ for (guint i = 0; i < G_N_ELEMENTS (encodings); i++) {
+ if (encodings[i].group != group)
+ continue;
+
+ gs_free char *name = g_strdup_printf ("%s " EM_DASH " %s",
+ _(encodings[i].name), encodings[i].charset);
+
+ GtkTreeIter iter;
+ gtk_tree_store_insert_with_values (store,
+ &iter,
+ submenu ? &parent_iter : NULL,
+ -1,
+ ENCODINGS_COL_ID, encodings[i].charset,
+ ENCODINGS_COL_TEXT, name,
+ -1);
+ }
+}
+
+static GtkTreeStore *
+encodings_tree_store_new (void)
+{
+ GtkTreeStore *store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+
+ append_encodings_for_group(store, GROUP_UTF8, FALSE); /* UTF-8 in main menu */
+ append_encodings_for_group(store, GROUP_CJKV, TRUE);
+ append_encodings_for_group(store, GROUP_OBSOLETE, TRUE);
+
+ return store;
+}
+
+static void
+init_encodings_combo (GtkWidget *widget)
+{
+ gs_unref_object GtkTreeStore *store = encodings_tree_store_new ();
+ gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
+}
+
+static gboolean
+s_to_rgba (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ const char *s;
+ GdkRGBA color;
+
+ g_variant_get (variant, "&s", &s);
+ if (!gdk_rgba_parse (&color, s))
+ return FALSE;
+
+ color.alpha = 1.0;
+ g_value_set_boxed (value, &color);
+ return TRUE;
+}
+
+static GVariant *
+rgba_to_s (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ GdkRGBA *color;
+ gs_free char *s = NULL;
+
+ color = g_value_get_boxed (value);
+ if (color == NULL)
+ return NULL;
+
+ s = gdk_rgba_to_string (color);
+ return g_variant_new_string (s);
+}
+
+static gboolean
+string_to_enum (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ GType (* get_type) (void) = user_data;
+ GEnumClass *klass;
+ GEnumValue *eval = NULL;
+ const char *s;
+ guint i;
+
+ g_variant_get (variant, "&s", &s);
+
+ klass = g_type_class_ref (get_type ());
+ for (i = 0; i < klass->n_values; ++i) {
+ if (strcmp (klass->values[i].value_nick, s) != 0)
+ continue;
+
+ eval = &klass->values[i];
+ break;
+ }
+
+ if (eval)
+ g_value_set_int (value, eval->value);
+
+ g_type_class_unref (klass);
+
+ return eval != NULL;
+}
+
+static GVariant *
+enum_to_string (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ GType (* get_type) (void) = user_data;
+ GEnumClass *klass;
+ GEnumValue *eval = NULL;
+ int val;
+ guint i;
+ GVariant *variant = NULL;
+
+ val = g_value_get_int (value);
+
+ klass = g_type_class_ref (get_type ());
+ for (i = 0; i < klass->n_values; ++i) {
+ if (klass->values[i].value != val)
+ continue;
+
+ eval = &klass->values[i];
+ break;
+ }
+
+ if (eval)
+ variant = g_variant_new_string (eval->value_nick);
+
+ g_type_class_unref (klass);
+
+ return variant;
+}
+
+static gboolean
+scrollbar_policy_to_bool (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ const char *str;
+
+ g_variant_get (variant, "&s", &str);
+ g_value_set_boolean (value, g_str_equal (str, "always"));
+
+ return TRUE;
+}
+
+static GVariant *
+bool_to_scrollbar_policy (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ return g_variant_new_string (g_value_get_boolean (value) ? "always" : "never");
+}
+
+static gboolean
+monospace_filter (const PangoFontFamily *family,
+ const PangoFontFace *face,
+ gpointer data)
+{
+ return pango_font_family_is_monospace ((PangoFontFamily *) family);
+}
+
+/* Called once per Preferences window, to initialize stuff that doesn't depend on the profile being edited */
+void
+profile_prefs_init (void)
+{
+ GtkWidget *w;
+ GtkBuilder *builder = the_pref_data->builder;
+ char *text;
+
+ the_pref_data->profile_signals = g_array_new (FALSE, FALSE, sizeof (ProfilePrefsSignal));
+ the_pref_data->profile_bindings = g_array_new (FALSE, FALSE, sizeof (ProfilePrefsBinding));
+
+ w = (GtkWidget *) gtk_builder_get_object (builder, "color-scheme-combobox");
+ init_color_scheme_menu (w);
+
+ w = (GtkWidget *) gtk_builder_get_object (builder, "encoding-combobox");
+ init_encodings_combo (w);
+
+ /* Translators: Appears as: [numeric entry] × width */
+ text = g_strdup_printf ("× %s", _("width"));
+ gtk_label_set_text ((GtkLabel *) gtk_builder_get_object (builder, "cell-width-scale-label"),
+ text);
+ g_free (text);
+ /* Translators: Appears as: [numeric entry] × height */
+ text = g_strdup_printf ("× %s", _("height"));
+ gtk_label_set_text ((GtkLabel *) gtk_builder_get_object (builder, "cell-height-scale-label"),
+ text);
+ g_free (text);
+}
+
+/* Called each time the user switches away from a profile, so it's no longer being edited */
+void
+profile_prefs_unload (void)
+{
+ profile_prefs_signal_handlers_disconnect_all ();
+ profile_prefs_settings_unbind_all ();
+}
+
+/* Called each time the user selects a new profile to edit */
+void
+profile_prefs_load (const char *uuid, GSettings *profile)
+{
+ GtkWidget *w;
+ GtkBuilder *builder = the_pref_data->builder;
+ guint i;
+
+ profile_prefs_unload ();
+
+ gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "profile-uuid")),
+ uuid);
+
+ profile_prefs_signal_connect (gtk_builder_get_object (builder, "default-size-reset-button"),
+ "clicked",
+ G_CALLBACK (default_size_reset_cb),
+ profile);
+ profile_prefs_signal_connect (gtk_builder_get_object (builder, "cell-scale-reset-button"),
+ "clicked",
+ G_CALLBACK (cell_scale_reset_cb),
+ profile);
+
+ /* Hook up the palette colorpickers and combo box */
+
+ for (i = 0; i < TERMINAL_PALETTE_SIZE; ++i)
+ {
+ char name[32];
+ char *text;
+
+ g_snprintf (name, sizeof (name), "palette-colorpicker-%u", i);
+ w = (GtkWidget *) gtk_builder_get_object (builder, name);
+
+ g_object_set_data (G_OBJECT (w), "palette-entry-index", GUINT_TO_POINTER (i));
+
+ text = g_strdup_printf (_("Choose Palette Color %u"), i);
+ gtk_color_button_set_title (GTK_COLOR_BUTTON (w), text);
+ g_free (text);
+
+ text = g_strdup_printf (_("Palette entry %u"), i);
+ gtk_widget_set_tooltip_text (w, text);
+ g_free (text);
+
+ profile_prefs_signal_connect (w, "notify::rgba",
+ G_CALLBACK (palette_color_notify_cb),
+ profile);
+ }
+
+ profile_palette_notify_colorpickers_cb (profile, TERMINAL_PROFILE_PALETTE_KEY, NULL);
+ profile_prefs_signal_connect (profile, "changed::" TERMINAL_PROFILE_PALETTE_KEY,
+ G_CALLBACK (profile_palette_notify_colorpickers_cb),
+ NULL);
+
+ w = (GtkWidget *) gtk_builder_get_object (builder, "palette-combobox");
+ profile_prefs_signal_connect (w, "notify::active",
+ G_CALLBACK (palette_scheme_combo_changed_cb),
+ profile);
+
+ profile_palette_notify_scheme_combo_cb (profile, TERMINAL_PROFILE_PALETTE_KEY, GTK_COMBO_BOX (w));
+ profile_prefs_signal_connect (profile, "changed::" TERMINAL_PROFILE_PALETTE_KEY,
+ G_CALLBACK (profile_palette_notify_scheme_combo_cb),
+ w);
+
+ /* Hook up the color scheme pickers and combo box */
+ w = (GtkWidget *) gtk_builder_get_object (builder, "color-scheme-combobox");
+ profile_prefs_signal_connect (w, "notify::active",
+ G_CALLBACK (color_scheme_combo_changed_cb),
+ profile);
+
+ profile_colors_notify_scheme_combo_cb (profile, NULL, GTK_COMBO_BOX (w));
+ profile_prefs_signal_connect (profile, "changed::" TERMINAL_PROFILE_FOREGROUND_COLOR_KEY,
+ G_CALLBACK (profile_colors_notify_scheme_combo_cb),
+ w);
+ profile_prefs_signal_connect (profile, "changed::" TERMINAL_PROFILE_BACKGROUND_COLOR_KEY,
+ G_CALLBACK (profile_colors_notify_scheme_combo_cb),
+ w);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "custom-command-entry"));
+ custom_command_entry_changed_cb (GTK_ENTRY (w));
+ profile_prefs_signal_connect (w, "changed",
+ G_CALLBACK (custom_command_entry_changed_cb), NULL);
+
+ profile_prefs_signal_connect (gtk_builder_get_object (builder, "reset-compat-defaults-button"),
+ "clicked",
+ G_CALLBACK (reset_compat_defaults_cb),
+ profile);
+
+ profile_prefs_settings_bind_with_mapping (profile,
+ TERMINAL_PROFILE_BACKGROUND_COLOR_KEY,
+ gtk_builder_get_object (builder,
+ "background-colorpicker"),
+ "rgba",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) s_to_rgba,
+ (GSettingsBindSetMapping) rgba_to_s,
+ NULL, NULL);
+
+ profile_prefs_settings_bind_with_mapping (profile,
+ TERMINAL_PROFILE_BACKSPACE_BINDING_KEY,
+ gtk_builder_get_object (builder,
+ "backspace-binding-combobox"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) string_to_enum,
+ (GSettingsBindSetMapping) enum_to_string,
+ vte_erase_binding_get_type, NULL);
+ profile_prefs_settings_bind (profile,
+ TERMINAL_PROFILE_BOLD_IS_BRIGHT_KEY,
+ gtk_builder_get_object (builder, "bold-is-bright-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_BOLD_COLOR_SAME_AS_FG_KEY,
+ gtk_builder_get_object (builder,
+ "bold-color-checkbutton"),
+ "active",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_INVERT_BOOLEAN |
+ G_SETTINGS_BIND_SET);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "bold-colorpicker"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_BOLD_COLOR_SAME_AS_FG_KEY,
+ w,
+ "sensitive",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_INVERT_BOOLEAN |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_BOLD_COLOR_KEY,
+ w,
+ "rgba",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_NO_SENSITIVITY,
+ (GSettingsBindGetMapping) s_to_rgba,
+ (GSettingsBindSetMapping) rgba_to_s,
+ NULL, NULL);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "cell-height-scale-spinbutton"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_CELL_HEIGHT_SCALE_KEY,
+ gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w)),
+ "value", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "cell-width-scale-spinbutton"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_CELL_WIDTH_SCALE_KEY,
+ gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w)),
+ "value", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_CURSOR_COLORS_SET_KEY,
+ gtk_builder_get_object (builder,
+ "cursor-colors-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "cursor-foreground-colorpicker"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_CURSOR_COLORS_SET_KEY,
+ w,
+ "sensitive",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_CURSOR_FOREGROUND_COLOR_KEY,
+ w,
+ "rgba",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_NO_SENSITIVITY,
+ (GSettingsBindGetMapping) s_to_rgba,
+ (GSettingsBindSetMapping) rgba_to_s,
+ NULL, NULL);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "cursor-background-colorpicker"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_CURSOR_COLORS_SET_KEY,
+ w,
+ "sensitive",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_CURSOR_BACKGROUND_COLOR_KEY,
+ w,
+ "rgba",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_NO_SENSITIVITY,
+ (GSettingsBindGetMapping) s_to_rgba,
+ (GSettingsBindSetMapping) rgba_to_s,
+ NULL, NULL);
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_HIGHLIGHT_COLORS_SET_KEY,
+ gtk_builder_get_object (builder,
+ "highlight-colors-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "highlight-foreground-colorpicker"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_HIGHLIGHT_COLORS_SET_KEY,
+ w,
+ "sensitive",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_HIGHLIGHT_FOREGROUND_COLOR_KEY,
+ w,
+ "rgba",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_NO_SENSITIVITY,
+ (GSettingsBindGetMapping) s_to_rgba,
+ (GSettingsBindSetMapping) rgba_to_s,
+ NULL, NULL);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "highlight-background-colorpicker"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_HIGHLIGHT_COLORS_SET_KEY,
+ w,
+ "sensitive",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_HIGHLIGHT_BACKGROUND_COLOR_KEY,
+ w,
+ "rgba",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_NO_SENSITIVITY,
+ (GSettingsBindGetMapping) s_to_rgba,
+ (GSettingsBindSetMapping) rgba_to_s,
+ NULL, NULL);
+
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_CURSOR_SHAPE_KEY,
+ gtk_builder_get_object (builder,
+ "cursor-shape-combobox"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) string_to_enum,
+ (GSettingsBindSetMapping) enum_to_string,
+ vte_cursor_shape_get_type, NULL);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_CURSOR_BLINK_MODE_KEY,
+ gtk_builder_get_object (builder,
+ "cursor-blink-mode-combobox"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) string_to_enum,
+ (GSettingsBindSetMapping) enum_to_string,
+ vte_cursor_blink_mode_get_type, NULL);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_TEXT_BLINK_MODE_KEY,
+ gtk_builder_get_object (builder,
+ "text-blink-mode-combobox"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) string_to_enum,
+ (GSettingsBindSetMapping) enum_to_string,
+ vte_text_blink_mode_get_type, NULL);
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_CUSTOM_COMMAND_KEY,
+ gtk_builder_get_object (builder,
+ "custom-command-entry"),
+ "text", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "default-size-columns-spinbutton"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_DEFAULT_SIZE_COLUMNS_KEY,
+ gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w)),
+ "value", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "default-size-rows-spinbutton"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_DEFAULT_SIZE_ROWS_KEY,
+ gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w)),
+ "value", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_DELETE_BINDING_KEY,
+ gtk_builder_get_object (builder,
+ "delete-binding-combobox"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) string_to_enum,
+ (GSettingsBindSetMapping) enum_to_string,
+ vte_erase_binding_get_type, NULL);
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_EXIT_ACTION_KEY,
+ gtk_builder_get_object (builder,
+ "exit-action-combobox"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) string_to_enum,
+ (GSettingsBindSetMapping) enum_to_string,
+ terminal_exit_action_get_type, NULL);
+ w = (GtkWidget*) gtk_builder_get_object (builder, "font-selector");
+ gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (w), monospace_filter, NULL, NULL);
+#if GTK_CHECK_VERSION (3, 24, 0)
+ gtk_font_chooser_set_level (GTK_FONT_CHOOSER (w), GTK_FONT_CHOOSER_LEVEL_FAMILY |
+ GTK_FONT_CHOOSER_LEVEL_SIZE);
+#endif
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_FONT_KEY,
+ w,
+ "font-name", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ profile_prefs_settings_bind_with_mapping (profile,
+ TERMINAL_PROFILE_FOREGROUND_COLOR_KEY,
+ gtk_builder_get_object (builder,
+ "foreground-colorpicker"),
+ "rgba",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) s_to_rgba,
+ (GSettingsBindSetMapping) rgba_to_s,
+ NULL, NULL);
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_LOGIN_SHELL_KEY,
+ gtk_builder_get_object (builder,
+ "login-shell-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ w = GTK_WIDGET (gtk_builder_get_object (builder, "scrollback-lines-spinbutton"));
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_SCROLLBACK_LINES_KEY,
+ gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w)),
+ "value", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_SCROLLBACK_UNLIMITED_KEY,
+ gtk_builder_get_object (builder,
+ "scrollback-limited-checkbutton"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET |
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_SCROLLBACK_UNLIMITED_KEY,
+ gtk_builder_get_object (builder,
+ "scrollback-box"),
+ "sensitive",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_INVERT_BOOLEAN |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind_with_mapping (profile,
+ TERMINAL_PROFILE_SCROLLBAR_POLICY_KEY,
+ gtk_builder_get_object (builder,
+ "scrollbar-checkbutton"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) scrollbar_policy_to_bool,
+ (GSettingsBindSetMapping) bool_to_scrollbar_policy,
+ NULL, NULL);
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE_KEY,
+ gtk_builder_get_object (builder,
+ "scroll-on-keystroke-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_SCROLL_ON_OUTPUT_KEY,
+ gtk_builder_get_object (builder,
+ "scroll-on-output-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_SYSTEM_FONT_KEY,
+ gtk_builder_get_object (builder,
+ "custom-font-checkbutton"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET |
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+
+ w = (GtkWidget *) gtk_builder_get_object (builder, "preserve-working-directory-combobox");
+ profile_prefs_settings_bind_with_mapping (profile, TERMINAL_PROFILE_PRESERVE_WORKING_DIRECTORY_KEY, w,
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+ (GSettingsBindGetMapping) string_to_enum,
+ (GSettingsBindSetMapping) enum_to_string,
+ terminal_preserve_working_directory_get_type, NULL);
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_CUSTOM_COMMAND_KEY,
+ gtk_builder_get_object (builder,
+ "use-custom-command-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_THEME_COLORS_KEY,
+ gtk_builder_get_object (builder,
+ "use-theme-colors-checkbutton"),
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_AUDIBLE_BELL_KEY,
+ gtk_builder_get_object (builder, "bell-checkbutton"),
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ profile_prefs_settings_bind (profile,
+ TERMINAL_PROFILE_USE_CUSTOM_COMMAND_KEY,
+ gtk_builder_get_object (builder, "custom-command-entry-label"),
+ "sensitive",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind (profile,
+ TERMINAL_PROFILE_USE_CUSTOM_COMMAND_KEY,
+ gtk_builder_get_object (builder, "custom-command-entry"),
+ "sensitive",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind (profile,
+ TERMINAL_PROFILE_USE_SYSTEM_FONT_KEY,
+ gtk_builder_get_object (builder, "font-selector"),
+ "sensitive",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_INVERT_BOOLEAN |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind (profile,
+ TERMINAL_PROFILE_USE_THEME_COLORS_KEY,
+ gtk_builder_get_object (builder, "colors-box"),
+ "sensitive",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_INVERT_BOOLEAN |
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ profile_prefs_settings_bind_writable (profile,
+ TERMINAL_PROFILE_PALETTE_KEY,
+ gtk_builder_get_object (builder, "palette-box"),
+ "sensitive",
+ FALSE);
+
+ /* Compatibility options */
+ w = (GtkWidget *) gtk_builder_get_object (builder, "encoding-combobox");
+ profile_prefs_signal_connect (w, "changed",
+ G_CALLBACK (profile_encoding_combo_changed_cb),
+ profile);
+
+ profile_notify_encoding_combo_cb (profile, TERMINAL_PROFILE_ENCODING_KEY, GTK_COMBO_BOX (w));
+ profile_prefs_signal_connect (profile, "changed::" TERMINAL_PROFILE_ENCODING_KEY,
+ G_CALLBACK (profile_notify_encoding_combo_cb),
+ w);
+
+ w = (GtkWidget *) gtk_builder_get_object (builder, "cjk-ambiguous-width-combobox");
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_CJK_UTF8_AMBIGUOUS_WIDTH_KEY,
+ w,
+ "active-id",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ w = (GtkWidget *) gtk_builder_get_object (builder, "enable-sixel-checkbutton");
+ profile_prefs_settings_bind (profile, TERMINAL_PROFILE_ENABLE_SIXEL_KEY, w,
+ "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ gtk_widget_set_visible (w, (vte_get_feature_flags() & VTE_FEATURE_FLAG_SIXEL) != 0);
+}
+
+/* Called once per Preferences window, to destroy stuff that doesn't depend on the profile being edited */
+void
+profile_prefs_destroy (void)
+{
+ profile_prefs_unload ();
+
+ g_array_free (the_pref_data->profile_signals, TRUE);
+ g_array_free (the_pref_data->profile_bindings, TRUE);
+}
diff --git a/src/profile-editor.h b/src/profile-editor.h
new file mode 100644
index 0000000..e83d393
--- /dev/null
+++ b/src/profile-editor.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2002 Havoc Pennington
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_PROFILE_EDITOR_H
+#define TERMINAL_PROFILE_EDITOR_H
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void profile_prefs_init (void);
+
+void profile_prefs_destroy (void);
+
+void profile_prefs_unload (void);
+
+void profile_prefs_load (const char *uuid,
+ GSettings *profile);
+
+G_END_DECLS
+
+#endif /* TERMINAL_PROFILE_EDITOR_H */
diff --git a/src/search-popover.ui b/src/search-popover.ui
new file mode 100644
index 0000000..4bea44d
--- /dev/null
+++ b/src/search-popover.ui
@@ -0,0 +1,251 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.19.0 -->
+<interface>
+ <requires lib="gtk+" version="3.16"/>
+ <template class="TerminalSearchPopover" parent="GtkWindow">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Find</property>
+ <property name="resizable">False</property>
+ <property name="skip_pager_hint">True</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">12</property>
+ <property name="margin_right">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">30</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <property name="placeholder_text" translatable="yes">Find</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_prev_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Find previous occurrence</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-up-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_next_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Find next occurrence</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-down-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="reveal_button">
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Toggle search options</property>
+ <property name="focus_on_click">False</property>
+ <property name="active">True</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">view-context-menu-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ <accessibility>
+ <relation type="controller-for" target="revealer"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">window-close-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="revealer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="transition_type">none</property>
+ <property name="reveal_child">True</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="match_case_checkbutton">
+ <property name="label" translatable="yes">_Match case</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="entire_word_checkbutton">
+ <property name="label" translatable="yes">Match _entire word only</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="regex_checkbutton">
+ <property name="label" translatable="yes">Match as _regular expression</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="wrap_around_checkbutton">
+ <property name="label" translatable="yes">_Wrap around</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..87a6cd9
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2008, 2010, 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <locale.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include "terminal-app.h"
+#include "terminal-debug.h"
+#include "terminal-gdbus.h"
+#include "terminal-i18n.h"
+#include "terminal-defines.h"
+#include "terminal-libgsystem.h"
+
+static char *app_id = NULL;
+
+#define INACTIVITY_TIMEOUT (100 /* ms */)
+
+static gboolean
+option_app_id_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ if (!g_application_id_is_valid (value) ||
+ !g_dbus_is_name (value)) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "\"%s\" is not a valid application ID", value);
+ return FALSE;
+ }
+
+ g_free (app_id);
+ app_id = g_strdup (value);
+
+ return TRUE;
+}
+
+static const GOptionEntry options[] = {
+ { "app-id", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, option_app_id_cb, "Application ID", "ID" },
+ { NULL }
+};
+
+/* We use up to 8 FDs per terminal, so let's bump the limit way up.
+ * However we need to restore the original limit for the child processes.
+ */
+
+static struct rlimit sv_rlimit_nofile;
+
+static void
+atfork_child_restore_rlimit_nofile (void)
+{
+ if (setrlimit (RLIMIT_NOFILE, &sv_rlimit_nofile) < 0)
+ _exit (127);
+}
+
+static gboolean
+increase_rlimit_nofile (void)
+{
+ struct rlimit l;
+
+ if (getrlimit (RLIMIT_NOFILE, &sv_rlimit_nofile) < 0)
+ return FALSE;
+
+ if (pthread_atfork (NULL, NULL, atfork_child_restore_rlimit_nofile) != 0)
+ return FALSE;
+
+ l.rlim_cur = l.rlim_max = sv_rlimit_nofile.rlim_max;
+ if (setrlimit (RLIMIT_NOFILE, &l) < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+init_server (int argc,
+ char *argv[],
+ GApplication **application)
+{
+ if (G_UNLIKELY ((getuid () != geteuid () ||
+ getgid () != getegid ()) &&
+ geteuid () == 0 &&
+ getegid () == 0)) {
+ g_printerr ("Wrong euid/egid, exiting.\n");
+ return _EXIT_FAILURE_WRONG_ID;
+ }
+
+ if (setlocale (LC_ALL, "") == NULL) {
+ g_printerr ("Locale not supported.\n");
+ return _EXIT_FAILURE_UNSUPPORTED_LOCALE;
+ }
+
+ terminal_i18n_init (TRUE);
+ const char *charset;
+ if (!g_get_charset (&charset)) {
+ g_printerr ("Non UTF-8 locale (%s) is not supported!\n", charset);
+ return _EXIT_FAILURE_NO_UTF8;
+ }
+
+ /* Sanitise environment */
+ g_unsetenv ("DBUS_STARTER_BUS_TYPE");
+
+ /* Not interested in silly debug spew polluting the journal, bug #749195 */
+ if (g_getenv ("G_ENABLE_DIAGNOSTIC") == NULL)
+ g_setenv ("G_ENABLE_DIAGNOSTIC", "0", TRUE);
+
+ _terminal_debug_init ();
+
+ /* Change directory to $HOME so we don't prevent unmounting, e.g. if the
+ * factory is started by nautilus-open-terminal. See bug #565328.
+ * On failure back to /.
+ */
+ const char *home_dir = g_get_home_dir ();
+ if (home_dir == NULL || chdir (home_dir) < 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-result"
+ chdir ("/");
+#pragma GCC diagnostic pop
+
+ g_set_prgname ("gnome-terminal-server");
+ g_set_application_name (_("Terminal"));
+
+ GError *error = NULL;
+ if (!gtk_init_with_args (&argc, &argv, NULL, options, NULL, &error)) {
+ if (error != NULL) {
+ g_printerr ("Failed to parse arguments: %s\n", error->message);
+ g_error_free (error);
+ }
+ return _EXIT_FAILURE_GTK_INIT;
+ }
+
+ if (!increase_rlimit_nofile ()) {
+ g_printerr ("Failed to increase RLIMIT_NOFILE: %m\n");
+ }
+
+ /* Now we can create the app */
+ GApplication *app = terminal_app_new (app_id);
+ g_free (app_id);
+ app_id = NULL;
+
+ /* We stay around a bit after the last window closed */
+ g_application_set_inactivity_timeout (app, INACTIVITY_TIMEOUT);
+
+ *application = app;
+ return 0;
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ gs_unref_object GApplication *app = NULL;
+ int r = init_server (argc, argv, &app);
+ if (r != 0)
+ return r;
+
+ /* Note that this flushes the D-Bus connection just before quitting,
+ * thus ensuring that all pending signal emissions (e.g. child-exited)
+ * are delivered.
+ */
+ return g_application_run (app, 0, NULL);
+}
diff --git a/src/terminal-accels.c b/src/terminal-accels.c
new file mode 100644
index 0000000..333c6d1
--- /dev/null
+++ b/src/terminal-accels.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington, Red Hat Inc.
+ * Copyright © 2008, 2011, 2012, 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "terminal-accels.h"
+#include "terminal-app.h"
+#include "terminal-debug.h"
+#include "terminal-schemas.h"
+#include "terminal-intl.h"
+#include "terminal-util.h"
+#include "terminal-libgsystem.h"
+
+/* NOTES
+ *
+ * There are two sources of keybindings changes, from GSettings and from
+ * the accel map (happens with in-place menu editing).
+ *
+ * When a keybinding gsettings key changes, we propagate that into the
+ * accel map.
+ * When the accel map changes, we queue a sync to GSettings.
+ *
+ * To avoid infinite loops, we short-circuit in both directions
+ * if the value is unchanged from last known.
+ *
+ * In the keybinding editor, when editing or clearing an accel, we write
+ * the change directly to GSettings and rely on the callback to
+ * actually apply the change to the accel map.
+ */
+
+#define KEY_CLOSE_TAB "close-tab"
+#define KEY_CLOSE_WINDOW "close-window"
+#define KEY_COPY "copy"
+#define KEY_COPY_HTML "copy-html"
+#define KEY_DETACH_TAB "detach-tab"
+#define KEY_EXPORT "export"
+#define KEY_FIND "find"
+#define KEY_FIND_CLEAR "find-clear"
+#define KEY_FIND_PREV "find-previous"
+#define KEY_FIND_NEXT "find-next"
+#define KEY_FULL_SCREEN "full-screen"
+#define KEY_HEADER_MENU "header-menu"
+#define KEY_HELP "help"
+#define KEY_MOVE_TAB_LEFT "move-tab-left"
+#define KEY_MOVE_TAB_RIGHT "move-tab-right"
+#define KEY_NEW_TAB "new-tab"
+#define KEY_NEW_WINDOW "new-window"
+#define KEY_NEXT_TAB "next-tab"
+#define KEY_PASTE "paste"
+#define KEY_PREFERENCES "preferences"
+#define KEY_PREV_TAB "prev-tab"
+#define KEY_PRINT "print"
+#define KEY_READ_ONLY "read-only"
+#define KEY_RESET_AND_CLEAR "reset-and-clear"
+#define KEY_RESET "reset"
+#define KEY_SAVE_CONTENTS "save-contents"
+#define KEY_SELECT_ALL "select-all"
+#define KEY_TOGGLE_MENUBAR "toggle-menubar"
+#define KEY_ZOOM_IN "zoom-in"
+#define KEY_ZOOM_NORMAL "zoom-normal"
+#define KEY_ZOOM_OUT "zoom-out"
+#define KEY_SWITCH_TAB_PREFIX "switch-to-tab-"
+
+#if 1
+/*
+* We don't want to enable content saving until vte supports it async.
+* So we disable this code for stable versions.
+*/
+#include "terminal-version.h"
+
+#if (TERMINAL_MINOR_VERSION & 1) != 0
+#define ENABLE_SAVE
+#else
+#undef ENABLE_SAVE
+#endif
+#endif
+
+typedef struct
+{
+ const char *user_visible_name;
+ const char *settings_key;
+ const char *action_name;
+ const GVariantType *action_parameter_type;
+ const char *action_parameter;
+ GVariant *parameter;
+ const char *shadow_action_name;
+} KeyEntry;
+
+typedef struct
+{
+ KeyEntry *key_entry;
+ guint n_elements;
+ const char *user_visible_name;
+ gboolean headerbar_only;
+} KeyEntryList;
+
+#define ENTRY_FULL(name, key, action, type, parameter, shadow_name) \
+ { name, key, "win." action, (const GVariantType *) type, parameter, NULL, shadow_name }
+#define ENTRY(name, key, action, type, parameter) \
+ ENTRY_FULL (name, key, action, type, parameter, "win.shadow")
+#define ENTRY_MDI(name, key, action, type, parameter) \
+ ENTRY_FULL (name, key, action, type, parameter, "win.shadow-mdi")
+
+static KeyEntry file_entries[] = {
+ ENTRY (N_("New Tab"), KEY_NEW_TAB, "new-terminal", "(ss)", "('tab','current')" ),
+ ENTRY (N_("New Window"), KEY_NEW_WINDOW, "new-terminal", "(ss)", "('window','current')"),
+#ifdef ENABLE_SAVE
+ ENTRY (N_("Save Contents"), KEY_SAVE_CONTENTS, "save-contents", NULL, NULL ),
+#endif
+#ifdef ENABLE_EXPORT
+ ENTRY (N_("Export"), KEY_EXPORT, "export", NULL, NULL ),
+#endif
+#ifdef ENABLE_PRINT
+ ENTRY (N_("Print"), KEY_PRINT, "print", NULL, NULL ),
+#endif
+ ENTRY (N_("Close Tab"), KEY_CLOSE_TAB, "close", "s", "'tab'" ),
+ ENTRY (N_("Close Window"), KEY_CLOSE_WINDOW, "close", "s", "'window'" ),
+};
+
+static KeyEntry edit_entries[] = {
+ ENTRY (N_("Copy"), KEY_COPY, "copy", "s", "'text'" ),
+ ENTRY (N_("Copy as HTML"), KEY_COPY_HTML, "copy", "s", "'html'" ),
+ ENTRY (N_("Paste"), KEY_PASTE, "paste-text", NULL, NULL ),
+ ENTRY (N_("Select All"), KEY_SELECT_ALL, "select-all", NULL, NULL ),
+ ENTRY (N_("Preferences"), KEY_PREFERENCES, "edit-preferences", NULL, NULL ),
+};
+
+static KeyEntry search_entries[] = {
+ ENTRY (N_("Find"), KEY_FIND, "find", NULL, NULL),
+ ENTRY (N_("Find Next"), KEY_FIND_NEXT, "find-forward", NULL, NULL),
+ ENTRY (N_("Find Previous"), KEY_FIND_PREV, "find-backward", NULL, NULL),
+ ENTRY (N_("Clear Highlight"), KEY_FIND_CLEAR, "find-clear", NULL, NULL)
+};
+
+static KeyEntry view_entries[] = {
+ ENTRY (N_("Hide and Show Menubar"), KEY_TOGGLE_MENUBAR, "menubar-visible", NULL, NULL),
+ ENTRY (N_("Full Screen"), KEY_FULL_SCREEN, "fullscreen", NULL, NULL),
+ ENTRY (N_("Zoom In"), KEY_ZOOM_IN, "zoom-in", NULL, NULL),
+ ENTRY (N_("Zoom Out"), KEY_ZOOM_OUT, "zoom-out", NULL, NULL),
+ ENTRY (N_("Normal Size"), KEY_ZOOM_NORMAL, "zoom-normal", NULL, NULL)
+};
+
+static KeyEntry terminal_entries[] = {
+ ENTRY (N_("Read-Only"), KEY_READ_ONLY, "read-only", NULL, NULL ),
+ ENTRY (N_("Reset"), KEY_RESET, "reset", "b", "false"),
+ ENTRY (N_("Reset and Clear"), KEY_RESET_AND_CLEAR, "reset", "b", "true" ),
+};
+
+static KeyEntry tabs_entries[] = {
+ ENTRY_MDI (N_("Switch to Previous Tab"), KEY_PREV_TAB, "tab-switch-left", NULL, NULL),
+ ENTRY_MDI (N_("Switch to Next Tab"), KEY_NEXT_TAB, "tab-switch-right", NULL, NULL),
+ ENTRY_MDI (N_("Move Tab to the Left"), KEY_MOVE_TAB_LEFT, "tab-move-left", NULL, NULL),
+ ENTRY_MDI (N_("Move Tab to the Right"), KEY_MOVE_TAB_RIGHT, "tab-move-right", NULL, NULL),
+ ENTRY_MDI (N_("Detach Tab"), KEY_DETACH_TAB, "tab-detach", NULL, NULL),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "1", "active-tab", "i", "0"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "2", "active-tab", "i", "1"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "3", "active-tab", "i", "2"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "4", "active-tab", "i", "3"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "5", "active-tab", "i", "4"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "6", "active-tab", "i", "5"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "7", "active-tab", "i", "6"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "8", "active-tab", "i", "7"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "9", "active-tab", "i", "8"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "10", "active-tab", "i", "9"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "11", "active-tab", "i", "10"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "12", "active-tab", "i", "11"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "13", "active-tab", "i", "12"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "14", "active-tab", "i", "13"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "15", "active-tab", "i", "14"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "16", "active-tab", "i", "15"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "17", "active-tab", "i", "16"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "18", "active-tab", "i", "17"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "19", "active-tab", "i", "18"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "20", "active-tab", "i", "19"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "21", "active-tab", "i", "20"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "22", "active-tab", "i", "21"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "23", "active-tab", "i", "22"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "24", "active-tab", "i", "23"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "25", "active-tab", "i", "24"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "26", "active-tab", "i", "25"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "27", "active-tab", "i", "26"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "28", "active-tab", "i", "27"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "29", "active-tab", "i", "28"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "30", "active-tab", "i", "29"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "31", "active-tab", "i", "30"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "32", "active-tab", "i", "31"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "33", "active-tab", "i", "32"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "34", "active-tab", "i", "33"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "35", "active-tab", "i", "34"),
+ ENTRY_MDI (N_("Switch to Last Tab"), KEY_SWITCH_TAB_PREFIX "last", "active-tab", "i", "-1"),
+};
+
+static KeyEntry help_entries[] = {
+ ENTRY (N_("Contents"), KEY_HELP, "help", NULL, NULL)
+};
+
+static KeyEntry global_entries[] = {
+ ENTRY (N_("Show Primary Menu"), KEY_HEADER_MENU, "header-menu", NULL, NULL),
+};
+
+#undef ENTRY_FULL
+#undef ENTRY
+#undef ENTRY_MDI
+
+static KeyEntryList all_entries[] =
+{
+ { file_entries, G_N_ELEMENTS (file_entries), N_("File"), FALSE },
+ { edit_entries, G_N_ELEMENTS (edit_entries), N_("Edit"), FALSE },
+ { view_entries, G_N_ELEMENTS (view_entries), N_("View"), FALSE },
+ { search_entries, G_N_ELEMENTS (search_entries), N_("Search"), FALSE },
+ { terminal_entries, G_N_ELEMENTS (terminal_entries), N_("Terminal"), FALSE },
+ { tabs_entries, G_N_ELEMENTS (tabs_entries), N_("Tabs"), FALSE },
+ { help_entries, G_N_ELEMENTS (help_entries), N_("Help"), FALSE },
+ { global_entries, G_N_ELEMENTS (global_entries), N_("Global"), TRUE },
+};
+
+enum
+{
+ ACTION_COLUMN,
+ KEYVAL_COLUMN,
+ N_COLUMNS
+};
+
+static GHashTable *settings_key_to_entry;
+static GSettings *keybinding_settings = NULL;
+
+GS_DEFINE_CLEANUP_FUNCTION(GtkTreePath*, _terminal_local_free_tree_path, gtk_tree_path_free)
+#define terminal_free_tree_path __attribute__((__cleanup__(_terminal_local_free_tree_path)))
+
+static char*
+binding_name (guint keyval,
+ GdkModifierType mask)
+{
+ if (keyval != 0)
+ return gtk_accelerator_name (keyval, mask);
+
+ return g_strdup ("disabled");
+}
+
+static void
+key_changed_cb (GSettings *settings,
+ const char *settings_key,
+ gpointer user_data)
+{
+ GtkApplication *application = user_data;
+ const gchar *accels[2] = { NULL, NULL };
+
+ _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+ "key %s changed\n",
+ settings_key);
+
+ KeyEntry *key_entry = g_hash_table_lookup (settings_key_to_entry, settings_key);
+ if (!key_entry)
+ {
+ /* shouldn't really happen, but let's be safe */
+ _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+ " WARNING: KeyEntry for changed key not found, bailing out\n");
+ return;
+ }
+
+ gs_free char *value = g_settings_get_string (settings, settings_key);
+
+ gs_free char *detailed = g_action_print_detailed_name (key_entry->action_name,
+ key_entry->parameter);
+ gs_unref_variant GVariant *shadow_parameter = g_variant_new_string (detailed);
+ gs_free char *shadow_detailed = g_action_print_detailed_name (key_entry->shadow_action_name,
+ shadow_parameter);
+
+ /* We want to always consume the action's accelerators, even if the corresponding
+ * action is insensitive, so the corresponding shortcut key escape code isn't sent
+ * to the terminal. See bug #453193, bug #138609, and bug #559728.
+ * Since GtkApplication's accelerators don't use GtkAccelGroup, we have no way
+ * to intercept/chain on its activation. The only way to do this that I found
+ * was to install an extra action with the same accelerator that shadows
+ * the real action and gets activated when the shadowed action is disabled.
+ */
+
+ if (g_str_equal (value, "disabled")) {
+ accels[0] = NULL;
+ } else {
+ accels[0] = value;
+ }
+
+ gtk_application_set_accels_for_action (application,
+ detailed,
+ accels);
+ gtk_application_set_accels_for_action (application,
+ shadow_detailed,
+ accels);
+}
+
+static void
+add_accel_entries (GApplication*application,
+ KeyEntry *entries,
+ guint n_entries)
+{
+ guint j;
+
+ for (j = 0; j < n_entries; ++j) {
+ KeyEntry *key_entry = &entries[j];
+ if (key_entry->action_parameter) {
+ GError *err = NULL;
+ key_entry->parameter = g_variant_parse (key_entry->action_parameter_type,
+ key_entry->action_parameter,
+ NULL, NULL, &err);
+ g_assert_no_error (err);
+
+ g_assert (key_entry->parameter != NULL);
+ }
+
+ g_hash_table_insert (settings_key_to_entry,
+ (gpointer) key_entry->settings_key,
+ key_entry);
+
+ key_changed_cb (keybinding_settings, key_entry->settings_key, application);
+ }
+}
+
+void
+terminal_accels_init (GApplication *application,
+ GSettings *settings,
+ gboolean use_headerbar)
+{
+ guint i, j;
+
+ keybinding_settings = g_object_ref (settings);
+
+ settings_key_to_entry = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* Initialise names of tab_switch_entries */
+ j = 1;
+ for (i = 0; i < G_N_ELEMENTS (tabs_entries); i++)
+ {
+ gs_free char *name = NULL;
+
+ if (tabs_entries[i].user_visible_name != NULL)
+ continue;
+
+ name = g_strdup_printf (_("Switch to Tab %u"), j++);
+ tabs_entries[i].user_visible_name = g_intern_string (name);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (all_entries); ++i) {
+ if (!use_headerbar && all_entries[i].headerbar_only)
+ continue;
+
+ add_accel_entries (application, all_entries[i].key_entry, all_entries[i].n_elements);
+ }
+
+ g_signal_connect (keybinding_settings, "changed", G_CALLBACK (key_changed_cb), application);
+}
+
+void
+terminal_accels_shutdown (void)
+{
+ guint i, j;
+
+ for (i = 0; i < G_N_ELEMENTS (all_entries); ++i) {
+ for (j = 0; j < all_entries[i].n_elements; ++j) {
+ KeyEntry *key_entry;
+
+ key_entry = &(all_entries[i].key_entry[j]);
+ if (key_entry->parameter)
+ g_variant_unref (key_entry->parameter);
+ }
+ }
+
+ g_signal_handlers_disconnect_by_func (keybinding_settings,
+ G_CALLBACK (key_changed_cb),
+ g_application_get_default ());
+
+ g_clear_pointer (&settings_key_to_entry, (GDestroyNotify) g_hash_table_unref);
+ g_clear_object (&keybinding_settings);
+}
+
+static gboolean
+foreach_row_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ const char *key = data;
+ KeyEntry *key_entry;
+
+ gtk_tree_model_get (model, iter,
+ KEYVAL_COLUMN, &key_entry,
+ -1);
+
+ if (key_entry == NULL ||
+ !g_str_equal (key_entry->settings_key, key))
+ return FALSE;
+
+ gtk_tree_model_row_changed (model, path, iter);
+ return TRUE;
+}
+
+static void
+treeview_key_changed_cb (GSettings *settings,
+ const char *key,
+ GtkTreeView *tree_view)
+{
+ gtk_tree_model_foreach (gtk_tree_view_get_model (tree_view), foreach_row_cb, (gpointer) key);
+}
+
+static void
+accel_set_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ KeyEntry *ke;
+
+ gtk_tree_model_get (model, iter,
+ KEYVAL_COLUMN, &ke,
+ -1);
+
+ if (ke == NULL) {
+ /* This is a title row */
+ g_object_set (cell,
+ "visible", FALSE,
+ NULL);
+ } else {
+ gs_free char *value;
+ guint key;
+ GdkModifierType mods;
+ gboolean writable;
+ GtkWidget *button = data;
+
+ value = g_settings_get_string (keybinding_settings, ke->settings_key);
+ gtk_accelerator_parse (value, &key, &mods);
+
+ writable = g_settings_is_writable (keybinding_settings, ke->settings_key) &&
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+ g_object_set (cell,
+ "visible", TRUE,
+ "sensitive", writable,
+ "editable", writable,
+ "accel-key", key,
+ "accel-mods", mods,
+ NULL);
+ }
+}
+
+static void
+accel_update (GtkTreeView *view,
+ GtkCellRendererAccel *cell,
+ gchar *path_string,
+ guint keyval,
+ GdkModifierType mask)
+{
+ GtkTreeModel *model;
+ terminal_free_tree_path GtkTreePath *path = NULL;
+ GtkTreeIter iter;
+ KeyEntry *ke;
+ gs_free char *str = NULL;
+
+ model = gtk_tree_view_get_model (view);
+
+ path = gtk_tree_path_new_from_string (path_string);
+ if (!path)
+ return;
+
+ if (!gtk_tree_model_get_iter (model, &iter, path))
+ return;
+
+ gtk_tree_model_get (model, &iter, KEYVAL_COLUMN, &ke, -1);
+
+ /* sanity check */
+ if (ke == NULL)
+ return;
+
+ str = binding_name (keyval, mask);
+ g_settings_set_string (keybinding_settings, ke->settings_key, str);
+}
+
+static void
+accel_edited_callback (GtkCellRendererAccel *cell,
+ gchar *path_string,
+ guint keyval,
+ GdkModifierType mask,
+ guint hardware_keycode,
+ GtkTreeView *view)
+{
+ accel_update (view, cell, path_string, keyval, mask);
+}
+
+static void
+accel_cleared_callback (GtkCellRendererAccel *cell,
+ gchar *path_string,
+ GtkTreeView *view)
+{
+ accel_update (view, cell, path_string, 0, 0);
+}
+
+static void
+treeview_destroy_cb (GtkWidget *tree_view,
+ gpointer user_data)
+{
+ g_signal_handlers_disconnect_by_func (keybinding_settings,
+ G_CALLBACK (treeview_key_changed_cb),
+ tree_view);
+}
+
+#ifdef ENABLE_DEBUG
+static void
+row_changed (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+ "ROW-CHANGED [%s]\n", gtk_tree_path_to_string (path) /* leak */);
+}
+#endif
+
+void
+terminal_accels_fill_treeview (GtkWidget *tree_view,
+ GtkWidget *disable_shortcuts_button)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell_renderer;
+ gs_unref_object GtkTreeStore *tree = NULL;
+ guint i;
+
+ /* Column 1 */
+ cell_renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("_Action"),
+ cell_renderer,
+ "text", ACTION_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+
+ /* Column 2 */
+ cell_renderer = gtk_cell_renderer_accel_new ();
+ g_object_set (cell_renderer,
+ "editable", TRUE,
+ "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_GTK,
+ NULL);
+
+ g_signal_connect (cell_renderer, "accel-edited",
+ G_CALLBACK (accel_edited_callback), tree_view);
+ g_signal_connect (cell_renderer, "accel-cleared",
+ G_CALLBACK (accel_cleared_callback), tree_view);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Shortcut _Key"));
+ gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, cell_renderer, accel_set_func,
+ disable_shortcuts_button, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+
+ /* Add the data */
+
+ tree = gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
+
+#ifdef ENABLE_DEBUG
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ACCELS)
+ g_signal_connect (tree, "row-changed", G_CALLBACK (row_changed), NULL);
+#endif
+
+ for (i = 0; i < G_N_ELEMENTS (all_entries); ++i)
+ {
+ GtkTreeIter parent_iter;
+ guint j;
+
+ gtk_tree_store_insert_with_values (tree, &parent_iter, NULL, -1,
+ ACTION_COLUMN, _(all_entries[i].user_visible_name),
+ KEYVAL_COLUMN, NULL,
+ -1);
+
+ for (j = 0; j < all_entries[i].n_elements; ++j)
+ {
+ KeyEntry *key_entry = &(all_entries[i].key_entry[j]);
+ GtkTreeIter iter;
+
+ gtk_tree_store_insert_with_values (tree, &iter, &parent_iter, -1,
+ ACTION_COLUMN, _(key_entry->user_visible_name),
+ KEYVAL_COLUMN, key_entry,
+ -1);
+ }
+ }
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (tree));
+
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+
+ g_signal_connect (keybinding_settings, "changed",
+ G_CALLBACK (treeview_key_changed_cb), tree_view);
+ g_signal_connect (tree_view, "destroy",
+ G_CALLBACK (treeview_destroy_cb), tree);
+}
diff --git a/src/terminal-accels.h b/src/terminal-accels.h
new file mode 100644
index 0000000..8c860a3
--- /dev/null
+++ b/src/terminal-accels.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_ACCELS_H
+#define TERMINAL_ACCELS_H
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void terminal_accels_init (GApplication *application,
+ GSettings *settings,
+ gboolean use_headerbar);
+
+void terminal_accels_shutdown (void);
+
+void terminal_accels_fill_treeview (GtkWidget *treeview,
+ GtkWidget *disable_shortcuts_button);
+
+G_END_DECLS
+
+#endif /* TERMINAL_ACCELS_H */
diff --git a/src/terminal-app.c b/src/terminal-app.c
new file mode 100644
index 0000000..ff91e15
--- /dev/null
+++ b/src/terminal-app.c
@@ -0,0 +1,1278 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2008, 2010, 2011, 2015, 2017 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#define G_SETTINGS_ENABLE_BACKEND
+#include <gio/gsettingsbackend.h>
+
+#include "terminal-intl.h"
+#include "terminal-debug.h"
+#include "terminal-app.h"
+#include "terminal-accels.h"
+#include "terminal-screen.h"
+#include "terminal-screen-container.h"
+#include "terminal-window.h"
+#include "terminal-profiles-list.h"
+#include "terminal-util.h"
+#include "profile-editor.h"
+#include "terminal-schemas.h"
+#include "terminal-gdbus.h"
+#include "terminal-defines.h"
+#include "terminal-prefs.h"
+#include "terminal-libgsystem.h"
+
+#ifdef ENABLE_SEARCH_PROVIDER
+#include "terminal-search-provider.h"
+#endif /* ENABLE_SEARCH_PROVIDER */
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define DESKTOP_INTERFACE_SETTINGS_SCHEMA "org.gnome.desktop.interface"
+
+#define SYSTEM_PROXY_SETTINGS_SCHEMA "org.gnome.system.proxy"
+
+#define GTK_SETTING_PREFER_DARK_THEME "gtk-application-prefer-dark-theme"
+
+#define GTK_DEBUG_SETTING_SCHEMA "org.gtk.Settings.Debug"
+#define GTK_DEBUG_ENABLE_INSPECTOR_KEY "enable-inspector-keybinding"
+#define GTK_DEBUG_ENABLE_INSPECTOR_TYPE G_VARIANT_TYPE_BOOLEAN
+
+#ifdef DISUNIFY_NEW_TERMINAL_SECTION
+#error Use a gsettings override instead
+#endif
+
+/*
+ * Session state is stored entirely in the RestartCommand command line.
+ *
+ * The number one rule: all stored information is EITHER per-session,
+ * per-profile, or set from a command line option. THERE CAN BE NO
+ * OVERLAP. The UI and implementation totally break if you overlap
+ * these categories. See gnome-terminal 1.x for why.
+ */
+
+struct _TerminalAppClass {
+ GtkApplicationClass parent_class;
+
+ void (* clipboard_targets_changed) (TerminalApp *app,
+ GtkClipboard *clipboard);
+};
+
+struct _TerminalApp
+{
+ GtkApplication parent_instance;
+
+ GDBusObjectManagerServer *object_manager;
+
+ TerminalSettingsList *profiles_list;
+
+ GHashTable *screen_map;
+
+ GSettings *global_settings;
+ GSettings *desktop_interface_settings;
+ GSettings *system_proxy_settings;
+ GSettings *gtk_debug_settings;
+
+#ifdef ENABLE_SEARCH_PROVIDER
+ TerminalSearchProvider *search_provider;
+#endif /* ENABLE_SEARCH_PROVIDER */
+
+ GMenuModel *menubar;
+ GMenu *menubar_new_terminal_section;
+ GMenu *menubar_set_profile_section;
+
+ GMenuModel *profilemenu;
+ GMenuModel *headermenu;
+ GMenu *headermenu_set_profile_section;
+
+ GMenu *set_profile_menu;
+
+ GtkClipboard *clipboard;
+ GdkAtom *clipboard_targets;
+ int n_clipboard_targets;
+
+ gboolean unified_menu;
+ gboolean use_headerbar;
+};
+
+enum
+{
+ CLIPBOARD_TARGETS_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* Debugging helper */
+
+static void
+terminal_app_init_debug (void)
+{
+#ifdef ENABLE_DEBUG
+ const char *env = g_getenv ("GTK_TEXT_DIR");
+ if (env != NULL) {
+ if (g_str_equal (env, "help")) {
+ g_printerr ("Usage: GTK_TEXT_DIR=ltr|rtl\n");
+ } else {
+ GtkTextDirection dir;
+ if (g_str_equal (env, "rtl"))
+ dir = GTK_TEXT_DIR_RTL;
+ else
+ dir = GTK_TEXT_DIR_LTR;
+
+ gtk_widget_set_default_direction (dir);
+ }
+ }
+
+ env = g_getenv ("GTK_SETTINGS");
+ if (env == NULL)
+ return;
+
+ GObject *settings = G_OBJECT (gtk_settings_get_default ());
+ GObjectClass *settings_class = G_OBJECT_GET_CLASS (settings);
+
+ if (g_str_equal (env, "help")) {
+ g_printerr ("Usage: GTK_SETTINGS=setting[,setting…] where 'setting' is one of these:\n");
+
+ guint n_props;
+ GParamSpec **props = g_object_class_list_properties (settings_class, &n_props);
+ for (guint i = 0; i < n_props; i++) {
+ if (G_PARAM_SPEC_VALUE_TYPE (props[i]) != G_TYPE_BOOLEAN)
+ continue;
+
+ GValue value = { 0, };
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_object_get_property (settings, props[i]->name, &value);
+ g_printerr (" %s (%s)\n", props[i]->name, g_value_get_boolean (&value) ? "true" : "false");
+ g_value_unset (&value);
+ }
+ g_printerr (" Use 'setting' to set to true, "
+ "'~setting' to set to false, "
+ "and '!setting' to invert.\n");
+ } else {
+ gs_strfreev char **tokens = g_strsplit (env, ",", -1);
+ for (guint i = 0; tokens[i] != NULL; i++) {
+ const char *prop = tokens[i];
+ char c = prop[0];
+ if (c == '~' || c == '!')
+ prop++;
+
+ GParamSpec *pspec = g_object_class_find_property (settings_class, prop);
+ if (pspec == NULL) {
+ g_printerr ("Setting \"%s\" does not exist.\n", prop);
+ } else if (G_PARAM_SPEC_VALUE_TYPE (pspec) != G_TYPE_BOOLEAN) {
+ g_printerr ("Setting \"%s\" is not boolean.\n", prop);
+ } else {
+ GValue value = { 0, };
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ if (c == '!') {
+ g_object_get_property (settings, pspec->name, &value);
+ g_value_set_boolean (&value, !g_value_get_boolean (&value));
+ } else if (c == '~') {
+ g_value_set_boolean (&value, FALSE);
+ } else {
+ g_value_set_boolean (&value, TRUE);
+ }
+ g_object_set_property (settings, pspec->name, &value);
+ g_value_unset (&value);
+ }
+ }
+ }
+#endif
+}
+
+/* Helper functions */
+
+static gboolean
+strv_contains_gnome (char **strv)
+{
+ if (strv == NULL)
+ return FALSE;
+
+ for (int i = 0; strv[i] != NULL; i++) {
+ if (g_ascii_strcasecmp (strv[i], "gnome") == 0 ||
+ g_ascii_strcasecmp (strv[i], "gnome-classic") == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * terminal_app_should_use_headerbar:
+ *
+ * Determines if the app should use headerbars. This is determined
+ * * If the pref is set, the pref value is used
+ * * Otherwise, if XDG_CURRENT_DESKTOP contains GNOME or GNOME-Classic,
+ * headerbar is used
+ * * Otherwise, headerbar is not used.
+ */
+static gboolean
+terminal_app_should_use_headerbar (TerminalApp *app)
+{
+ gboolean set, use;
+ g_settings_get (app->global_settings, TERMINAL_SETTING_HEADERBAR_KEY, "mb", &set, &use);
+ if (set)
+ return use;
+
+ const char *desktop = g_getenv ("XDG_CURRENT_DESKTOP");
+ if (desktop == NULL)
+ return FALSE;
+
+ char **desktops = g_strsplit (desktop, G_SEARCHPATH_SEPARATOR_S, -1);
+ use = strv_contains_gnome (desktops);
+ g_strfreev (desktops);
+
+ return use;
+}
+
+static gboolean
+load_css_from_resource (GApplication *application,
+ GtkCssProvider *provider,
+ gboolean theme)
+{
+ const char *base_path;
+ gs_free char *uri;
+ gs_unref_object GFile *file;
+ gs_free_error GError *error = NULL;
+
+ base_path = g_application_get_resource_base_path (application);
+
+ if (theme) {
+ gs_free char *str, *theme_name;
+
+ g_object_get (gtk_settings_get_default (), "gtk-theme-name", &str, NULL);
+ theme_name = g_ascii_strdown (str, -1);
+ uri = g_strdup_printf ("resource://%s/css/%s/terminal.css", base_path, theme_name);
+ } else {
+ uri = g_strdup_printf ("resource://%s/css/terminal.css", base_path);
+ }
+
+ file = g_file_new_for_uri (uri);
+ if (!g_file_query_exists (file, NULL /* cancellable */))
+ return FALSE;
+
+ if (!gtk_css_provider_load_from_file (provider, file, &error))
+ g_assert_no_error (error);
+
+ return TRUE;
+}
+
+static void
+add_css_provider (GApplication *application,
+ gboolean theme)
+{
+ gs_unref_object GtkCssProvider *provider;
+
+ provider = gtk_css_provider_new ();
+ if (!load_css_from_resource (application, provider, theme))
+ return;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static void
+app_load_css (GApplication *application)
+{
+ add_css_provider (application, FALSE);
+ add_css_provider (application, TRUE);
+}
+
+char *
+terminal_app_new_profile (TerminalApp *app,
+ GSettings *base_profile,
+ const char *name)
+{
+ char *uuid;
+
+ if (base_profile) {
+ gs_free char *base_uuid;
+
+ base_uuid = terminal_settings_list_dup_uuid_from_child (app->profiles_list, base_profile);
+ uuid = terminal_settings_list_clone_child (app->profiles_list, base_uuid, name);
+ } else {
+ uuid = terminal_settings_list_add_child (app->profiles_list, name);
+ }
+
+ return uuid;
+}
+
+void
+terminal_app_remove_profile (TerminalApp *app,
+ GSettings *profile)
+{
+ g_return_if_fail (TERMINAL_IS_APP (app));
+ g_return_if_fail (G_IS_SETTINGS (profile));
+
+ gs_unref_object GSettings *default_profile = terminal_settings_list_ref_default_child (app->profiles_list);
+ if (default_profile == profile)
+ return;
+
+ /* First, we need to switch any screen using this profile to the default profile */
+ gs_free_list GList *screens = g_hash_table_get_values (app->screen_map);
+ for (GList *l = screens; l != NULL; l = l->next) {
+ TerminalScreen *screen = TERMINAL_SCREEN (l->data);
+ if (terminal_screen_get_profile (screen) != profile)
+ continue;
+
+ terminal_screen_set_profile (screen, default_profile);
+ }
+
+ /* Now we can safely remove the profile */
+ gs_free char *uuid = terminal_settings_list_dup_uuid_from_child (app->profiles_list, profile);
+ terminal_settings_list_remove_child (app->profiles_list, uuid);
+}
+
+static void
+terminal_app_theme_variant_changed_cb (GSettings *settings,
+ const char *key,
+ GtkSettings *gtk_settings)
+{
+ TerminalThemeVariant theme;
+
+ theme = g_settings_get_enum (settings, key);
+ if (theme == TERMINAL_THEME_VARIANT_SYSTEM)
+ gtk_settings_reset_property (gtk_settings, GTK_SETTING_PREFER_DARK_THEME);
+ else
+ g_object_set (gtk_settings,
+ GTK_SETTING_PREFER_DARK_THEME,
+ theme == TERMINAL_THEME_VARIANT_DARK,
+ NULL);
+}
+
+/* Submenus for New Terminal per profile, and to change profiles */
+
+static void terminal_app_update_profile_menus (TerminalApp *app);
+
+typedef struct {
+ char *uuid;
+ char *label;
+} ProfileData;
+
+static void
+profile_data_clear (ProfileData *data)
+{
+ g_free (data->uuid);
+ g_free (data->label);
+}
+
+typedef struct {
+ GArray *array;
+ TerminalApp *app;
+} ProfilesForeachData;
+
+static void
+foreach_profile_cb (TerminalSettingsList *list,
+ const char *uuid,
+ GSettings *profile,
+ ProfilesForeachData *user_data)
+{
+ ProfileData data;
+ data.uuid = g_strdup (uuid);
+ data.label = g_settings_get_string (profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+
+ g_array_append_val (user_data->array, data);
+
+ /* only connect if we haven't seen this profile before */
+ if (g_signal_handler_find (profile, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, terminal_app_update_profile_menus, user_data->app) == 0)
+ g_signal_connect_swapped (profile, "changed::" TERMINAL_PROFILE_VISIBLE_NAME_KEY,
+ G_CALLBACK (terminal_app_update_profile_menus), user_data->app);
+}
+
+static int
+compare_profile_label_cb (gconstpointer ap,
+ gconstpointer bp)
+{
+ const ProfileData *a = ap;
+ const ProfileData *b = bp;
+
+ return g_utf8_collate (a->label, b->label);
+}
+
+static void
+menu_append_numbered (GMenu *menu,
+ const char *label,
+ int num,
+ const char *action_name,
+ GVariant *target /* floating, consumed */)
+{
+ gs_free_gstring GString *str;
+ gs_unref_object GMenuItem *item;
+ const char *p;
+
+ /* Who'd use more that 4 underscores in a profile name... */
+ str = g_string_sized_new (strlen (label) + 4 + 1 + 8);
+
+ if (num < 10)
+ g_string_append_printf (str, "_%Id. ", num);
+ else if (num < 36)
+ g_string_append_printf (str, "_%c. ", (char)('A' + num - 10));
+
+ /* Append the label with underscores elided */
+ for (p = label; *p; p++) {
+ if (*p == '_')
+ g_string_append (str, "__");
+ else
+ g_string_append_c (str, *p);
+ }
+
+ item = g_menu_item_new (str->str, NULL);
+ g_menu_item_set_action_and_target_value (item, action_name, target);
+ g_menu_append_item (menu, item);
+}
+
+static void
+append_new_terminal_item (GMenu *section,
+ const char *label,
+ const char *target,
+ ProfileData *data,
+ guint n_profiles)
+{
+ gs_unref_object GMenuItem *item = g_menu_item_new (label, NULL);
+
+ if (n_profiles > 1) {
+ gs_unref_object GMenu *submenu = g_menu_new ();
+
+ for (guint i = 0; i < n_profiles; i++) {
+ menu_append_numbered (submenu, data[i].label, i + 1,
+ "win.new-terminal",
+ g_variant_new ("(ss)", target, data[i].uuid));
+ }
+
+ g_menu_item_set_link (item, G_MENU_LINK_SUBMENU, G_MENU_MODEL (submenu));
+ } else {
+ g_menu_item_set_action_and_target (item, "win.new-terminal",
+ "(ss)", target, "current");
+ }
+ g_menu_append_item (section, item);
+}
+
+static void
+fill_header_new_terminal_menu (GMenuModel *menu,
+ ProfileData *data,
+ guint n_profiles)
+{
+ gs_unref_object GMenu *section = NULL;
+
+ if (n_profiles <= 1)
+ return;
+
+ section = g_menu_new ();
+
+ for (guint i = 0; i < n_profiles; i++) {
+ menu_append_numbered (section, data[i].label, i + 1,
+ "win.new-terminal",
+ g_variant_new ("(ss)", "default", data[i].uuid));
+ }
+
+ g_menu_append_section (G_MENU (menu), _("New Terminal"), G_MENU_MODEL (section));
+}
+
+static void
+fill_new_terminal_section (TerminalApp *app,
+ GMenu *section,
+ ProfileData *profiles,
+ guint n_profiles)
+{
+ if (terminal_app_get_menu_unified (app)) {
+ append_new_terminal_item (section, _("New _Terminal"), "default", profiles, n_profiles);
+ } else {
+ append_new_terminal_item (section, _("New _Tab"), "tab", profiles, n_profiles);
+ append_new_terminal_item (section, _("New _Window"), "window", profiles, n_profiles);
+ }
+}
+
+static GMenu *
+set_profile_submenu_new (ProfileData *data,
+ guint n_profiles)
+{
+ /* No submenu if there's only one profile */
+ if (n_profiles <= 1)
+ return NULL;
+
+ GMenu *menu = g_menu_new ();
+ for (guint i = 0; i < n_profiles; i++) {
+ menu_append_numbered (menu, data[i].label, i + 1,
+ "win.profile",
+ g_variant_new_string (data[i].uuid));
+ }
+
+ return menu;
+}
+
+static void
+terminal_app_update_profile_menus (TerminalApp *app)
+{
+ g_clear_object (&app->set_profile_menu);
+
+ /* Get profiles list and sort by label */
+ gs_unref_array GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (ProfileData),
+ terminal_settings_list_get_n_children (app->profiles_list));
+ g_array_set_clear_func (array, (GDestroyNotify) profile_data_clear);
+
+ ProfilesForeachData data = { array, app };
+ terminal_settings_list_foreach_child (app->profiles_list,
+ (TerminalSettingsListForeachFunc) foreach_profile_cb,
+ &data);
+ g_array_sort (array, compare_profile_label_cb);
+
+ ProfileData *profiles = (ProfileData*) array->data;
+ guint n_profiles = array->len;
+
+ app->set_profile_menu = set_profile_submenu_new (profiles, n_profiles);
+
+ if (app->menubar != NULL) {
+ g_menu_remove_all (G_MENU (app->menubar_new_terminal_section));
+ fill_new_terminal_section (app, app->menubar_new_terminal_section, profiles, n_profiles);
+
+ g_menu_remove_all (G_MENU (app->menubar_set_profile_section));
+ if (app->set_profile_menu != NULL) {
+ g_menu_append_submenu (app->menubar_set_profile_section, _("Change _Profile"),
+ G_MENU_MODEL (app->set_profile_menu));
+ }
+ }
+
+ if (app->profilemenu != NULL) {
+ g_menu_remove_all (G_MENU (app->profilemenu));
+ fill_header_new_terminal_menu (app->profilemenu, profiles, n_profiles);
+ }
+
+ if (app->headermenu != NULL) {
+ g_menu_remove_all (G_MENU (app->headermenu_set_profile_section));
+ if (app->set_profile_menu != NULL) {
+ g_menu_append_submenu (app->headermenu_set_profile_section, _("_Profile"),
+ G_MENU_MODEL (app->set_profile_menu));
+ }
+ }
+}
+
+static GMenuModel *
+terminal_app_create_menubar (TerminalApp *app,
+ gboolean shell_shows_menubar)
+{
+ /* If the menubar is shown by the shell, omit mnemonics for the submenus. This is because Alt+F etc.
+ * are more important to be usable in the terminal, the menu cannot be replaced runtime (to toggle
+ * between mnemonic and non-mnemonic versions), gtk-enable-mnemonics or gtk_window_set_mnemonic_modifier()
+ * don't effect the menubar either, so there wouldn't be a way to disable Alt+F for File etc. otherwise.
+ * Furthermore, the menu would even grab mnemonics from the File and Preferences windows.
+ * In Unity, Alt+F10 opens the menubar, this should be good enough for keyboard navigation.
+ * If the menubar is shown by the app, toggling mnemonics is handled in terminal-window.c using
+ * gtk_window_set_mnemonic_modifier().
+ * See bug 792978 for details. */
+ terminal_util_load_objects_resource (shell_shows_menubar ? "/org/gnome/terminal/ui/menubar-without-mnemonics.ui"
+ : "/org/gnome/terminal/ui/menubar-with-mnemonics.ui",
+ "menubar", &app->menubar,
+ "new-terminal-section", &app->menubar_new_terminal_section,
+ "set-profile-section", &app->menubar_set_profile_section,
+ NULL);
+
+ /* Install profile sections */
+ terminal_app_update_profile_menus (app);
+
+ return app->menubar;
+}
+
+static void
+terminal_app_create_headermenu (TerminalApp *app)
+{
+ terminal_util_load_objects_resource ("/org/gnome/terminal/ui/headerbar-menu.ui",
+ "headermenu", &app->headermenu,
+ "set-profile-section", &app->headermenu_set_profile_section,
+ NULL);
+
+ /* Install profile sections */
+ terminal_app_update_profile_menus (app);
+}
+
+static void
+terminal_app_create_profilemenu (TerminalApp *app)
+{
+ app->profilemenu = G_MENU_MODEL (g_menu_new ());
+
+ /* Install profile sections */
+ terminal_app_update_profile_menus (app);
+}
+
+/* Clipboard */
+
+static void
+free_clipboard_targets (TerminalApp *app)
+{
+ g_free (app->clipboard_targets);
+ app->clipboard_targets = NULL;
+ app->n_clipboard_targets = 0;
+}
+
+static void
+update_clipboard_targets (TerminalApp *app,
+ GdkAtom *targets,
+ int n_targets)
+{
+ free_clipboard_targets (app);
+
+ /* Sometimes we receive targets == NULL but n_targets == -1 */
+ if (targets != NULL && n_targets < 255) {
+ app->clipboard_targets = g_memdup (targets, sizeof (targets[0]) * n_targets);
+ app->n_clipboard_targets = n_targets;
+ }
+}
+
+static void
+clipboard_targets_received_cb (GtkClipboard *clipboard,
+ GdkAtom *targets,
+ int n_targets,
+ TerminalApp *app)
+{
+ update_clipboard_targets (app, targets, n_targets);
+
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_CLIPBOARD) {
+ g_printerr ("Clipboard has %d targets:", app->n_clipboard_targets);
+
+ int i;
+ for (i = 0; i < app->n_clipboard_targets; i++) {
+ gs_free char *atom_name = gdk_atom_name (app->clipboard_targets[i]);
+ g_printerr (" %s", atom_name);
+ }
+ g_printerr ("\n");
+ }
+
+ g_signal_emit (app, signals[CLIPBOARD_TARGETS_CHANGED], 0, clipboard);
+}
+
+static void
+clipboard_owner_change_cb (GtkClipboard *clipboard,
+ GdkEvent *event G_GNUC_UNUSED,
+ TerminalApp *app)
+{
+ _terminal_debug_print (TERMINAL_DEBUG_CLIPBOARD,
+ "Clipboard owner changed\n");
+
+ clipboard_targets_received_cb (clipboard, NULL, 0, app); /* clear */
+
+ /* We can do this without holding a reference to @app since
+ * the app lives as long as the process.
+ */
+ gtk_clipboard_request_targets (clipboard,
+ (GtkClipboardTargetsReceivedFunc) clipboard_targets_received_cb,
+ app);
+}
+
+/* Callbacks from former app menu.
+ * The preferences one is still used with the "--preferences" cmdline option. */
+
+static void
+app_menu_preferences_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalApp *app = user_data;
+
+ terminal_app_edit_preferences (app, NULL, NULL);
+}
+
+static void
+app_menu_help_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ terminal_util_show_help (NULL);
+}
+
+static void
+app_menu_about_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ terminal_util_show_about ();
+}
+
+static void
+app_menu_quit_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GtkApplication *application = user_data;
+ GtkWindow *window;
+
+ window = gtk_application_get_active_window (application);
+ if (TERMINAL_IS_WINDOW (window))
+ terminal_window_request_close (TERMINAL_WINDOW (window));
+ else /* a dialogue */
+ gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+/* Class implementation */
+
+G_DEFINE_TYPE (TerminalApp, terminal_app, GTK_TYPE_APPLICATION)
+
+/* GApplicationClass impl */
+
+static void
+terminal_app_activate (GApplication *application)
+{
+ /* No-op required because GApplication is stupid */
+}
+
+static void
+terminal_app_startup (GApplication *application)
+{
+ TerminalApp *app = TERMINAL_APP (application);
+ const GActionEntry action_entries[] = {
+ { "preferences", app_menu_preferences_cb, NULL, NULL, NULL },
+ { "help", app_menu_help_cb, NULL, NULL, NULL },
+ { "about", app_menu_about_cb, NULL, NULL, NULL },
+ { "quit", app_menu_quit_cb, NULL, NULL, NULL }
+ };
+
+ g_application_set_resource_base_path (application, TERMINAL_RESOURCES_PATH_PREFIX);
+
+ G_APPLICATION_CLASS (terminal_app_parent_class)->startup (application);
+
+ /* Need to set the WM class (bug #685742) */
+ gdk_set_program_class("Gnome-terminal");
+
+ g_action_map_add_action_entries (G_ACTION_MAP (application),
+ action_entries, G_N_ELEMENTS (action_entries),
+ application);
+
+ app_load_css (application);
+
+ /* Figure out whether the shell shows the menubar */
+ gboolean shell_shows_menubar;
+ g_object_get (gtk_settings_get_default (),
+ "gtk-shell-shows-menubar", &shell_shows_menubar,
+ NULL);
+
+ /* Create menubar */
+ terminal_app_create_menubar (app, shell_shows_menubar);
+
+ /* Keep dynamic menus updated */
+ g_signal_connect_swapped (app->profiles_list, "children-changed",
+ G_CALLBACK (terminal_app_update_profile_menus), app);
+
+ /* Show/hide the menubar as appropriate: If the shell wants to show the menubar, make it available. */
+ if (shell_shows_menubar)
+ gtk_application_set_menubar (GTK_APPLICATION (app),
+ terminal_app_get_menubar (app));
+
+ _terminal_debug_print (TERMINAL_DEBUG_SERVER, "Startup complete\n");
+}
+
+/* GObjectClass impl */
+
+static void
+terminal_app_init (TerminalApp *app)
+{
+ terminal_app_init_debug ();
+
+ gtk_window_set_default_icon_name (GNOME_TERMINAL_ICON_NAME);
+
+ /* Desktop proxy settings */
+ app->system_proxy_settings = g_settings_new (SYSTEM_PROXY_SETTINGS_SCHEMA);
+
+ /* Desktop Interface settings */
+ app->desktop_interface_settings = g_settings_new (DESKTOP_INTERFACE_SETTINGS_SCHEMA);
+
+ /* Terminal global settings */
+ app->global_settings = g_settings_new (TERMINAL_SETTING_SCHEMA);
+
+ /* Gtk debug settings */
+ app->gtk_debug_settings = terminal_g_settings_new (GTK_DEBUG_SETTING_SCHEMA,
+ GTK_DEBUG_ENABLE_INSPECTOR_KEY,
+ GTK_DEBUG_ENABLE_INSPECTOR_TYPE);
+
+ /* These are internal settings that exists only for distributions
+ * to override, so we cache them on startup and don't react to changes.
+ */
+ app->unified_menu = g_settings_get_boolean (app->global_settings, TERMINAL_SETTING_UNIFIED_MENU_KEY);
+ app->use_headerbar = terminal_app_should_use_headerbar (app);
+
+ GtkSettings *gtk_settings = gtk_settings_get_default ();
+ terminal_app_theme_variant_changed_cb (app->global_settings,
+ TERMINAL_SETTING_THEME_VARIANT_KEY, gtk_settings);
+ g_signal_connect (app->global_settings,
+ "changed::" TERMINAL_SETTING_THEME_VARIANT_KEY,
+ G_CALLBACK (terminal_app_theme_variant_changed_cb),
+ gtk_settings);
+
+ /* Clipboard targets */
+ GdkDisplay *display = gdk_display_get_default ();
+ app->clipboard = gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD);
+ clipboard_owner_change_cb (app->clipboard, NULL, app);
+ g_signal_connect (app->clipboard, "owner-change",
+ G_CALLBACK (clipboard_owner_change_cb), app);
+
+ if (!gdk_display_supports_selection_notification (display))
+ g_printerr ("Display does not support owner-change; copy/paste will be broken!\n");
+
+ /* Get the profiles */
+ app->profiles_list = terminal_profiles_list_new ();
+
+ app->screen_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ gs_unref_object GSettings *settings = g_settings_get_child (app->global_settings, "keybindings");
+ terminal_accels_init (G_APPLICATION (app), settings, app->use_headerbar);
+}
+
+static void
+terminal_app_finalize (GObject *object)
+{
+ TerminalApp *app = TERMINAL_APP (object);
+
+ g_signal_handlers_disconnect_by_func (app->clipboard,
+ G_CALLBACK (clipboard_owner_change_cb),
+ app);
+ free_clipboard_targets (app);
+
+ g_signal_handlers_disconnect_by_func (app->profiles_list,
+ G_CALLBACK (terminal_app_update_profile_menus),
+ app);
+ g_hash_table_destroy (app->screen_map);
+
+ g_object_unref (app->global_settings);
+ g_object_unref (app->desktop_interface_settings);
+ g_object_unref (app->system_proxy_settings);
+ g_clear_object (&app->gtk_debug_settings);
+
+ g_clear_object (&app->menubar);
+ g_clear_object (&app->menubar_new_terminal_section);
+ g_clear_object (&app->menubar_set_profile_section);
+ g_clear_object (&app->profilemenu);
+ g_clear_object (&app->headermenu);
+ g_clear_object (&app->headermenu_set_profile_section);
+ g_clear_object (&app->set_profile_menu);
+
+ terminal_accels_shutdown ();
+
+ G_OBJECT_CLASS (terminal_app_parent_class)->finalize (object);
+}
+
+static gboolean
+terminal_app_dbus_register (GApplication *application,
+ GDBusConnection *connection,
+ const gchar *object_path,
+ GError **error)
+{
+ TerminalApp *app = TERMINAL_APP (application);
+ gs_unref_object TerminalObjectSkeleton *object = NULL;
+ gs_unref_object TerminalFactory *factory = NULL;
+
+ if (!G_APPLICATION_CLASS (terminal_app_parent_class)->dbus_register (application,
+ connection,
+ object_path,
+ error))
+ return FALSE;
+
+#ifdef ENABLE_SEARCH_PROVIDER
+ if (g_settings_get_boolean (app->global_settings, TERMINAL_SETTING_SHELL_INTEGRATION_KEY)) {
+ gs_unref_object TerminalSearchProvider *search_provider;
+
+ search_provider = terminal_search_provider_new ();
+
+ if (!terminal_search_provider_dbus_register (search_provider,
+ connection,
+ TERMINAL_SEARCH_PROVIDER_PATH,
+ error))
+ return FALSE;
+
+ gs_transfer_out_value (&app->search_provider, &search_provider);
+ }
+#endif /* ENABLE_SEARCH_PROVIDER */
+
+ object = terminal_object_skeleton_new (TERMINAL_FACTORY_OBJECT_PATH);
+ factory = terminal_factory_impl_new ();
+ terminal_object_skeleton_set_factory (object, factory);
+
+ app->object_manager = g_dbus_object_manager_server_new (TERMINAL_OBJECT_PATH_PREFIX);
+ g_dbus_object_manager_server_export (app->object_manager, G_DBUS_OBJECT_SKELETON (object));
+
+ /* And export the object */
+ g_dbus_object_manager_server_set_connection (app->object_manager, connection);
+ return TRUE;
+}
+
+static void
+terminal_app_dbus_unregister (GApplication *application,
+ GDBusConnection *connection,
+ const gchar *object_path)
+{
+ TerminalApp *app = TERMINAL_APP (application);
+
+ if (app->object_manager) {
+ g_dbus_object_manager_server_unexport (app->object_manager, TERMINAL_FACTORY_OBJECT_PATH);
+ g_object_unref (app->object_manager);
+ app->object_manager = NULL;
+ }
+
+#ifdef ENABLE_SEARCH_PROVIDER
+ if (app->search_provider) {
+ terminal_search_provider_dbus_unregister (app->search_provider, connection, TERMINAL_SEARCH_PROVIDER_PATH);
+ g_object_unref (app->search_provider);
+ app->search_provider = NULL;
+ }
+#endif /* ENABLE_SEARCH_PROVIDER */
+
+ G_APPLICATION_CLASS (terminal_app_parent_class)->dbus_unregister (application,
+ connection,
+ object_path);
+}
+
+static void
+terminal_app_class_init (TerminalAppClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GApplicationClass *g_application_class = G_APPLICATION_CLASS (klass);
+
+ object_class->finalize = terminal_app_finalize;
+
+ g_application_class->activate = terminal_app_activate;
+ g_application_class->startup = terminal_app_startup;
+ g_application_class->dbus_register = terminal_app_dbus_register;
+ g_application_class->dbus_unregister = terminal_app_dbus_unregister;
+
+ signals[CLIPBOARD_TARGETS_CHANGED] =
+ g_signal_new (I_("clipboard-targets-changed"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalAppClass, clipboard_targets_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+}
+
+/* Public API */
+
+GApplication *
+terminal_app_new (const char *app_id)
+{
+ const GApplicationFlags flags = G_APPLICATION_IS_SERVICE;
+
+ return g_object_new (TERMINAL_TYPE_APP,
+ "application-id", app_id ? app_id : TERMINAL_APPLICATION_ID,
+ "flags", flags,
+ NULL);
+}
+
+TerminalScreen *
+terminal_app_get_screen_by_uuid (TerminalApp *app,
+ const char *uuid)
+{
+ g_return_val_if_fail (TERMINAL_IS_APP (app), NULL);
+
+ return g_hash_table_lookup (app->screen_map, uuid);
+}
+
+char *
+terminal_app_dup_screen_object_path (TerminalApp *app,
+ TerminalScreen *screen)
+{
+ char *object_path = g_strdup_printf (TERMINAL_RECEIVER_OBJECT_PATH_FORMAT,
+ terminal_screen_get_uuid (screen));
+ object_path = g_strdelimit (object_path, "-", '_');
+ g_assert (g_variant_is_object_path (object_path));
+ return object_path;
+}
+
+/**
+ * terminal_app_get_receiver_impl_by_object_path:
+ * @app:
+ * @object_path:
+ *
+ * Returns: (transfer full): the #TerminalReceiverImpl for @object_path, or %NULL
+ */
+static TerminalReceiverImpl *
+terminal_app_get_receiver_impl_by_object_path (TerminalApp *app,
+ const char *object_path)
+{
+ gs_unref_object GDBusObject *skeleton =
+ g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (app->object_manager),
+ object_path);
+ if (skeleton == NULL || !TERMINAL_IS_OBJECT_SKELETON (skeleton))
+ return NULL;
+
+ TerminalReceiverImpl *impl = NULL;
+ g_object_get (skeleton, "receiver", &impl, NULL);
+ if (impl == NULL)
+ return NULL;
+
+ g_assert (TERMINAL_IS_RECEIVER_IMPL (impl));
+ return impl;
+}
+
+/**
+ * terminal_app_get_screen_by_object_path:
+ * @app:
+ * @object_path:
+ *
+ * Returns: (transfer full): the #TerminalScreen for @object_path, or %NULL
+ */
+TerminalScreen *
+terminal_app_get_screen_by_object_path (TerminalApp *app,
+ const char *object_path)
+{
+ gs_unref_object TerminalReceiverImpl *impl =
+ terminal_app_get_receiver_impl_by_object_path (app, object_path);
+ if (impl == NULL)
+ return NULL;
+
+ return terminal_receiver_impl_get_screen (impl);
+}
+
+void
+terminal_app_register_screen (TerminalApp *app,
+ TerminalScreen *screen)
+{
+ const char *uuid = terminal_screen_get_uuid (screen);
+ g_hash_table_insert (app->screen_map, g_strdup (uuid), screen);
+
+ gs_free char *object_path = terminal_app_dup_screen_object_path (app, screen);
+ TerminalObjectSkeleton *skeleton = terminal_object_skeleton_new (object_path);
+
+ TerminalReceiverImpl *impl = terminal_receiver_impl_new (screen);
+ terminal_object_skeleton_set_receiver (skeleton, TERMINAL_RECEIVER (impl));
+ g_object_unref (impl);
+
+ g_dbus_object_manager_server_export (app->object_manager,
+ G_DBUS_OBJECT_SKELETON (skeleton));
+}
+
+void
+terminal_app_unregister_screen (TerminalApp *app,
+ TerminalScreen *screen)
+{
+ const char *uuid = terminal_screen_get_uuid (screen);
+ gboolean found = g_hash_table_remove (app->screen_map, uuid);
+ g_warn_if_fail (found);
+ if (!found)
+ return; /* repeat unregistering */
+
+ gs_free char *object_path = terminal_app_dup_screen_object_path (app, screen);
+ gs_unref_object TerminalReceiverImpl *impl =
+ terminal_app_get_receiver_impl_by_object_path (app, object_path);
+ g_warn_if_fail (impl != NULL);
+
+ if (impl != NULL)
+ terminal_receiver_impl_unset_screen (impl);
+
+ g_dbus_object_manager_server_unexport (app->object_manager, object_path);
+}
+
+GdkAtom *
+terminal_app_get_clipboard_targets (TerminalApp *app,
+ GtkClipboard *clipboard,
+ int *n_targets)
+{
+ g_return_val_if_fail (TERMINAL_IS_APP (app), NULL);
+ g_return_val_if_fail (n_targets != NULL, NULL);
+
+ if (clipboard != app->clipboard) {
+ *n_targets = 0;
+ return NULL;
+ }
+
+ *n_targets = app->n_clipboard_targets;
+ return app->clipboard_targets;
+}
+
+void
+terminal_app_edit_preferences (TerminalApp *app,
+ GSettings *profile,
+ const char *widget_name)
+{
+ terminal_prefs_show_preferences (profile, widget_name);
+}
+
+/**
+ * terminal_app_get_profiles_list:
+ *
+ * Returns: (transfer none): returns the singleton profiles list #TerminalSettingsList
+ */
+TerminalSettingsList *
+terminal_app_get_profiles_list (TerminalApp *app)
+{
+ return app->profiles_list;
+}
+
+/**
+ * terminal_app_get_menubar:
+ * @app: a #TerminalApp
+ *
+ * Returns: (tranfer none): the main window menu bar as a #GMenuModel
+ */
+GMenuModel *
+terminal_app_get_menubar (TerminalApp *app)
+{
+ return app->menubar;
+}
+
+/**
+ * terminal_app_get_headermenu:
+ * @app: a #TerminalApp
+ *
+ * Returns: (tranfer none): the main window headerbar menu bar as a #GMenuModel
+ */
+GMenuModel *
+terminal_app_get_headermenu (TerminalApp *app)
+{
+ if (app->headermenu == NULL)
+ terminal_app_create_headermenu (app);
+
+ return app->headermenu;
+}
+
+/**
+ * terminal_app_get_profilemenu:
+ * @app: a #TerminalApp
+ *
+ * Returns: (tranfer none): the main window headerbar profile menu as a #GMenuModel
+ */
+GMenuModel *
+terminal_app_get_profilemenu (TerminalApp *app)
+{
+ if (app->profilemenu == NULL)
+ terminal_app_create_profilemenu (app);
+
+ return app->profilemenu;
+}
+
+/**
+ * terminal_app_get_profile_section:
+ * @app: a #TerminalApp
+ *
+ * Returns: (tranfer none): the main window's menubar's profiles section as a #GMenuModel
+ */
+GMenuModel *
+terminal_app_get_profile_section (TerminalApp *app)
+{
+ return G_MENU_MODEL (app->set_profile_menu);
+}
+
+/**
+ * terminal_app_get_global_settings:
+ * @app: a #TerminalApp
+ *
+ * Returns: (tranfer none): the cached #GSettings object for the org.gnome.Terminal.Preferences schema
+ */
+GSettings *
+terminal_app_get_global_settings (TerminalApp *app)
+{
+ return app->global_settings;
+}
+
+/**
+ * terminal_app_get_desktop_interface_settings:
+ * @app: a #TerminalApp
+ *
+ * Returns: (tranfer none): the cached #GSettings object for the org.gnome.interface schema
+ */
+GSettings *
+terminal_app_get_desktop_interface_settings (TerminalApp *app)
+{
+ return app->desktop_interface_settings;
+}
+
+/**
+ * terminal_app_get_proxy_settings:
+ * @app: a #TerminalApp
+ *
+ * Returns: (tranfer none): the cached #GSettings object for the org.gnome.system.proxy schema
+ */
+GSettings *
+terminal_app_get_proxy_settings (TerminalApp *app)
+{
+ return app->system_proxy_settings;
+}
+
+GSettings *
+terminal_app_get_gtk_debug_settings (TerminalApp *app)
+{
+ return app->gtk_debug_settings;
+}
+
+/**
+ * terminal_app_get_system_font:
+ * @app:
+ *
+ * Creates a #PangoFontDescription for the system monospace font.
+ *
+ * Returns: (transfer full): a new #PangoFontDescription
+ */
+PangoFontDescription *
+terminal_app_get_system_font (TerminalApp *app)
+{
+ gs_free char *font = NULL;
+
+ g_return_val_if_fail (TERMINAL_IS_APP (app), NULL);
+
+ font = g_settings_get_string (app->desktop_interface_settings, MONOSPACE_FONT_KEY_NAME);
+
+ return pango_font_description_from_string (font);
+}
+
+/**
+ * FIXME
+ */
+GDBusObjectManagerServer *
+terminal_app_get_object_manager (TerminalApp *app)
+{
+ g_warn_if_fail (app->object_manager != NULL);
+ return app->object_manager;
+}
+
+gboolean
+terminal_app_get_menu_unified (TerminalApp *app)
+{
+ g_return_val_if_fail (TERMINAL_IS_APP (app), TRUE);
+
+ return app->unified_menu;
+}
+
+gboolean
+terminal_app_get_use_headerbar (TerminalApp *app)
+{
+ g_return_val_if_fail (TERMINAL_IS_APP (app), FALSE);
+
+ return app->use_headerbar;
+}
+
+gboolean
+terminal_app_get_dialog_use_headerbar (TerminalApp *app)
+{
+ g_return_val_if_fail (TERMINAL_IS_APP (app), FALSE);
+
+ gboolean dialog_use_header;
+ g_object_get (gtk_settings_get_default (),
+ "gtk-dialogs-use-header", &dialog_use_header,
+ NULL);
+
+ return dialog_use_header && app->use_headerbar;
+}
diff --git a/src/terminal-app.h b/src/terminal-app.h
new file mode 100644
index 0000000..a36361e
--- /dev/null
+++ b/src/terminal-app.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2008 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_APP_H
+#define TERMINAL_APP_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+#include "terminal-profiles-list.h"
+
+G_BEGIN_DECLS
+
+#define GNOME_TERMINAL_ICON_NAME "org.gnome.Terminal"
+
+#define TERMINAL_RESOURCES_PATH_PREFIX "/org/gnome/terminal"
+
+#define MONOSPACE_FONT_KEY_NAME "monospace-font-name"
+
+/* TerminalApp */
+
+#define TERMINAL_TYPE_APP (terminal_app_get_type ())
+#define TERMINAL_APP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_APP, TerminalApp))
+#define TERMINAL_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_APP, TerminalAppClass))
+#define TERMINAL_IS_APP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_APP))
+#define TERMINAL_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_APP))
+#define TERMINAL_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_APP, TerminalAppClass))
+
+typedef struct _TerminalAppClass TerminalAppClass;
+typedef struct _TerminalApp TerminalApp;
+
+GType terminal_app_get_type (void);
+
+GApplication *terminal_app_new (const char *app_id);
+
+#define terminal_app_get (TerminalApp *) g_application_get_default
+
+GDBusObjectManagerServer *terminal_app_get_object_manager (TerminalApp *app);
+
+GdkAtom *terminal_app_get_clipboard_targets (TerminalApp *app,
+ GtkClipboard *clipboard,
+ int *n_targets);
+
+void terminal_app_edit_preferences (TerminalApp *app,
+ GSettings *profile,
+ const char *widget_name);
+
+char *terminal_app_new_profile (TerminalApp *app,
+ GSettings *default_base_profile,
+ const char *name);
+
+void terminal_app_remove_profile (TerminalApp *app,
+ GSettings *profile);
+
+char *terminal_app_dup_screen_object_path (TerminalApp *app,
+ TerminalScreen *screen);
+
+TerminalScreen *terminal_app_get_screen_by_uuid (TerminalApp *app,
+ const char *uuid);
+
+TerminalScreen *terminal_app_get_screen_by_object_path (TerminalApp *app,
+ const char *object_path);
+
+void terminal_app_register_screen (TerminalApp *app,
+ TerminalScreen *screen);
+
+void terminal_app_unregister_screen (TerminalApp *app,
+ TerminalScreen *screen);
+
+TerminalSettingsList *terminal_app_get_profiles_list (TerminalApp *app);
+
+/* Menus */
+
+GMenuModel *terminal_app_get_menubar (TerminalApp *app);
+
+GMenuModel *terminal_app_get_headermenu (TerminalApp *app);
+
+GMenuModel *terminal_app_get_profilemenu (TerminalApp *app);
+
+GMenuModel *terminal_app_get_profile_section (TerminalApp *app);
+
+gboolean terminal_app_get_menu_unified (TerminalApp *app);
+
+gboolean terminal_app_get_use_headerbar (TerminalApp *app);
+
+gboolean terminal_app_get_dialog_use_headerbar (TerminalApp *app);
+
+/* GSettings */
+
+GSettings *terminal_app_get_global_settings (TerminalApp *app);
+
+GSettings *terminal_app_get_desktop_interface_settings (TerminalApp *app);
+
+GSettings *terminal_app_get_proxy_settings (TerminalApp *app);
+
+GSettings *terminal_app_get_gtk_debug_settings (TerminalApp *app);
+
+PangoFontDescription *terminal_app_get_system_font (TerminalApp *app);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_APP_H */
diff --git a/src/terminal-client-utils.c b/src/terminal-client-utils.c
new file mode 100644
index 0000000..e929281
--- /dev/null
+++ b/src/terminal-client-utils.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2011, 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-client-utils.h"
+#include "terminal-defines.h"
+#include "terminal-libgsystem.h"
+
+#include <string.h>
+
+#include <gio/gio.h>
+
+#include <gdk/gdk.h>
+#if defined(TERMINAL_COMPILATION) && defined(GDK_WINDOWING_X11)
+#include <gdk/gdkx.h>
+#endif
+
+/**
+ * terminal_client_append_create_instance_options:
+ * @builder: a #GVariantBuilder of #GVariantType "a{sv}"
+ * @display: (array element-type=guint8):
+ * @startup_id: (array element-type=guint8):
+ * @geometry:
+ * @role:
+ * @profile:
+ * @title:
+ * @maximise_window:
+ * @fullscreen_window:
+ *
+ * Appends common options to @builder.
+ */
+void
+terminal_client_append_create_instance_options (GVariantBuilder *builder,
+ const char *display_name,
+ const char *startup_id,
+ const char *geometry,
+ const char *role,
+ const char *profile,
+ const char *encoding,
+ const char *title,
+ gboolean active,
+ gboolean maximise_window,
+ gboolean fullscreen_window)
+{
+ /* Bytestring options */
+ if (display_name != NULL)
+ g_variant_builder_add (builder, "{sv}",
+ "display", g_variant_new_bytestring (display_name));
+ if (startup_id)
+ g_variant_builder_add (builder, "{sv}",
+ "desktop-startup-id", g_variant_new_bytestring (startup_id));
+
+ /* String options */
+ if (profile)
+ g_variant_builder_add (builder, "{sv}",
+ "profile", g_variant_new_string (profile));
+ if (encoding)
+ g_variant_builder_add (builder, "{sv}",
+ "encoding", g_variant_new_string (encoding));
+ if (title)
+ g_variant_builder_add (builder, "{sv}",
+ "title", g_variant_new_string (title));
+ if (geometry)
+ g_variant_builder_add (builder, "{sv}",
+ "geometry", g_variant_new_string (geometry));
+ if (role)
+ g_variant_builder_add (builder, "{sv}",
+ "role", g_variant_new_string (role));
+
+ /* Boolean options */
+ if (active)
+ g_variant_builder_add (builder, "{sv}",
+ "active", g_variant_new_boolean (active));
+
+ if (maximise_window)
+ g_variant_builder_add (builder, "{sv}",
+ "maximize-window", g_variant_new_boolean (TRUE));
+ if (fullscreen_window)
+ g_variant_builder_add (builder, "{sv}",
+ "fullscreen-window", g_variant_new_boolean (TRUE));
+}
+
+/**
+ * terminal_client_append_exec_options:
+ * @builder: a #GVariantBuilder of #GVariantType "a{sv}"
+ * @pass_environment: whether to pass the current environment
+ * @working_directory: (allow-none): the cwd, or %NULL
+ * @fd_array: (array lenght=fd_array_len):
+ * @fd_array_len:
+ * @shell:
+ *
+ * Appends the environment and the working directory to @builder.
+ */
+void
+terminal_client_append_exec_options (GVariantBuilder *builder,
+ gboolean pass_environment,
+ const char *working_directory,
+ PassFdElement *fd_array,
+ gsize fd_array_len,
+ gboolean shell)
+{
+ if (pass_environment) {
+ gs_strfreev char **envv;
+
+ envv = g_get_environ ();
+ envv = g_environ_unsetenv (envv, "COLORTERM");
+ envv = g_environ_unsetenv (envv, "COLUMNS");
+ envv = g_environ_unsetenv (envv, "DESKTOP_STARTUP_ID");
+ envv = g_environ_unsetenv (envv, "EXIT_CODE");
+ envv = g_environ_unsetenv (envv, "EXIT_STATUS");
+ envv = g_environ_unsetenv (envv, "GIO_LAUNCHED_DESKTOP_FILE");
+ envv = g_environ_unsetenv (envv, "GIO_LAUNCHED_DESKTOP_FILE_PID");
+ envv = g_environ_unsetenv (envv, "GNOME_DESKTOP_ICON");
+ envv = g_environ_unsetenv (envv, "INVOCATION_ID");
+ envv = g_environ_unsetenv (envv, "JOURNAL_STREAM");
+ envv = g_environ_unsetenv (envv, "LINES");
+ envv = g_environ_unsetenv (envv, "LISTEN_FDNAMES");
+ envv = g_environ_unsetenv (envv, "LISTEN_FDS");
+ envv = g_environ_unsetenv (envv, "LISTEN_PID");
+ envv = g_environ_unsetenv (envv, "MAINPID");
+ envv = g_environ_unsetenv (envv, "MANAGERPID");
+ envv = g_environ_unsetenv (envv, "NOTIFY_SOCKET");
+ envv = g_environ_unsetenv (envv, "NOTIFY_SOCKET");
+ envv = g_environ_unsetenv (envv, "PIDFILE");
+ envv = g_environ_unsetenv (envv, "PWD");
+ envv = g_environ_unsetenv (envv, "REMOTE_ADDR");
+ envv = g_environ_unsetenv (envv, "REMOTE_PORT");
+ envv = g_environ_unsetenv (envv, "SERVICE_RESULT");
+ envv = g_environ_unsetenv (envv, "TERM");
+ envv = g_environ_unsetenv (envv, "VTE_VERSION");
+ envv = g_environ_unsetenv (envv, "WATCHDOG_PID");
+ envv = g_environ_unsetenv (envv, "WATCHDOG_USEC");
+ envv = g_environ_unsetenv (envv, "WINDOWID");
+
+ envv = g_environ_unsetenv (envv, TERMINAL_ENV_SERVICE_NAME);
+ envv = g_environ_unsetenv (envv, TERMINAL_ENV_SCREEN);
+
+ g_variant_builder_add (builder, "{sv}",
+ "environ",
+ g_variant_new_bytestring_array ((const char * const *) envv, -1));
+ }
+
+ if (working_directory)
+ g_variant_builder_add (builder, "{sv}",
+ "cwd", g_variant_new_bytestring (working_directory));
+
+ if (shell)
+ g_variant_builder_add (builder, "{sv}",
+ "shell",
+ g_variant_new_boolean (TRUE));
+
+ if (fd_array_len) {
+ gsize i;
+
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("{sv}"));
+ g_variant_builder_add (builder, "s", "fd-set");
+
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("v"));
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("a(ih)"));
+ for (i = 0; i < fd_array_len; i++) {
+ g_variant_builder_add (builder, "(ih)", fd_array[i].fd, fd_array[i].index);
+ }
+ g_variant_builder_close (builder); /* a(ih) */
+ g_variant_builder_close (builder); /* v */
+
+ g_variant_builder_close (builder); /* {sv} */
+ }
+}
+
+/**
+ * terminal_client_get_fallback_startup_id:
+ *
+ * Returns: a fallback startup ID, or %NULL
+ */
+char *
+terminal_client_get_fallback_startup_id (void)
+{
+#if defined(TERMINAL_COMPILATION) && defined(GDK_WINDOWING_X11)
+ GdkDisplay *display;
+ Display *xdisplay;
+ Window xwindow;
+ XEvent event;
+
+ display = gdk_display_get_default ();
+ if (display == NULL || !GDK_IS_X11_DISPLAY (display))
+ goto out;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+ {
+ XSetWindowAttributes attrs;
+ Atom atom_name;
+ Atom atom_type;
+ const char *name;
+
+ attrs.override_redirect = True;
+ attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
+
+ xwindow =
+ XCreateWindow (xdisplay,
+ RootWindow (xdisplay, 0),
+ -100, -100, 1, 1,
+ 0,
+ CopyFromParent,
+ CopyFromParent,
+ (Visual *)CopyFromParent,
+ CWOverrideRedirect | CWEventMask,
+ &attrs);
+
+ atom_name = XInternAtom (xdisplay, "WM_NAME", TRUE);
+ g_assert (atom_name != None);
+ atom_type = XInternAtom (xdisplay, "STRING", TRUE);
+ g_assert (atom_type != None);
+
+ name = "Fake Window";
+ XChangeProperty (xdisplay,
+ xwindow, atom_name,
+ atom_type,
+ 8, PropModeReplace, (unsigned char *)name, strlen (name));
+ }
+
+ XWindowEvent (xdisplay,
+ xwindow,
+ PropertyChangeMask,
+ &event);
+
+ XDestroyWindow(xdisplay, xwindow);
+
+ return g_strdup_printf ("_TIME%lu", event.xproperty.time);
+out:
+#endif
+ return NULL;
+}
diff --git a/src/terminal-client-utils.h b/src/terminal-client-utils.h
new file mode 100644
index 0000000..0a70637
--- /dev/null
+++ b/src/terminal-client-utils.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_CLIENT_UTILS_H
+#define TERMINAL_CLIENT_UTILS_H
+
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+G_BEGIN_DECLS
+
+void terminal_client_append_create_instance_options (GVariantBuilder *builder,
+ const char *display_name,
+ const char *startup_id,
+ const char *geometry,
+ const char *role,
+ const char *profile,
+ const char *encoding,
+ const char *title,
+ gboolean active,
+ gboolean maximise_window,
+ gboolean fullscreen_window);
+
+typedef struct {
+ int index;
+ int fd;
+} PassFdElement;
+
+void terminal_client_append_exec_options (GVariantBuilder *builder,
+ gboolean pass_environment,
+ const char *working_directory,
+ PassFdElement *fd_array,
+ gsize fd_array_len,
+ gboolean shell);
+
+char * terminal_client_get_fallback_startup_id (void);
+
+G_END_DECLS
+
+#endif /* TERMINAL_UTIL_UTILS_H */
diff --git a/src/terminal-debug.c b/src/terminal-debug.c
new file mode 100644
index 0000000..d08829e
--- /dev/null
+++ b/src/terminal-debug.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2002,2003 Red Hat, 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include "terminal-debug.h"
+
+TerminalDebugFlags _terminal_debug_flags;
+
+void
+_terminal_debug_init(void)
+{
+#ifdef ENABLE_DEBUG
+ const GDebugKey keys[] = {
+ { "accels", TERMINAL_DEBUG_ACCELS },
+ { "clipboard", TERMINAL_DEBUG_CLIPBOARD },
+ { "encodings", TERMINAL_DEBUG_ENCODINGS },
+ { "server", TERMINAL_DEBUG_SERVER },
+ { "geometry", TERMINAL_DEBUG_GEOMETRY },
+ { "mdi", TERMINAL_DEBUG_MDI },
+ { "processes", TERMINAL_DEBUG_PROCESSES },
+ { "profile", TERMINAL_DEBUG_PROFILE },
+ { "settings-list", TERMINAL_DEBUG_SETTINGS_LIST },
+ { "search", TERMINAL_DEBUG_SEARCH },
+ };
+
+ _terminal_debug_flags = g_parse_debug_string (g_getenv ("GNOME_TERMINAL_DEBUG"),
+ keys, G_N_ELEMENTS (keys));
+
+#endif /* ENABLE_DEBUG */
+}
+
diff --git a/src/terminal-debug.h b/src/terminal-debug.h
new file mode 100644
index 0000000..0fafcc3
--- /dev/null
+++ b/src/terminal-debug.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2002 Red Hat, 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* The interfaces in this file are subject to change at any time. */
+
+#ifndef ENABLE_DEBUG_H
+#define ENABLE_DEBUG_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ TERMINAL_DEBUG_ACCELS = 1 << 0,
+ TERMINAL_DEBUG_CLIPBOARD = 1 << 1,
+ TERMINAL_DEBUG_ENCODINGS = 1 << 2,
+ TERMINAL_DEBUG_SERVER = 1 << 3,
+ TERMINAL_DEBUG_GEOMETRY = 1 << 4,
+ TERMINAL_DEBUG_MDI = 1 << 5,
+ TERMINAL_DEBUG_PROCESSES = 1 << 6,
+ TERMINAL_DEBUG_PROFILE = 1 << 7,
+ TERMINAL_DEBUG_SETTINGS_LIST = 1 << 8,
+ TERMINAL_DEBUG_SEARCH = 1 << 9
+} TerminalDebugFlags;
+
+void _terminal_debug_init(void);
+
+extern TerminalDebugFlags _terminal_debug_flags;
+static inline gboolean _terminal_debug_on (TerminalDebugFlags flags) G_GNUC_CONST G_GNUC_UNUSED;
+
+static inline gboolean
+_terminal_debug_on (TerminalDebugFlags flags)
+{
+ return (_terminal_debug_flags & flags) == flags;
+}
+
+#ifdef ENABLE_DEBUG
+#define _TERMINAL_DEBUG_IF(flags) if (G_UNLIKELY (_terminal_debug_on (flags)))
+#else
+#define _TERMINAL_DEBUG_IF(flags) if (0)
+#endif
+
+#if defined(__GNUC__) && G_HAVE_GNUC_VARARGS
+#define _terminal_debug_print(flags, fmt, ...) \
+ G_STMT_START { _TERMINAL_DEBUG_IF(flags) g_printerr(fmt, ##__VA_ARGS__); } G_STMT_END
+#else
+#include <stdarg.h>
+#include <glib/gstdio.h>
+static void _terminal_debug_print (guint flags, const char *fmt, ...)
+{
+ if (_terminal_debug_on (flags)) {
+ va_list ap;
+ va_start (ap, fmt);
+ g_vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ }
+}
+#endif
+
+G_END_DECLS
+
+#endif /* !ENABLE_DEBUG_H */
diff --git a/src/terminal-defines.h b/src/terminal-defines.h
new file mode 100644
index 0000000..b9ffba2
--- /dev/null
+++ b/src/terminal-defines.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_DEFINES_H
+#define TERMINAL_DEFINES_H
+
+G_BEGIN_DECLS
+
+enum {
+ _EXIT_FAILURE_WRONG_ID = 7,
+ _EXIT_FAILURE_NO_UTF8 = 8,
+ _EXIT_FAILURE_UNSUPPORTED_LOCALE = 9,
+ _EXIT_FAILURE_GTK_INIT = 10
+};
+
+#define TERMINAL_APPLICATION_ID "org.gnome.Terminal"
+
+#define TERMINAL_OBJECT_PATH_PREFIX "/org/gnome/Terminal"
+#define TERMINAL_OBJECT_INTERFACE_PREFIX "org.gnome.Terminal"
+
+#define TERMINAL_FACTORY_OBJECT_PATH TERMINAL_OBJECT_PATH_PREFIX "/Factory0"
+#define TERMINAL_FACTORY_INTERFACE_NAME TERMINAL_OBJECT_INTERFACE_PREFIX ".Factory0"
+
+#define TERMINAL_RECEIVER_OBJECT_PATH_FORMAT TERMINAL_OBJECT_PATH_PREFIX "/screen/%s"
+#define TEMRINAL_RECEIVER_INTERFACE_NAME TERMINAL_OBJECT_INTERFACE_PREFIX ".Terminal0"
+
+#define TERMINAL_SEARCH_PROVIDER_PATH TERMINAL_OBJECT_PATH_PREFIX "/SearchProvider"
+
+#define TERMINAL_ENV_SERVICE_NAME "GNOME_TERMINAL_SERVICE"
+#define TERMINAL_ENV_SCREEN "GNOME_TERMINAL_SCREEN"
+
+G_END_DECLS
+
+#endif /* !TERMINAL_DEFINES_H */
diff --git a/src/terminal-enums.h b/src/terminal-enums.h
new file mode 100644
index 0000000..93f1460
--- /dev/null
+++ b/src/terminal-enums.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2002 Mathias Hasselmann
+ * Copyright © 2008, 2010 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_ENUMS_H
+#define TERMINAL_ENUMS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ TERMINAL_NEW_TERMINAL_MODE_WINDOW,
+ TERMINAL_NEW_TERMINAL_MODE_TAB
+} TerminalNewTerminalMode;
+
+typedef enum {
+ TERMINAL_NEW_TAB_POSITION_LAST,
+ TERMINAL_NEW_TAB_POSITION_NEXT
+} TerminalNewTabPosition;
+
+typedef enum
+{
+ TERMINAL_EXIT_CLOSE,
+ TERMINAL_EXIT_RESTART,
+ TERMINAL_EXIT_HOLD
+} TerminalExitAction;
+
+typedef enum {
+ TERMINAL_SETTINGS_LIST_FLAG_NONE = 0,
+ TERMINAL_SETTINGS_LIST_FLAG_HAS_DEFAULT = 1 << 0,
+ TERMINAL_SETTINGS_LIST_FLAG_ALLOW_EMPTY = 1 << 1
+} TerminalSettingsListFlags;
+
+typedef enum {
+ TERMINAL_CJK_WIDTH_NARROW = 1,
+ TERMINAL_CJK_WIDTH_WIDE = 2
+} TerminalCJKWidth;
+
+typedef enum {
+ TERMINAL_THEME_VARIANT_SYSTEM = 0,
+ TERMINAL_THEME_VARIANT_LIGHT = 1,
+ TERMINAL_THEME_VARIANT_DARK = 2
+} TerminalThemeVariant;
+
+typedef enum {
+ TERMINAL_PRESERVE_WORKING_DIRECTORY_NEVER = 0,
+ TERMINAL_PRESERVE_WORKING_DIRECTORY_SAFE = 1,
+ TERMINAL_PRESERVE_WORKING_DIRECTORY_ALWAYS = 2,
+} TerminalPreserveWorkingDirectory;
+
+G_END_DECLS
+
+#endif /* TERMINAL_ENUMS_H */
diff --git a/src/terminal-gdbus.c b/src/terminal-gdbus.c
new file mode 100644
index 0000000..655bf3e
--- /dev/null
+++ b/src/terminal-gdbus.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright © 2011, 2012 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-gdbus.h"
+
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+#include "terminal-app.h"
+#include "terminal-debug.h"
+#include "terminal-defines.h"
+#include "terminal-mdi-container.h"
+#include "terminal-util.h"
+#include "terminal-window.h"
+#include "terminal-libgsystem.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define TERMINAL_RECEIVER_IMPL_GET_PRIVATE(impl)(G_TYPE_INSTANCE_GET_PRIVATE ((impl), TERMINAL_TYPE_RECEIVER_IMPL, TerminalReceiverImplPrivate))
+
+struct _TerminalReceiverImplPrivate {
+ TerminalScreen *screen; /* unowned! */
+};
+
+enum {
+ PROP_0,
+ PROP_SCREEN
+};
+
+/* helper functions */
+
+static void
+child_exited_cb (VteTerminal *terminal,
+ int exit_code,
+ TerminalReceiver *receiver)
+{
+ terminal_receiver_emit_child_exited (receiver, exit_code);
+}
+
+static void
+terminal_receiver_impl_set_screen (TerminalReceiverImpl *impl,
+ TerminalScreen *screen)
+{
+ TerminalReceiverImplPrivate *priv;
+
+ g_return_if_fail (TERMINAL_IS_RECEIVER_IMPL (impl));
+ g_return_if_fail (screen == NULL || TERMINAL_IS_SCREEN (screen));
+
+ priv = impl->priv;
+ if (priv->screen == screen)
+ return;
+
+ if (priv->screen) {
+ g_signal_handlers_disconnect_matched (priv->screen,
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, impl);
+ }
+
+ priv->screen = screen;
+ if (screen) {
+ g_signal_connect (screen, "child-exited",
+ G_CALLBACK (child_exited_cb),
+ impl);
+ }
+
+ g_object_notify (G_OBJECT (impl), "screen");
+}
+
+/* Class implementation */
+
+typedef struct {
+ TerminalReceiver *receiver;
+ GDBusMethodInvocation *invocation;
+} ExecData;
+
+static void
+exec_data_free (ExecData *data)
+{
+ g_object_unref (data->receiver);
+ g_object_unref (data->invocation);
+ g_free (data);
+}
+
+static void
+exec_cb (TerminalScreen *screen, /* unused, may be %NULL */
+ GError *error, /* set on error, %NULL on success */
+ ExecData *data)
+{
+ /* Note: these calls transfer the ref */
+ g_object_ref (data->invocation);
+ if (error) {
+ g_dbus_method_invocation_return_gerror (data->invocation, error);
+ } else {
+ terminal_receiver_complete_exec (data->receiver, data->invocation, NULL /* outfdlist */);
+ }
+}
+
+static gboolean
+terminal_receiver_impl_exec (TerminalReceiver *receiver,
+ GDBusMethodInvocation *invocation,
+ GUnixFDList *fd_list,
+ GVariant *options,
+ GVariant *arguments)
+{
+ TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (receiver);
+ TerminalReceiverImplPrivate *priv = impl->priv;
+ const char *working_directory;
+ gboolean shell;
+ gsize exec_argc;
+ gs_free char **exec_argv = NULL; /* container needs to be freed, strings not owned */
+ gs_free char **envv = NULL; /* container needs to be freed, strings not owned */
+ gs_unref_variant GVariant *fd_array = NULL;
+
+ if (priv->screen == NULL) {
+ g_dbus_method_invocation_return_error_literal (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "Terminal already closed");
+ goto out;
+ }
+
+ if (!g_variant_lookup (options, "cwd", "^&ay", &working_directory))
+ working_directory = NULL;
+ if (!g_variant_lookup (options, "shell", "b", &shell))
+ shell = FALSE;
+ if (!g_variant_lookup (options, "environ", "^a&ay", &envv))
+ envv = NULL;
+ if (!g_variant_lookup (options, "fd-set", "@a(ih)", &fd_array))
+ fd_array = NULL;
+
+ /* Check environment */
+ if (!terminal_util_check_envv((const char * const*)envv)) {
+ g_dbus_method_invocation_return_error_literal (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Malformed environment");
+ goto out;
+ }
+
+ /* Check FD passing */
+ if ((fd_list != NULL) ^ (fd_array != NULL)) {
+ g_dbus_method_invocation_return_error_literal (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Must pass both fd-set options and a FD list");
+ goto out;
+ }
+ if (fd_list != NULL && fd_array != NULL) {
+ const int *fd_array_data;
+ gsize fd_array_data_len, i;
+ int n_fds;
+
+ fd_array_data = g_variant_get_fixed_array (fd_array, &fd_array_data_len, 2 * sizeof (int));
+ n_fds = g_unix_fd_list_get_length (fd_list);
+ for (i = 0; i < fd_array_data_len; i++) {
+ const int fd = fd_array_data[2 * i];
+ const int idx = fd_array_data[2 * i + 1];
+
+ if (fd == -1) {
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Passing of invalid FD %d not supported", fd);
+ goto out;
+ }
+ if (fd == STDIN_FILENO ||
+ fd == STDOUT_FILENO ||
+ fd == STDERR_FILENO) {
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Passing of std%s not supported",
+ fd == STDIN_FILENO ? "in" : fd == STDOUT_FILENO ? "out" : "err");
+ goto out;
+ }
+ if (idx < 0 || idx >= n_fds) {
+ g_dbus_method_invocation_return_error_literal (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Handle out of range");
+ goto out;
+ }
+ }
+ }
+
+ if (working_directory != NULL)
+ _terminal_debug_print (TERMINAL_DEBUG_SERVER,
+ "CWD is '%s'\n", working_directory);
+
+ exec_argv = (char **) g_variant_get_bytestring_array (arguments, &exec_argc);
+
+ ExecData *exec_data = g_new (ExecData, 1);
+ exec_data->receiver = g_object_ref (receiver);
+ /* We want to transfer the ownership of @invocation to ExecData here, but
+ * we have to temporarily ref it so that in the error case below (where
+ * terminal_screen_exec() frees the exec data via the supplied callback,
+ * the g_dbus_method_invocation_take_error() calll still can take ownership
+ * of the invocation's ref passed to this function (terminal_receiver_impl_exec()).
+ */
+ exec_data->invocation = g_object_ref (invocation);
+
+ GError *err = NULL;
+ if (!terminal_screen_exec (priv->screen,
+ exec_argc > 0 ? exec_argv : NULL,
+ envv,
+ shell,
+ working_directory,
+ fd_list, fd_array,
+ (TerminalScreenExecCallback) exec_cb,
+ exec_data /* adopted */,
+ (GDestroyNotify) exec_data_free,
+ NULL /* cancellable */,
+ &err)) {
+ /* Transfers ownership of @invocation */
+ g_dbus_method_invocation_take_error (invocation, err);
+ }
+
+ /* Now we can remove that extra ref again. */
+ g_object_unref (invocation);
+
+out:
+
+ return TRUE; /* handled */
+}
+
+static void
+terminal_receiver_impl_iface_init (TerminalReceiverIface *iface)
+{
+ iface->handle_exec = terminal_receiver_impl_exec;
+}
+
+G_DEFINE_TYPE_WITH_CODE (TerminalReceiverImpl, terminal_receiver_impl, TERMINAL_TYPE_RECEIVER_SKELETON,
+ G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_RECEIVER, terminal_receiver_impl_iface_init))
+
+static void
+terminal_receiver_impl_init (TerminalReceiverImpl *impl)
+{
+ impl->priv = TERMINAL_RECEIVER_IMPL_GET_PRIVATE (impl);
+}
+
+static void
+terminal_receiver_impl_dispose (GObject *object)
+{
+ TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (object);
+
+ terminal_receiver_impl_set_screen (impl, NULL);
+
+ G_OBJECT_CLASS (terminal_receiver_impl_parent_class)->dispose (object);
+}
+
+static void
+terminal_receiver_impl_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (object);
+
+ switch (prop_id) {
+ case PROP_SCREEN:
+ g_value_set_object (value, terminal_receiver_impl_get_screen (impl));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_receiver_impl_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (object);
+
+ switch (prop_id) {
+ case PROP_SCREEN:
+ terminal_receiver_impl_set_screen (impl, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_receiver_impl_class_init (TerminalReceiverImplClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = terminal_receiver_impl_dispose;
+ gobject_class->get_property = terminal_receiver_impl_get_property;
+ gobject_class->set_property = terminal_receiver_impl_set_property;
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_SCREEN,
+ g_param_spec_object ("screen", NULL, NULL,
+ TERMINAL_TYPE_SCREEN,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private (gobject_class, sizeof (TerminalReceiverImplPrivate));
+}
+
+/* public API */
+
+/**
+ * terminal_receiver_impl_new:
+ * @screen: a #TerminalScreen
+ *
+ * Returns: a new #TerminalReceiverImpl for @screen
+ */
+TerminalReceiverImpl *
+terminal_receiver_impl_new (TerminalScreen *screen)
+{
+ return g_object_new (TERMINAL_TYPE_RECEIVER_IMPL,
+ "screen", screen,
+ NULL);
+}
+
+/**
+ * terminal_receiver_impl_get_screen:
+ * @impl: a #TerminalReceiverImpl
+ *
+ * Returns: (transfer none): the impl's #TerminalScreen, or %NULL
+ */
+TerminalScreen *
+terminal_receiver_impl_get_screen (TerminalReceiverImpl *impl)
+{
+ g_return_val_if_fail (TERMINAL_IS_RECEIVER_IMPL (impl), NULL);
+
+ return impl->priv->screen;
+}
+
+/**
+ * terminal_receiver_impl_unget_screen:
+ * @impl: a #TerminalReceiverImpl
+ *
+ * Unsets the impls #TerminalScreen.
+ */
+void
+terminal_receiver_impl_unset_screen (TerminalReceiverImpl *impl)
+{
+ g_return_if_fail (TERMINAL_IS_RECEIVER_IMPL (impl));
+
+ terminal_receiver_impl_set_screen (impl, NULL);
+}
+
+/* ---------------------------------------------------------------------------
+ * TerminalFactoryImpl
+ * ---------------------------------------------------------------------------
+ */
+
+struct _TerminalFactoryImplPrivate {
+ gpointer dummy;
+};
+
+static gboolean
+terminal_factory_impl_create_instance (TerminalFactory *factory,
+ GDBusMethodInvocation *invocation,
+ GVariant *options)
+{
+ TerminalApp *app = terminal_app_get ();
+
+ /* If a parent screen is specified, use that to fill in missing information */
+ TerminalScreen *parent_screen = NULL;
+ const char *parent_screen_object_path;
+ if (g_variant_lookup (options, "parent-screen", "&o", &parent_screen_object_path)) {
+ parent_screen = terminal_app_get_screen_by_object_path (app, parent_screen_object_path);
+ if (parent_screen == NULL) {
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "Failed to get screen from object path %s",
+ parent_screen_object_path);
+ return TRUE;
+ }
+ }
+
+ /* Try getting a parent window, first by parent screen then by window ID;
+ * if that fails, create a new window.
+ */
+ TerminalWindow *window = NULL;
+ gboolean have_new_window = FALSE;
+ const char *window_from_screen_object_path;
+ if (g_variant_lookup (options, "window-from-screen", "&o", &window_from_screen_object_path)) {
+ TerminalScreen *window_screen =
+ terminal_app_get_screen_by_object_path (app, window_from_screen_object_path);
+ if (window_screen == NULL) {
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "Failed to get screen from object path %s",
+ parent_screen_object_path);
+ return TRUE;
+ }
+
+ GtkWidget *win = gtk_widget_get_toplevel (GTK_WIDGET (window_screen));
+ if (TERMINAL_IS_WINDOW (win))
+ window = TERMINAL_WINDOW (win);
+ }
+
+ /* Support old client */
+ guint window_id;
+ if (window == NULL && g_variant_lookup (options, "window-id", "u", &window_id)) {
+ GtkWindow *win = gtk_application_get_window_by_id (GTK_APPLICATION (app), window_id);
+
+ if (!TERMINAL_IS_WINDOW (win)) {
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "Nonexisting window %u referenced",
+ window_id);
+ return TRUE;
+ }
+
+ window = TERMINAL_WINDOW (win);
+ }
+
+ /* Still no parent window? Create a new one */
+ if (window == NULL) {
+ const char *startup_id, *role;
+ gboolean start_maximized, start_fullscreen;
+
+ window = terminal_window_new (G_APPLICATION (app));
+ have_new_window = TRUE;
+
+ if (g_variant_lookup (options, "desktop-startup-id", "^&ay", &startup_id))
+ gtk_window_set_startup_id (GTK_WINDOW (window), startup_id);
+
+ /* Overwrite the default, unique window role set in terminal_window_init */
+ if (g_variant_lookup (options, "role", "&s", &role))
+ gtk_window_set_role (GTK_WINDOW (window), role);
+
+ gboolean show_menubar;
+ if (g_variant_lookup (options, "show-menubar", "b", &show_menubar))
+ terminal_window_set_menubar_visible (window, show_menubar);
+
+ if (g_variant_lookup (options, "fullscreen-window", "b", &start_fullscreen) &&
+ start_fullscreen) {
+ gtk_window_fullscreen (GTK_WINDOW (window));
+ }
+ if (g_variant_lookup (options, "maximize-window", "b", &start_maximized) &&
+ start_maximized) {
+ gtk_window_maximize (GTK_WINDOW (window));
+ }
+
+ have_new_window = TRUE;
+ }
+
+ g_assert_nonnull (window);
+
+ const char *title;
+ if (!g_variant_lookup (options, "title", "&s", &title))
+ title = NULL;
+
+ double zoom;
+ if (!g_variant_lookup (options, "zoom", "d", &zoom)) {
+ if (parent_screen != NULL)
+ zoom = vte_terminal_get_font_scale (VTE_TERMINAL (parent_screen));
+ else
+ zoom = 1.0;
+ }
+
+ /* Look up the profile */
+ gs_unref_object GSettings *profile = NULL;
+ const char *profile_uuid;
+ if (!g_variant_lookup (options, "profile", "&s", &profile_uuid))
+ profile_uuid = NULL;
+
+ if (profile_uuid == NULL && parent_screen != NULL) {
+ profile = terminal_screen_ref_profile (parent_screen);
+ } else {
+ GError *err = NULL;
+ profile = terminal_profiles_list_ref_profile_by_uuid (terminal_app_get_profiles_list (app),
+ profile_uuid /* default if NULL */,
+ &err);
+ if (profile == NULL) {
+ g_dbus_method_invocation_return_gerror (invocation, err);
+ g_error_free (err);
+ return TRUE;
+ }
+ }
+
+ g_assert_nonnull (profile);
+
+ /* Now we can create the new screen */
+ TerminalScreen *screen = terminal_screen_new (profile, title, zoom);
+ terminal_window_add_screen (window, screen, -1);
+
+ /* Apply window properties */
+ gboolean active;
+ if (g_variant_lookup (options, "active", "b", &active) &&
+ active) {
+ terminal_window_switch_screen (window, screen);
+ gtk_widget_grab_focus (GTK_WIDGET (screen));
+ }
+
+ if (have_new_window) {
+ const char *geometry;
+
+ if (g_variant_lookup (options, "geometry", "&s", &geometry) &&
+ !terminal_window_parse_geometry (window, geometry))
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "Invalid geometry string \"%s\"", geometry);
+ }
+
+ gboolean present_window;
+ gboolean present_window_set = g_variant_lookup (options, "present-window", "b", &present_window);
+
+ if (have_new_window || (present_window_set && present_window))
+ gtk_window_present (GTK_WINDOW (window));
+
+ gs_free char *object_path = terminal_app_dup_screen_object_path (app, screen);
+ terminal_factory_complete_create_instance (factory, invocation, object_path);
+
+ return TRUE; /* handled */
+}
+
+static void
+terminal_factory_impl_iface_init (TerminalFactoryIface *iface)
+{
+ iface->handle_create_instance = terminal_factory_impl_create_instance;
+}
+
+G_DEFINE_TYPE_WITH_CODE (TerminalFactoryImpl, terminal_factory_impl, TERMINAL_TYPE_FACTORY_SKELETON,
+ G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_FACTORY, terminal_factory_impl_iface_init))
+
+static void
+terminal_factory_impl_init (TerminalFactoryImpl *impl)
+{
+ impl->priv = G_TYPE_INSTANCE_GET_PRIVATE (impl, TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImplPrivate);
+}
+
+static void
+terminal_factory_impl_class_init (TerminalFactoryImplClass *klass)
+{
+ /* g_type_class_add_private (klass, sizeof (TerminalFactoryImplPrivate)); */
+}
+
+/**
+ * terminal_factory_impl_new:
+ *
+ * Returns: (transfer full): a new #TerminalFactoryImpl
+ */
+TerminalFactory *
+terminal_factory_impl_new (void)
+{
+ return g_object_new (TERMINAL_TYPE_FACTORY_IMPL, NULL);
+}
diff --git a/src/terminal-gdbus.h b/src/terminal-gdbus.h
new file mode 100644
index 0000000..16e80d7
--- /dev/null
+++ b/src/terminal-gdbus.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_RECEIVER_IMPL_H
+#define TERMINAL_RECEIVER_IMPL_H
+
+#include <glib-object.h>
+
+#include "terminal-gdbus-generated.h"
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_RECEIVER_IMPL (terminal_receiver_impl_get_type ())
+#define TERMINAL_RECEIVER_IMPL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_RECEIVER_IMPL, TerminalReceiverImpl))
+#define TERMINAL_RECEIVER_IMPL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_RECEIVER_IMPL, TerminalReceiverImplClass))
+#define TERMINAL_IS_RECEIVER_IMPL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_RECEIVER_IMPL))
+#define TERMINAL_IS_RECEIVER_IMPL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_RECEIVER_IMPL))
+#define TERMINAL_RECEIVER_IMPL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_RECEIVER_IMPL, TerminalReceiverImplClass))
+
+typedef struct _TerminalReceiverImpl TerminalReceiverImpl;
+typedef struct _TerminalReceiverImplClass TerminalReceiverImplClass;
+typedef struct _TerminalReceiverImplPrivate TerminalReceiverImplPrivate;
+
+struct _TerminalReceiverImpl
+{
+ TerminalReceiverSkeleton parent_instance;
+
+ /*< private >*/
+ TerminalReceiverImplPrivate *priv;
+};
+
+struct _TerminalReceiverImplClass
+{
+ TerminalReceiverSkeletonClass parent_class;
+};
+
+GType terminal_receiver_impl_get_type (void);
+
+TerminalReceiverImpl *terminal_receiver_impl_new (TerminalScreen *screen);
+
+TerminalScreen *terminal_receiver_impl_get_screen (TerminalReceiverImpl *impl);
+
+void terminal_receiver_impl_unset_screen (TerminalReceiverImpl *impl);
+
+/* ------------------------------------------------------------------------- */
+
+#define TERMINAL_TYPE_FACTORY_IMPL (terminal_factory_impl_get_type ())
+#define TERMINAL_FACTORY_IMPL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImpl))
+#define TERMINAL_FACTORY_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImplClass))
+#define TERMINAL_IS_FACTORY_IMPL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_FACTORY_IMPL))
+#define TERMINAL_IS_FACTORY_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_FACTORY_IMPL))
+#define TERMINAL_FACTORY_IMPL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImplClass))
+
+typedef struct _TerminalFactoryImpl TerminalFactoryImpl;
+typedef struct _TerminalFactoryImplPrivate TerminalFactoryImplPrivate;
+typedef struct _TerminalFactoryImplClass TerminalFactoryImplClass;
+
+struct _TerminalFactoryImplClass {
+ TerminalFactorySkeletonClass parent_class;
+};
+
+struct _TerminalFactoryImpl
+{
+ TerminalFactorySkeleton parent_instance;
+
+ TerminalFactoryImplPrivate *priv;
+};
+
+GType terminal_factory_impl_get_type (void);
+
+TerminalFactory *terminal_factory_impl_new (void);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_RECEIVER_IMPL_H */
diff --git a/src/terminal-headerbar.c b/src/terminal-headerbar.c
new file mode 100644
index 0000000..fc929d7
--- /dev/null
+++ b/src/terminal-headerbar.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright © 2018 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "terminal-headerbar.h"
+#include "terminal-app.h"
+#include "terminal-libgsystem.h"
+
+typedef struct _TerminalHeaderbarPrivate TerminalHeaderbarPrivate;
+
+struct _TerminalHeaderbar
+{
+ GtkHeaderBar parent_instance;
+};
+
+struct _TerminalHeaderbarClass
+{
+ GtkHeaderBarClass parent_class;
+};
+
+struct _TerminalHeaderbarPrivate
+{
+ GtkWidget *profilebutton;
+ GtkWidget *menubutton;
+};
+
+enum {
+ PROP_0,
+ LAST_PROP
+};
+
+enum {
+ LAST_SIGNAL
+};
+
+/* static guint signals[LAST_SIGNAL]; */
+/* static GParamSpec *pspecs[LAST_PROP]; */
+
+G_DEFINE_TYPE_WITH_PRIVATE (TerminalHeaderbar, terminal_headerbar, GTK_TYPE_HEADER_BAR)
+
+#define PRIV(obj) ((TerminalHeaderbarPrivate *) terminal_headerbar_get_instance_private ((TerminalHeaderbar *)(obj)))
+
+static void
+profilemenu_items_changed_cb (GMenuModel *menu,
+ int position G_GNUC_UNUSED,
+ int removed G_GNUC_UNUSED,
+ int added G_GNUC_UNUSED,
+ TerminalHeaderbarPrivate *priv)
+{
+ if (g_menu_model_get_n_items (menu) > 0)
+ gtk_widget_show (priv->profilebutton);
+ else
+ gtk_widget_hide (priv->profilebutton);
+}
+
+/* Class implementation */
+
+static void
+terminal_headerbar_init (TerminalHeaderbar *headerbar)
+{
+
+ TerminalHeaderbarPrivate *priv = PRIV (headerbar);
+ GtkWidget *widget = GTK_WIDGET (headerbar);
+ TerminalApp *app = terminal_app_get ();
+ GMenuModel *profilemenu;
+
+ gtk_widget_init_template (widget);
+
+ gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->menubutton),
+ terminal_app_get_headermenu (app));
+
+ profilemenu = terminal_app_get_profilemenu (app);
+ gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->profilebutton),
+ profilemenu);
+
+ g_signal_connect (profilemenu, "items-changed",
+ G_CALLBACK (profilemenu_items_changed_cb), priv);
+ profilemenu_items_changed_cb (profilemenu, 0, 0, 0, priv);
+}
+
+static void
+terminal_headerbar_dispose (GObject *object)
+{
+ TerminalHeaderbar *headerbar = TERMINAL_HEADERBAR (object);
+ TerminalHeaderbarPrivate *priv = PRIV (headerbar);
+ TerminalApp *app = terminal_app_get ();
+
+ GMenuModel *profilemenu = terminal_app_get_profilemenu (app);
+ g_signal_handlers_disconnect_by_func (profilemenu,
+ G_CALLBACK (profilemenu_items_changed_cb),
+ priv);
+
+ G_OBJECT_CLASS (terminal_headerbar_parent_class)->dispose (object);
+}
+
+static void
+terminal_headerbar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ // TerminalHeaderbar *headerbar = TERMINAL_HEADERBAR (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_headerbar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_headerbar_class_init (TerminalHeaderbarClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->dispose = terminal_headerbar_dispose;
+ gobject_class->get_property = terminal_headerbar_get_property;
+ gobject_class->set_property = terminal_headerbar_set_property;
+
+ /* g_object_class_install_properties (gobject_class, G_N_ELEMENTS (pspecs), pspecs); */
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/terminal/ui/headerbar.ui");
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalHeaderbar, menubutton);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalHeaderbar, profilebutton);
+}
+
+/* public API */
+
+/**
+ * terminal_headerbar_new:
+ *
+ * Returns: a new #TerminalHeaderbar
+ */
+GtkWidget *
+terminal_headerbar_new (void)
+{
+ return g_object_new (TERMINAL_TYPE_HEADERBAR,
+ NULL);
+}
diff --git a/src/terminal-headerbar.h b/src/terminal-headerbar.h
new file mode 100644
index 0000000..f4ee6f7
--- /dev/null
+++ b/src/terminal-headerbar.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2018 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_HEADERBAR (terminal_headerbar_get_type ())
+#define TERMINAL_HEADERBAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_HEADERBAR, TerminalHeaderbar))
+#define TERMINAL_HEADERBAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_HEADERBAR, TerminalHeaderbarClass))
+#define TERMINAL_IS_HEADERBAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_HEADERBAR))
+#define TERMINAL_IS_HEADERBAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_HEADERBAR))
+#define TERMINAL_HEADERBAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_HEADERBAR, TerminalHeaderbarClass))
+
+typedef struct _TerminalHeaderbar TerminalHeaderbar;
+typedef struct _TerminalHeaderbarClass TerminalHeaderbarClass;
+
+GType terminal_headerbar_get_type (void);
+
+GtkWidget *terminal_headerbar_new (void);
+
+G_END_DECLS
diff --git a/src/terminal-headerbar.ui b/src/terminal-headerbar.ui
new file mode 100644
index 0000000..c48a350
--- /dev/null
+++ b/src/terminal-headerbar.ui
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2018 Christian Persch
+
+ 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 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope conf it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<interface>
+ <template class="TerminalHeaderbar" parent="GtkHeaderBar">
+ <property name="can-focus">False</property>
+ <property name="visible">True</property>
+ <property name="show-close-button">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="action-name">win.new-terminal</property>
+ <property name="action-target">('tab-default','current')</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">tab-new-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="profilebutton">
+ <property name="visible">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <style>
+ <class name="image-button"/>
+ <class name="disclosure-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">pan-down-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="menubutton">
+ <property name="visible">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="action-name">win.header-menu</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="action-name">win.find</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/src/terminal-headermenu.ui b/src/terminal-headermenu.ui
new file mode 100644
index 0000000..42d5296
--- /dev/null
+++ b/src/terminal-headermenu.ui
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2012 Christian Persch
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<interface>
+ <menu id="headermenu">
+ <section>
+ <attribute name="display-hint">horizontal-buttons</attribute>
+ <item>
+ <attribute name="label" translatable="yes">Zoom _Out</attribute>
+ <attribute name="verb-icon">zoom-out-symbolic</attribute>
+ <attribute name="action">win.zoom-out</attribute>
+ </item>
+ <item>
+ <attribute name="label">100%</attribute>
+ <attribute name="action">win.zoom-normal</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Zoom _In</attribute>
+ <attribute name="verb-icon">zoom-in-symbolic</attribute>
+ <attribute name="action">win.zoom-in</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">New _Window</attribute>
+ <attribute name="action">win.new-terminal</attribute>
+ <attribute name="target" type="(ss)">('window', 'current')</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Full Screen</attribute>
+ <attribute name="action">win.enter-fullscreen</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Read-_Only</attribute>
+ <attribute name="action">win.read-only</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Set _Title…</attribute>
+ <attribute name="action">win.set-title</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ <section id="set-profile-section" />
+ <submenu>
+ <attribute name="label" translatable="yes">_Advanced</attribute>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Reset</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">false</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Reset and C_lear</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">true</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_1. 80×24</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(80, 24)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_2. 80×43</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(80, 43)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_3. 132×24</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(132, 24)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_4. 132×43</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(132, 43)</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Inspector</attribute>
+ <attribute name="action">win.inspector</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ </section>
+ </submenu>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Preferences</attribute>
+ <attribute name="action">app.preferences</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Help</attribute>
+ <attribute name="action">app.help</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_About</attribute>
+ <attribute name="action">app.about</attribute>
+ </item>
+ </section>
+ </menu>
+</interface>
diff --git a/src/terminal-i18n.c b/src/terminal-i18n.c
new file mode 100644
index 0000000..7ae520e
--- /dev/null
+++ b/src/terminal-i18n.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2002 Havoc Pennington
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "terminal-i18n.h"
+
+#include <libintl.h>
+
+void
+terminal_i18n_init (gboolean set_default)
+{
+ bindtextdomain (GETTEXT_PACKAGE, TERM_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ if (set_default)
+ textdomain (GETTEXT_PACKAGE);
+}
diff --git a/src/terminal-i18n.h b/src/terminal-i18n.h
new file mode 100644
index 0000000..689bb82
--- /dev/null
+++ b/src/terminal-i18n.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2002 Havoc Pennington
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_I18N_H
+#define TERMINAL_I18N_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+void terminal_i18n_init (gboolean set_default);
+
+G_END_DECLS
+
+#endif /* TERMINAL_I18N_H */
diff --git a/src/terminal-icon-button.c b/src/terminal-icon-button.c
new file mode 100644
index 0000000..3014fc0
--- /dev/null
+++ b/src/terminal-icon-button.c
@@ -0,0 +1,50 @@
+/*
+ * terminal-icon-button.c
+ *
+ * Copyright © 2010 - Paolo Borelli
+ * Copyright © 2011 - Ignacio Casal Quinteiro
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-icon-button.h"
+#include "terminal-libgsystem.h"
+
+GtkWidget *
+terminal_icon_button_new (const char *gicon_name)
+{
+ GtkWidget *button, *image;
+ gs_unref_object GIcon *icon;
+
+ button = (GtkWidget *) g_object_new (GTK_TYPE_BUTTON,
+ "relief", GTK_RELIEF_NONE,
+ "focus-on-click", FALSE,
+ NULL);
+
+ icon = g_themed_icon_new_with_default_fallbacks (gicon_name);
+ image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
+
+ gtk_widget_show (image);
+ gtk_container_add (GTK_CONTAINER (button), image);
+
+ return button;
+}
+
+GtkWidget *
+terminal_close_button_new (void)
+{
+ return terminal_icon_button_new ("window-close-symbolic");
+}
diff --git a/src/terminal-icon-button.h b/src/terminal-icon-button.h
new file mode 100644
index 0000000..ec0a8db
--- /dev/null
+++ b/src/terminal-icon-button.h
@@ -0,0 +1,33 @@
+/*
+ * terminal-close-button.h
+ *
+ * Copyright © 2010 - 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TERMINAL_ICON_BUTTON_H__
+#define __TERMINAL_ICON_BUTTON_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+GtkWidget *terminal_icon_button_new (const char *gicon_name);
+
+GtkWidget *terminal_close_button_new (void);
+
+G_END_DECLS
+
+#endif /* __TERMINAL_ICON_BUTTON_H__ */
diff --git a/src/terminal-info-bar.c b/src/terminal-info-bar.c
new file mode 100644
index 0000000..8ffca18
--- /dev/null
+++ b/src/terminal-info-bar.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2010 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "terminal-info-bar.h"
+#include "terminal-libgsystem.h"
+
+#include <gtk/gtk.h>
+
+#define TERMINAL_INFO_BAR_GET_PRIVATE(info_bar)(G_TYPE_INSTANCE_GET_PRIVATE ((info_bar), TERMINAL_TYPE_INFO_BAR, TerminalInfoBarPrivate))
+
+struct _TerminalInfoBarPrivate
+{
+ GtkWidget *content_box;
+};
+
+G_DEFINE_TYPE (TerminalInfoBar, terminal_info_bar, GTK_TYPE_INFO_BAR)
+
+/* helper functions */
+
+static void
+terminal_info_bar_init (TerminalInfoBar *bar)
+{
+ GtkInfoBar *info_bar = GTK_INFO_BAR (bar);
+ TerminalInfoBarPrivate *priv;
+
+ priv = bar->priv = TERMINAL_INFO_BAR_GET_PRIVATE (bar);
+
+ priv->content_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (info_bar)),
+ priv->content_box, TRUE, TRUE, 0);
+}
+
+static void
+terminal_info_bar_class_init (TerminalInfoBarClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (gobject_class, sizeof (TerminalInfoBarPrivate));
+}
+
+/* public API */
+
+/**
+ * terminal_info_bar_new:
+ * @type: a #GtkMessageType
+ *
+ * Returns: a new #TerminalInfoBar for @screen
+ */
+GtkWidget *
+terminal_info_bar_new (GtkMessageType type,
+ const char *first_button_text,
+ ...)
+{
+ GtkWidget *info_bar;
+ va_list args;
+
+ info_bar = g_object_new (TERMINAL_TYPE_INFO_BAR,
+ "message-type", type,
+ NULL);
+
+ va_start (args, first_button_text);
+ while (first_button_text != NULL) {
+ int response_id;
+
+ response_id = va_arg (args, int);
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ first_button_text, response_id);
+
+ first_button_text = va_arg (args, const char *);
+ }
+ va_end (args);
+
+ return info_bar;
+}
+
+void
+terminal_info_bar_format_text (TerminalInfoBar *bar,
+ const char *format,
+ ...)
+{
+ TerminalInfoBarPrivate *priv;
+ gs_free char *text = NULL;
+ GtkWidget *label;
+ va_list args;
+
+ g_return_if_fail (TERMINAL_IS_INFO_BAR (bar));
+
+ priv = bar->priv;
+
+ va_start (args, format);
+ text = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ label = gtk_label_new (text);
+
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_label_set_yalign (GTK_LABEL (label), 0.0);
+
+ gtk_box_pack_start (GTK_BOX (priv->content_box), label, FALSE, FALSE, 0);
+ gtk_widget_show_all (priv->content_box);
+}
diff --git a/src/terminal-info-bar.h b/src/terminal-info-bar.h
new file mode 100644
index 0000000..87a5234
--- /dev/null
+++ b/src/terminal-info-bar.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2010 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_INFO_BAR_H
+#define TERMINAL_INFO_BAR_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_INFO_BAR (terminal_info_bar_get_type ())
+#define TERMINAL_INFO_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_INFO_BAR, TerminalInfoBar))
+#define TERMINAL_INFO_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_INFO_BAR, TerminalInfoBarClass))
+#define TERMINAL_IS_INFO_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_INFO_BAR))
+#define TERMINAL_IS_INFO_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_INFO_BAR))
+#define TERMINAL_INFO_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_INFO_BAR, TerminalInfoBarClass))
+
+typedef struct _TerminalInfoBar TerminalInfoBar;
+typedef struct _TerminalInfoBarClass TerminalInfoBarClass;
+typedef struct _TerminalInfoBarPrivate TerminalInfoBarPrivate;
+
+struct _TerminalInfoBar
+{
+ GtkInfoBar parent_instance;
+
+ /*< private >*/
+ TerminalInfoBarPrivate *priv;
+};
+
+struct _TerminalInfoBarClass
+{
+ GtkInfoBarClass parent_class;
+};
+
+GType terminal_info_bar_get_type (void);
+
+GtkWidget *terminal_info_bar_new (GtkMessageType type,
+ const char *first_button_text,
+ ...) G_GNUC_NULL_TERMINATED;
+
+void terminal_info_bar_format_text (TerminalInfoBar *bar,
+ const char *format,
+ ...) G_GNUC_PRINTF (2, 3);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_INFO_BAR_H */
diff --git a/src/terminal-intl.h b/src/terminal-intl.h
new file mode 100644
index 0000000..daaa963
--- /dev/null
+++ b/src/terminal-intl.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2002 Havoc Pennington
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_INTL_H
+#define TERMINAL_INTL_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define I_(string) g_intern_static_string (string)
+
+G_END_DECLS
+
+#endif /* TERMINAL_INTL_H */
diff --git a/src/terminal-libgsystem.h b/src/terminal-libgsystem.h
new file mode 100644
index 0000000..906a127
--- /dev/null
+++ b/src/terminal-libgsystem.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright © 2012 Colin Walters <walters@verbum.org>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSYSTEM_LOCAL_ALLOC_H__
+#define __GSYSTEM_LOCAL_ALLOC_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define gs_transfer_out_value(outp, srcp) G_STMT_START { \
+ if (outp) \
+ { \
+ *(outp) = *(srcp); \
+ *(srcp) = NULL; \
+ } \
+ } G_STMT_END;
+
+#define GS_DEFINE_CLEANUP_FUNCTION(Type, name, func) \
+ static inline void name (void *v) \
+ { \
+ func (*(Type*)v); \
+ }
+
+#define GS_DEFINE_CLEANUP_FUNCTION0(Type, name, func) \
+ static inline void name (void *v) \
+ { \
+ if (*(Type*)v) \
+ func (*(Type*)v); \
+ }
+
+/* These functions shouldn't be invoked directly;
+ * they are stubs that:
+ * 1) Take a pointer to the location (typically itself a pointer).
+ * 2) Provide %NULL-safety where it doesn't exist already (e.g. g_object_unref)
+ */
+GS_DEFINE_CLEANUP_FUNCTION0(GArray*, gs_local_array_unref, g_array_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GBytes*, gs_local_bytes_unref, g_bytes_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GChecksum*, gs_local_checksum_free, g_checksum_free)
+GS_DEFINE_CLEANUP_FUNCTION0(GError*, gs_local_free_error, g_error_free)
+GS_DEFINE_CLEANUP_FUNCTION0(GHashTable*, gs_local_hashtable_unref, g_hash_table_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, gs_local_key_file_unref, g_key_file_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GList*, gs_local_list_free, g_list_free)
+GS_DEFINE_CLEANUP_FUNCTION0(GMatchInfo*, gs_local_match_info_free, g_match_info_free)
+GS_DEFINE_CLEANUP_FUNCTION0(GObject*, gs_local_obj_unref, g_object_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GPtrArray*, gs_local_ptrarray_unref, g_ptr_array_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GRegex*, gs_local_regex_unref, g_regex_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GSettingsSchema*, gs_local_settings_schema_unref, g_settings_schema_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GSettingsSchemaKey*, gs_local_settings_schema_key_unref, g_settings_schema_key_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GVariant*, gs_local_variant_unref, g_variant_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GVariantBuilder*, gs_local_variant_builder_unref, g_variant_builder_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GVariantIter*, gs_local_variant_iter_free, g_variant_iter_free)
+
+GS_DEFINE_CLEANUP_FUNCTION(char**, gs_local_strfreev, g_strfreev)
+GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free)
+
+/* special */
+
+static inline void gs_local_gstring_free (void *v) \
+{ \
+ if (*(GString**)v) \
+ g_string_free (*(GString**)v, TRUE); \
+}
+
+/**
+ * gs_free:
+ *
+ * Call g_free() on a variable location when it goes out of scope.
+ */
+#define gs_free __attribute__ ((cleanup(gs_local_free)))
+
+/**
+ * gs_unref_object:
+ *
+ * Call g_object_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_object_unref(), the variable may be
+ * %NULL.
+ */
+#define gs_unref_object __attribute__ ((cleanup(gs_local_obj_unref)))
+
+/**
+ * gs_unref_variant:
+ *
+ * Call g_variant_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_variant_unref(), the variable may be
+ * %NULL.
+ */
+#define gs_unref_variant __attribute__ ((cleanup(gs_local_variant_unref)))
+
+/**
+ * gs_free_variant_iter:
+ *
+ * Call g_variant_iter_free() on a variable location when it goes out of
+ * scope.
+ */
+#define gs_free_variant_iter __attribute__ ((cleanup(gs_local_variant_iter_free)))
+
+/**
+ * gs_free_variant_builder:
+ *
+ * Call g_variant_builder_unref() on a variable location when it goes out of
+ * scope.
+ */
+#define gs_unref_variant_builder __attribute__ ((cleanup(gs_local_variant_builder_unref)))
+
+/**
+ * gs_unref_array:
+ *
+ * Call g_array_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_array_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_array __attribute__ ((cleanup(gs_local_array_unref)))
+
+/**
+ * gs_unref_ptrarray:
+ *
+ * Call g_ptr_array_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_ptr_array_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_ptrarray __attribute__ ((cleanup(gs_local_ptrarray_unref)))
+
+/**
+ * gs_unref_hashtable:
+ *
+ * Call g_hash_table_unref() on a variable location when it goes out
+ * of scope. Note that unlike g_hash_table_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_hashtable __attribute__ ((cleanup(gs_local_hashtable_unref)))
+
+/**
+ * gs_unref_key_file:
+ *
+ * Call g_key_file_unref() on a variable location when it goes out
+ * of scope. Note that unlike g_key_file_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_key_file __attribute__ ((cleanup(gs_local_key_file_unref)))
+
+/**
+ * gs_free_checksum:
+ *
+ * Call g_checksum_free() on a variable location when it goes out
+ * of scope. Note that unlike g_checksum_free(), the variable may
+ * be %NULL.
+ */
+#define gs_free_checksum __attribute__ ((cleanup(gs_local_checksum_free)))
+
+/**
+ * gs_unref_bytes:
+ *
+ * Call g_bytes_unref() on a variable location when it goes out
+ * of scope. Note that unlike g_bytes_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_bytes __attribute__ ((cleanup(gs_local_bytes_unref)))
+
+/**
+ * gs_strfreev:
+ *
+ * Call g_strfreev() on a variable location when it goes out of scope.
+ */
+#define gs_strfreev __attribute__ ((cleanup(gs_local_strfreev)))
+
+/**
+ * gs_free_error:
+ *
+ * Call g_error_free() on a variable location when it goes out of scope.
+ */
+#define gs_free_error __attribute__ ((cleanup(gs_local_free_error)))
+
+/**
+ * gs_free_list:
+ *
+ * Call g_list_free() on a variable location when it goes out of scope.
+ */
+#define gs_free_list __attribute__ ((cleanup(gs_local_list_free)))
+
+/**
+ * gs_unref_regex:
+ *
+ * Call g_regex_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_regex_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_regex __attribute__ ((cleanup(gs_local_regex_unref)))
+
+/**
+ * gs_free_match_info:
+ *
+ * Call g_regex_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_regex_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_free_match_info __attribute__ ((cleanup(gs_local_match_info_free)))
+
+/**
+ * gs_unref_settings_schema:
+ *
+ * Call g_settings_schema_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_settings_schema_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_settings_schema __attribute__ ((cleanup(gs_local_settings_schema_unref)))
+
+/**
+ * gs_unref_settings_schema_source:
+ *
+ * Call g_settings_schema_source_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_settings_schema_source_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_settings_schema_source __attribute__ ((cleanup(gs_local_settings_schema_source_unref)))
+
+/**
+ * gs_unref_settings_schema_key:
+ *
+ * Call g_settings_schema_key_unref() on a variable location when it goes out of
+ * scope. Note that unlike g_settings_schema_key_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_settings_schema_key __attribute__ ((cleanup(gs_local_settings_schema_key_unref)))
+
+/**
+ * gs_free_gstring:
+ *
+ * Call g_string_free(TRUE) on a variable location when it goes out
+ * of scope. Note that unlike g_string_free(), the variable may
+ * be %NULL.
+ */
+#define gs_free_gstring __attribute__ ((cleanup(gs_local_gstring_free)))
+
+G_END_DECLS
+
+#endif
diff --git a/src/terminal-marshal.list b/src/terminal-marshal.list
new file mode 100644
index 0000000..3e91f60
--- /dev/null
+++ b/src/terminal-marshal.list
@@ -0,0 +1 @@
+BOOLEAN:STRING,INT,UINT
diff --git a/src/terminal-mdi-container.c b/src/terminal-mdi-container.c
new file mode 100644
index 0000000..76464a9
--- /dev/null
+++ b/src/terminal-mdi-container.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright © 2008, 2010, 2011, 2012 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "terminal-mdi-container.h"
+#include "terminal-debug.h"
+#include "terminal-intl.h"
+
+enum {
+ SCREEN_ADDED,
+ SCREEN_REMOVED,
+ SCREEN_SWITCHED,
+ SCREENS_REORDERED,
+ SCREEN_CLOSE_REQUEST,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_INTERFACE (TerminalMdiContainer, terminal_mdi_container, GTK_TYPE_WIDGET)
+
+static void
+terminal_mdi_container_default_init (TerminalMdiContainerInterface *iface)
+{
+ signals[SCREEN_ADDED] =
+ g_signal_new (I_("screen-added"),
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalMdiContainerInterface, screen_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1, TERMINAL_TYPE_SCREEN);
+
+ signals[SCREEN_ADDED] =
+ g_signal_new (I_("screen-removed"),
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalMdiContainerInterface, screen_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1, TERMINAL_TYPE_SCREEN);
+
+ signals[SCREEN_ADDED] =
+ g_signal_new (I_("screen-switched"),
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalMdiContainerInterface, screen_switched),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 2, TERMINAL_TYPE_SCREEN, TERMINAL_TYPE_SCREEN);
+
+ signals[SCREENS_REORDERED] =
+ g_signal_new (I_("screens-reordered"),
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalMdiContainerInterface, screens_reordered),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ signals[SCREEN_CLOSE_REQUEST] =
+ g_signal_new (I_("screen-close-request"),
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalMdiContainerInterface, screen_close_request),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1, TERMINAL_TYPE_SCREEN);
+
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("active-screen", NULL, NULL,
+ TERMINAL_TYPE_SCREEN,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+/* public API */
+
+void
+terminal_mdi_container_add_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int position)
+{
+ g_return_if_fail (TERMINAL_IS_MDI_CONTAINER (container));
+ g_return_if_fail (TERMINAL_IS_SCREEN (screen));
+
+ TERMINAL_MDI_CONTAINER_GET_IFACE (container)->add_screen (container, screen, position);
+}
+
+void
+terminal_mdi_container_remove_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen)
+{
+ g_return_if_fail (TERMINAL_IS_MDI_CONTAINER (container));
+ g_return_if_fail (TERMINAL_IS_SCREEN (screen));
+
+ TERMINAL_MDI_CONTAINER_GET_IFACE (container)->remove_screen (container, screen);
+}
+
+TerminalScreen *
+terminal_mdi_container_get_active_screen (TerminalMdiContainer *container)
+{
+ g_return_val_if_fail (TERMINAL_IS_MDI_CONTAINER (container), NULL);
+
+ return TERMINAL_MDI_CONTAINER_GET_IFACE (container)->get_active_screen (container);
+}
+
+void
+terminal_mdi_container_set_active_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen)
+{
+ g_return_if_fail (TERMINAL_IS_MDI_CONTAINER (container));
+ g_return_if_fail (TERMINAL_IS_SCREEN (screen));
+
+ TERMINAL_MDI_CONTAINER_GET_IFACE (container)->set_active_screen (container, screen);
+}
+
+
+GList *
+terminal_mdi_container_list_screens (TerminalMdiContainer *container)
+{
+ g_return_val_if_fail (TERMINAL_IS_MDI_CONTAINER (container), NULL);
+
+ return TERMINAL_MDI_CONTAINER_GET_IFACE (container)->list_screens (container);
+}
+
+GList *
+terminal_mdi_container_list_screen_containers (TerminalMdiContainer *container)
+{
+ g_return_val_if_fail (TERMINAL_IS_MDI_CONTAINER (container), NULL);
+
+ return TERMINAL_MDI_CONTAINER_GET_IFACE (container)->list_screen_containers (container);
+}
+
+int
+terminal_mdi_container_get_n_screens (TerminalMdiContainer *container)
+{
+ g_return_val_if_fail (TERMINAL_IS_MDI_CONTAINER (container), 0);
+
+ return TERMINAL_MDI_CONTAINER_GET_IFACE (container)->get_n_screens (container);
+}
+
+int
+terminal_mdi_container_get_active_screen_num (TerminalMdiContainer *container)
+{
+ g_return_val_if_fail (TERMINAL_IS_MDI_CONTAINER (container), -1);
+
+ return TERMINAL_MDI_CONTAINER_GET_IFACE (container)->get_active_screen_num (container);
+}
+
+void
+terminal_mdi_container_set_active_screen_num (TerminalMdiContainer *container,
+ int position)
+{
+ g_return_if_fail (TERMINAL_IS_MDI_CONTAINER (container));
+
+ TERMINAL_MDI_CONTAINER_GET_IFACE (container)->set_active_screen_num (container, position);
+}
+
+void
+terminal_mdi_container_reorder_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int new_position)
+{
+ g_return_if_fail (TERMINAL_IS_MDI_CONTAINER (container));
+
+ return TERMINAL_MDI_CONTAINER_GET_IFACE (container)->reorder_screen (container, screen, new_position);
+}
+
+void
+terminal_mdi_container_change_screen (TerminalMdiContainer *container,
+ int change)
+{
+ int active, n;
+
+ g_return_if_fail (TERMINAL_IS_MDI_CONTAINER (container));
+ g_return_if_fail (change == -1 || change == 1);
+
+ n = terminal_mdi_container_get_n_screens (container);
+ active = terminal_mdi_container_get_active_screen_num (container);
+
+ active += change;
+ if (active < 0)
+ active = n - 1;
+ else if (active >= n)
+ active = 0;
+
+ terminal_mdi_container_set_active_screen_num (container, active);
+}
diff --git a/src/terminal-mdi-container.h b/src/terminal-mdi-container.h
new file mode 100644
index 0000000..829521f
--- /dev/null
+++ b/src/terminal-mdi-container.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2008, 2010, 2012 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_MDI_CONTAINER_H
+#define TERMINAL_MDI_CONTAINER_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_MDI_CONTAINER (terminal_mdi_container_get_type ())
+#define TERMINAL_MDI_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TERMINAL_TYPE_MDI_CONTAINER, TerminalMdiContainer))
+#define TERMINAL_IS_MDI_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TERMINAL_TYPE_MDI_CONTAINER))
+#define TERMINAL_MDI_CONTAINER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), TERMINAL_TYPE_MDI_CONTAINER, TerminalMdiContainerInterface))
+
+typedef struct _TerminalMdiContainer TerminalMdiContainer;
+typedef struct _TerminalMdiContainerInterface TerminalMdiContainerInterface;
+
+struct _TerminalMdiContainerInterface {
+ GTypeInterface parent_iface;
+
+ /* vfuncs */
+ void (* add_screen) (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int position);
+ void (* remove_screen) (TerminalMdiContainer *container,
+ TerminalScreen *screen);
+ TerminalScreen * (* get_active_screen) (TerminalMdiContainer *container);
+ void (* set_active_screen) (TerminalMdiContainer *container,
+ TerminalScreen *screen);
+ GList * (* list_screens) (TerminalMdiContainer *container);
+ GList * (* list_screen_containers) (TerminalMdiContainer *container);
+ int (* get_n_screens) (TerminalMdiContainer *container);
+ int (* get_active_screen_num) (TerminalMdiContainer *container);
+ void (* set_active_screen_num) (TerminalMdiContainer *container,
+ int position);
+ void (* reorder_screen) (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int new_position);
+
+ /* signals */
+ void (* screen_added) (TerminalMdiContainer *container,
+ TerminalScreen *screen);
+ void (* screen_removed) (TerminalMdiContainer *container,
+ TerminalScreen *screen);
+ void (* screen_switched) (TerminalMdiContainer *container,
+ TerminalScreen *old_active_screen,
+ TerminalScreen *new_active_screen);
+ void (* screens_reordered) (TerminalMdiContainer *container);
+ void (* screen_close_request) (TerminalMdiContainer *container,
+ TerminalScreen *screen);
+};
+
+GType terminal_mdi_container_get_type (void);
+
+void terminal_mdi_container_add_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int position);
+
+void terminal_mdi_container_remove_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen);
+
+TerminalScreen *terminal_mdi_container_get_active_screen (TerminalMdiContainer *container);
+
+void terminal_mdi_container_set_active_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen);
+
+void terminal_mdi_container_set_active_screen_num (TerminalMdiContainer *container,
+ int position);
+
+GList *terminal_mdi_container_list_screens (TerminalMdiContainer *container);
+
+GList *terminal_mdi_container_list_screen_containers (TerminalMdiContainer *container);
+
+int terminal_mdi_container_get_n_screens (TerminalMdiContainer *container);
+
+int terminal_mdi_container_get_active_screen_num (TerminalMdiContainer *container);
+
+void terminal_mdi_container_reorder_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int new_position);
+
+void terminal_mdi_container_change_screen (TerminalMdiContainer *container,
+ int change);
+
+G_END_DECLS
+
+#endif /* TERMINAL_MDI_CONTAINER_H */
diff --git a/src/terminal-menu-button.c b/src/terminal-menu-button.c
new file mode 100644
index 0000000..fbe30f2
--- /dev/null
+++ b/src/terminal-menu-button.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2017 Christian Persch
+ *
+ * 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 3 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
+ * MERCHANMENUILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-menu-button.h"
+#include "terminal-intl.h"
+#include "terminal-libgsystem.h"
+
+/* All this just because GtkToggleButton:toggled is RUN_FIRST (and the
+ * notify::active comes after the toggled signal). :-(
+ */
+
+enum
+{
+ UPDATE_MENU,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+static void popup_menu_selection_done_cb (GtkMenu *menu,
+ GtkMenuButton *button);
+
+/* The menu button sets itself insensitive when it has no menu.
+ * Work around this by using an empty menu.
+ */
+static void
+set_empty_menu (GtkMenuButton *button)
+{
+ gs_unref_object GMenu *menu = g_menu_new ();
+ gtk_menu_button_set_menu_model (button, G_MENU_MODEL (menu));
+}
+
+static void
+disconnect_popup_menu (GtkMenuButton *button)
+{
+ GtkMenu *popup_menu = gtk_menu_button_get_popup (button);
+
+ if (popup_menu)
+ g_signal_handlers_disconnect_by_func
+ (popup_menu, G_CALLBACK (popup_menu_selection_done_cb), button);
+}
+
+static void
+popup_menu_selection_done_cb (GtkMenu *menu,
+ GtkMenuButton *button)
+{
+ disconnect_popup_menu (button);
+ set_empty_menu (button);
+}
+
+/* Class implementation */
+
+G_DEFINE_TYPE (TerminalMenuButton, terminal_menu_button, GTK_TYPE_MENU_BUTTON);
+
+static void
+terminal_menu_button_init (TerminalMenuButton *button_)
+{
+ GtkButton *button = GTK_BUTTON (button_);
+ GtkMenuButton *menu_button = GTK_MENU_BUTTON (button_);
+
+ gtk_button_set_relief (button, GTK_RELIEF_NONE);
+ gtk_button_set_focus_on_click (button, FALSE);
+ gtk_menu_button_set_use_popover (menu_button, FALSE);
+ set_empty_menu (menu_button);
+}
+
+static void
+terminal_menu_button_toggled (GtkToggleButton *button)
+{
+ gboolean active = gtk_toggle_button_get_active (button); /* this is already the new state */
+
+ /* On activate, update the menu */
+ if (active)
+ g_signal_emit (button, signals[UPDATE_MENU], 0);
+
+ GTK_TOGGLE_BUTTON_CLASS (terminal_menu_button_parent_class)->toggled (button);
+}
+
+static void
+terminal_menu_button_update_menu (TerminalMenuButton *button)
+{
+ GtkMenuButton *gtk_button = GTK_MENU_BUTTON (button);
+ GtkMenu *popup_menu = gtk_menu_button_get_popup (gtk_button);
+
+ if (popup_menu)
+ g_signal_connect (popup_menu, "selection-done",
+ G_CALLBACK (popup_menu_selection_done_cb), button);
+}
+
+static void
+terminal_menu_button_dispose (GObject *object)
+{
+ disconnect_popup_menu (GTK_MENU_BUTTON (object));
+
+ G_OBJECT_CLASS (terminal_menu_button_parent_class)->dispose (object);
+}
+
+static void
+terminal_menu_button_class_init (TerminalMenuButtonClass *klass)
+{
+ klass->update_menu = terminal_menu_button_update_menu;
+
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = terminal_menu_button_dispose;
+
+ GtkToggleButtonClass *toggle_button_class = GTK_TOGGLE_BUTTON_CLASS (klass);
+ toggle_button_class->toggled = terminal_menu_button_toggled;
+
+ signals[UPDATE_MENU] =
+ g_signal_new (I_("update-menu"),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalMenuButtonClass, update_menu),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+/* public API */
+
+/**
+ * terminal_menu_button_new:
+ *
+ * Returns: a new #TerminalMenuButton
+ */
+GtkWidget *
+terminal_menu_button_new (void)
+{
+ return g_object_new (TERMINAL_TYPE_MENU_BUTTON, NULL);
+}
diff --git a/src/terminal-menu-button.h b/src/terminal-menu-button.h
new file mode 100644
index 0000000..c9362d0
--- /dev/null
+++ b/src/terminal-menu-button.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2008, 2017 Christian Persch
+ *
+ * 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 3 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
+ * MERCHANMENUILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_MENU_BUTTON_H
+#define TERMINAL_MENU_BUTTON_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_MENU_BUTTON (terminal_menu_button_get_type ())
+#define TERMINAL_MENU_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_MENU_BUTTON, TerminalMenuButton))
+#define TERMINAL_MENU_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_MENU_BUTTON, TerminalMenuButtonClass))
+#define TERMINAL_IS_MENU_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_MENU_BUTTON))
+#define TERMINAL_IS_MENU_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_MENU_BUTTON))
+#define TERMINAL_MENU_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_MENU_BUTTON, TerminalMenuButtonClass))
+
+typedef struct _TerminalMenuButton TerminalMenuButton;
+typedef struct _TerminalMenuButtonClass TerminalMenuButtonClass;
+typedef struct _TerminalMenuButtonPrivate TerminalMenuButtonPrivate;
+
+struct _TerminalMenuButton
+{
+ GtkMenuButton parent_instance;
+};
+
+struct _TerminalMenuButtonClass
+{
+ GtkMenuButtonClass parent_class;
+
+ /* Signals */
+ void (* update_menu) (TerminalMenuButton *menu_button);
+};
+
+GType terminal_menu_button_get_type (void);
+
+GtkWidget *terminal_menu_button_new (void);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_MENU_BUTTON_H */
diff --git a/src/terminal-menubar.ui.in b/src/terminal-menubar.ui.in
new file mode 100644
index 0000000..794d92d
--- /dev/null
+++ b/src/terminal-menubar.ui.in
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2012, 2017 Christian Persch
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<interface>
+ <menu id="menubar">
+ <submenu>
+ <WITH_MNEMONIC><attribute name="label" translatable="yes">_File</attribute></WITH_MNEMONIC>
+ <WITHOUT_MNEMONIC><attribute name="label" translatable="yes">File</attribute></WITHOUT_MNEMONIC>
+ <section id="new-terminal-section" />
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Save Contents…</attribute>
+ <attribute name="action">win.save-contents</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Export…</attribute>
+ <attribute name="action">win.export</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Print…</attribute>
+ <attribute name="action">win.print</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">C_lose Tab</attribute>
+ <attribute name="action">win.close</attribute>
+ <attribute name="target">tab</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Close Window</attribute>
+ <attribute name="action">win.close</attribute>
+ <attribute name="target">window</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <WITH_MNEMONIC><attribute name="label" translatable="yes">_Edit</attribute></WITH_MNEMONIC>
+ <WITHOUT_MNEMONIC><attribute name="label" translatable="yes">Edit</attribute></WITHOUT_MNEMONIC>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Copy</attribute>
+ <attribute name="action">win.copy</attribute>
+ <attribute name="target">text</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Copy as _HTML</attribute>
+ <attribute name="action">win.copy</attribute>
+ <attribute name="target">html</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Paste</attribute>
+ <attribute name="action">win.paste-text</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Paste as _Filenames</attribute>
+ <attribute name="action">win.paste-uris</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Select _All</attribute>
+ <attribute name="action">win.select-all</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">P_references</attribute>
+ <attribute name="action">win.edit-preferences</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <WITH_MNEMONIC><attribute name="label" translatable="yes">_View</attribute></WITH_MNEMONIC>
+ <WITHOUT_MNEMONIC><attribute name="label" translatable="yes">View</attribute></WITHOUT_MNEMONIC>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Show _Menubar</attribute>
+ <attribute name="action">win.menubar-visible</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Full Screen</attribute>
+ <attribute name="action">win.fullscreen</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Zoom _In</attribute>
+ <attribute name="action">win.zoom-in</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Normal Size</attribute>
+ <attribute name="action">win.zoom-normal</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Zoom _Out</attribute>
+ <attribute name="action">win.zoom-out</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <WITH_MNEMONIC><attribute name="label" translatable="yes">_Search</attribute></WITH_MNEMONIC>
+ <WITHOUT_MNEMONIC><attribute name="label" translatable="yes">Search</attribute></WITHOUT_MNEMONIC>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Find…</attribute>
+ <attribute name="action">win.find</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Find _Next</attribute>
+ <attribute name="action">win.find-forward</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Find _Previous</attribute>
+ <attribute name="action">win.find-backward</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Clear Highlight</attribute>
+ <attribute name="action">win.find-clear</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <WITH_MNEMONIC><attribute name="label" translatable="yes">_Terminal</attribute></WITH_MNEMONIC>
+ <WITHOUT_MNEMONIC><attribute name="label" translatable="yes">Terminal</attribute></WITHOUT_MNEMONIC>
+ <section>
+ <section id="set-profile-section" />
+ <item>
+ <attribute name="label" translatable="yes">Set _Title…</attribute>
+ <attribute name="action">win.set-title</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Read-_Only</attribute>
+ <attribute name="action">win.read-only</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Reset</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">false</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Reset and C_lear</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">true</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_1. 80×24</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(80, 24)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_2. 80×43</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(80, 43)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_3. 132×24</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(132, 24)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_4. 132×43</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(132, 43)</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <WITH_MNEMONIC><attribute name="label" translatable="yes">Ta_bs</attribute></WITH_MNEMONIC>
+ <WITHOUT_MNEMONIC><attribute name="label" translatable="yes">Tabs</attribute></WITHOUT_MNEMONIC>
+ <attribute name="action">win.tabs-menu</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Previous Tab</attribute>
+ <attribute name="action">win.tab-switch-left</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Next Tab</attribute>
+ <attribute name="action">win.tab-switch-right</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Move Terminal _Left</attribute>
+ <attribute name="action">win.tab-move-left</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Move Terminal _Right</attribute>
+ <attribute name="action">win.tab-move-right</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Detach Terminal</attribute>
+ <attribute name="action">win.tab-detach</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <WITH_MNEMONIC><attribute name="label" translatable="yes">_Help</attribute></WITH_MNEMONIC>
+ <WITHOUT_MNEMONIC><attribute name="label" translatable="yes">Help</attribute></WITHOUT_MNEMONIC>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Contents</attribute>
+ <attribute name="action">win.help</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_About</attribute>
+ <attribute name="action">win.about</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Inspector</attribute>
+ <attribute name="action">win.inspector</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ </section>
+ </submenu>
+ </menu>
+</interface>
diff --git a/src/terminal-nautilus.c b/src/terminal-nautilus.c
new file mode 100644
index 0000000..6e9a341
--- /dev/null
+++ b/src/terminal-nautilus.c
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ * Copyright © 2011 Christian Persch
+ * Author: Christian Neumair <chris@gnome-de.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include <nautilus-extension.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "terminal-i18n.h"
+#include "terminal-client-utils.h"
+#include "terminal-defines.h"
+#include "terminal-gdbus-generated.h"
+
+/* Nautilus extension class */
+
+#define TERMINAL_TYPE_NAUTILUS (terminal_nautilus_get_type ())
+#define TERMINAL_NAUTILUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_NAUTILUS, TerminalNautilus))
+#define TERMINAL_NAUTILUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_NAUTILUS, TerminalNautilusClass))
+#define TERMINAL_IS_NAUTILUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_NAUTILUS))
+#define TERMINAL_IS_NAUTILUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_NAUTILUS))
+#define TERMINAL_NAUTILUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_NAUTILUS, TerminalNautilusClass))
+
+typedef struct _TerminalNautilus TerminalNautilus;
+typedef struct _TerminalNautilusClass TerminalNautilusClass;
+
+struct _TerminalNautilus {
+ GObject parent_instance;
+
+ GSettings *lockdown_prefs;
+};
+
+struct _TerminalNautilusClass {
+ GObjectClass parent_class;
+};
+
+static GType terminal_nautilus_get_type (void);
+
+/* Nautilus menu item class */
+
+#define TERMINAL_TYPE_NAUTILUS_MENU_ITEM (terminal_nautilus_menu_item_get_type ())
+#define TERMINAL_NAUTILUS_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_NAUTILUS_MENU_ITEM, TerminalNautilusMenuItem))
+#define TERMINAL_NAUTILUS_MENU_ITEM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_NAUTILUS_MENU_ITEM, TerminalNautilusMenuItemClass))
+#define TERMINAL_IS_NAUTILUS_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_NAUTILUS_MENU_ITEM))
+#define TERMINAL_IS_NAUTILUS_MENU_ITEM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_NAUTILUS_MENU_ITEM))
+#define TERMINAL_NAUTILUS_MENU_ITEM_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_NAUTILUS_MENU_ITEM, TerminalNautilusMenuItemClass))
+
+typedef struct _TerminalNautilusMenuItem TerminalNautilusMenuItem;
+typedef struct _TerminalNautilusMenuItemClass TerminalNautilusMenuItemClass;
+
+struct _TerminalNautilusMenuItem {
+ NautilusMenuItem parent_instance;
+
+ TerminalNautilus *nautilus;
+ NautilusFileInfo *file_info;
+ gboolean remote_terminal;
+};
+
+struct _TerminalNautilusMenuItemClass {
+ NautilusMenuItemClass parent_class;
+};
+
+static GType terminal_nautilus_menu_item_get_type (void);
+
+/* --- */
+
+#define TERMINAL_ICON_NAME "org.gnome.Terminal"
+
+typedef enum {
+ /* local files. Always open "conventionally", i.e. cd and spawn. */
+ FILE_INFO_LOCAL,
+ FILE_INFO_DESKTOP,
+ /* SFTP: Shell terminals are opened "remote" (i.e. with ssh client),
+ * commands are executed like OTHER.
+ */
+ FILE_INFO_SFTP,
+ /* OTHER: Terminals and commands are opened by mapping the URI back
+ * to ~/.gvfs, i.e. to the GVFS FUSE bridge.
+ */
+ FILE_INFO_OTHER
+} TerminalFileInfo;
+
+static TerminalFileInfo
+get_terminal_file_info_from_uri (const char *uri)
+{
+ TerminalFileInfo ret;
+ char *uri_scheme;
+
+ uri_scheme = g_uri_parse_scheme (uri);
+
+ if (uri_scheme == NULL) {
+ ret = FILE_INFO_OTHER;
+ } else if (strcmp (uri_scheme, "file") == 0) {
+ ret = FILE_INFO_LOCAL;
+ } else if (strcmp (uri_scheme, "x-nautilus-desktop") == 0) {
+ ret = FILE_INFO_DESKTOP;
+ } else if (strcmp (uri_scheme, "sftp") == 0 ||
+ strcmp (uri_scheme, "ssh") == 0) {
+ ret = FILE_INFO_SFTP;
+ } else {
+ ret = FILE_INFO_OTHER;
+ }
+
+ g_free (uri_scheme);
+
+ return ret;
+}
+
+/* Helpers */
+
+#define NAUTILUS_SETTINGS_SCHEMA "org.gnome.Nautilus"
+#define GNOME_DESKTOP_LOCKDOWN_SETTINGS_SCHEMA "org.gnome.desktop.lockdown"
+
+/* a very simple URI parsing routine from Launchpad #333462, until GLib supports URI parsing (GNOME #489862) */
+#define SFTP_PREFIX "sftp://"
+static void
+parse_sftp_uri (GFile *file,
+ char **user,
+ char **host,
+ unsigned int *port,
+ char **path)
+{
+ char *tmp, *save;
+ char *uri;
+
+ uri = g_file_get_uri (file);
+ g_assert (uri != NULL);
+ save = uri;
+
+ *path = NULL;
+ *user = NULL;
+ *host = NULL;
+ *port = 0;
+
+ /* skip intial 'sftp:// prefix */
+ g_assert (!strncmp (uri, SFTP_PREFIX, strlen (SFTP_PREFIX)));
+ uri += strlen (SFTP_PREFIX);
+
+ /* cut out the path */
+ tmp = strchr (uri, '/');
+ if (tmp != NULL) {
+ *path = g_uri_unescape_string (tmp, "/");
+ *tmp = '\0';
+ }
+
+ /* read the username - it ends with @ */
+ tmp = strchr (uri, '@');
+ if (tmp != NULL) {
+ *tmp++ = '\0';
+
+ *user = strdup (uri);
+ if (strchr (*user, ':') != NULL) {
+ /* chop the password */
+ *(strchr (*user, ':')) = '\0';
+ }
+
+ uri = tmp;
+ }
+
+ /* now read the port, starts with : */
+ tmp = strchr (uri, ':');
+ if (tmp != NULL) {
+ *tmp++ = '\0';
+ *port = atoi (tmp); /*FIXME: getservbyname*/
+ }
+
+ /* what is left is the host */
+ *host = strdup (uri);
+ g_free (save);
+}
+
+static char **
+ssh_argv (const char *uri,
+ int *argcp)
+{
+ GFile *file;
+ char **argv;
+ int argc;
+ char *host_name, *path, *user_name, *quoted_path;
+ guint host_port;
+
+ g_assert (uri != NULL);
+
+ argv = g_new0 (char *, 9);
+ argc = 0;
+ argv[argc++] = g_strdup ("ssh");
+ argv[argc++] = g_strdup ("-t");
+
+ file = g_file_new_for_uri (uri);
+ parse_sftp_uri (file, &user_name, &host_name, &host_port, &path);
+ g_object_unref (file);
+
+ if (user_name != NULL) {
+ argv[argc++ ]= g_strdup_printf ("%s@%s", user_name, host_name);
+ g_free (host_name);
+ g_free (user_name);
+ } else {
+ argv[argc++] = host_name;
+ }
+
+ if (host_port != 0) {
+ argv[argc++] = g_strdup ("-p");
+ argv[argc++] = g_strdup_printf ("%u", host_port);
+ }
+
+ /* FIXME to we have to consider the remote file encoding? */
+ quoted_path = g_shell_quote (path);
+
+ /* login shell */
+ argv[argc++] = g_strdup_printf ("cd %s && exec $SHELL -l", quoted_path);
+
+ g_free (path);
+ g_free (quoted_path);
+
+ *argcp = argc;
+ return argv;
+}
+
+static gboolean
+terminal_locked_down (TerminalNautilus *nautilus)
+{
+ return g_settings_get_boolean (nautilus->lockdown_prefs,
+ "disable-command-line");
+}
+
+/* used to determine for remote URIs whether GVFS is capable of mapping them to ~/.gvfs */
+static gboolean
+uri_has_local_path (const char *uri)
+{
+ GFile *file;
+ char *path;
+ gboolean ret;
+
+ file = g_file_new_for_uri (uri);
+ path = g_file_get_path (file);
+
+ ret = (path != NULL);
+
+ g_free (path);
+ g_object_unref (file);
+
+ return ret;
+}
+
+/* Nautilus menu item class */
+
+typedef struct {
+ TerminalNautilus *nautilus;
+ guint32 timestamp;
+ char *path;
+ char *uri;
+ TerminalFileInfo info;
+ gboolean remote;
+} ExecData;
+
+static void
+exec_data_free (ExecData *data)
+{
+ g_object_unref (data->nautilus);
+ g_free (data->path);
+ g_free (data->uri);
+
+ g_free (data);
+}
+
+/* FIXME: make this async */
+static gboolean
+create_terminal (ExecData *data /* transfer full */)
+{
+ TerminalFactory *factory;
+ TerminalReceiver *receiver;
+ GError *error = NULL;
+ GVariantBuilder builder;
+ char *object_path;
+ char startup_id[32];
+ char **argv;
+ int argc;
+
+ factory = terminal_factory_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ TERMINAL_APPLICATION_ID,
+ TERMINAL_FACTORY_OBJECT_PATH,
+ NULL /* cancellable */,
+ &error);
+ if (factory == NULL) {
+ g_dbus_error_strip_remote_error (error);
+ g_printerr ("Error constructing proxy for %s:%s: %s\n",
+ TERMINAL_APPLICATION_ID, TERMINAL_FACTORY_OBJECT_PATH,
+ error->message);
+ g_error_free (error);
+ exec_data_free (data);
+ return FALSE;
+ }
+
+ g_snprintf (startup_id, sizeof (startup_id), "_TIME%u", data->timestamp);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ terminal_client_append_create_instance_options (&builder,
+ gdk_display_get_name (gdk_display_get_default ()),
+ startup_id,
+ NULL /* geometry */,
+ NULL /* role */,
+ NULL /* use default profile */,
+ NULL /* use profile encoding */,
+ NULL /* title */,
+ TRUE, /* active */
+ FALSE /* maximised */,
+ FALSE /* fullscreen */);
+
+ if (!terminal_factory_call_create_instance_sync
+ (factory,
+ g_variant_builder_end (&builder),
+ &object_path,
+ NULL /* cancellable */,
+ &error)) {
+ g_dbus_error_strip_remote_error (error);
+ g_printerr ("Error creating terminal: %s\n", error->message);
+ g_error_free (error);
+ g_object_unref (factory);
+ exec_data_free (data);
+ return FALSE;
+ }
+
+ g_object_unref (factory);
+
+ receiver = terminal_receiver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ TERMINAL_APPLICATION_ID,
+ object_path,
+ NULL /* cancellable */,
+ &error);
+ if (receiver == NULL) {
+ g_dbus_error_strip_remote_error (error);
+ g_printerr ("Failed to create proxy for terminal: %s\n", error->message);
+ g_error_free (error);
+ g_free (object_path);
+ exec_data_free (data);
+ return FALSE;
+ }
+
+ g_free (object_path);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ terminal_client_append_exec_options (&builder,
+ TRUE, /* pass environment */
+ data->path,
+ NULL, 0, /* FD array */
+ TRUE /* shell */);
+
+ if (data->info == FILE_INFO_SFTP &&
+ data->remote) {
+ argv = ssh_argv (data->uri, &argc);
+ } else {
+ argv = NULL; argc = 0;
+ }
+
+ if (!terminal_receiver_call_exec_sync (receiver,
+ g_variant_builder_end (&builder),
+ g_variant_new_bytestring_array ((const char * const *) argv, argc),
+ NULL /* in FD list */,
+ NULL /* out FD list */,
+ NULL /* cancellable */,
+ &error)) {
+ g_dbus_error_strip_remote_error (error);
+ g_printerr ("Error: %s\n", error->message);
+ g_error_free (error);
+ g_strfreev (argv);
+ g_object_unref (receiver);
+ exec_data_free (data);
+ return FALSE;
+ }
+
+ g_strfreev (argv);
+
+ exec_data_free (data);
+
+ g_object_unref (receiver);
+
+ return TRUE;
+}
+
+static void
+terminal_nautilus_menu_item_activate (NautilusMenuItem *item)
+{
+ TerminalNautilusMenuItem *menu_item = TERMINAL_NAUTILUS_MENU_ITEM (item);
+ TerminalNautilus *nautilus = menu_item->nautilus;
+ char *uri, *path;
+ TerminalFileInfo info;
+ ExecData *data;
+
+ uri = nautilus_file_info_get_activation_uri (menu_item->file_info);
+ if (uri == NULL)
+ return;
+
+ path = NULL;
+ info = get_terminal_file_info_from_uri (uri);
+
+ switch (info) {
+ case FILE_INFO_LOCAL:
+ path = g_filename_from_uri (uri, NULL, NULL);
+ break;
+
+ case FILE_INFO_DESKTOP:
+ path = g_strdup (g_get_home_dir ());
+ break;
+
+ case FILE_INFO_SFTP:
+ if (menu_item->remote_terminal)
+ break;
+
+ /* fall through */
+
+ case FILE_INFO_OTHER: {
+ GFile *file;
+
+ /* map back remote URI to local path */
+ file = g_file_new_for_uri (uri);
+ path = g_file_get_path (file);
+ g_object_unref (file);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (path == NULL && (info != FILE_INFO_SFTP || !menu_item->remote_terminal)) {
+ g_free (uri);
+ return;
+ }
+
+ data = g_new (ExecData, 1);
+ data->nautilus = g_object_ref (nautilus);
+ data->timestamp = gtk_get_current_event_time ();
+ data->path = path;
+ data->uri = uri;
+ data->info = info;
+ data->remote = menu_item->remote_terminal;
+
+ create_terminal (data);
+}
+
+G_DEFINE_DYNAMIC_TYPE (TerminalNautilusMenuItem, terminal_nautilus_menu_item, NAUTILUS_TYPE_MENU_ITEM)
+
+static void
+terminal_nautilus_menu_item_init (TerminalNautilusMenuItem *nautilus_menu_item)
+{
+}
+
+static void
+terminal_nautilus_menu_item_dispose (GObject *object)
+{
+ TerminalNautilusMenuItem *menu_item = TERMINAL_NAUTILUS_MENU_ITEM (object);
+
+ if (menu_item->file_info != NULL) {
+ g_object_unref (menu_item->file_info);
+ menu_item->file_info = NULL;
+ }
+ if (menu_item->nautilus != NULL) {
+ g_object_unref (menu_item->nautilus);
+ menu_item->nautilus = NULL;
+ }
+
+ G_OBJECT_CLASS (terminal_nautilus_menu_item_parent_class)->dispose (object);
+}
+
+static void
+terminal_nautilus_menu_item_class_init (TerminalNautilusMenuItemClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ NautilusMenuItemClass *menu_item_class = NAUTILUS_MENU_ITEM_CLASS (klass);
+
+ gobject_class->dispose = terminal_nautilus_menu_item_dispose;
+
+ menu_item_class->activate = terminal_nautilus_menu_item_activate;
+}
+
+static void
+terminal_nautilus_menu_item_class_finalize (TerminalNautilusMenuItemClass *class)
+{
+}
+
+static NautilusMenuItem *
+terminal_nautilus_menu_item_new (TerminalNautilus *nautilus,
+ NautilusFileInfo *file_info,
+ TerminalFileInfo terminal_file_info,
+ gboolean remote_terminal,
+ gboolean is_file_item)
+{
+ TerminalNautilusMenuItem *item;
+ const char *action_name;
+ const char *name;
+ const char *tooltip;
+
+ if (is_file_item) {
+ action_name = remote_terminal ? "TerminalNautilus:OpenRemote"
+ : "TerminalNautilus:OpenLocal";
+ } else {
+ action_name = remote_terminal ? "TerminalNautilus:OpenFolderRemote"
+ : "TerminalNautilus:OpenFolderLocal";
+ }
+
+ switch (terminal_file_info) {
+ case FILE_INFO_SFTP:
+ if (remote_terminal) {
+ name = _("Open in _Remote Terminal");
+ } else {
+ name = _("Open in _Local Terminal");
+ }
+
+ if (is_file_item) {
+ tooltip = _("Open the currently selected folder in a terminal");
+ } else {
+ tooltip = _("Open the currently open folder in a terminal");
+ }
+ break;
+
+ case FILE_INFO_LOCAL:
+ case FILE_INFO_OTHER:
+ name = _("Open in T_erminal");
+
+ if (is_file_item) {
+ tooltip = _("Open the currently selected folder in a terminal");
+ } else {
+ tooltip = _("Open the currently open folder in a terminal");
+ }
+ break;
+
+ case FILE_INFO_DESKTOP:
+ name = _("Open T_erminal");
+ tooltip = _("Open a terminal");
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ item = g_object_new (TERMINAL_TYPE_NAUTILUS_MENU_ITEM,
+ "name", action_name,
+ "label", name,
+ "tip", tooltip,
+ "icon", TERMINAL_ICON_NAME,
+ NULL);
+
+ item->nautilus = g_object_ref (nautilus);
+ item->file_info = g_object_ref (file_info);
+ item->remote_terminal = remote_terminal;
+
+ return (NautilusMenuItem *) item;
+}
+
+/* Nautilus extension class implementation */
+
+static GList *
+terminal_nautilus_get_background_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *file_info)
+{
+ TerminalNautilus *nautilus = TERMINAL_NAUTILUS (provider);
+ gchar *uri;
+ GList *items;
+ NautilusMenuItem *item;
+ TerminalFileInfo terminal_file_info;
+
+ if (terminal_locked_down (nautilus))
+ return NULL;
+
+ uri = nautilus_file_info_get_activation_uri (file_info);
+ if (uri == NULL)
+ return NULL;
+
+ items = NULL;
+
+ terminal_file_info = get_terminal_file_info_from_uri (uri);
+
+
+ if (terminal_file_info == FILE_INFO_SFTP) {
+ /* remote SSH location */
+ item = terminal_nautilus_menu_item_new (nautilus,
+ file_info,
+ terminal_file_info,
+ TRUE,
+ FALSE);
+ items = g_list_append (items, item);
+ }
+
+ if (terminal_file_info == FILE_INFO_DESKTOP ||
+ uri_has_local_path (uri)) {
+ /* local locations and remote locations that offer local back-mapping */
+ item = terminal_nautilus_menu_item_new (nautilus,
+ file_info,
+ terminal_file_info,
+ FALSE,
+ FALSE);
+ items = g_list_append (items, item);
+ }
+
+ g_free (uri);
+
+ return items;
+}
+
+static GList *
+terminal_nautilus_get_file_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ GList *files)
+{
+ TerminalNautilus *nautilus = TERMINAL_NAUTILUS (provider);
+ gchar *uri;
+ GList *items;
+ NautilusMenuItem *item;
+ NautilusFileInfo *file_info;
+ GFileType file_type;
+ TerminalFileInfo terminal_file_info;
+
+ if (terminal_locked_down (nautilus))
+ return NULL;
+
+ /* Only add items when passed exactly one file */
+ if (files == NULL || files->next != NULL)
+ return NULL;
+
+ file_info = (NautilusFileInfo *) files->data;
+ file_type = nautilus_file_info_get_file_type (file_info);
+ if (!nautilus_file_info_is_directory (file_info) &&
+ file_type != G_FILE_TYPE_SHORTCUT &&
+ file_type != G_FILE_TYPE_MOUNTABLE)
+ return NULL;
+
+ uri = nautilus_file_info_get_activation_uri (file_info);
+ if (uri == NULL)
+ return NULL;
+
+ items = NULL;
+
+ terminal_file_info = get_terminal_file_info_from_uri (uri);
+
+ switch (terminal_file_info) {
+ case FILE_INFO_LOCAL:
+ case FILE_INFO_SFTP:
+ case FILE_INFO_OTHER:
+ if (terminal_file_info == FILE_INFO_SFTP ||
+ uri_has_local_path (uri)) {
+ item = terminal_nautilus_menu_item_new (nautilus,
+ file_info,
+ terminal_file_info,
+ terminal_file_info == FILE_INFO_SFTP,
+ TRUE);
+ items = g_list_append (items, item);
+ }
+
+ if (terminal_file_info == FILE_INFO_SFTP &&
+ uri_has_local_path (uri)) {
+ item = terminal_nautilus_menu_item_new (nautilus,
+ file_info,
+ terminal_file_info,
+ FALSE,
+ TRUE);
+ items = g_list_append (items, item);
+ }
+
+ case FILE_INFO_DESKTOP:
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ g_free (uri);
+
+ return items;
+}
+
+static void
+terminal_nautilus_menu_provider_iface_init (NautilusMenuProviderIface *iface)
+{
+ iface->get_background_items = terminal_nautilus_get_background_items;
+ iface->get_file_items = terminal_nautilus_get_file_items;
+}
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TerminalNautilus, terminal_nautilus, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE_DYNAMIC (NAUTILUS_TYPE_MENU_PROVIDER,
+ terminal_nautilus_menu_provider_iface_init))
+
+static void
+terminal_nautilus_init (TerminalNautilus *nautilus)
+{
+ nautilus->lockdown_prefs = g_settings_new (GNOME_DESKTOP_LOCKDOWN_SETTINGS_SCHEMA);
+}
+
+static void
+terminal_nautilus_dispose (GObject *object)
+{
+ TerminalNautilus *nautilus = TERMINAL_NAUTILUS (object);
+
+ g_clear_object (&nautilus->lockdown_prefs);
+
+ G_OBJECT_CLASS (terminal_nautilus_parent_class)->dispose (object);
+}
+
+static void
+terminal_nautilus_class_init (TerminalNautilusClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = terminal_nautilus_dispose;
+
+ terminal_i18n_init (FALSE);
+}
+
+static void
+terminal_nautilus_class_finalize (TerminalNautilusClass *class)
+{
+}
+
+/* Nautilus extension */
+
+static GType type_list[1];
+
+#define EXPORT __attribute__((__visibility__("default"))) extern
+
+EXPORT void
+nautilus_module_initialize (GTypeModule *module)
+{
+ terminal_nautilus_register_type (module);
+ terminal_nautilus_menu_item_register_type (module);
+
+ type_list[0] = TERMINAL_TYPE_NAUTILUS;
+}
+
+EXPORT void
+nautilus_module_shutdown (void)
+{
+}
+
+EXPORT void
+nautilus_module_list_types (const GType **types,
+ int *num_types)
+{
+ *types = type_list;
+ *num_types = G_N_ELEMENTS (type_list);
+}
diff --git a/src/terminal-notebook-menu.ui b/src/terminal-notebook-menu.ui
new file mode 100644
index 0000000..d5c7f41
--- /dev/null
+++ b/src/terminal-notebook-menu.ui
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2012 Christian Persch
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<interface>
+ <menu id="notebook-popup">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Move Terminal _Left</attribute>
+ <attribute name="action">win.tab-move-left</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Move Terminal _Right</attribute>
+ <attribute name="action">win.tab-move-right</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Detach Terminal</attribute>
+ <attribute name="action">win.tab-detach</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Set _Title…</attribute>
+ <attribute name="action">win.set-title</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">C_lose Terminal</attribute>
+ <attribute name="action">win.close</attribute>
+ <attribute name="target">tab</attribute>
+ </item>
+ </section>
+ </menu>
+</interface>
diff --git a/src/terminal-notebook.c b/src/terminal-notebook.c
new file mode 100644
index 0000000..356a389
--- /dev/null
+++ b/src/terminal-notebook.c
@@ -0,0 +1,593 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2008, 2010, 2011, 2012 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "terminal-notebook.h"
+
+#include <gtk/gtk.h>
+
+#include "terminal-debug.h"
+#include "terminal-app.h"
+#include "terminal-intl.h"
+#include "terminal-mdi-container.h"
+#include "terminal-screen-container.h"
+#include "terminal-tab-label.h"
+#include "terminal-schemas.h"
+#include "terminal-libgsystem.h"
+
+#define TERMINAL_NOTEBOOK_GET_PRIVATE(notebook)(G_TYPE_INSTANCE_GET_PRIVATE ((notebook), TERMINAL_TYPE_NOTEBOOK, TerminalNotebookPrivate))
+
+struct _TerminalNotebookPrivate
+{
+ TerminalScreen *active_screen;
+ GtkPolicyType policy;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ACTIVE_SCREEN,
+ PROP_TAB_POLICY
+};
+
+#define ACTION_AREA_BORDER_WIDTH (2)
+#define ACTION_BUTTON_SPACING (6)
+
+/* helper functions */
+
+static void
+update_tab_visibility (TerminalNotebook *notebook,
+ int change)
+{
+ TerminalNotebookPrivate *priv = notebook->priv;
+ GtkNotebook *gtk_notebook = GTK_NOTEBOOK (notebook);
+ int new_n_pages;
+ gboolean show_tabs;
+
+ if (gtk_widget_in_destruction (GTK_WIDGET (notebook)))
+ return;
+
+ new_n_pages = gtk_notebook_get_n_pages (gtk_notebook) + change;
+ /* Don't do anything if we're going to have zero pages (and thus close the window) */
+ if (new_n_pages == 0)
+ return;
+
+ switch (priv->policy) {
+ case GTK_POLICY_ALWAYS:
+ show_tabs = TRUE;
+ break;
+ case GTK_POLICY_AUTOMATIC:
+ show_tabs = new_n_pages > 1;
+ break;
+ case GTK_POLICY_NEVER:
+ case GTK_POLICY_EXTERNAL:
+ default:
+ show_tabs = FALSE;
+ break;
+ }
+
+ gtk_notebook_set_show_tabs (gtk_notebook, show_tabs);
+}
+
+static void
+close_button_clicked_cb (TerminalTabLabel *tab_label,
+ gpointer user_data)
+{
+ TerminalScreen *screen;
+ TerminalNotebook *notebook;
+
+ screen = terminal_tab_label_get_screen (tab_label);
+
+ /* notebook is not passed as user_data because it can change during DND
+ * and the close button is not notified about that, see bug 731998.
+ */
+ notebook = TERMINAL_NOTEBOOK (gtk_widget_get_ancestor (GTK_WIDGET (screen),
+ TERMINAL_TYPE_NOTEBOOK));
+
+ if (notebook != NULL)
+ g_signal_emit_by_name (notebook, "screen-close-request", screen);
+}
+
+
+static void
+remove_reorder_bindings (GtkBindingSet *binding_set,
+ guint keysym)
+{
+ guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
+ gtk_binding_entry_skip (binding_set, keysym, GDK_MOD1_MASK);
+ gtk_binding_entry_skip (binding_set, keypad_keysym, GDK_MOD1_MASK);
+}
+
+/* TerminalMdiContainer impl */
+
+static void
+terminal_notebook_add_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int position)
+{
+ TerminalNotebook *notebook = TERMINAL_NOTEBOOK (container);
+ GtkNotebook *gtk_notebook = GTK_NOTEBOOK (notebook);
+ GtkWidget *screen_container, *tab_label;
+
+ g_warn_if_fail (gtk_widget_get_parent (GTK_WIDGET (screen)) == NULL);
+
+ screen_container = terminal_screen_container_new (screen);
+ gtk_widget_show (screen_container);
+
+ update_tab_visibility (notebook, +1);
+
+ tab_label = terminal_tab_label_new (screen);
+ g_signal_connect (tab_label, "close-button-clicked",
+ G_CALLBACK (close_button_clicked_cb), NULL);
+
+ gtk_notebook_insert_page (gtk_notebook,
+ screen_container,
+ tab_label,
+ position);
+ gtk_container_child_set (GTK_CONTAINER (notebook),
+ screen_container,
+ "tab-expand", TRUE,
+ "tab-fill", TRUE,
+ NULL);
+ gtk_notebook_set_tab_reorderable (gtk_notebook, screen_container, TRUE);
+#if 0
+ gtk_notebook_set_tab_detachable (gtk_notebook, screen_container, TRUE);
+#endif
+}
+
+static void
+terminal_notebook_remove_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen)
+{
+ TerminalNotebook *notebook = TERMINAL_NOTEBOOK (container);
+ TerminalScreenContainer *screen_container;
+
+ g_warn_if_fail (gtk_widget_is_ancestor (GTK_WIDGET (screen), GTK_WIDGET (notebook)));
+
+ update_tab_visibility (notebook, -1);
+
+ screen_container = terminal_screen_container_get_from_screen (screen);
+ gtk_container_remove (GTK_CONTAINER (notebook),
+ GTK_WIDGET (screen_container));
+}
+
+static TerminalScreen *
+terminal_notebook_get_active_screen (TerminalMdiContainer *container)
+{
+ TerminalNotebook *notebook = TERMINAL_NOTEBOOK (container);
+ GtkNotebook *gtk_notebook = GTK_NOTEBOOK (notebook);
+ GtkWidget *widget;
+
+ widget = gtk_notebook_get_nth_page (gtk_notebook, gtk_notebook_get_current_page (gtk_notebook));
+ return terminal_screen_container_get_screen (TERMINAL_SCREEN_CONTAINER (widget));
+}
+
+static void
+terminal_notebook_set_active_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen)
+{
+ TerminalNotebook *notebook = TERMINAL_NOTEBOOK (container);
+ GtkNotebook *gtk_notebook = GTK_NOTEBOOK (notebook);
+ TerminalScreenContainer *screen_container;
+ GtkWidget *widget;
+
+ screen_container = terminal_screen_container_get_from_screen (screen);
+ widget = GTK_WIDGET (screen_container);
+
+ gtk_notebook_set_current_page (gtk_notebook,
+ gtk_notebook_page_num (gtk_notebook, widget));
+}
+
+static GList *
+terminal_notebook_list_screen_containers (TerminalMdiContainer *container)
+{
+ /* We are trusting that GtkNotebook will return pages in order */
+ return gtk_container_get_children (GTK_CONTAINER (container));
+}
+
+static GList *
+terminal_notebook_list_screens (TerminalMdiContainer *container)
+{
+ GList *list, *l;
+
+ list = terminal_notebook_list_screen_containers (container);
+ for (l = list; l != NULL; l = l->next)
+ l->data = terminal_screen_container_get_screen ((TerminalScreenContainer *) l->data);
+
+ return list;
+}
+
+static int
+terminal_notebook_get_n_screens (TerminalMdiContainer *container)
+{
+ return gtk_notebook_get_n_pages (GTK_NOTEBOOK (container));
+}
+
+static int
+terminal_notebook_get_active_screen_num (TerminalMdiContainer *container)
+{
+ return gtk_notebook_get_current_page (GTK_NOTEBOOK (container));
+}
+
+static void
+terminal_notebook_set_active_screen_num (TerminalMdiContainer *container,
+ int position)
+{
+ GtkNotebook *gtk_notebook = GTK_NOTEBOOK (container);
+
+ gtk_notebook_set_current_page (gtk_notebook, position);
+}
+
+static void
+terminal_notebook_reorder_screen (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ int new_position)
+{
+ GtkNotebook *notebook = GTK_NOTEBOOK (container);
+ GtkWidget *child;
+ int n, pos;
+
+ g_return_if_fail (new_position == 1 || new_position == -1);
+
+ child = GTK_WIDGET (terminal_screen_container_get_from_screen (screen));
+ n = gtk_notebook_get_n_pages (notebook);
+ pos = gtk_notebook_page_num (notebook, child);
+
+ pos += new_position;
+ gtk_notebook_reorder_child (notebook, child,
+ pos < 0 ? n - 1 : pos < n ? pos : 0);
+}
+
+static void
+terminal_notebook_mdi_iface_init (TerminalMdiContainerInterface *iface)
+{
+ iface->add_screen = terminal_notebook_add_screen;
+ iface->remove_screen = terminal_notebook_remove_screen;
+ iface->get_active_screen = terminal_notebook_get_active_screen;
+ iface->set_active_screen = terminal_notebook_set_active_screen;
+ iface->list_screens = terminal_notebook_list_screens;
+ iface->list_screen_containers = terminal_notebook_list_screen_containers;
+ iface->get_n_screens = terminal_notebook_get_n_screens;
+ iface->get_active_screen_num = terminal_notebook_get_active_screen_num;
+ iface->set_active_screen_num = terminal_notebook_set_active_screen_num;
+ iface->reorder_screen = terminal_notebook_reorder_screen;
+}
+
+G_DEFINE_TYPE_WITH_CODE (TerminalNotebook, terminal_notebook, GTK_TYPE_NOTEBOOK,
+ G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_MDI_CONTAINER, terminal_notebook_mdi_iface_init))
+
+/* GtkNotebookClass impl */
+
+static void
+terminal_notebook_switch_page (GtkNotebook *gtk_notebook,
+ GtkWidget *child,
+ guint page_num)
+{
+ TerminalNotebook *notebook = TERMINAL_NOTEBOOK (gtk_notebook);
+ TerminalNotebookPrivate *priv = notebook->priv;
+ TerminalScreen *screen, *old_active_screen;
+
+ GTK_NOTEBOOK_CLASS (terminal_notebook_parent_class)->switch_page (gtk_notebook, child, page_num);
+
+ screen = terminal_screen_container_get_screen (TERMINAL_SCREEN_CONTAINER (child));
+
+ old_active_screen = priv->active_screen;
+ if (screen == old_active_screen)
+ return;
+
+ /* Workaround to remove gtknotebook's feature of computing its size based on
+ * all pages. When the widget is hidden, its size will not be taken into
+ * account.
+ * FIXME!
+ */
+// if (old_active_screen)
+// gtk_widget_hide (GTK_WIDGET (terminal_screen_container_get_from_screen (old_active_screen)));
+ /* Make sure that the widget is no longer hidden due to the workaround */
+// if (child)
+// gtk_widget_show (child);
+ if (old_active_screen)
+ gtk_widget_hide (GTK_WIDGET (old_active_screen));
+ if (screen)
+ gtk_widget_show (GTK_WIDGET (screen));
+
+ priv->active_screen = screen;
+
+ g_signal_emit_by_name (notebook, "screen-switched", old_active_screen, screen);
+ g_object_notify (G_OBJECT (notebook), "active-screen");
+}
+
+static void
+terminal_notebook_page_added (GtkNotebook *gtk_notebook,
+ GtkWidget *child,
+ guint page_num)
+{
+ TerminalNotebook *notebook = TERMINAL_NOTEBOOK (gtk_notebook);
+ void (* page_added) (GtkNotebook *, GtkWidget *, guint) =
+ GTK_NOTEBOOK_CLASS (terminal_notebook_parent_class)->page_added;
+
+ if (page_added)
+ page_added (gtk_notebook, child, page_num);
+
+ update_tab_visibility (notebook, 0);
+ g_signal_emit_by_name (gtk_notebook, "screen-added",
+ terminal_screen_container_get_screen (TERMINAL_SCREEN_CONTAINER (child)));
+}
+
+static void
+terminal_notebook_page_removed (GtkNotebook *gtk_notebook,
+ GtkWidget *child,
+ guint page_num)
+{
+ TerminalNotebook *notebook = TERMINAL_NOTEBOOK (gtk_notebook);
+ void (* page_removed) (GtkNotebook *, GtkWidget *, guint) =
+ GTK_NOTEBOOK_CLASS (terminal_notebook_parent_class)->page_removed;
+
+ if (page_removed)
+ page_removed (gtk_notebook, child, page_num);
+
+ update_tab_visibility (notebook, 0);
+ g_signal_emit_by_name (gtk_notebook, "screen-removed",
+ terminal_screen_container_get_screen (TERMINAL_SCREEN_CONTAINER (child)));
+}
+
+static void
+terminal_notebook_page_reordered (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num)
+{
+ void (* page_reordered) (GtkNotebook *, GtkWidget *, guint) =
+ GTK_NOTEBOOK_CLASS (terminal_notebook_parent_class)->page_reordered;
+
+ if (page_reordered)
+ page_reordered (notebook, child, page_num);
+
+ g_signal_emit_by_name (notebook, "screens-reordered");
+}
+
+static GtkNotebook *
+terminal_notebook_create_window (GtkNotebook *notebook,
+ GtkWidget *page,
+ gint x,
+ gint y)
+{
+ return GTK_NOTEBOOK_CLASS (terminal_notebook_parent_class)->create_window (notebook, page, x, y);
+}
+
+/* GtkWidgetClass impl */
+
+static void
+terminal_notebook_grab_focus (GtkWidget *widget)
+{
+ TerminalScreen *screen;
+
+ screen = terminal_mdi_container_get_active_screen (TERMINAL_MDI_CONTAINER (widget));
+ gtk_widget_grab_focus (GTK_WIDGET (screen));
+}
+
+/* GObjectClass impl */
+
+static void
+terminal_notebook_init (TerminalNotebook *notebook)
+{
+ TerminalNotebookPrivate *priv;
+
+ priv = notebook->priv = TERMINAL_NOTEBOOK_GET_PRIVATE (notebook);
+
+ priv->active_screen = NULL;
+ priv->policy = GTK_POLICY_AUTOMATIC;
+}
+
+static void
+terminal_notebook_constructed (GObject *object)
+{
+ GSettings *settings;
+ GtkWidget *widget = GTK_WIDGET (object);
+ GtkNotebook *notebook = GTK_NOTEBOOK (object);
+
+ G_OBJECT_CLASS (terminal_notebook_parent_class)->constructed (object);
+
+ settings = terminal_app_get_global_settings (terminal_app_get ());
+
+ update_tab_visibility (TERMINAL_NOTEBOOK (notebook), 0);
+ g_settings_bind (settings,
+ TERMINAL_SETTING_TAB_POLICY_KEY,
+ object,
+ "tab-policy",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
+
+ g_settings_bind (settings,
+ TERMINAL_SETTING_TAB_POSITION_KEY,
+ object,
+ "tab-pos",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
+
+ gtk_notebook_set_scrollable (notebook, TRUE);
+ gtk_notebook_set_show_border (notebook, FALSE);
+ gtk_notebook_set_group_name (notebook, I_("gnome-terminal-window"));
+
+ /* Necessary for scroll events */
+ gtk_widget_add_events (widget, GDK_SCROLL_MASK);
+}
+
+static void
+terminal_notebook_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalMdiContainer *mdi_container = TERMINAL_MDI_CONTAINER (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE_SCREEN:
+ g_value_set_object (value, terminal_notebook_get_active_screen (mdi_container));
+ break;
+ case PROP_TAB_POLICY:
+ g_value_set_enum (value, terminal_notebook_get_tab_policy (TERMINAL_NOTEBOOK (mdi_container)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_notebook_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalMdiContainer *mdi_container = TERMINAL_MDI_CONTAINER (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE_SCREEN:
+ terminal_notebook_set_active_screen (mdi_container, g_value_get_object (value));
+ break;
+ case PROP_TAB_POLICY:
+ terminal_notebook_set_tab_policy (TERMINAL_NOTEBOOK (mdi_container), g_value_get_enum (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_notebook_class_init (TerminalNotebookClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkNotebookClass *notebook_class = GTK_NOTEBOOK_CLASS (klass);
+
+ g_type_class_add_private (gobject_class, sizeof (TerminalNotebookPrivate));
+
+ gobject_class->constructed = terminal_notebook_constructed;
+ gobject_class->get_property = terminal_notebook_get_property;
+ gobject_class->set_property = terminal_notebook_set_property;
+
+ g_object_class_override_property (gobject_class, PROP_ACTIVE_SCREEN, "active-screen");
+
+ widget_class->grab_focus = terminal_notebook_grab_focus;
+
+ notebook_class->switch_page = terminal_notebook_switch_page;
+ notebook_class->create_window = terminal_notebook_create_window;
+ notebook_class->page_added = terminal_notebook_page_added;
+ notebook_class->page_removed = terminal_notebook_page_removed;
+ notebook_class->page_reordered = terminal_notebook_page_reordered;
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_TAB_POLICY,
+ g_param_spec_enum ("tab-policy", NULL, NULL,
+ GTK_TYPE_POLICY_TYPE,
+ GTK_POLICY_AUTOMATIC,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /* Remove unwanted and interfering keybindings */
+ GtkBindingSet *binding_set = gtk_binding_set_by_class (terminal_notebook_parent_class);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK);
+ remove_reorder_bindings (binding_set, GDK_KEY_Up);
+ remove_reorder_bindings (binding_set, GDK_KEY_Down);
+ remove_reorder_bindings (binding_set, GDK_KEY_Left);
+ remove_reorder_bindings (binding_set, GDK_KEY_Right);
+ remove_reorder_bindings (binding_set, GDK_KEY_Home);
+ remove_reorder_bindings (binding_set, GDK_KEY_Home);
+ remove_reorder_bindings (binding_set, GDK_KEY_End);
+ remove_reorder_bindings (binding_set, GDK_KEY_End);
+}
+
+/* public API */
+
+/**
+ * terminal_notebook_new:
+ *
+ * Returns: (transfer full): a new #TerminalNotebook
+ */
+GtkWidget *
+terminal_notebook_new (void)
+{
+ return g_object_new (TERMINAL_TYPE_NOTEBOOK, NULL);
+}
+
+void
+terminal_notebook_set_tab_policy (TerminalNotebook *notebook,
+ GtkPolicyType policy)
+{
+ TerminalNotebookPrivate *priv = notebook->priv;
+
+ if (priv->policy == policy)
+ return;
+
+ priv->policy = policy;
+ update_tab_visibility (notebook, 0);
+
+ g_object_notify (G_OBJECT (notebook), "tab-policy");
+}
+
+GtkPolicyType
+terminal_notebook_get_tab_policy (TerminalNotebook *notebook)
+{
+ return notebook->priv->policy;
+}
+
+GtkWidget *
+terminal_notebook_get_action_box (TerminalNotebook *notebook,
+ GtkPackType pack_type)
+{
+ GtkNotebook *gtk_notebook;
+ GtkWidget *box, *inner_box;
+
+ g_return_val_if_fail (TERMINAL_IS_NOTEBOOK (notebook), NULL);
+
+ gtk_notebook = GTK_NOTEBOOK (notebook);
+ box = gtk_notebook_get_action_widget (gtk_notebook, pack_type);
+ if (box != NULL) {
+ gs_free_list GList *list;
+
+ list = gtk_container_get_children (GTK_CONTAINER (box));
+ g_assert (list->data != NULL);
+ return list->data;
+ }
+
+ /* Create container for the buttons */
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (box), ACTION_AREA_BORDER_WIDTH);
+
+ inner_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, ACTION_BUTTON_SPACING);
+ gtk_box_pack_start (GTK_BOX (box), inner_box, TRUE, FALSE, 0);
+ gtk_widget_show (inner_box);
+
+ gtk_notebook_set_action_widget (gtk_notebook, box, pack_type);
+ gtk_widget_show (box);
+
+ /* FIXME: this appears to be necessary to make the icon buttons contained
+ * in the action area render the same way as buttons in the tab labels (e.g.
+ * the close button). gtk+ bug?
+ */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ gtk_style_context_add_region (gtk_widget_get_style_context (box),
+ GTK_STYLE_REGION_TAB,
+ pack_type == GTK_PACK_START ? GTK_REGION_FIRST : GTK_REGION_LAST);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ return inner_box;
+}
diff --git a/src/terminal-notebook.h b/src/terminal-notebook.h
new file mode 100644
index 0000000..68cd51f
--- /dev/null
+++ b/src/terminal-notebook.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2008, 2010, 2012 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_NOTEBOOK_H
+#define TERMINAL_NOTEBOOK_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_NOTEBOOK (terminal_notebook_get_type ())
+#define TERMINAL_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_NOTEBOOK, TerminalNotebook))
+#define TERMINAL_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_NOTEBOOK, TerminalNotebookClass))
+#define TERMINAL_IS_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_NOTEBOOK))
+#define TERMINAL_IS_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_NOTEBOOK))
+#define TERMINAL_NOTEBOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_NOTEBOOK, TerminalNotebookClass))
+
+typedef struct _TerminalNotebook TerminalNotebook;
+typedef struct _TerminalNotebookClass TerminalNotebookClass;
+typedef struct _TerminalNotebookPrivate TerminalNotebookPrivate;
+
+struct _TerminalNotebook
+{
+ GtkNotebook parent_instance;
+
+ /*< private >*/
+ TerminalNotebookPrivate *priv;
+};
+
+struct _TerminalNotebookClass
+{
+ GtkNotebookClass parent_class;
+};
+
+GType terminal_notebook_get_type (void);
+
+GtkWidget *terminal_notebook_new (void);
+
+void terminal_notebook_set_tab_policy (TerminalNotebook *notebook,
+ GtkPolicyType policy);
+GtkPolicyType terminal_notebook_get_tab_policy (TerminalNotebook *notebook);
+
+GtkWidget *terminal_notebook_get_action_box (TerminalNotebook *notebook,
+ GtkPackType pack_type);
+
+G_END_DECLS
+
+#endif /* TERMINAL_NOTEBOOK_H */
diff --git a/src/terminal-options.c b/src/terminal-options.c
new file mode 100644
index 0000000..afe4545
--- /dev/null
+++ b/src/terminal-options.c
@@ -0,0 +1,1696 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2008, 2017 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+
+#include "terminal-options.h"
+#include "terminal-client-utils.h"
+#include "terminal-defines.h"
+#include "terminal-schemas.h"
+#include "terminal-screen.h"
+#include "terminal-app.h"
+#include "terminal-util.h"
+#include "terminal-version.h"
+#include "terminal-libgsystem.h"
+
+static int verbosity = 1;
+
+void
+terminal_fprintf (FILE* fp,
+ int verbosity_level,
+ const char* format,
+ ...)
+{
+ if (verbosity < verbosity_level)
+ return;
+
+ va_list args;
+ va_start(args, format);
+ gs_free char *str = g_strdup_vprintf(format, args);
+ va_end(args);
+
+ gs_strfreev char **lines = g_strsplit_set(str, "\n\r", -1);
+ for (gsize i = 0; lines[i]; ++i) {
+ if (lines[i][0] != '\0')
+ g_fprintf(fp, "# %s\n", lines[i]);
+ }
+}
+
+static TerminalVerbosity
+verbosity_from_log_level (GLogLevelFlags log_level)
+{
+ guint level = log_level & G_LOG_LEVEL_MASK;
+ TerminalVerbosity res;
+ level = level & ~(level - 1); /* extract the highest bit */
+ switch (level) {
+ case G_LOG_LEVEL_DEBUG:
+ res = TERMINAL_VERBOSITY_DEBUG;
+ break;
+ case G_LOG_LEVEL_INFO:
+ res = TERMINAL_VERBOSITY_DETAIL;
+ break;
+ default:
+ /* better display than lose important messages */
+ res = TERMINAL_VERBOSITY_NORMAL;
+ }
+ return res;
+}
+
+/* Need to install a special log writer so we never output
+ * anything without the '# ' prepended, in case --print-environment
+ * is used.
+ *
+ * FIXME: Until issue glib#2087 is fixed, apply a simple log level filter
+ * to prevent spamming dconf (and other) debug messages to stderr,
+ * see issue gnome-terminal#42.
+ */
+GLogWriterOutput
+terminal_log_writer (GLogLevelFlags log_level,
+ const GLogField *fields,
+ gsize n_fields,
+ gpointer user_data)
+{
+ TerminalVerbosity level = verbosity_from_log_level(log_level);
+ for (gsize i = 0; i < n_fields; i++) {
+ if (g_str_equal (fields[i].key, "MESSAGE"))
+ terminal_fprintf (stderr, level, "%s\n", (const char*)fields[i].value);
+ }
+
+ return G_LOG_WRITER_HANDLED;
+}
+
+static GOptionContext *get_goption_context (TerminalOptions *options);
+
+static TerminalSettingsList *
+terminal_options_ensure_profiles_list (TerminalOptions *options)
+{
+ if (options->profiles_list == NULL)
+ options->profiles_list = terminal_profiles_list_new ();
+
+ return options->profiles_list;
+}
+
+static char *
+terminal_util_key_file_get_string_unescape (GKeyFile *key_file,
+ const char *group,
+ const char *key,
+ GError **error)
+{
+ char *escaped, *unescaped;
+
+ escaped = g_key_file_get_string (key_file, group, key, error);
+ if (!escaped)
+ return NULL;
+
+ unescaped = g_strcompress (escaped);
+ g_free (escaped);
+
+ return unescaped;
+}
+
+static char **
+terminal_util_key_file_get_argv (GKeyFile *key_file,
+ const char *group,
+ const char *key,
+ int *argc,
+ GError **error)
+{
+ char **argv;
+ char *flat;
+ gboolean retval;
+
+ flat = terminal_util_key_file_get_string_unescape (key_file, group, key, error);
+ if (!flat)
+ return NULL;
+
+ retval = g_shell_parse_argv (flat, argc, &argv, error);
+ g_free (flat);
+
+ if (retval)
+ return argv;
+
+ return NULL;
+}
+
+static InitialTab*
+initial_tab_new (char *profile /* adopts */)
+{
+ InitialTab *it;
+
+ it = g_slice_new (InitialTab);
+
+ it->profile = profile;
+ it->exec_argv = NULL;
+ it->title = NULL;
+ it->working_dir = NULL;
+ it->zoom = 1.0;
+ it->zoom_set = FALSE;
+ it->active = FALSE;
+ it->fd_list = NULL;
+ it->fd_array = NULL;
+
+ return it;
+}
+
+static void
+initial_tab_free (InitialTab *it)
+{
+ g_free (it->profile);
+ g_strfreev (it->exec_argv);
+ g_free (it->title);
+ g_free (it->working_dir);
+ g_clear_object (&it->fd_list);
+ if (it->fd_array)
+ g_array_unref (it->fd_array);
+ g_slice_free (InitialTab, it);
+}
+
+static InitialWindow*
+initial_window_new (guint source_tag)
+{
+ InitialWindow *iw;
+
+ iw = g_slice_new0 (InitialWindow);
+ iw->source_tag = source_tag;
+
+ return iw;
+}
+
+static void
+initial_window_free (InitialWindow *iw)
+{
+ g_list_free_full (iw->tabs, (GDestroyNotify) initial_tab_free);
+ g_free (iw->geometry);
+ g_free (iw->role);
+ g_slice_free (InitialWindow, iw);
+}
+
+static void
+apply_window_defaults (TerminalOptions *options,
+ InitialWindow *iw)
+{
+ if (options->default_role)
+ {
+ iw->role = options->default_role;
+ options->default_role = NULL;
+ }
+
+ if (iw->geometry == NULL)
+ iw->geometry = g_strdup (options->default_geometry);
+
+ if (options->default_window_menubar_forced)
+ {
+ iw->force_menubar_state = TRUE;
+ iw->menubar_state = options->default_window_menubar_state;
+
+ options->default_window_menubar_forced = FALSE;
+ }
+
+ iw->start_fullscreen |= options->default_fullscreen;
+ iw->start_maximized |= options->default_maximize;
+}
+
+static void
+apply_tab_defaults (TerminalOptions *options,
+ InitialTab *it)
+{
+ it->wait = options->default_wait;
+}
+
+static InitialWindow*
+add_new_window (TerminalOptions *options,
+ char *profile /* adopts */,
+ gboolean implicit_if_first_window)
+{
+ InitialWindow *iw;
+ InitialTab *it;
+
+ iw = initial_window_new (0);
+ iw->implicit_first_window = (options->initial_windows == NULL) && implicit_if_first_window;
+ apply_window_defaults (options, iw);
+
+ it = initial_tab_new (profile);
+
+ /* If this is an implicit first window, the new tab should be active */
+ if (iw->implicit_first_window)
+ it->active = TRUE;
+
+ iw->tabs = g_list_prepend (NULL, it);
+ apply_tab_defaults (options, it);
+
+ options->initial_windows = g_list_append (options->initial_windows, iw);
+ return iw;
+}
+
+static InitialWindow*
+ensure_top_window (TerminalOptions *options,
+ gboolean implicit_if_first_window)
+{
+ InitialWindow *iw;
+
+ if (options->initial_windows == NULL)
+ iw = add_new_window (options, NULL /* profile */, implicit_if_first_window);
+ else
+ iw = g_list_last (options->initial_windows)->data;
+
+ g_assert_nonnull (iw->tabs);
+
+ return iw;
+}
+
+static InitialTab*
+ensure_top_tab (TerminalOptions *options)
+{
+ InitialWindow *iw;
+ InitialTab *it;
+
+ iw = ensure_top_window (options, TRUE);
+
+ g_assert_nonnull (iw->tabs);
+
+ it = g_list_last (iw->tabs)->data;
+
+ return it;
+}
+
+/* handle deprecated command line options */
+
+static void
+deprecated_option_warning (const gchar *option_name)
+{
+ terminal_printerr (_("Option “%s” is deprecated and might be removed in a later version of gnome-terminal."),
+ option_name);
+ terminal_printerr ("\n");
+}
+
+static void
+deprecated_command_option_warning (const char *option_name)
+{
+ deprecated_option_warning (option_name);
+
+ /* %s is being replaced with "-- " (without quotes), which must be used literally, not translatable */
+ terminal_printerr (_("Use “%s” to terminate the options and put the command line to execute after it."), "-- ");
+ terminal_printerr ("\n");
+}
+
+static gboolean
+unsupported_option_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ terminal_printerr (_("Option “%s” is no longer supported in this version of gnome-terminal."),
+ option_name);
+ terminal_printerr ("\n");
+ return TRUE; /* we do not want to bail out here but continue */
+}
+
+static gboolean
+unsupported_option_fatal_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
+ _("Option “%s” is no longer supported in this version of gnome-terminal."),
+ option_name);
+ return FALSE;
+}
+
+
+static gboolean G_GNUC_NORETURN
+option_version_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ terminal_print ("GNOME Terminal %s using VTE %u.%u.%u %s\n",
+ VERSION,
+ vte_get_major_version (),
+ vte_get_minor_version (),
+ vte_get_micro_version (),
+ vte_get_features ());
+ exit (EXIT_SUCCESS);
+}
+
+static gboolean
+option_verbosity_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ if (g_str_equal (option_name, "--quiet") || g_str_equal (option_name, "-q"))
+ verbosity = 0;
+ else
+ verbosity++;
+
+ return TRUE;
+}
+
+static gboolean
+option_app_id_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ if (!g_application_id_is_valid (value)) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "\"%s\" is not a valid application ID", value);
+ return FALSE;
+ }
+
+ g_free (options->server_app_id);
+ options->server_app_id = g_strdup (value);
+
+ return TRUE;
+}
+
+static gboolean
+option_command_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ GError *err = NULL;
+ char **exec_argv;
+
+ deprecated_command_option_warning (option_name);
+
+ if (!g_shell_parse_argv (value, NULL, &exec_argv, &err))
+ {
+ g_set_error(error,
+ G_OPTION_ERROR,
+ G_OPTION_ERROR_BAD_VALUE,
+ _("Argument to “%s” is not a valid command: %s"),
+ "--command/-e",
+ err->message);
+ g_error_free (err);
+ return FALSE;
+ }
+
+ if (options->initial_windows)
+ {
+ InitialTab *it = ensure_top_tab (options);
+
+ g_strfreev (it->exec_argv);
+ it->exec_argv = exec_argv;
+ }
+ else
+ {
+ g_strfreev (options->exec_argv);
+ options->exec_argv = exec_argv;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_profile_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ char *profile;
+
+ profile = terminal_profiles_list_dup_uuid_or_name (terminal_options_ensure_profiles_list (options),
+ value, error);
+ if (profile == NULL)
+ {
+ terminal_printerr ("Profile '%s' specified but not found. Attempting to fall back "
+ "to the default profile.\n", value);
+ g_clear_error (error);
+ profile = terminal_profiles_list_dup_uuid_or_name (terminal_options_ensure_profiles_list (options),
+ NULL, error);
+ }
+
+ if (profile == NULL)
+ return FALSE;
+
+ if (options->initial_windows)
+ {
+ InitialTab *it = ensure_top_tab (options);
+
+ g_free (it->profile);
+ it->profile = profile;
+ }
+ else
+ {
+ g_free (options->default_profile);
+ options->default_profile = profile;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_profile_id_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ char *profile;
+
+ profile = terminal_profiles_list_dup_uuid (terminal_options_ensure_profiles_list (options),
+ value, error);
+ if (profile == NULL)
+ return FALSE;
+
+ if (options->initial_windows)
+ {
+ InitialTab *it = ensure_top_tab (options);
+
+ g_free (it->profile);
+ it->profile = profile;
+ }
+ else
+ {
+ g_free (options->default_profile);
+ options->default_profile = profile;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+option_window_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ char *profile;
+
+ if (value != NULL) {
+ profile = terminal_profiles_list_dup_uuid_or_name (terminal_options_ensure_profiles_list (options),
+ value, error);
+
+ if (value && profile == NULL) {
+ terminal_printerr ("Profile '%s' specified but not found. Attempting to fall back "
+ "to the default profile.\n", value);
+ g_clear_error (error);
+ profile = terminal_profiles_list_dup_uuid_or_name (terminal_options_ensure_profiles_list (options),
+ NULL, error);
+ }
+
+ if (profile == NULL)
+ return FALSE;
+ } else
+ profile = NULL;
+
+ add_new_window (options, profile /* adopts */, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+option_tab_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ char *profile;
+
+ if (value != NULL) {
+ profile = terminal_profiles_list_dup_uuid_or_name (terminal_options_ensure_profiles_list (options),
+ value, error);
+ if (profile == NULL)
+ return FALSE;
+ } else
+ profile = NULL;
+
+ if (options->initial_windows)
+ {
+ InitialWindow *iw;
+
+ iw = g_list_last (options->initial_windows)->data;
+ iw->tabs = g_list_append (iw->tabs, initial_tab_new (profile /* adopts */));
+ }
+ else
+ add_new_window (options, profile /* adopts */, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+option_role_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ InitialWindow *iw;
+
+ if (options->initial_windows)
+ {
+ iw = g_list_last (options->initial_windows)->data;
+ iw->role = g_strdup (value);
+ }
+ else if (!options->default_role)
+ options->default_role = g_strdup (value);
+ else
+ {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
+ "%s", _("Two roles given for one window"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_show_menubar_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ InitialWindow *iw;
+
+ if (options->initial_windows)
+ {
+ iw = g_list_last (options->initial_windows)->data;
+ if (iw->force_menubar_state && iw->menubar_state == TRUE)
+ {
+ terminal_printerr_detail (_("“%s” option given twice for the same window\n"),
+ "--show-menubar");
+
+ return TRUE;
+ }
+
+ iw->force_menubar_state = TRUE;
+ iw->menubar_state = TRUE;
+ }
+ else
+ {
+ options->default_window_menubar_forced = TRUE;
+ options->default_window_menubar_state = TRUE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_hide_menubar_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ InitialWindow *iw;
+
+ if (options->initial_windows)
+ {
+ iw = g_list_last (options->initial_windows)->data;
+
+ if (iw->force_menubar_state && iw->menubar_state == FALSE)
+ {
+ terminal_printerr_detail (_("“%s” option given twice for the same window\n"),
+ "--hide-menubar");
+ return TRUE;
+ }
+
+ iw->force_menubar_state = TRUE;
+ iw->menubar_state = FALSE;
+ }
+ else
+ {
+ options->default_window_menubar_forced = TRUE;
+ options->default_window_menubar_state = FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_maximize_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ InitialWindow *iw;
+
+ if (options->initial_windows)
+ {
+ iw = g_list_last (options->initial_windows)->data;
+ iw->start_maximized = TRUE;
+ }
+ else
+ options->default_maximize = TRUE;
+
+ return TRUE;
+}
+
+static gboolean
+option_fullscreen_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ if (options->initial_windows)
+ {
+ InitialWindow *iw;
+
+ iw = g_list_last (options->initial_windows)->data;
+ iw->start_fullscreen = TRUE;
+ }
+ else
+ options->default_fullscreen = TRUE;
+
+ return TRUE;
+}
+
+static gboolean
+option_geometry_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ if (options->initial_windows)
+ {
+ InitialWindow *iw;
+
+ iw = g_list_last (options->initial_windows)->data;
+ iw->geometry = g_strdup (value);
+ }
+ else
+ options->default_geometry = g_strdup (value);
+
+ return TRUE;
+}
+
+static gboolean
+option_load_config_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ GFile *file;
+ char *config_file;
+ GKeyFile *key_file;
+ gboolean result;
+
+ file = g_file_new_for_commandline_arg (value);
+ config_file = g_file_get_path (file);
+ g_object_unref (file);
+
+ key_file = g_key_file_new ();
+ result = g_key_file_load_from_file (key_file, config_file, 0, error) &&
+ terminal_options_merge_config (options, key_file,
+ strcmp (option_name, "load-config") == 0 ? SOURCE_DEFAULT : SOURCE_SESSION,
+ error);
+ g_key_file_free (key_file);
+ g_free (config_file);
+
+ return result;
+}
+
+static gboolean
+option_title_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ if (options->initial_windows)
+ {
+ InitialTab *it = ensure_top_tab (options);
+
+ g_free (it->title);
+ it->title = g_strdup (value);
+ }
+ else
+ {
+ g_free (options->default_title);
+ options->default_title = g_strdup (value);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_working_directory_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ if (options->initial_windows)
+ {
+ InitialTab *it = ensure_top_tab (options);
+
+ g_free (it->working_dir);
+ it->working_dir = g_strdup (value);
+ }
+ else
+ {
+ g_free (options->default_working_dir);
+ options->default_working_dir = g_strdup (value);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_wait_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ if (options->initial_windows)
+ {
+ InitialTab *it = ensure_top_tab (options);
+
+ g_free (it->working_dir);
+ it->wait = TRUE;
+ }
+ else
+ {
+ options->default_wait = TRUE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+option_pass_fd_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ errno = 0;
+ char *end;
+ gint64 v = g_ascii_strtoll (value, &end, 10);
+ if (errno || end == value || v == -1 || v < G_MININT || v > G_MAXINT) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Failed to parse \"%s\" as file descriptor number",
+ value);
+ return FALSE;
+ }
+
+ int fd = v;
+ if (fd == STDIN_FILENO ||
+ fd == STDOUT_FILENO ||
+ fd == STDERR_FILENO) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "FD passing of %s is not supported",
+ fd == STDIN_FILENO ? "stdin" : fd == STDOUT_FILENO ? "stdout" : "stderr");
+ return FALSE;
+ }
+
+ InitialTab *it = ensure_top_tab (options);
+ if (it->fd_list == NULL)
+ it->fd_list = g_unix_fd_list_new ();
+ if (it->fd_array == NULL)
+ it->fd_array = g_array_sized_new (FALSE /* zero terminate */,
+ TRUE /* clear */,
+ sizeof (PassFdElement),
+ 8 /* that should be plenty */);
+
+
+ for (guint i = 0; i < it->fd_array->len; i++) {
+ PassFdElement *e = &g_array_index (it->fd_array, PassFdElement, i);
+ if (e->fd == fd) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ _("Cannot pass FD %d twice"), fd);
+ return FALSE;
+ }
+ }
+
+ int idx = g_unix_fd_list_append (it->fd_list, fd, error);
+ if (idx == -1) {
+ g_prefix_error (error, "%d: ", fd);
+ return FALSE;
+ }
+
+ PassFdElement e = { idx, fd };
+ g_array_append_val (it->fd_array, e);
+
+#if 0
+ if (fd == STDOUT_FILENO ||
+ fd == STDERR_FILENO)
+ verbosity = 0;
+ if (fd == STDIN_FILENO)
+ it->wait = TRUE;
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+option_active_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ InitialTab *it;
+
+ it = ensure_top_tab (options);
+ it->active = TRUE;
+
+ return TRUE;
+}
+
+static gboolean
+option_zoom_callback (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ double zoom;
+ char *end;
+
+ /* Try reading a locale-style double first, in case it was
+ * typed by a person, then fall back to ascii_strtod (we
+ * always save session in C locale format)
+ */
+ end = NULL;
+ errno = 0;
+ zoom = g_strtod (value, &end);
+ if (end == NULL || *end != '\0')
+ {
+ g_set_error (error,
+ G_OPTION_ERROR,
+ G_OPTION_ERROR_BAD_VALUE,
+ _("“%s” is not a valid zoom factor"),
+ value);
+ return FALSE;
+ }
+
+ if (zoom < (TERMINAL_SCALE_MINIMUM + 1e-6))
+ {
+ terminal_printerr (_("Zoom factor “%g” is too small, using %g\n"),
+ zoom,
+ TERMINAL_SCALE_MINIMUM);
+ zoom = TERMINAL_SCALE_MINIMUM;
+ }
+
+ if (zoom > (TERMINAL_SCALE_MAXIMUM - 1e-6))
+ {
+ terminal_printerr (_("Zoom factor “%g” is too large, using %g\n"),
+ zoom,
+ TERMINAL_SCALE_MAXIMUM);
+ zoom = TERMINAL_SCALE_MAXIMUM;
+ }
+
+ if (options->initial_windows)
+ {
+ InitialTab *it = ensure_top_tab (options);
+ it->zoom = zoom;
+ it->zoom_set = TRUE;
+ }
+ else
+ {
+ options->zoom = zoom;
+ options->zoom_set = TRUE;
+ }
+
+ return TRUE;
+}
+
+/* Evaluation of the arguments given to the command line options */
+static gboolean
+digest_options_callback (GOptionContext *context,
+ GOptionGroup *group,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+ InitialTab *it;
+
+ if (options->execute)
+ {
+ if (options->exec_argv == NULL)
+ {
+ g_set_error (error,
+ G_OPTION_ERROR,
+ G_OPTION_ERROR_BAD_VALUE,
+ _("Option “%s” requires specifying the command to run"
+ " on the rest of the command line"),
+ "--execute/-x");
+ return FALSE;
+ }
+
+ /* Apply -x/--execute command only to the first tab */
+ it = ensure_top_tab (options);
+ it->exec_argv = options->exec_argv;
+ options->exec_argv = NULL;
+ }
+
+ return TRUE;
+}
+
+/**
+ * terminal_options_parse:
+ * @argcp: (inout) address of the argument count. Changed if any arguments were handled
+ * @argvp: (inout) address of the argument vector. Any parameters understood by
+ * the terminal #GOptionContext are removed
+ * @error: a #GError to fill in
+ *
+ * Parses the argument vector *@argvp.
+ *
+ * Returns: a new #TerminalOptions containing the windows and tabs to open,
+ * or %NULL on error.
+ */
+TerminalOptions *
+terminal_options_parse (int *argcp,
+ char ***argvp,
+ GError **error)
+{
+ TerminalOptions *options;
+ GOptionContext *context;
+ gboolean retval;
+ int i;
+ char **argv = *argvp;
+
+ options = g_new0 (TerminalOptions, 1);
+
+ options->print_environment = FALSE;
+ options->default_window_menubar_forced = FALSE;
+ options->default_window_menubar_state = TRUE;
+ options->default_fullscreen = FALSE;
+ options->default_maximize = FALSE;
+ options->execute = FALSE;
+
+ const char *startup_id = g_getenv ("DESKTOP_STARTUP_ID");
+ if (startup_id && startup_id[0] &&
+ g_utf8_validate (startup_id, -1, NULL))
+ options->startup_id = g_strdup (startup_id);
+ else
+ options->startup_id = NULL;
+ options->display_name = NULL;
+ options->initial_windows = NULL;
+ options->default_role = NULL;
+ options->default_geometry = NULL;
+ options->default_title = NULL;
+ options->zoom = 1.0;
+ options->zoom_set = FALSE;
+
+ options->default_working_dir = g_get_current_dir ();
+
+ /* Collect info from gnome-terminal private env vars */
+ const char *server_unique_name = g_getenv (TERMINAL_ENV_SERVICE_NAME);
+ if (server_unique_name != NULL) {
+ if (g_dbus_is_unique_name (server_unique_name))
+ options->server_unique_name = g_strdup (server_unique_name);
+ else
+ terminal_printerr ("Warning: %s set but \"%s\" is not a unique D-Bus name.\n",
+ TERMINAL_ENV_SERVICE_NAME,
+ server_unique_name);
+ }
+
+ const char *parent_screen_object_path = g_getenv (TERMINAL_ENV_SCREEN);
+ if (parent_screen_object_path != NULL) {
+ if (g_variant_is_object_path (parent_screen_object_path))
+ options->parent_screen_object_path = g_strdup (parent_screen_object_path);
+ else
+ terminal_printerr ("Warning: %s set but \"%s\" is not a valid D-Bus object path.\n",
+ TERMINAL_ENV_SCREEN,
+ parent_screen_object_path);
+ }
+
+ /* The old -x/--execute option is broken, so we need to pre-scan for it. */
+ /* We now also support passing the command after the -- switch. */
+ options->exec_argv = NULL;
+ for (i = 1 ; i < *argcp; ++i)
+ {
+ gboolean is_execute;
+ gboolean is_dashdash;
+ int j, last;
+
+ is_execute = strcmp (argv[i], "-x") == 0 || strcmp (argv[i], "--execute") == 0;
+ is_dashdash = strcmp (argv[i], "--") == 0;
+
+ if (!is_execute && !is_dashdash)
+ continue;
+
+ if (is_execute)
+ deprecated_command_option_warning (argv[i]);
+
+ options->execute = is_execute;
+
+ /* Skip the switch */
+ last = i;
+ ++i;
+ if (i == *argcp)
+ break; /* we'll complain about this later for -x/--execute; it's fine for -- */
+
+ /* Collect the args, and remove them from argv */
+ options->exec_argv = g_new0 (char*, *argcp - i + 1);
+ for (j = 0; i < *argcp; ++i, ++j)
+ options->exec_argv[j] = g_strdup (argv[i]);
+ options->exec_argv[j] = NULL;
+
+ *argcp = last;
+ break;
+ }
+
+ context = get_goption_context (options);
+ retval = g_option_context_parse (context, argcp, argvp, error);
+ g_option_context_free (context);
+
+ if (!retval) {
+ terminal_options_free (options);
+ return NULL;
+ }
+
+ /* Do this here so that gdk_display is initialized */
+ if (options->startup_id == NULL)
+ options->startup_id = terminal_client_get_fallback_startup_id ();
+ /* Still NULL? */
+ if (options->startup_id == NULL)
+ terminal_printerr_detail ("Warning: DESKTOP_STARTUP_ID not set and no fallback available.\n");
+
+ GdkDisplay *display = gdk_display_get_default ();
+ if (display != NULL)
+ options->display_name = g_strdup (gdk_display_get_name (display));
+
+ /* Sanity check */
+ guint wait = 0;
+ for (GList *lw = options->initial_windows; lw != NULL; lw = lw->next) {
+ InitialWindow *iw = lw->data;
+ for (GList *lt = iw->tabs; lt != NULL; lt = lt->next) {
+ InitialTab *it = lt->data;
+ if (it->wait)
+ wait++;
+ }
+ }
+
+ if (wait > 1) {
+ g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ _("Can only use --wait once"));
+ return FALSE;
+ }
+
+ options->wait = wait != 0;
+ return options;
+}
+
+/**
+ * terminal_options_merge_config:
+ * @options:
+ * @key_file: a #GKeyFile containing to merge the options from
+ * @source_tag: a source_tag to use in new #InitialWindow<!-- -->s
+ * @error: a #GError to fill in
+ *
+ * Merges the saved options from @key_file into @options.
+ *
+ * Returns: %TRUE if @key_file was a valid key file containing a stored
+ * terminal configuration, or %FALSE on error
+ */
+gboolean
+terminal_options_merge_config (TerminalOptions *options,
+ GKeyFile *key_file,
+ guint source_tag,
+ GError **error)
+{
+ int version, compat_version;
+ char **groups;
+ guint i;
+ gboolean have_error = FALSE;
+ GList *initial_windows = NULL;
+
+ if (!g_key_file_has_group (key_file, TERMINAL_CONFIG_GROUP))
+ {
+ g_set_error_literal (error, TERMINAL_OPTION_ERROR,
+ TERMINAL_OPTION_ERROR_INVALID_CONFIG_FILE,
+ _("Not a valid terminal config file."));
+ return FALSE;
+ }
+
+ version = g_key_file_get_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_VERSION, NULL);
+ compat_version = g_key_file_get_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_COMPAT_VERSION, NULL);
+
+ if (version <= 0 ||
+ compat_version <= 0 ||
+ compat_version > TERMINAL_CONFIG_COMPAT_VERSION)
+ {
+ g_set_error_literal (error, TERMINAL_OPTION_ERROR,
+ TERMINAL_OPTION_ERROR_INCOMPATIBLE_CONFIG_FILE,
+ _("Incompatible terminal config file version."));
+ return FALSE;
+ }
+
+ groups = g_key_file_get_string_list (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_WINDOWS, NULL, error);
+ if (!groups)
+ return FALSE;
+
+ for (i = 0; groups[i]; ++i)
+ {
+ const char *window_group = groups[i];
+ char *active_terminal;
+ char **tab_groups;
+ InitialWindow *iw;
+ guint j;
+
+ tab_groups = g_key_file_get_string_list (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_TABS, NULL, error);
+ if (!tab_groups)
+ continue; /* no tabs in this window, skip it */
+
+ iw = initial_window_new (source_tag);
+ initial_windows = g_list_append (initial_windows, iw);
+ apply_window_defaults (options, iw);
+
+ active_terminal = g_key_file_get_string (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_ACTIVE_TAB, NULL);
+ iw->role = g_key_file_get_string (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_ROLE, NULL);
+ iw->geometry = g_key_file_get_string (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_GEOMETRY, NULL);
+ iw->start_fullscreen = g_key_file_get_boolean (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_FULLSCREEN, NULL);
+ iw->start_maximized = g_key_file_get_boolean (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_MAXIMIZED, NULL);
+ if (g_key_file_has_key (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_MENUBAR_VISIBLE, NULL))
+ {
+ iw->force_menubar_state = TRUE;
+ iw->menubar_state = g_key_file_get_boolean (key_file, window_group, TERMINAL_CONFIG_WINDOW_PROP_MENUBAR_VISIBLE, NULL);
+ }
+
+ for (j = 0; tab_groups[j]; ++j)
+ {
+ const char *tab_group = tab_groups[j];
+ InitialTab *it;
+ char *profile;
+
+ profile = g_key_file_get_string (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_PROFILE_ID, NULL);
+ it = initial_tab_new (profile /* adopts */);
+
+ iw->tabs = g_list_append (iw->tabs, it);
+
+ if (g_strcmp0 (active_terminal, tab_group) == 0)
+ it->active = TRUE;
+
+/* it->width = g_key_file_get_integer (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_WIDTH, NULL);
+ it->height = g_key_file_get_integer (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_HEIGHT, NULL);*/
+ it->working_dir = terminal_util_key_file_get_string_unescape (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_WORKING_DIRECTORY, NULL);
+ it->title = g_key_file_get_string (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_TITLE, NULL);
+
+ if (g_key_file_has_key (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_COMMAND, NULL) &&
+ !(it->exec_argv = terminal_util_key_file_get_argv (key_file, tab_group, TERMINAL_CONFIG_TERMINAL_PROP_COMMAND, NULL, error)))
+ {
+ have_error = TRUE;
+ break;
+ }
+ }
+
+ g_free (active_terminal);
+ g_strfreev (tab_groups);
+
+ if (have_error)
+ break;
+ }
+
+ g_strfreev (groups);
+
+ if (have_error)
+ {
+ g_list_free_full (initial_windows, (GDestroyNotify) initial_window_free);
+ return FALSE;
+ }
+
+ options->initial_windows = g_list_concat (options->initial_windows, initial_windows);
+
+ return TRUE;
+}
+
+/**
+ * terminal_options_ensure_window:
+ * @options:
+ *
+ * Ensure that @options will contain at least one window to open.
+ */
+void
+terminal_options_ensure_window (TerminalOptions *options)
+{
+ gs_unref_object GSettings *global_settings =
+ g_settings_new (TERMINAL_SETTING_SCHEMA);
+
+ gs_free char *mode_str = g_settings_get_string (global_settings,
+ TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY);
+
+ gboolean implicit_if_first_window = g_str_equal (mode_str, "tab");
+ ensure_top_window (options, implicit_if_first_window);
+}
+
+/**
+ * terminal_options_free:
+ * @options:
+ *
+ * Frees @options.
+ */
+void
+terminal_options_free (TerminalOptions *options)
+{
+ g_list_free_full (options->initial_windows, (GDestroyNotify) initial_window_free);
+
+ g_free (options->default_role);
+ g_free (options->default_geometry);
+ g_free (options->default_working_dir);
+ g_free (options->default_title);
+ g_free (options->default_profile);
+
+ g_strfreev (options->exec_argv);
+
+ g_free (options->server_unique_name);
+ g_free (options->parent_screen_object_path);
+
+ g_free (options->display_name);
+ g_free (options->startup_id);
+ g_free (options->server_app_id);
+
+ g_free (options->sm_client_id);
+ g_free (options->sm_config_prefix);
+
+ g_clear_object (&options->profiles_list);
+
+ g_free (options);
+}
+
+static GOptionContext *
+get_goption_context (TerminalOptions *options)
+{
+ const GOptionEntry global_unique_goptions[] = {
+ {
+ "app-id",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ option_app_id_callback,
+ "Server application ID",
+ "ID"
+ },
+ {
+ "disable-factory",
+ 0,
+ G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ unsupported_option_fatal_callback,
+ N_("Do not register with the activation nameserver, do not re-use an active terminal"),
+ NULL
+ },
+ {
+ "load-config",
+ 0,
+ G_OPTION_FLAG_FILENAME,
+ G_OPTION_ARG_CALLBACK,
+ option_load_config_cb,
+ N_("Load a terminal configuration file"),
+ N_("FILE")
+ },
+ {
+ "save-config",
+ 0,
+ G_OPTION_FLAG_FILENAME | G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ unsupported_option_callback,
+ NULL, NULL
+ },
+ {
+ "no-environment",
+ 0,
+ 0,
+ G_OPTION_ARG_NONE,
+ &options->no_environment,
+ N_("Do not pass the environment"),
+ NULL
+ },
+ {
+ "preferences",
+ 0,
+ 0,
+ G_OPTION_ARG_NONE,
+ &options->show_preferences,
+ N_("Show preferences window"),
+ NULL
+ },
+ {
+ "print-environment",
+ 'p',
+ 0,
+ G_OPTION_ARG_NONE,
+ &options->print_environment,
+ N_("Print environment variables to interact with the terminal"),
+ NULL
+ },
+ {
+ "version",
+ 0,
+ G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ option_version_cb,
+ NULL,
+ NULL
+ },
+ {
+ "verbose",
+ 'v',
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_verbosity_cb,
+ N_("Increase diagnostic verbosity"),
+ NULL
+ },
+ {
+ "quiet",
+ 'q',
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_verbosity_cb,
+ N_("Suppress output"),
+ NULL
+ },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };
+
+ const GOptionEntry global_multiple_goptions[] = {
+ {
+ "window",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_window_callback,
+ N_("Open a new window containing a tab with the default profile"),
+ NULL
+ },
+ {
+ "tab",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_tab_callback,
+ N_("Open a new tab in the last-opened window with the default profile"),
+ NULL
+ },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };
+
+ const GOptionEntry window_goptions[] = {
+ {
+ "show-menubar",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_show_menubar_callback,
+ N_("Turn on the menubar"),
+ NULL
+ },
+ {
+ "hide-menubar",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_hide_menubar_callback,
+ N_("Turn off the menubar"),
+ NULL
+ },
+ {
+ "maximize",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_maximize_callback,
+ N_("Maximize the window"),
+ NULL
+ },
+ {
+ "full-screen",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_fullscreen_callback,
+ N_("Full-screen the window"),
+ NULL
+ },
+ {
+ "geometry",
+ 0,
+ 0,
+ G_OPTION_ARG_CALLBACK,
+ option_geometry_callback,
+ N_("Set the window size; for example: 80x24, or 80x24+200+200 (COLSxROWS+X+Y)"),
+ N_("GEOMETRY")
+ },
+ {
+ "role",
+ 0,
+ 0,
+ G_OPTION_ARG_CALLBACK,
+ option_role_callback,
+ N_("Set the window role"),
+ N_("ROLE")
+ },
+ {
+ "active",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_active_callback,
+ N_("Set the last specified tab as the active one in its window"),
+ NULL
+ },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };
+
+ const GOptionEntry terminal_goptions[] = {
+ {
+ "command",
+ 'e',
+ G_OPTION_FLAG_FILENAME,
+ G_OPTION_ARG_CALLBACK,
+ option_command_callback,
+ N_("Execute the argument to this option inside the terminal"),
+ NULL
+ },
+ {
+ "profile",
+ 0,
+ 0,
+ G_OPTION_ARG_CALLBACK,
+ option_profile_cb,
+ N_("Use the given profile instead of the default profile"),
+ N_("PROFILE-NAME")
+ },
+ {
+ "title",
+ 't',
+ 0,
+ G_OPTION_ARG_CALLBACK,
+ option_title_callback,
+ N_("Set the initial terminal title"),
+ N_("TITLE")
+ },
+ {
+ "working-directory",
+ 0,
+ G_OPTION_FLAG_FILENAME,
+ G_OPTION_ARG_CALLBACK,
+ option_working_directory_callback,
+ N_("Set the working directory"),
+ N_("DIRNAME")
+ },
+ {
+ "wait",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_wait_cb,
+ N_("Wait until the child exits"),
+ NULL
+ },
+ {
+ "fd",
+ 0,
+ 0,
+ G_OPTION_ARG_CALLBACK,
+ option_pass_fd_cb,
+ N_("Forward file descriptor"),
+ /* FD = file descriptor */
+ N_("FD")
+ },
+ {
+ "zoom",
+ 0,
+ 0,
+ G_OPTION_ARG_CALLBACK,
+ option_zoom_callback,
+ N_("Set the terminal’s zoom factor (1.0 = normal size)"),
+ N_("ZOOM")
+ },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };
+
+ const GOptionEntry internal_goptions[] = {
+ {
+ "profile-id",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ option_profile_id_cb,
+ NULL, NULL
+ },
+ {
+ "window-with-profile",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ option_window_callback,
+ NULL, NULL
+ },
+ {
+ "tab-with-profile",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ option_tab_callback,
+ NULL, NULL
+ },
+ {
+ "window-with-profile-internal-id",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ option_window_callback,
+ NULL, NULL
+ },
+ {
+ "tab-with-profile-internal-id",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ option_tab_callback,
+ NULL, NULL
+ },
+ {
+ "default-working-directory",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_FILENAME,
+ &options->default_working_dir,
+ NULL, NULL,
+ },
+ {
+ "use-factory",
+ 0,
+ G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK,
+ unsupported_option_callback,
+ NULL, NULL
+ },
+ {
+ "startup-id",
+ 0,
+ G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_STRING,
+ &options->startup_id,
+ NULL,
+ NULL
+ },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };
+
+ const GOptionEntry smclient_goptions[] = {
+ { "sm-client-disable", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &options->sm_client_disable, NULL, NULL },
+ { "sm-client-state-file", 0, G_OPTION_FLAG_HIDDEN | G_OPTION_FLAG_FILENAME, G_OPTION_ARG_CALLBACK, option_load_config_cb, NULL, NULL },
+ { "sm-client-id", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &options->sm_client_id, NULL, NULL },
+ { "sm-disable", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &options->sm_client_disable, NULL, NULL },
+ { "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &options->sm_config_prefix, NULL, NULL },
+ { NULL }
+ };
+
+ GOptionContext *context;
+ GOptionGroup *group;
+ gs_free char *parameter;
+
+ parameter = g_strdup_printf ("[-- %s …]", _("COMMAND"));
+ context = g_option_context_new (parameter);
+ g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
+ g_option_context_set_ignore_unknown_options (context, FALSE);
+
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+
+ group = g_option_group_new ("gnome-terminal",
+ N_("GNOME Terminal Emulator"),
+ N_("Show GNOME Terminal options"),
+ options,
+ NULL);
+ g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+ g_option_group_add_entries (group, global_unique_goptions);
+ g_option_group_add_entries (group, internal_goptions);
+ g_option_group_set_parse_hooks (group, NULL, digest_options_callback);
+ g_option_context_set_main_group (context, group);
+
+ group = g_option_group_new ("terminal",
+ N_("Options to open new windows or terminal tabs; more than one of these may be specified:"),
+ N_("Show terminal options"),
+ options,
+ NULL);
+ g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+ g_option_group_add_entries (group, global_multiple_goptions);
+ g_option_context_add_group (context, group);
+
+ group = g_option_group_new ("window-options",
+ N_("Window options; if used before the first --window or --tab argument, sets the default for all windows:"),
+ N_("Show per-window options"),
+ options,
+ NULL);
+ g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+ g_option_group_add_entries (group, window_goptions);
+ g_option_context_add_group (context, group);
+
+ group = g_option_group_new ("terminal-options",
+ N_("Terminal options; if used before the first --window or --tab argument, sets the default for all terminals:"),
+ N_("Show per-terminal options"),
+ options,
+ NULL);
+ g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+ g_option_group_add_entries (group, terminal_goptions);
+ g_option_context_add_group (context, group);
+
+ group = g_option_group_new ("sm-client", "", "", options, NULL);
+ g_option_group_add_entries (group, smclient_goptions);
+ g_option_context_add_group (context, group);
+
+ return context;
+}
diff --git a/src/terminal-options.h b/src/terminal-options.h
new file mode 100644
index 0000000..3ac4070
--- /dev/null
+++ b/src/terminal-options.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2008 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_OPTIONS_H
+#define TERMINAL_OPTIONS_H
+
+#include <glib.h>
+#include <stdio.h>
+
+#include <gio/gunixfdlist.h>
+
+#include "terminal-profiles-list.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_CONFIG_VERSION (1) /* Bump this for any changes */
+#define TERMINAL_CONFIG_COMPAT_VERSION (1) /* Bump this for incompatible changes */
+
+#define TERMINAL_CONFIG_GROUP "GNOME Terminal Configuration"
+#define TERMINAL_CONFIG_PROP_VERSION "Version"
+#define TERMINAL_CONFIG_PROP_COMPAT_VERSION "CompatVersion"
+#define TERMINAL_CONFIG_PROP_WINDOWS "Windows"
+
+#define TERMINAL_CONFIG_WINDOW_PROP_ACTIVE_TAB "ActiveTerminal"
+#define TERMINAL_CONFIG_WINDOW_PROP_FULLSCREEN "Fullscreen"
+#define TERMINAL_CONFIG_WINDOW_PROP_GEOMETRY "Geometry"
+#define TERMINAL_CONFIG_WINDOW_PROP_MAXIMIZED "Maximized"
+#define TERMINAL_CONFIG_WINDOW_PROP_MENUBAR_VISIBLE "MenubarVisible"
+#define TERMINAL_CONFIG_WINDOW_PROP_ROLE "Role"
+#define TERMINAL_CONFIG_WINDOW_PROP_TABS "Terminals"
+
+#define TERMINAL_CONFIG_TERMINAL_PROP_HEIGHT "Height"
+#define TERMINAL_CONFIG_TERMINAL_PROP_COMMAND "Command"
+#define TERMINAL_CONFIG_TERMINAL_PROP_PROFILE_ID "ProfileID"
+#define TERMINAL_CONFIG_TERMINAL_PROP_TITLE "Title"
+#define TERMINAL_CONFIG_TERMINAL_PROP_WIDTH "Width"
+#define TERMINAL_CONFIG_TERMINAL_PROP_WORKING_DIRECTORY "WorkingDirectory"
+#define TERMINAL_CONFIG_TERMINAL_PROP_ZOOM "Zoom"
+
+enum
+{
+ SOURCE_DEFAULT = 0,
+ SOURCE_SESSION = 1
+};
+
+typedef struct
+{
+ TerminalSettingsList *profiles_list; /* may be NULL */
+
+ gboolean print_environment;
+
+ char *server_unique_name;
+ char *parent_screen_object_path;
+
+ char *server_app_id;
+ char *startup_id;
+ char *display_name;
+ gboolean show_preferences;
+ GList *initial_windows;
+ gboolean default_window_menubar_forced;
+ gboolean default_window_menubar_state;
+ gboolean default_fullscreen;
+ gboolean default_maximize;
+ gboolean default_wait;
+ char *default_role;
+ char *default_geometry;
+ char *default_working_dir;
+ char *default_title;
+ char **exec_argv;
+ char *default_profile;
+ gboolean default_profile_is_id;
+ gboolean no_environment;
+
+ gboolean execute;
+ double zoom;
+
+ gboolean sm_client_disable;
+ char *sm_client_id;
+ char *sm_config_prefix;
+
+ guint zoom_set : 1;
+ guint wait : 1;
+} TerminalOptions;
+
+typedef struct
+{
+ char *profile;
+ gboolean profile_is_id;
+ char **exec_argv;
+ char *title;
+ char *working_dir;
+ double zoom;
+ GUnixFDList *fd_list;
+ GArray *fd_array;
+ guint zoom_set : 1;
+ guint active : 1;
+ guint wait : 1;
+} InitialTab;
+
+typedef struct
+{
+ guint source_tag;
+ gboolean implicit_first_window;
+
+ GList *tabs; /* list of InitialTab */
+
+ gboolean force_menubar_state;
+ gboolean menubar_state;
+
+ gboolean start_fullscreen;
+ gboolean start_maximized;
+
+ char *geometry;
+ char *role;
+
+} InitialWindow;
+
+#define TERMINAL_OPTION_ERROR (g_quark_from_static_string ("terminal-option-error"))
+
+typedef enum {
+ TERMINAL_OPTION_ERROR_NOT_SUPPORTED,
+ TERMINAL_OPTION_ERROR_NOT_IN_FACTORY,
+ TERMINAL_OPTION_ERROR_EXCLUSIVE_OPTIONS,
+ TERMINAL_OPTION_ERROR_INVALID_CONFIG_FILE,
+ TERMINAL_OPTION_ERROR_INCOMPATIBLE_CONFIG_FILE
+} TerminalOptionError;
+
+TerminalOptions *terminal_options_parse (int *argcp,
+ char ***argvp,
+ GError **error);
+
+gboolean terminal_options_merge_config (TerminalOptions *options,
+ GKeyFile *key_file,
+ guint source_tag,
+ GError **error);
+
+void terminal_options_ensure_window (TerminalOptions *options);
+
+const char *terminal_options_get_service_name (TerminalOptions *options);
+
+const char *terminal_options_get_parent_screen_object_path (TerminalOptions *options);
+
+void terminal_options_free (TerminalOptions *options);
+
+typedef enum {
+ TERMINAL_VERBOSITY_QUIET = 0,
+ TERMINAL_VERBOSITY_NORMAL = 1,
+ TERMINAL_VERBOSITY_DETAIL = 2,
+ TERMINAL_VERBOSITY_DEBUG = 3
+} TerminalVerbosity;
+
+void terminal_fprintf (FILE* fp,
+ int verbosity_level,
+ const char* format,
+ ...) G_GNUC_PRINTF(3, 4);
+
+#define terminal_print_level(level,...) terminal_fprintf(stdout, TERMINAL_VERBOSITY_ ## level, __VA_ARGS__)
+#define terminal_printerr_level(level,...) terminal_fprintf(stderr, TERMINAL_VERBOSITY_ ## level, __VA_ARGS__)
+
+#define terminal_print(...) terminal_print_level(NORMAL, __VA_ARGS__)
+#define terminal_print_detail(...) terminal_print_level(DETAIL, __VA_ARGS__)
+#define terminal_print_debug(...) terminal_print_level(DEBUG, __VA_ARGS__)
+
+#define terminal_printerr_detail(...) terminal_printerr_level(DETAIL, __VA_ARGS__)
+#define terminal_printerr(...) terminal_printerr_level(NORMAL, __VA_ARGS__)
+#define terminal_printerr_debug(...) terminal_printerr_level(DEBUG, __VA_ARGS__)
+
+GLogWriterOutput terminal_log_writer (GLogLevelFlags log_level,
+ const GLogField *fields,
+ gsize n_fields,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_OPTIONS_H */
diff --git a/src/terminal-pcre2.h b/src/terminal-pcre2.h
new file mode 100644
index 0000000..af7e8e4
--- /dev/null
+++ b/src/terminal-pcre2.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2015 Christian Persch
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This programme is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#ifdef __VTE_VTE_H__
+#error "Must include terminal-pcre2.h before vte/vte.h"
+#endif
+
+#define PCRE2_CODE_UNIT_WIDTH 0
+#include <pcre2.h>
diff --git a/src/terminal-prefs.c b/src/terminal-prefs.c
new file mode 100644
index 0000000..05d2cf8
--- /dev/null
+++ b/src/terminal-prefs.c
@@ -0,0 +1,922 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington, Red Hat Inc.
+ * Copyright © 2008, 2011, 2012, 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <uuid.h>
+#include <dconf.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "profile-editor.h"
+#include "terminal-prefs.h"
+#include "terminal-accels.h"
+#include "terminal-app.h"
+#include "terminal-debug.h"
+#include "terminal-schemas.h"
+#include "terminal-util.h"
+#include "terminal-profiles-list.h"
+#include "terminal-libgsystem.h"
+
+PrefData *the_pref_data = NULL; /* global */
+
+/* Bottom */
+
+static void
+prefs_dialog_help_button_clicked_cb (GtkWidget *button,
+ PrefData *data)
+{
+ terminal_util_show_help ("pref");
+}
+
+static void
+prefs_dialog_close_button_clicked_cb (GtkWidget *button,
+ PrefData *data)
+{
+ gtk_widget_destroy (data->dialog);
+}
+
+/* Sidebar */
+
+static inline GSimpleAction *
+lookup_action (GtkWindow *window,
+ const char *name)
+{
+ GAction *action;
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (window), name);
+ g_return_val_if_fail (action != NULL, NULL);
+
+ return G_SIMPLE_ACTION (action);
+}
+
+/* Update the sidebar (visibility of icons, sensitivity of menu entries) to reflect the default and the selected profiles. */
+static void
+listbox_update (GtkListBox *box)
+{
+ int i;
+ GtkListBoxRow *row;
+ GSettings *profile;
+ gs_unref_object GSettings *default_profile;
+ GtkStack *stack;
+ GtkMenuButton *button;
+
+ default_profile = terminal_settings_list_ref_default_child (the_pref_data->profiles_list);
+
+ /* GTK+ doesn't seem to like if a popover is assigned to multiple buttons at once
+ * (not even temporarily), so make sure to remove it from the previous button first. */
+ for (i = 0; (row = gtk_list_box_get_row_at_index (box, i)) != NULL; i++) {
+ button = g_object_get_data (G_OBJECT (row), "popover-button");
+ gtk_menu_button_set_popover (button, NULL);
+ }
+
+ for (i = 0; (row = gtk_list_box_get_row_at_index (box, i)) != NULL; i++) {
+ profile = g_object_get_data (G_OBJECT (row), "gsettings");
+
+ gboolean is_selected_profile = (profile != NULL && profile == the_pref_data->selected_profile);
+ gboolean is_default_profile = (profile != NULL && profile == default_profile);
+
+ stack = g_object_get_data (G_OBJECT (row), "home-stack");
+ gtk_stack_set_visible_child_name (stack, is_default_profile ? "home" : "placeholder");
+
+ stack = g_object_get_data (G_OBJECT (row), "popover-stack");
+ gtk_stack_set_visible_child_name (stack, is_selected_profile ? "button" : "placeholder");
+ if (is_selected_profile) {
+ g_simple_action_set_enabled (lookup_action (GTK_WINDOW (the_pref_data->dialog), "delete"), !is_default_profile);
+ g_simple_action_set_enabled (lookup_action (GTK_WINDOW (the_pref_data->dialog), "set-as-default"), !is_default_profile);
+
+ GtkPopover *popover_menu = GTK_POPOVER (gtk_builder_get_object (the_pref_data->builder, "popover-menu"));
+ button = g_object_get_data (G_OBJECT (row), "popover-button");
+ gtk_menu_button_set_popover (button, GTK_WIDGET (popover_menu));
+ gtk_popover_set_relative_to (popover_menu, GTK_WIDGET (button));
+ }
+ }
+}
+
+static void
+update_window_title (void)
+{
+ GtkListBoxRow *row = the_pref_data->selected_list_box_row;
+ if (row == NULL)
+ return;
+
+ GSettings *profile = g_object_get_data (G_OBJECT (row), "gsettings");
+ GtkLabel *label = g_object_get_data (G_OBJECT (row), "label");
+ const char *text = gtk_label_get_text (label);
+ gs_free char *subtitle;
+ gs_free char *title;
+
+ if (profile == NULL) {
+ subtitle = g_strdup (text);
+ } else {
+ subtitle = g_strdup_printf (_("Profile “%s”"), text);
+ }
+
+ title = g_strdup_printf (_("Preferences – %s"), subtitle);
+ gtk_window_set_title (GTK_WINDOW (the_pref_data->dialog), title);
+}
+
+/* A new entry is selected in the sidebar */
+static void
+listbox_row_selected_cb (GtkListBox *box,
+ GtkListBoxRow *row,
+ GtkStack *stack)
+{
+ profile_prefs_unload ();
+
+ /* row can be NULL intermittently during a profile meta operations */
+ g_free (the_pref_data->selected_profile_uuid);
+ if (row != NULL) {
+ the_pref_data->selected_profile = g_object_get_data (G_OBJECT (row), "gsettings");
+ the_pref_data->selected_profile_uuid = g_strdup (g_object_get_data (G_OBJECT (row), "uuid"));
+ } else {
+ the_pref_data->selected_profile = NULL;
+ the_pref_data->selected_profile_uuid = NULL;
+ }
+ the_pref_data->selected_list_box_row = row;
+
+ listbox_update (box);
+
+ if (row != NULL) {
+ if (the_pref_data->selected_profile != NULL) {
+ profile_prefs_load (the_pref_data->selected_profile_uuid, the_pref_data->selected_profile);
+ }
+
+ char *stack_child_name = g_object_get_data (G_OBJECT (row), "stack_child_name");
+ gtk_stack_set_visible_child_name (stack, stack_child_name);
+ }
+
+ update_window_title ();
+}
+
+/* A profile's name changed, perhaps externally */
+static void
+profile_name_changed_cb (GtkLabel *label,
+ GParamSpec *pspec,
+ GtkListBoxRow *row)
+{
+ gtk_list_box_row_changed (row); /* trigger re-sorting */
+
+ if (row == the_pref_data->selected_list_box_row)
+ update_window_title ();
+}
+
+/* Select a profile in the sidebar by UUID */
+static gboolean
+listbox_select_profile (const char *uuid)
+{
+ GtkListBoxRow *row;
+ for (int i = 0; (row = gtk_list_box_get_row_at_index (the_pref_data->listbox, i)) != NULL; i++) {
+ const char *rowuuid = g_object_get_data (G_OBJECT (row), "uuid");
+ if (g_strcmp0 (rowuuid, uuid) == 0) {
+ g_signal_emit_by_name (row, "activate");
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* Create a new profile now, select it, update the UI. */
+static void
+profile_new_now (const char *name)
+{
+ gs_free char *uuid = terminal_app_new_profile (terminal_app_get (), NULL, name);
+
+ listbox_select_profile (uuid);
+}
+
+/* Clone the selected profile now, select it, update the UI. */
+static void
+profile_clone_now (const char *name)
+{
+ if (the_pref_data->selected_profile == NULL)
+ return;
+
+ gs_free char *uuid = terminal_app_new_profile (terminal_app_get (), the_pref_data->selected_profile, name);
+
+ listbox_select_profile (uuid);
+}
+
+/* Rename the selected profile now, update the UI. */
+static void
+profile_rename_now (const char *name)
+{
+ if (the_pref_data->selected_profile == NULL)
+ return;
+
+ /* This will automatically trigger a call to profile_name_changed_cb(). */
+ g_settings_set_string (the_pref_data->selected_profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY, name);
+}
+
+/* Delete the selected profile now, update the UI. */
+static void
+profile_delete_now (const char *dummy)
+{
+ if (the_pref_data->selected_profile == NULL)
+ return;
+
+ /* Prepare to select the next one, or if there's no such then the previous one. */
+ int index = gtk_list_box_row_get_index (the_pref_data->selected_list_box_row);
+ GtkListBoxRow *new_selected_row = gtk_list_box_get_row_at_index (the_pref_data->listbox, index + 1);
+ if (new_selected_row == NULL)
+ new_selected_row = gtk_list_box_get_row_at_index (the_pref_data->listbox, index - 1);
+ GSettings *new_selected_profile = g_object_get_data (G_OBJECT (new_selected_row), "gsettings");
+ gs_free char *uuid = NULL;
+ if (new_selected_profile != NULL)
+ uuid = terminal_settings_list_dup_uuid_from_child (the_pref_data->profiles_list, new_selected_profile);
+
+ terminal_app_remove_profile (terminal_app_get (), the_pref_data->selected_profile);
+
+ listbox_select_profile (uuid);
+}
+
+/* "Set as default" selected. Do it now without asking for confirmation. */
+static void
+profile_set_as_default_cb (GSimpleAction *simple,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ if (the_pref_data->selected_profile_uuid == NULL)
+ return;
+
+ /* This will automatically trigger a call to listbox_update() via "default-changed". */
+ terminal_settings_list_set_default_child (the_pref_data->profiles_list, the_pref_data->selected_profile_uuid);
+}
+
+
+static void
+popover_dialog_cancel_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ GtkPopover *popover_dialog = GTK_POPOVER (gtk_builder_get_object (the_pref_data->builder, "popover-dialog"));
+
+ gtk_popover_popdown (popover_dialog);
+}
+
+static void
+popover_dialog_ok_clicked_cb (GtkButton *button,
+ void (*fn) (const char *))
+{
+ GtkEntry *entry = GTK_ENTRY (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-entry"));
+ const char *name = gtk_entry_get_text (entry);
+
+ /* Perform what we came for */
+ (*fn) (name);
+
+ /* Hide/popdown the popover */
+ popover_dialog_cancel_clicked_cb (button, NULL);
+}
+
+static void
+popover_dialog_closed_cb (GtkPopover *popover,
+ gpointer user_data)
+{
+
+ GtkEntry *entry = GTK_ENTRY (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-entry"));
+ gtk_entry_set_text (entry, "");
+
+ GtkButton *ok = GTK_BUTTON (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-ok"));
+ GtkButton *cancel = GTK_BUTTON (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-cancel"));
+
+ g_signal_handlers_disconnect_matched (ok, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+ G_CALLBACK (popover_dialog_ok_clicked_cb), NULL);
+ g_signal_handlers_disconnect_matched (cancel, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+ G_CALLBACK (popover_dialog_cancel_clicked_cb), NULL);
+ g_signal_handlers_disconnect_matched (popover, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+ G_CALLBACK (popover_dialog_closed_cb), NULL);
+}
+
+
+/* Updates the OK button's sensitivity (insensitive if entry field is empty or whitespace only).
+ * The entry's initial value and OK's initial sensitivity have to match in the .ui file. */
+static void
+popover_dialog_notify_text_cb (GtkEntry *entry,
+ GParamSpec *pspec,
+ GtkWidget *ok)
+{
+ gs_free char *text = g_strchomp (g_strdup (gtk_entry_get_text (entry)));
+ gtk_widget_set_sensitive (ok, text[0] != '\0');
+}
+
+
+/* Common dialog for entering new profile name, or confirming deletion */
+static void
+profile_popup_dialog (GtkWidget *relative_to,
+ const char *header,
+ const char *body,
+ const char *entry_text,
+ const char *ok_text,
+ void (*fn) (const char *))
+{
+ GtkLabel *label1 = GTK_LABEL (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-label1"));
+ gtk_label_set_text (label1, header);
+
+ GtkLabel *label2 = GTK_LABEL (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-label2"));
+ gtk_label_set_text (label2, body);
+
+ GtkEntry *entry = GTK_ENTRY (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-entry"));
+ if (entry_text != NULL) {
+ gtk_entry_set_text (entry, entry_text);
+ gtk_widget_show (GTK_WIDGET (entry));
+ } else {
+ gtk_entry_set_text (entry, "."); /* to make the OK button sensitive */
+ gtk_widget_hide (GTK_WIDGET (entry));
+ }
+
+ GtkButton *ok = GTK_BUTTON (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-ok"));
+ gtk_button_set_label (ok, ok_text);
+ GtkButton *cancel = GTK_BUTTON (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-cancel"));
+ GtkPopover *popover_dialog = GTK_POPOVER (gtk_builder_get_object (the_pref_data->builder, "popover-dialog"));
+
+ g_signal_connect (ok, "clicked", G_CALLBACK (popover_dialog_ok_clicked_cb), fn);
+ g_signal_connect (cancel, "clicked", G_CALLBACK (popover_dialog_cancel_clicked_cb), NULL);
+ g_signal_connect (popover_dialog, "closed", G_CALLBACK (popover_dialog_closed_cb), NULL);
+
+ gtk_popover_set_relative_to (popover_dialog, relative_to);
+ gtk_popover_set_position (popover_dialog, GTK_POS_BOTTOM);
+ gtk_popover_set_default_widget (popover_dialog, GTK_WIDGET (ok));
+
+ gtk_popover_popup (popover_dialog);
+
+ gtk_widget_grab_focus (entry_text != NULL ? GTK_WIDGET (entry) : GTK_WIDGET (cancel));
+}
+
+/* "New" selected, ask for profile name */
+static void
+profile_new_cb (GtkButton *button,
+ gpointer user_data)
+{
+ profile_popup_dialog (GTK_WIDGET (the_pref_data->new_profile_button),
+ _("New Profile"),
+ _("Enter name for new profile with default settings:"),
+ "",
+ _("Create"),
+ profile_new_now);
+}
+
+/* "Clone" selected, ask for profile name */
+static void
+profile_clone_cb (GSimpleAction *simple,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ gs_free char *name = g_settings_get_string (the_pref_data->selected_profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+
+ gs_free char *label = g_strdup_printf (_("Enter name for new profile based on “%s”:"), name);
+ gs_free char *clone_name = g_strdup_printf (_("%s (Copy)"), name);
+
+ profile_popup_dialog (GTK_WIDGET (the_pref_data->selected_list_box_row),
+ _("Clone Profile"),
+ label,
+ clone_name,
+ _("Clone"),
+ profile_clone_now);
+}
+
+/* "Rename" selected, ask for new name */
+static void
+profile_rename_cb (GSimpleAction *simple,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ if (the_pref_data->selected_profile == NULL)
+ return;
+
+ gs_free char *name = g_settings_get_string (the_pref_data->selected_profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+
+ gs_free char *label = g_strdup_printf (_("Enter new name for profile “%s”:"), name);
+
+ profile_popup_dialog (GTK_WIDGET (the_pref_data->selected_list_box_row),
+ _("Rename Profile"),
+ label,
+ name,
+ _("Rename"),
+ profile_rename_now);
+}
+
+/* "Delete" selected, ask for confirmation */
+static void
+profile_delete_cb (GSimpleAction *simple,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ if (the_pref_data->selected_profile == NULL)
+ return;
+
+ gs_free char *name = g_settings_get_string (the_pref_data->selected_profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+
+ gs_free char *label = g_strdup_printf (_("Really delete profile “%s”?"), name);
+
+ profile_popup_dialog (GTK_WIDGET (the_pref_data->selected_list_box_row),
+ _("Delete Profile"),
+ label,
+ NULL,
+ _("Delete"),
+ profile_delete_now);
+}
+
+/* Create a (non-header) row of the sidebar, either a global or a profile entry. */
+static GtkListBoxRow *
+listbox_create_row (const char *name,
+ const char *stack_child_name,
+ const char *uuid,
+ GSettings *gsettings /* adopted */,
+ gpointer sort_order)
+{
+ GtkListBoxRow *row = GTK_LIST_BOX_ROW (gtk_list_box_row_new ());
+
+ g_object_set_data_full (G_OBJECT (row), "stack_child_name", g_strdup (stack_child_name), g_free);
+ g_object_set_data_full (G_OBJECT (row), "uuid", g_strdup (uuid), g_free);
+ if (gsettings != NULL)
+ g_object_set_data_full (G_OBJECT (row), "gsettings", gsettings, (GDestroyNotify)g_object_unref);
+ g_object_set_data (G_OBJECT (row), "sort_order", sort_order);
+
+ GtkBox *hbox = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0));
+ gtk_widget_set_margin_start (GTK_WIDGET (hbox), 6);
+ gtk_widget_set_margin_end (GTK_WIDGET (hbox), 6);
+ gtk_widget_set_margin_top (GTK_WIDGET (hbox), 6);
+ gtk_widget_set_margin_bottom (GTK_WIDGET (hbox), 6);
+
+ GtkLabel *label = GTK_LABEL (gtk_label_new (name));
+ if (gsettings != NULL) {
+ g_signal_connect (label, "notify::label", G_CALLBACK (profile_name_changed_cb), row);
+ g_settings_bind (gsettings,
+ TERMINAL_PROFILE_VISIBLE_NAME_KEY,
+ label,
+ "label",
+ G_SETTINGS_BIND_GET);
+ }
+ gtk_label_set_xalign (label, 0);
+ gtk_box_pack_start (hbox, GTK_WIDGET (label), TRUE, TRUE, 0);
+ g_object_set_data (G_OBJECT (row), "label", label);
+
+ /* Always add the "default" symbol and the "menu" button, even on rows of global prefs.
+ * Use GtkStack to possible achieve visibility:hidden on it.
+ * This is so that all listbox rows have the same dimensions, and the width doesn't change
+ * as you switch the default profile. */
+
+ GtkStack *popover_stack = GTK_STACK (gtk_stack_new ());
+ gtk_widget_set_margin_start (GTK_WIDGET (popover_stack), 6);
+ GtkMenuButton *popover_button = GTK_MENU_BUTTON (gtk_menu_button_new ());
+ gtk_button_set_relief (GTK_BUTTON (popover_button), GTK_RELIEF_NONE);
+ gtk_stack_add_named (popover_stack, GTK_WIDGET (popover_button), "button");
+ GtkLabel *popover_label = GTK_LABEL (gtk_label_new (""));
+ gtk_stack_add_named (popover_stack, GTK_WIDGET (popover_label), "placeholder");
+ g_object_set_data (G_OBJECT (row), "popover-stack", popover_stack);
+ g_object_set_data (G_OBJECT (row), "popover-button", popover_button);
+
+ gtk_box_pack_end (hbox, GTK_WIDGET (popover_stack), FALSE, FALSE, 0);
+
+ GtkStack *home_stack = GTK_STACK (gtk_stack_new ());
+ gtk_widget_set_margin_start (GTK_WIDGET (home_stack), 12);
+ GtkImage *home_image = GTK_IMAGE (gtk_image_new_from_icon_name ("emblem-default-symbolic", GTK_ICON_SIZE_BUTTON));
+ gtk_widget_set_tooltip_text (GTK_WIDGET (home_image), _("This is the default profile"));
+ gtk_stack_add_named (home_stack, GTK_WIDGET (home_image), "home");
+ GtkLabel *home_label = GTK_LABEL (gtk_label_new (""));
+ gtk_stack_add_named (home_stack, GTK_WIDGET (home_label), "placeholder");
+ g_object_set_data (G_OBJECT (row), "home-stack", home_stack);
+
+ gtk_box_pack_end (hbox, GTK_WIDGET (home_stack), FALSE, FALSE, 0);
+
+ gtk_container_add (GTK_CONTAINER (row), GTK_WIDGET (hbox));
+
+ gtk_widget_show_all (GTK_WIDGET (row));
+
+ gtk_stack_set_visible_child_name (popover_stack, "placeholder");
+ gtk_stack_set_visible_child_name (home_stack, "placeholder");
+
+ return row;
+}
+
+/* Add all the non-profile rows to the sidebar */
+static void
+listbox_add_all_globals (PrefData *data)
+{
+ GtkListBoxRow *row;
+
+ row = listbox_create_row (_("General"),
+ "general-prefs",
+ NULL, NULL, (gpointer) 0);
+ gtk_list_box_insert (data->listbox, GTK_WIDGET (row), -1);
+
+ row = listbox_create_row (_("Shortcuts"),
+ "shortcut-prefs",
+ NULL, NULL, (gpointer) 1);
+ gtk_list_box_insert (data->listbox, GTK_WIDGET (row), -1);
+}
+
+/* Remove all the profile rows from the sidebar */
+static void
+listbox_remove_all_profiles (PrefData *data)
+{
+ int i = 0;
+
+ data->selected_profile = NULL;
+ g_free (data->selected_profile_uuid);
+ data->selected_profile_uuid = NULL;
+ profile_prefs_unload ();
+
+ GtkListBoxRow *row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (the_pref_data->listbox), 0);
+ g_signal_emit_by_name (row, "activate");
+
+ while ((row = gtk_list_box_get_row_at_index (data->listbox, i)) != NULL) {
+ if (g_object_get_data (G_OBJECT (row), "gsettings") != NULL) {
+ gtk_widget_destroy (GTK_WIDGET (row));
+ } else {
+ i++;
+ }
+ }
+}
+
+/* Add all the profiles to the sidebar */
+static void
+listbox_add_all_profiles (PrefData *data)
+{
+ GList *list, *l;
+ GtkListBoxRow *row;
+
+ list = terminal_settings_list_ref_children (data->profiles_list);
+
+ for (l = list; l != NULL; l = l->next) {
+ GSettings *profile = (GSettings *) l->data;
+ gs_free gchar *uuid = terminal_settings_list_dup_uuid_from_child (data->profiles_list, profile);
+
+ row = listbox_create_row (NULL,
+ "profile-prefs",
+ uuid,
+ profile /* adopts */,
+ (gpointer) 42);
+ gtk_list_box_insert (data->listbox, GTK_WIDGET (row), -1);
+ }
+
+ g_list_free(list); /* the items themselves were adopted into the model above */
+
+ listbox_update (data->listbox); /* FIXME: This is not needed but I don't know why :-) */
+}
+
+/* Re-add all the profiles to the sidebar.
+ * This is called when a profile is added or removed, and also when the list of profiles is
+ * modified externally.
+ * Try to keep the selected profile, whenever possible.
+ * When the list is modified externally, the terminal_settings_list_*() methods seem to preserve
+ * the GSettings object for every profile that remains in the list. There's no guarantee however
+ * that a newly created GSettings can't receive the same address that a ceased one used to have.
+ * So don't rely on GSettings* to keep track of the selected profile, use the UUID instead. */
+static void
+listbox_readd_profiles (PrefData *data)
+{
+ gs_free char *uuid = g_strdup (data->selected_profile_uuid);
+
+ listbox_remove_all_profiles (data);
+ listbox_add_all_profiles (data);
+
+ if (uuid != NULL)
+ listbox_select_profile (uuid);
+}
+
+/* Create a header row ("Global" or "Profiles +") */
+static GtkWidget *
+listboxrow_create_header (const char *text,
+ gboolean visible_button)
+{
+ GtkBox *hbox = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0));
+ gtk_widget_set_margin_start (GTK_WIDGET (hbox), 6);
+ gtk_widget_set_margin_end (GTK_WIDGET (hbox), 6);
+ gtk_widget_set_margin_top (GTK_WIDGET (hbox), 6);
+ gtk_widget_set_margin_bottom (GTK_WIDGET (hbox), 6);
+
+ GtkLabel *label = GTK_LABEL (gtk_label_new (NULL));
+ gs_free char *markup = g_markup_printf_escaped ("<b>%s</b>", text);
+ gtk_label_set_markup (label, markup);
+ gtk_label_set_xalign (label, 0);
+ gtk_box_pack_start (hbox, GTK_WIDGET (label), TRUE, TRUE, 0);
+
+ /* Always add a "new profile" button. Use GtkStack to possible achieve visibility:hidden on it.
+ * This is so that both header rows have the same dimensions. */
+
+ GtkStack *stack = GTK_STACK (gtk_stack_new ());
+ GtkButton *button = GTK_BUTTON (gtk_button_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_BUTTON));
+ gtk_button_set_relief (button, GTK_RELIEF_NONE);
+ gtk_stack_add_named (stack, GTK_WIDGET (button), "button");
+ GtkLabel *labelx = GTK_LABEL (gtk_label_new (""));
+ gtk_stack_add_named (stack, GTK_WIDGET (labelx), "placeholder");
+
+ gtk_box_pack_end (hbox, GTK_WIDGET (stack), FALSE, FALSE, 0);
+
+ gtk_widget_show_all (GTK_WIDGET (hbox));
+
+ if (visible_button) {
+ gtk_stack_set_visible_child_name (stack, "button");
+ g_signal_connect (button, "clicked", G_CALLBACK (profile_new_cb), NULL);
+ the_pref_data->new_profile_button = GTK_WIDGET (button);
+ } else {
+ gtk_stack_set_visible_child_name (stack, "placeholder");
+ }
+
+ return GTK_WIDGET (hbox);
+}
+
+/* Manage the creation or removal of the header row ("Global" or "Profiles +") */
+static void
+listboxrow_update_header (GtkListBoxRow *row,
+ GtkListBoxRow *before,
+ gpointer user_data)
+{
+ if (before == NULL) {
+ if (gtk_list_box_row_get_header (row) == NULL) {
+ gtk_list_box_row_set_header (row, listboxrow_create_header (_("Global"), FALSE));
+ }
+ return;
+ }
+
+ GSettings *profile = g_object_get_data (G_OBJECT (row), "gsettings");
+ if (profile != NULL) {
+ GSettings *profile_before = g_object_get_data (G_OBJECT (before), "gsettings");
+ if (profile_before != NULL) {
+ gtk_list_box_row_set_header (row, NULL);
+ } else {
+ if (gtk_list_box_row_get_header (row) == NULL) {
+ gtk_list_box_row_set_header (row, listboxrow_create_header (_("Profiles"), TRUE));
+ }
+ }
+ }
+}
+
+/* Sort callback for rows of the sidebar (global and profile ones).
+ * Global ones are kept at the top in fixed order. This is implemented via sort_order
+ * which is an integer disguised as a pointer for ease of implementation.
+ * Profile ones are sorted lexicographically. */
+static gint
+listboxrow_compare_cb (GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gpointer user_data)
+{
+ gpointer sort_order_1 = g_object_get_data (G_OBJECT (row1), "sort_order");
+ gpointer sort_order_2 = g_object_get_data (G_OBJECT (row2), "sort_order");
+
+ if (sort_order_1 != sort_order_2)
+ return sort_order_1 < sort_order_2 ? -1 : 1;
+
+ GtkLabel *label1 = g_object_get_data (G_OBJECT (row1), "label");
+ const char *text1 = gtk_label_get_text (label1);
+ GtkLabel *label2 = g_object_get_data (G_OBJECT (row2), "label");
+ const char *text2 = gtk_label_get_text (label2);
+
+ return g_utf8_collate (text1, text2);
+}
+
+/* Keybindings tab */
+
+/* Make sure the treeview is repainted with the correct text color, see bug 792139. */
+static void
+shortcuts_button_toggled_cb (GtkWidget *widget,
+ GtkTreeView *tree_view)
+{
+ gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+}
+
+/* misc */
+
+static void
+prefs_dialog_destroy_cb (GtkWidget *widget,
+ PrefData *data)
+{
+ /* Don't run this handler again */
+ g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (prefs_dialog_destroy_cb), data);
+
+ g_signal_handlers_disconnect_by_func (data->profiles_list,
+ G_CALLBACK (listbox_readd_profiles), data);
+ g_signal_handlers_disconnect_by_func (data->profiles_list,
+ G_CALLBACK (listbox_update), data->listbox);
+
+ profile_prefs_destroy ();
+
+ g_object_unref (data->builder);
+ g_free (data->selected_profile_uuid);
+ g_free (data);
+}
+
+void
+terminal_prefs_show_preferences (GSettings *profile, const char *widget_name)
+{
+ TerminalApp *app = terminal_app_get ();
+ PrefData *data;
+ GtkWidget *dialog, *tree_view;
+ GtkWidget *show_menubar_button, *disable_mnemonics_button, *disable_menu_accel_button;
+ GtkWidget *disable_shortcuts_button;
+ GtkWidget *theme_variant_label, *theme_variant_combo;
+ GtkWidget *new_terminal_mode_label, *new_terminal_mode_combo;
+ GtkWidget *new_tab_position_combo;
+ GtkWidget *close_button, *help_button;
+ GtkWidget *content_box, *general_frame, *keybindings_frame;
+ GSettings *settings;
+
+ const GActionEntry action_entries[] = {
+ { "clone", profile_clone_cb, NULL, NULL, NULL },
+ { "rename", profile_rename_cb, NULL, NULL, NULL },
+ { "delete", profile_delete_cb, NULL, NULL, NULL },
+ { "set-as-default", profile_set_as_default_cb, NULL, NULL, NULL },
+ };
+
+ if (the_pref_data != NULL)
+ goto done;
+
+ the_pref_data = g_new0 (PrefData, 1);
+ data = the_pref_data;
+ data->profiles_list = terminal_app_get_profiles_list (app);
+
+ /* FIXME this method is only used from here. Inline it here instead. */
+ data->builder = terminal_util_load_widgets_resource ("/org/gnome/terminal/ui/preferences.ui",
+ "preferences-dialog",
+ "preferences-dialog", &dialog,
+ "dialogue-content-box", &content_box,
+ "general-frame", &general_frame,
+ "keybindings-frame", &keybindings_frame,
+ "close-button", &close_button,
+ "help-button", &help_button,
+ "default-show-menubar-checkbutton", &show_menubar_button,
+ "theme-variant-label", &theme_variant_label,
+ "theme-variant-combobox", &theme_variant_combo,
+ "new-terminal-mode-label", &new_terminal_mode_label,
+ "new-terminal-mode-combobox", &new_terminal_mode_combo,
+ "disable-mnemonics-checkbutton", &disable_mnemonics_button,
+ "disable-shortcuts-checkbutton", &disable_shortcuts_button,
+ "disable-menu-accel-checkbutton", &disable_menu_accel_button,
+ "new-tab-position-combobox", &new_tab_position_combo,
+ "accelerators-treeview", &tree_view,
+ "the-stack", &data->stack,
+ "the-listbox", &data->listbox,
+ NULL);
+
+ data->dialog = dialog;
+
+ gtk_window_set_application (GTK_WINDOW (data->dialog), GTK_APPLICATION (terminal_app_get ()));
+
+ terminal_util_bind_mnemonic_label_sensitivity (dialog);
+
+ settings = terminal_app_get_global_settings (app);
+
+ g_action_map_add_action_entries (G_ACTION_MAP (dialog),
+ action_entries, G_N_ELEMENTS (action_entries),
+ data);
+
+ /* Sidebar */
+
+ gtk_list_box_set_header_func (GTK_LIST_BOX (data->listbox),
+ listboxrow_update_header,
+ NULL,
+ NULL);
+ g_signal_connect (data->listbox, "row-selected", G_CALLBACK (listbox_row_selected_cb), data->stack);
+ gtk_list_box_set_sort_func (data->listbox, listboxrow_compare_cb, NULL, NULL);
+
+ listbox_add_all_globals (data);
+ listbox_add_all_profiles (data);
+ g_signal_connect_swapped (data->profiles_list, "children-changed",
+ G_CALLBACK (listbox_readd_profiles), data);
+ g_signal_connect_swapped (data->profiles_list, "default-changed",
+ G_CALLBACK (listbox_update), data->listbox);
+
+ GtkEntry *entry = GTK_ENTRY (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-entry"));
+ GtkButton *ok = GTK_BUTTON (gtk_builder_get_object (the_pref_data->builder, "popover-dialog-ok"));
+ g_signal_connect (entry, "notify::text", G_CALLBACK (popover_dialog_notify_text_cb), ok);
+
+ /* General page */
+
+ gboolean shell_shows_menubar;
+ g_object_get (gtk_settings_get_default (),
+ "gtk-shell-shows-menubar", &shell_shows_menubar,
+ NULL);
+ if (shell_shows_menubar || terminal_app_get_use_headerbar (app)) {
+ gtk_widget_set_visible (show_menubar_button, FALSE);
+ } else {
+ g_settings_bind (settings,
+ TERMINAL_SETTING_DEFAULT_SHOW_MENUBAR_KEY,
+ show_menubar_button,
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ }
+
+ g_settings_bind (settings,
+ TERMINAL_SETTING_THEME_VARIANT_KEY,
+ theme_variant_combo,
+ "active-id",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ if (terminal_app_get_menu_unified (app) ||
+ terminal_app_get_use_headerbar (app)) {
+ g_settings_bind (settings,
+ TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY,
+ new_terminal_mode_combo,
+ "active-id",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ } else {
+ gtk_widget_set_visible (new_terminal_mode_label, FALSE);
+ gtk_widget_set_visible (new_terminal_mode_combo, FALSE);
+ }
+
+ g_settings_bind (settings,
+ TERMINAL_SETTING_NEW_TAB_POSITION_KEY,
+ new_tab_position_combo,
+ "active-id",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ if (shell_shows_menubar) {
+ gtk_widget_set_visible (disable_mnemonics_button, FALSE);
+ } else {
+ g_settings_bind (settings,
+ TERMINAL_SETTING_ENABLE_MNEMONICS_KEY,
+ disable_mnemonics_button,
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ }
+ g_settings_bind (settings,
+ TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY,
+ disable_menu_accel_button,
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ /* Shortcuts page */
+
+ g_settings_bind (settings,
+ TERMINAL_SETTING_ENABLE_SHORTCUTS_KEY,
+ disable_shortcuts_button,
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+
+ g_signal_connect (disable_shortcuts_button, "toggled",
+ G_CALLBACK (shortcuts_button_toggled_cb), tree_view);
+
+ terminal_accels_fill_treeview (tree_view, disable_shortcuts_button);
+
+ /* Profile page */
+
+ profile_prefs_init ();
+
+ /* Move action widgets to titlebar when headerbar is used */
+ if (terminal_app_get_dialog_use_headerbar (app)) {
+ GtkWidget *headerbar;
+ GtkWidget *bbox;
+
+ headerbar = g_object_new (GTK_TYPE_HEADER_BAR,
+ "show-close-button", TRUE,
+ NULL);
+ bbox = gtk_widget_get_parent (help_button);
+
+ gtk_container_remove (GTK_CONTAINER (bbox), g_object_ref (help_button));
+ gtk_header_bar_pack_start (GTK_HEADER_BAR (headerbar), help_button);
+ g_object_unref (help_button);
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (help_button),
+ "text-button");
+
+ gtk_widget_show (headerbar);
+ gtk_widget_hide (bbox);
+
+ gtk_window_set_titlebar (GTK_WINDOW (dialog), headerbar);
+
+ /* Remove extra spacing around the content, and extra frames */
+ g_object_set (G_OBJECT (content_box), "margin", 0, NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (general_frame), GTK_SHADOW_NONE);
+ gtk_frame_set_shadow_type (GTK_FRAME (keybindings_frame), GTK_SHADOW_NONE);
+ }
+
+ /* misc */
+
+ g_signal_connect (close_button, "clicked", G_CALLBACK (prefs_dialog_close_button_clicked_cb), data);
+ g_signal_connect (help_button, "clicked", G_CALLBACK (prefs_dialog_help_button_clicked_cb), data);
+ g_signal_connect (dialog, "destroy", G_CALLBACK (prefs_dialog_destroy_cb), data);
+
+ g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *) &the_pref_data);
+
+done:
+ if (profile != NULL) {
+ gs_free char *uuid = terminal_settings_list_dup_uuid_from_child (the_pref_data->profiles_list, profile);
+ listbox_select_profile (uuid);
+ } else {
+ GtkListBoxRow *row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (the_pref_data->listbox), 0);
+ g_signal_emit_by_name (row, "activate");
+ }
+
+ terminal_util_dialog_focus_widget (the_pref_data->builder, widget_name);
+
+ gtk_window_present (GTK_WINDOW (the_pref_data->dialog));
+}
diff --git a/src/terminal-prefs.h b/src/terminal-prefs.h
new file mode 100644
index 0000000..ecb4129
--- /dev/null
+++ b/src/terminal-prefs.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_PREFS_H
+#define TERMINAL_PREFS_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-profiles-list.h"
+
+G_BEGIN_DECLS
+
+/* FIXME move back to the .c file if profile-editor.c is also merged there,
+ * also remove the terminal-profiles-list.h incude above. */
+/* FIXME PrefData is a very bad name, rename to PrefsDialog maybe? */
+
+/* Everything about a preferences dialog */
+typedef struct {
+ TerminalSettingsList *profiles_list;
+
+ GSettings *selected_profile;
+ GtkListBoxRow *selected_list_box_row;
+ char *selected_profile_uuid; /* a copy thereof, to survive changes to profiles_list */
+
+ GtkBuilder *builder;
+ GtkWidget *dialog;
+ GtkListBox *listbox;
+ GtkWidget *new_profile_button;
+ GtkWidget *stack;
+
+ GArray *profile_signals;
+ GArray *profile_bindings;
+} PrefData;
+
+extern PrefData *the_pref_data; /* global */
+
+void terminal_prefs_show_preferences (GSettings *profile, const char *widget_name);
+
+G_END_DECLS
+
+#endif /* TERMINAL_PREFS_H */
diff --git a/src/terminal-profiles-list.c b/src/terminal-profiles-list.c
new file mode 100644
index 0000000..6a85bc1
--- /dev/null
+++ b/src/terminal-profiles-list.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2011, 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-profiles-list.h"
+#include "terminal-schemas.h"
+#include "terminal-libgsystem.h"
+
+#include <string.h>
+#include <uuid.h>
+
+/* Counts occurrences of @str in @strv */
+static guint
+strv_contains (char **strv,
+ const char *str,
+ guint *idx)
+{
+ guint n, i;
+
+ if (strv == NULL)
+ return 0;
+
+ n = 0;
+ for (i = 0; strv[i]; i++) {
+ if (strcmp (strv[i], str) == 0) {
+ n++;
+ if (idx)
+ *idx = i;
+ }
+ }
+
+ return n;
+}
+
+static gboolean
+valid_uuid (const char *str,
+ GError **error)
+{
+ if (terminal_settings_list_valid_uuid (str))
+ return TRUE;
+
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "\"%s\" is not a valid UUID", str);
+ return FALSE;
+}
+
+/**
+ * terminal_profiles_list_new:
+ *
+ * Returns: (transfer full): a new #TerminalSettingsList for the profiles list
+ */
+TerminalSettingsList *
+terminal_profiles_list_new (void)
+{
+ return terminal_settings_list_new (TERMINAL_PROFILES_PATH_PREFIX,
+ TERMINAL_PROFILES_LIST_SCHEMA,
+ TERMINAL_PROFILE_SCHEMA,
+ TERMINAL_SETTINGS_LIST_FLAG_HAS_DEFAULT);
+}
+
+static void
+get_profile_names (TerminalSettingsList *list,
+ char ***profilesp,
+ char ***namesp)
+{
+ char **profiles, **names;
+ guint i, n;
+
+ *profilesp = profiles = terminal_settings_list_dupv_children (list);
+
+ n = g_strv_length (profiles);
+ *namesp = names = g_new0 (char *, n + 1);
+ for (i = 0; i < n; i++) {
+ gs_unref_object GSettings *profile;
+
+ profile = terminal_settings_list_ref_child (list, profiles[i]);
+ names[i] = g_settings_get_string (profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+ }
+
+ names[n] = NULL;
+}
+
+/**
+ * terminal_profiles_list_ref_children_sorted:
+ * @list:
+ *
+ * Returns: (transfer full):
+ */
+GList *
+terminal_profiles_list_ref_children_sorted (TerminalSettingsList *list)
+{
+ return g_list_sort (terminal_settings_list_ref_children (list),
+ terminal_profiles_compare);
+}
+
+/**
+ * terminal_profiles_list_dup_uuid:
+ * @list:
+ * @uuid: (allow-none):
+ * @error:
+ *
+ * Returns: (transfer full): the UUID of the profile specified by @uuid, or %NULL
+ */
+char *
+terminal_profiles_list_dup_uuid (TerminalSettingsList *list,
+ const char *uuid,
+ GError **error)
+{
+ char *rv;
+
+ if (uuid == NULL) {
+ rv = terminal_settings_list_dup_default_child (list);
+ if (rv == NULL)
+ goto err;
+ return rv;
+ } else if (!valid_uuid (uuid, error))
+ return NULL;
+
+ if (terminal_settings_list_has_child (list, uuid))
+ return g_strdup (uuid);
+
+ err:
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "No profile with UUID \"%s\" exists", uuid);
+ return NULL;
+}
+
+/**
+ * terminal_profiles_list_ref_profile_by_uuid_or_name:
+ * @list:
+ * @uuid:
+ * @error:
+ *
+ * Returns: (transfer full): the profile #GSettings specified by @uuid, or %NULL
+ */
+GSettings *
+terminal_profiles_list_ref_profile_by_uuid (TerminalSettingsList *list,
+ const char *uuid,
+ GError **error)
+{
+ gs_free char *profile_uuid;
+ GSettings *profile;
+
+ profile_uuid = terminal_profiles_list_dup_uuid (list, uuid, error);
+ if (profile_uuid == NULL)
+ return NULL;
+
+ profile = terminal_settings_list_ref_child (list, profile_uuid);
+ return profile;
+}
+
+/**
+ * terminal_profiles_list_get_profile_by_uuid:
+ * @list:
+ * @uuid: (allow-none):
+ * @error:
+ *
+ * Returns: (transfer full): the UUID of the profile specified by @uuid, or %NULL
+ */
+char *
+terminal_profiles_list_dup_uuid_or_name (TerminalSettingsList *list,
+ const char *uuid_or_name,
+ GError **error)
+{
+ char **profiles, **profile_names;
+ char *rv;
+ guint n, i;
+
+ rv = terminal_profiles_list_dup_uuid (list, uuid_or_name, NULL);
+ if (rv != NULL)
+ return rv;
+
+ /* Not found as UUID; try finding a profile with this string as 'visible-name' */
+ get_profile_names (list, &profiles, &profile_names);
+ n = strv_contains (profile_names, uuid_or_name, &i);
+
+ if (n == 0) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "No profile with UUID or name \"%s\" exists", uuid_or_name);
+ rv = NULL;
+ } else if (n != 1) {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "No profile with UUID \"%s\" found and name is ambiguous", uuid_or_name);
+ rv = NULL;
+ } else {
+ rv = g_strdup (profiles[i]);
+ }
+
+ g_strfreev (profiles);
+ g_strfreev (profile_names);
+
+ return rv;
+}
+
+/**
+ * terminal_profiles_list_ref_profile_by_uuid_or_name:
+ * @list:
+ * @uuid:
+ * @error:
+ *
+ * Returns: (transfer full): the profile #GSettings specified by @uuid, or %NULL
+ */
+GSettings *
+terminal_profiles_list_ref_profile_by_uuid_or_name (TerminalSettingsList *list,
+ const char *uuid_or_name,
+ GError **error)
+{
+ gs_free char *uuid;
+ GSettings *profile;
+
+ uuid = terminal_profiles_list_dup_uuid_or_name (list, uuid_or_name, error);
+ if (uuid == NULL)
+ return NULL;
+
+ profile = terminal_settings_list_ref_child (list, uuid);
+ g_assert (profile != NULL);
+ return profile;
+}
+
+int
+terminal_profiles_compare (gconstpointer pa,
+ gconstpointer pb)
+{
+ GSettings *a = (GSettings *) pa;
+ GSettings *b = (GSettings *) pb;
+ gs_free char *na = NULL;
+ gs_free char *nb = NULL;
+ gs_free char *patha = NULL;
+ gs_free char *pathb = NULL;
+ int result;
+
+ if (pa == pb)
+ return 0;
+ if (pa == NULL)
+ return 1;
+ if (pb == NULL)
+ return -1;
+
+ na = g_settings_get_string (a, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+ nb = g_settings_get_string (b, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+ result = g_utf8_collate (na, nb);
+ if (result != 0)
+ return result;
+
+ g_object_get (a, "path", &patha, NULL);
+ g_object_get (b, "path", &pathb, NULL);
+ return strcmp (patha, pathb);
+}
diff --git a/src/terminal-profiles-list.h b/src/terminal-profiles-list.h
new file mode 100644
index 0000000..179d3e3
--- /dev/null
+++ b/src/terminal-profiles-list.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_PROFILES_LIST_H
+#define TERMINAL_PROFILES_LIST_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "terminal-settings-list.h"
+
+G_BEGIN_DECLS
+
+TerminalSettingsList *terminal_profiles_list_new (void);
+
+GList *terminal_profiles_list_ref_children_sorted (TerminalSettingsList *list);
+
+char *terminal_profiles_list_dup_uuid (TerminalSettingsList *list,
+ const char *uuid,
+ GError **error);
+
+GSettings *terminal_profiles_list_ref_profile_by_uuid (TerminalSettingsList *list,
+ const char *uuid,
+ GError **error);
+
+char *terminal_profiles_list_dup_uuid_or_name (TerminalSettingsList *list,
+ const char *uuid_or_name,
+ GError **error);
+
+GSettings *terminal_profiles_list_ref_profile_by_uuid_or_name (TerminalSettingsList *list,
+ const char *uuid_or_name,
+ GError **error);
+
+int terminal_profiles_compare (gconstpointer pa,
+ gconstpointer pb);
+
+G_END_DECLS
+
+#endif /* TERMINAL_PROFILES_LIST_H */
diff --git a/src/terminal-regex.c b/src/terminal-regex.c
new file mode 100644
index 0000000..cf51453
--- /dev/null
+++ b/src/terminal-regex.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright © 2015 Egmont Koblinger
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdio.h>
+
+#include "terminal-regex.h"
+
+#ifdef TERMINAL_REGEX_MAIN
+
+/* Shorthand for expecting the pattern to match the entire input string */
+#define ENTIRE ((char *) 1)
+
+static char*
+get_match (const char *pattern, const char *string, GRegexMatchFlags match_flags)
+{
+ GRegex *regex;
+ GMatchInfo *match_info;
+ gchar *match;
+
+ regex = g_regex_new (pattern, 0, 0, NULL);
+ g_regex_match (regex, string, match_flags, &match_info);
+ match = g_match_info_fetch (match_info, 0);
+
+ g_free (regex);
+ g_free (match_info);
+ return match;
+}
+
+/* Macros rather than functions to report useful line numbers on failure. */
+#define assert_match(__pattern, __string, __expected) do { \
+ gchar *__actual_match = get_match(__pattern, __string, 0); \
+ const gchar *__expected_match = __expected; \
+ if (__expected_match == ENTIRE) __expected_match = __string; \
+ g_assert_cmpstr(__actual_match, ==, __expected_match); \
+ g_free (__actual_match); \
+} while (0)
+
+#define assert_match_anchored(__pattern, __string, __expected) do { \
+ gchar *__actual_match = get_match(__pattern, __string, G_REGEX_MATCH_ANCHORED); \
+ const gchar *__expected_match = __expected; \
+ if (__expected_match == ENTIRE) __expected_match = __string; \
+ g_assert_cmpstr(__actual_match, ==, __expected_match); \
+ g_free (__actual_match); \
+} while (0)
+
+int
+main (int argc, char **argv)
+{
+ /* SCHEME is case insensitive */
+ assert_match_anchored (SCHEME, "http", ENTIRE);
+ assert_match_anchored (SCHEME, "HTTPS", ENTIRE);
+
+ /* USER is nonempty, alphanumeric, dot, plus and dash */
+ assert_match_anchored (USER, "", NULL);
+ assert_match_anchored (USER, "dr.john-smith", ENTIRE);
+ assert_match_anchored (USER, "abc+def@ghi", "abc+def");
+
+ /* PASS is optional colon-prefixed value, allowing quite some characters, but definitely not @ */
+ assert_match_anchored (PASS, "", ENTIRE);
+ assert_match_anchored (PASS, "nocolon", "");
+ assert_match_anchored (PASS, ":s3cr3T", ENTIRE);
+ assert_match_anchored (PASS, ":$?#@host", ":$?#");
+
+ /* Hostname of at least 1 component, containing at least one non-digit in at least one of the segments */
+ assert_match_anchored (HOSTNAME1, "example.com", ENTIRE);
+ assert_match_anchored (HOSTNAME1, "a-b.c-d", ENTIRE);
+ assert_match_anchored (HOSTNAME1, "a_b", "a"); /* TODO: can/should we totally abort here? */
+ assert_match_anchored (HOSTNAME1, "déjà-vu.com", ENTIRE);
+ assert_match_anchored (HOSTNAME1, "➡.ws", ENTIRE);
+ assert_match_anchored (HOSTNAME1, "cömbining-áccents", ENTIRE);
+ assert_match_anchored (HOSTNAME1, "12", NULL);
+ assert_match_anchored (HOSTNAME1, "12.34", NULL);
+ assert_match_anchored (HOSTNAME1, "12.ab", ENTIRE);
+// assert_match_anchored (HOSTNAME1, "ab.12", NULL); /* errr... could we fail here?? */
+
+ /* Hostname of at least 2 components, containing at least one non-digit in at least one of the segments */
+ assert_match_anchored (HOSTNAME2, "example.com", ENTIRE);
+ assert_match_anchored (HOSTNAME2, "example", NULL);
+ assert_match_anchored (HOSTNAME2, "12", NULL);
+ assert_match_anchored (HOSTNAME2, "12.34", NULL);
+ assert_match_anchored (HOSTNAME2, "12.ab", ENTIRE);
+ assert_match_anchored (HOSTNAME2, "ab.12", NULL);
+// assert_match_anchored (HOSTNAME2, "ab.cd.12", NULL); /* errr... could we fail here?? */
+
+ /* IPv4 segment (number between 0 and 255) */
+ assert_match_anchored (DEFS "(?&S4)", "0", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "1", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "9", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "10", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "99", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "100", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "200", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "250", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "255", ENTIRE);
+ assert_match_anchored (DEFS "(?&S4)", "256", NULL);
+ assert_match_anchored (DEFS "(?&S4)", "260", NULL);
+ assert_match_anchored (DEFS "(?&S4)", "300", NULL);
+ assert_match_anchored (DEFS "(?&S4)", "1000", NULL);
+ assert_match_anchored (DEFS "(?&S4)", "", NULL);
+ assert_match_anchored (DEFS "(?&S4)", "a1b", NULL);
+
+ /* IPv4 addresses */
+ assert_match_anchored (DEFS "(?&IPV4)", "11.22.33.44", ENTIRE);
+ assert_match_anchored (DEFS "(?&IPV4)", "0.1.254.255", ENTIRE);
+ assert_match_anchored (DEFS "(?&IPV4)", "75.150.225.300", NULL);
+ assert_match_anchored (DEFS "(?&IPV4)", "1.2.3.4.5", "1.2.3.4"); /* we could also bail out and not match at all */
+
+ /* IPv6 addresses */
+ assert_match_anchored (DEFS "(?&IPV6)", "11:::22", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22::33:44::55:66", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "dead::beef", ENTIRE);
+ assert_match_anchored (DEFS "(?&IPV6)", "faded::bee", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "live::pork", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "::1", ENTIRE);
+ assert_match_anchored (DEFS "(?&IPV6)", "11::22:33::44", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:::33", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "dead:beef::192.168.1.1", ENTIRE);
+ assert_match_anchored (DEFS "(?&IPV6)", "192.168.1.1", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:77:87654", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22::33:45678", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:192.168.1.12345", NULL);
+
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:77", NULL); /* no :: */
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:77:88", ENTIRE);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:77:88:99", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "::11:22:33:44:55:66:77", ENTIRE); /* :: at the start */
+ assert_match_anchored (DEFS "(?&IPV6)", "::11:22:33:44:55:66:77:88", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33::44:55:66:77", ENTIRE); /* :: in the middle */
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33::44:55:66:77:88", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:77::", ENTIRE); /* :: at the end */
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:77:88::", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "::", ENTIRE); /* :: only */
+
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:192.168.1.1", NULL); /* no :: */
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:192.168.1.1", ENTIRE);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66:77:192.168.1.1", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "::11:22:33:44:55:192.168.1.1", ENTIRE); /* :: at the start */
+ assert_match_anchored (DEFS "(?&IPV6)", "::11:22:33:44:55:66:192.168.1.1", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33::44:55:192.168.1.1", ENTIRE); /* :: in the imddle */
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33::44:55:66:192.168.1.1", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55::192.168.1.1", ENTIRE); /* :: at the end(ish) */
+ assert_match_anchored (DEFS "(?&IPV6)", "11:22:33:44:55:66::192.168.1.1", NULL);
+ assert_match_anchored (DEFS "(?&IPV6)", "::192.168.1.1", ENTIRE); /* :: only(ish) */
+
+ /* URL_HOST is either a hostname, or an IPv4 address, or a bracket-enclosed IPv6 address */
+ assert_match_anchored (DEFS URL_HOST, "example", ENTIRE);
+ assert_match_anchored (DEFS URL_HOST, "example.com", ENTIRE);
+ assert_match_anchored (DEFS URL_HOST, "11.22.33.44", ENTIRE);
+ assert_match_anchored (DEFS URL_HOST, "[11.22.33.44]", NULL);
+ assert_match_anchored (DEFS URL_HOST, "dead::be:ef", "dead"); /* TODO: can/should we totally abort here? */
+ assert_match_anchored (DEFS URL_HOST, "[dead::be:ef]", ENTIRE);
+
+ /* EMAIL_HOST is either an at least two-component hostname, or a bracket-enclosed IPv[46] address */
+ assert_match_anchored (DEFS EMAIL_HOST, "example", NULL);
+ assert_match_anchored (DEFS EMAIL_HOST, "example.com", ENTIRE);
+ assert_match_anchored (DEFS EMAIL_HOST, "11.22.33.44", NULL);
+ assert_match_anchored (DEFS EMAIL_HOST, "[11.22.33.44]", ENTIRE);
+ assert_match_anchored (DEFS EMAIL_HOST, "[11.22.33.456]", NULL);
+ assert_match_anchored (DEFS EMAIL_HOST, "dead::be:ef", NULL);
+ assert_match_anchored (DEFS EMAIL_HOST, "[dead::be:ef]", ENTIRE);
+
+ /* Number between 1 and 65535 (helper for port) */
+ assert_match_anchored (N_1_65535, "0", NULL);
+ assert_match_anchored (N_1_65535, "1", ENTIRE);
+ assert_match_anchored (N_1_65535, "10", ENTIRE);
+ assert_match_anchored (N_1_65535, "100", ENTIRE);
+ assert_match_anchored (N_1_65535, "1000", ENTIRE);
+ assert_match_anchored (N_1_65535, "10000", ENTIRE);
+ assert_match_anchored (N_1_65535, "60000", ENTIRE);
+ assert_match_anchored (N_1_65535, "65000", ENTIRE);
+ assert_match_anchored (N_1_65535, "65500", ENTIRE);
+ assert_match_anchored (N_1_65535, "65530", ENTIRE);
+ assert_match_anchored (N_1_65535, "65535", ENTIRE);
+ assert_match_anchored (N_1_65535, "65536", NULL);
+ assert_match_anchored (N_1_65535, "65540", NULL);
+ assert_match_anchored (N_1_65535, "65600", NULL);
+ assert_match_anchored (N_1_65535, "66000", NULL);
+ assert_match_anchored (N_1_65535, "70000", NULL);
+ assert_match_anchored (N_1_65535, "100000", NULL);
+ assert_match_anchored (N_1_65535, "", NULL);
+ assert_match_anchored (N_1_65535, "a1b", NULL);
+
+ /* PORT is an optional colon-prefixed value */
+ assert_match_anchored (PORT, "", ENTIRE);
+ assert_match_anchored (PORT, ":1", ENTIRE);
+ assert_match_anchored (PORT, ":65535", ENTIRE);
+ assert_match_anchored (PORT, ":65536", ""); /* TODO: can/should we totally abort here? */
+
+ /* Parentheses are only allowed in matching pairs, see bug 763980. */
+ /* TODO: add tests for PATHCHARS and PATHNONTERM; and/or URLPATH */
+ assert_match_anchored (DEFS URLPATH, "/ab/cd", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/ab/cd.html.", "/ab/cd.html");
+ assert_match_anchored (DEFS URLPATH, "/The_Offspring_(album)", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/The_Offspring)", "/The_Offspring");
+ assert_match_anchored (DEFS URLPATH, "/a((b(c)d)e(f))", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/a((b(c)d)e(f)))", "/a((b(c)d)e(f))");
+ assert_match_anchored (DEFS URLPATH, "/a(b).(c).", "/a(b).(c)");
+ assert_match_anchored (DEFS URLPATH, "/a.(b.(c.).).(d.(e.).).)", "/a.(b.(c.).).(d.(e.).)");
+ assert_match_anchored (DEFS URLPATH, "/a)b(c", "/a");
+ assert_match_anchored (DEFS URLPATH, "/.", "/");
+ assert_match_anchored (DEFS URLPATH, "/(.", "/");
+ assert_match_anchored (DEFS URLPATH, "/).", "/");
+ assert_match_anchored (DEFS URLPATH, "/().", "/()");
+ assert_match_anchored (DEFS URLPATH, "/", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/php?param[]=value1&param[]=value2", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/foo?param1[index1]=value1&param2[index2]=value2", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/[[[]][]]", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/[([])]([()])", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/([()])[([])]", ENTIRE);
+ assert_match_anchored (DEFS URLPATH, "/[(])", "/");
+ assert_match_anchored (DEFS URLPATH, "/([)]", "/");
+
+
+ /* Put the components together and test the big picture */
+
+ assert_match (REGEX_URL_AS_IS, "There's no URL here http:/foo", NULL);
+ assert_match (REGEX_URL_AS_IS, "Visit http://example.com for details", "http://example.com");
+ assert_match (REGEX_URL_AS_IS, "Trailing dot http://foo/bar.html.", "http://foo/bar.html");
+ assert_match (REGEX_URL_AS_IS, "Trailing ellipsis http://foo/bar.html...", "http://foo/bar.html");
+ assert_match (REGEX_URL_AS_IS, "Trailing comma http://foo/bar,baz,", "http://foo/bar,baz");
+ assert_match (REGEX_URL_AS_IS, "Trailing semicolon http://foo/bar;baz;", "http://foo/bar;baz");
+ assert_match (REGEX_URL_AS_IS, "See <http://foo/bar>", "http://foo/bar");
+ assert_match (REGEX_URL_AS_IS, "<http://foo.bar/asdf.qwer.html>", "http://foo.bar/asdf.qwer.html");
+ assert_match (REGEX_URL_AS_IS, "Go to http://192.168.1.1.", "http://192.168.1.1");
+ assert_match (REGEX_URL_AS_IS, "If not, see <http://www.gnu.org/licenses/>.", "http://www.gnu.org/licenses/");
+ assert_match (REGEX_URL_AS_IS, "<a href=\"http://foo/bar\">foo</a>", "http://foo/bar");
+ assert_match (REGEX_URL_AS_IS, "<a href='http://foo/bar'>foo</a>", "http://foo/bar");
+ assert_match (REGEX_URL_AS_IS, "<url>http://foo/bar</url>", "http://foo/bar");
+
+ assert_match (REGEX_URL_AS_IS, "http://", NULL);
+ assert_match (REGEX_URL_AS_IS, "http://a", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://aa.", "http://aa");
+ assert_match (REGEX_URL_AS_IS, "http://aa.b", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://aa.bb", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://aa.bb/c", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://aa.bb/cc", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://aa.bb/cc/", ENTIRE);
+
+ assert_match (REGEX_URL_AS_IS, "HtTp://déjà-vu.com:10000/déjà/vu", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "HTTP://joe:sEcReT@➡.ws:1080", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "https://cömbining-áccents", ENTIRE);
+
+ assert_match (REGEX_URL_AS_IS, "http://111.222.33.44", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://111.222.33.44/", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://111.222.33.44/foo", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://1.2.3.4:5555/xyz", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "https://[dead::beef]:12345/ipv6", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "https://[dead::beef:11.22.33.44]", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://1.2.3.4:", "http://1.2.3.4"); /* TODO: can/should we totally abort here? */
+ assert_match (REGEX_URL_AS_IS, "https://dead::beef/no-brackets-ipv6", "https://dead"); /* ditto */
+ assert_match (REGEX_URL_AS_IS, "http://111.222.333.444/", NULL);
+ assert_match (REGEX_URL_AS_IS, "http://1.2.3.4:70000", "http://1.2.3.4"); /* TODO: can/should we totally abort here? */
+ assert_match (REGEX_URL_AS_IS, "http://[dead::beef:111.222.333.444]", NULL);
+
+ /* Username, password */
+ assert_match (REGEX_URL_AS_IS, "http://joe@example.com", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://user.name:sec.ret@host.name", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://joe:secret@[::1]", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://dudewithnopassword:@example.com", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://safeguy:!#$%^&*@host", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http://invalidusername!@host", "http://invalidusername");
+
+ assert_match (REGEX_URL_AS_IS, "http://ab.cd/ef?g=h&i=j|k=l#m=n:o=p", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "http:///foo", NULL);
+
+ /* Parentheses are only allowed in matching pairs, see bug 763980. */
+ assert_match (REGEX_URL_AS_IS, "https://en.wikipedia.org/wiki/The_Offspring_(album)", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "[markdown](https://en.wikipedia.org/wiki/The_Offspring)", "https://en.wikipedia.org/wiki/The_Offspring");
+ assert_match (REGEX_URL_AS_IS, "[markdown](https://en.wikipedia.org/wiki/The_Offspring_(album))", "https://en.wikipedia.org/wiki/The_Offspring_(album)");
+ assert_match (REGEX_URL_AS_IS, "[markdown](http://foo.bar/(a(b)c)d)e)f", "http://foo.bar/(a(b)c)d");
+ assert_match (REGEX_URL_AS_IS, "[markdown](http://foo.bar/a)b(c", "http://foo.bar/a");
+
+ /* Apostrophes are allowed, except at trailing position if the URL is preceded by an apostrophe, see bug 448044. */
+ assert_match (REGEX_URL_AS_IS, "https://en.wikipedia.org/wiki/Moore's_law", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "<a href=\"https://en.wikipedia.org/wiki/Moore's_law\">", "https://en.wikipedia.org/wiki/Moore's_law");
+ assert_match (REGEX_URL_AS_IS, "https://en.wikipedia.org/wiki/Cryin'", ENTIRE);
+ assert_match (REGEX_URL_AS_IS, "<a href=\"https://en.wikipedia.org/wiki/Cryin'\">", "https://en.wikipedia.org/wiki/Cryin'");
+ assert_match (REGEX_URL_AS_IS, "<a href='https://en.wikipedia.org/wiki/Aerosmith'>", "https://en.wikipedia.org/wiki/Aerosmith");
+
+ /* No scheme */
+ assert_match (REGEX_URL_HTTP, "www.foo.bar/baz", ENTIRE);
+ assert_match (REGEX_URL_HTTP, "WWW3.foo.bar/baz", ENTIRE);
+ assert_match (REGEX_URL_HTTP, "FTP.FOO.BAR/BAZ", ENTIRE); /* FIXME if no scheme is given and url starts with ftp, can we make the protocol ftp instead of http? */
+ assert_match (REGEX_URL_HTTP, "ftpxy.foo.bar/baz", ENTIRE);
+// assert_match (REGEX_URL_HTTP, "ftp.123/baz", NULL); /* errr... could we fail here?? */
+ assert_match (REGEX_URL_HTTP, "foo.bar/baz", NULL);
+ assert_match (REGEX_URL_HTTP, "abc.www.foo.bar/baz", NULL);
+ assert_match (REGEX_URL_HTTP, "uvwww.foo.bar/baz", NULL);
+ assert_match (REGEX_URL_HTTP, "xftp.foo.bar/baz", NULL);
+
+ /* file:/ or file://(hostname)?/ */
+ assert_match (REGEX_URL_FILE, "file:", NULL);
+ assert_match (REGEX_URL_FILE, "file:/", ENTIRE);
+ assert_match (REGEX_URL_FILE, "file://", NULL);
+ assert_match (REGEX_URL_FILE, "file:///", ENTIRE);
+ assert_match (REGEX_URL_FILE, "file:////", NULL);
+ assert_match (REGEX_URL_FILE, "file:etc/passwd", NULL);
+ assert_match (REGEX_URL_FILE, "File:/etc/passwd", ENTIRE);
+ assert_match (REGEX_URL_FILE, "FILE:///etc/passwd", ENTIRE);
+ assert_match (REGEX_URL_FILE, "file:////etc/passwd", NULL);
+ assert_match (REGEX_URL_FILE, "file://host.name", NULL);
+ assert_match (REGEX_URL_FILE, "file://host.name/", ENTIRE);
+ assert_match (REGEX_URL_FILE, "file://host.name/etc", ENTIRE);
+
+ assert_match (REGEX_URL_FILE, "See file:/.", "file:/");
+ assert_match (REGEX_URL_FILE, "See file:///.", "file:///");
+ assert_match (REGEX_URL_FILE, "See file:/lost+found.", "file:/lost+found");
+ assert_match (REGEX_URL_FILE, "See file:///lost+found.", "file:///lost+found");
+
+ /* Email */
+ assert_match (REGEX_EMAIL, "Write to foo@bar.com.", "foo@bar.com");
+ assert_match (REGEX_EMAIL, "Write to <foo@bar.com>", "foo@bar.com");
+ assert_match (REGEX_EMAIL, "Write to mailto:foo@bar.com.", "mailto:foo@bar.com");
+ assert_match (REGEX_EMAIL, "Write to MAILTO:FOO@BAR.COM.", "MAILTO:FOO@BAR.COM");
+ assert_match (REGEX_EMAIL, "Write to foo@[1.2.3.4]", "foo@[1.2.3.4]");
+ assert_match (REGEX_EMAIL, "Write to foo@[1.2.3.456]", NULL);
+ assert_match (REGEX_EMAIL, "Write to foo@[1::2345]", "foo@[1::2345]");
+ assert_match (REGEX_EMAIL, "Write to foo@[dead::beef]", "foo@[dead::beef]");
+ assert_match (REGEX_EMAIL, "Write to foo@1.2.3.4", NULL);
+ assert_match (REGEX_EMAIL, "Write to foo@1.2.3.456", NULL);
+ assert_match (REGEX_EMAIL, "Write to foo@1::2345", NULL);
+ assert_match (REGEX_EMAIL, "Write to foo@dead::beef", NULL);
+ assert_match (REGEX_EMAIL, "<baz email=\"foo@bar.com\"/>", "foo@bar.com");
+ assert_match (REGEX_EMAIL, "<baz email='foo@bar.com'/>", "foo@bar.com");
+ assert_match (REGEX_EMAIL, "<email>foo@bar.com</email>", "foo@bar.com");
+
+ /* Sip, examples from rfc 3261 */
+ assert_match (REGEX_URL_VOIP, "sip:alice@atlanta.com;maddr=239.255.255.1;ttl=15", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "sip:alice@atlanta.com", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "sip:alice:secretword@atlanta.com;transport=tcp", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "sips:alice@atlanta.com?subject=project%20x&priority=urgent", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "sip:+1-212-555-1212:1234@gateway.com;user=phone", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "sips:1212@gateway.com", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "sip:alice@192.0.2.4", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "sip:atlanta.com;method=REGISTER?to=alice%40atlanta.com", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "SIP:alice;day=tuesday@atlanta.com", ENTIRE);
+ assert_match (REGEX_URL_VOIP, "Dial sip:alice@192.0.2.4.", "sip:alice@192.0.2.4");
+
+ /* Extremely long match, bug 770147 */
+ assert_match (REGEX_URL_AS_IS, "http://www.example.com/ThisPathConsistsOfMoreThan1024Characters"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", ENTIRE);
+
+ printf("terminal-regex tests passed :)\n");
+ return 0;
+}
+
+#endif /* TERMINAL_REGEX_MAIN */
diff --git a/src/terminal-regex.h b/src/terminal-regex.h
new file mode 100644
index 0000000..143a8fa
--- /dev/null
+++ b/src/terminal-regex.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright © 2015 Egmont Koblinger
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Mini style-guide:
+ *
+ * #define'd fragments should preferably have an outermost group, for the
+ * exact same reason as why usually in C/C++ #define's the values are enclosed
+ * in parentheses: that is, so that you don't get surprised when you use the
+ * macro and append a quantifier.
+ *
+ * For repeated fragments prefer regex-style (?(DEFINE)(?<NAME>(...))) and use
+ * as (?&NAME), so that the regex string and the compiled regex object is
+ * smaller.
+ *
+ * Build small blocks, comment and unittest them heavily.
+ *
+ * Use free-spacing mode for improved readability. The hardest to read is
+ * which additional characters belong to a "(?" prefix. To improve
+ * readability, place a space after this, and for symmetry, before the closing
+ * parenthesis. Also place a space around "|" characters. No space before
+ * quantifiers. Try to be consistent with the existing style (yes I know the
+ * existing style is not consistent either, but please do your best).
+ *
+ * See http://www.rexegg.com/regex-disambiguation.html for all the "(?"
+ * syntaxes.
+ */
+
+#ifndef TERMINAL_REGEX_H
+#define TERMINAL_REGEX_H
+
+/* Lookbehind to see if there's a preceding apostrophe.
+ * Unlike the other *_DEF macros which define regex subroutines,
+ * this one is a named capture that defines APOS_START to either
+ * an apostrophe or the empty string, depending on the character
+ * preceding this APOS_START_DEF construct. */
+#define APOS_START_DEF "(?<APOS_START>(?<='))?"
+
+#define SCHEME "(?ix: news | telnet | nntp | https? | ftps? | sftp | webcal )"
+
+#define USERCHARS "-+.[:alnum:]"
+/* Nonempty username, e.g. "john.smith" */
+#define USER "[" USERCHARS "]+"
+
+#define PASSCHARS_CLASS "[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]"
+/* Optional colon-prefixed password. I guess empty password should be allowed, right? E.g. ":secret", ":", "" */
+#define PASS "(?x: :" PASSCHARS_CLASS "* )?"
+
+/* Optional at-terminated username (with perhaps a password too), e.g. "joe@", "pete:secret@", "" */
+#define USERPASS "(?:" USER PASS "@)?"
+
+/* S4: IPv4 segment (number between 0 and 255) with lookahead at the end so that we don't match "25" in the string "256".
+ The lookahead could go to the last segment of IPv4 only but this construct allows nicer unittesting. */
+#define S4_DEF "(?(DEFINE)(?<S4>(?x: (?: [0-9] | [1-9][0-9] | 1[0-9]{2} | 2[0-4][0-9] | 25[0-5] ) (?! [0-9] ) )))"
+
+/* IPV4: Decimal IPv4, e.g. "1.2.3.4", with lookahead (implemented in S4) at the end so that we don't match "192.168.1.123" in the string "192.168.1.1234". */
+#define IPV4_DEF S4_DEF "(?(DEFINE)(?<IPV4>(?x: (?: (?&S4) \\. ){3} (?&S4) )))"
+
+/* IPv6, including embedded IPv4, e.g. "::1", "dead:beef::1.2.3.4".
+ * Lookahead for the next char not being a dot or digit, so it doesn't get stuck matching "dead:beef::1" in "dead:beef::1.2.3.4".
+ * This is not required since the surrounding brackets would trigger backtracking, but it allows nicer unittesting.
+ * TODO: more strict check (right number of colons, etc.)
+ * TODO: add zone_id: RFC 4007 section 11, RFC 6874 */
+
+/* S6: IPv6 segment, S6C: IPv6 segment followed by a comma, CS6: comma followed by an IPv6 segment */
+#define S6_DEF "(?(DEFINE)(?<S6>[[:xdigit:]]{1,4})(?<CS6>:(?&S6))(?<S6C>(?&S6):))"
+
+/* No :: shorthand */
+#define IPV6_FULL "(?x: (?&S6C){7} (?&S6) )"
+/* Begins with :: */
+#define IPV6_LEFT "(?x: : (?&CS6){1,7} )"
+/* :: somewhere in the middle - use negative lookahead to make sure there aren't too many colons in total */
+#define IPV6_MID "(?x: (?! (?: [[:xdigit:]]*: ){8} ) (?&S6C){1,6} (?&CS6){1,6} )"
+/* Ends with :: */
+#define IPV6_RIGHT "(?x: (?&S6C){1,7} : )"
+/* Is "::" and nothing more */
+#define IPV6_NULL "(?x: :: )"
+
+/* The same ones for IPv4-embedded notation, without the actual IPv4 part */
+#define IPV6V4_FULL "(?x: (?&S6C){6} )"
+#define IPV6V4_LEFT "(?x: :: (?&S6C){0,5} )" /* includes "::<ipv4>" */
+#define IPV6V4_MID "(?x: (?! (?: [[:xdigit:]]*: ){7} ) (?&S6C){1,4} (?&CS6){1,4} ) :"
+#define IPV6V4_RIGHT "(?x: (?&S6C){1,5} : )"
+
+/* IPV6: An IPv6 address (possibly with an embedded IPv4).
+ * This macro defines both IPV4 and IPV6, since the latter one requires the former. */
+#define IP_DEF IPV4_DEF S6_DEF "(?(DEFINE)(?<IPV6>(?x: (?: " IPV6_NULL " | " IPV6_LEFT " | " IPV6_MID " | " IPV6_RIGHT " | " IPV6_FULL " | (?: " IPV6V4_FULL " | " IPV6V4_LEFT " | " IPV6V4_MID " | " IPV6V4_RIGHT " ) (?&IPV4) ) (?! [.:[:xdigit:]] ) )))"
+
+/* Either an alphanumeric character or dash; or if [negative lookahead] not ASCII
+ * then any graphical Unicode character.
+ * A segment can consist entirely of numbers.
+ * (Note: PCRE doesn't support character class subtraction/intersection.) */
+#define HOSTNAMESEGMENTCHARS_CLASS "(?x: [-[:alnum:]] | (?! [[:ascii:]] ) [[:graph:]] )"
+
+/* A hostname of at least 1 component. The last component cannot be entirely numbers.
+ * E.g. "foo", "example.com", "1234.com", but not "foo.123" */
+#define HOSTNAME1 "(?x: (?: " HOSTNAMESEGMENTCHARS_CLASS "+ \\. )* " HOSTNAMESEGMENTCHARS_CLASS "* (?! [0-9] ) " HOSTNAMESEGMENTCHARS_CLASS "+ )"
+
+/* A hostname of at least 2 components. The last component cannot be entirely numbers.
+ * E.g. "example.com", "1234.com", but not "1234.56" */
+#define HOSTNAME2 "(?x: (?: " HOSTNAMESEGMENTCHARS_CLASS "+ \\.)+ " HOSTNAME1 " )"
+
+/* For URL: Hostname, IPv4, or bracket-enclosed IPv6, e.g. "example.com", "1.2.3.4", "[::1]" */
+#define URL_HOST "(?x: " HOSTNAME1 " | (?&IPV4) | \\[ (?&IPV6) \\] )"
+
+/* For e-mail: Hostname of at least two segments, or bracket-enclosed IPv4 or IPv6, e.g. "example.com", "[1.2.3.4]", "[::1]".
+ * Technically an e-mail with a single-component hostname might be valid on a local network, but let's avoid tons of false positives (e.g. in a typical shell prompt). */
+#define EMAIL_HOST "(?x: " HOSTNAME2 " | \\[ (?: (?&IPV4) | (?&IPV6) ) \\] )"
+
+/* Number between 1 and 65535, with lookahead at the end so that we don't match "6789" in the string "67890",
+ and in turn we don't eventually match "http://host:6789" in "http://host:67890". */
+#define N_1_65535 "(?x: (?: [1-9][0-9]{0,3} | [1-5][0-9]{4} | 6[0-4][0-9]{3} | 65[0-4][0-9]{2} | 655[0-2][0-9] | 6553[0-5] ) (?! [0-9] ) )"
+
+/* Optional colon-prefixed port, e.g. ":1080", "" */
+#define PORT "(?x: \\:" N_1_65535 " )?"
+
+/* Omit the parentheses, see below */
+#define PATHCHARS_CLASS "[-[:alnum:]\\Q_$.+!*,:;@&=?/~#|%'\\E]"
+/* Chars to end a URL. Apostrophe only allowed if there wasn't one in front of the URL, see bug 448044 */
+#define PATHTERM_CLASS "[-[:alnum:]\\Q_$+*:@&=/~#|%'\\E]"
+#define PATHTERM_NOAPOS_CLASS "[-[:alnum:]\\Q_$+*:@&=/~#|%\\E]"
+
+/* Recursive definition of PATH that allows parentheses and square brackets only if balanced, see bug 763980. */
+#define PATH_INNER_DEF "(?(DEFINE)(?<PATH_INNER>(?x: (?: " PATHCHARS_CLASS "* (?: \\( (?&PATH_INNER) \\) | \\[ (?&PATH_INNER) \\] ) )* " PATHCHARS_CLASS "* )))"
+/* Same as above, but the last character (if exists and is not a parenthesis) must be from PATHTERM_CLASS. */
+#define PATH_DEF "(?(DEFINE)(?<PATH>(?x: (?: " PATHCHARS_CLASS "* (?: \\( (?&PATH_INNER) \\) | \\[ (?&PATH_INNER) \\] ) )* (?: " PATHCHARS_CLASS "* (?(<APOS_START>)" PATHTERM_NOAPOS_CLASS "|" PATHTERM_CLASS ") )? )))"
+
+#define URLPATH "(?x: /(?&PATH) )?"
+#define VOIP_PATH "(?x: [;?](?&PATH) )?"
+
+/* Now let's put these fragments together */
+
+#define DEFS APOS_START_DEF IP_DEF PATH_INNER_DEF PATH_DEF
+
+#define REGEX_URL_AS_IS DEFS SCHEME "://" USERPASS URL_HOST PORT URLPATH
+/* TODO: also support file:/etc/passwd */
+#define REGEX_URL_FILE DEFS "(?ix: file:/ (?: / (?: " HOSTNAME1 " )? / )? (?! / ) )(?&PATH)"
+/* Lookbehind so that we don't catch "abc.www.foo.bar", bug 739757. Lookahead for www/ftp for convenience (so that we can reuse HOSTNAME1). */
+/* The commented-out variant looks more like our other definitions, but fails with PCRE 10.34. See GNOME/gnome-terminal#221.
+ * TODO: revert to this nicer pattern some time after 10.35's release.
+ * #define REGEX_URL_HTTP DEFS "(?<!(?:" HOSTNAMESEGMENTCHARS_CLASS "|[.]))(?=(?i:www|ftp))" HOSTNAME1 PORT URLPATH
+ */
+#define REGEX_URL_HTTP APOS_START_DEF "(?<!(?:" HOSTNAMESEGMENTCHARS_CLASS "|[.]))(?=(?i:www|ftp))" HOSTNAME1 PORT PATH_INNER_DEF PATH_DEF URLPATH
+#define REGEX_URL_VOIP DEFS "(?i:h323:|sips?:)" USERPASS URL_HOST PORT VOIP_PATH
+#define REGEX_EMAIL DEFS "(?i:mailto:)?" USER "@" EMAIL_HOST
+#define REGEX_NEWS_MAN "(?i:news:|man:|info:)[-[:alnum:]\\Q^_{|}~!\"#$%&'()*+,./;:=?`\\E]+"
+
+#endif /* !TERMINAL_REGEX_H */
diff --git a/src/terminal-schemas.h b/src/terminal-schemas.h
new file mode 100644
index 0000000..cffc4ed
--- /dev/null
+++ b/src/terminal-schemas.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2008, 2010 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_SCHEMAS_H
+#define TERMINAL_SCHEMAS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define TERMINAL_SCHEMA_VERSION (3u)
+
+#define TERMINAL_KEYBINDINGS_SCHEMA "org.gnome.Terminal.Legacy.Keybindings"
+#define TERMINAL_PROFILE_SCHEMA "org.gnome.Terminal.Legacy.Profile"
+#define TERMINAL_SETTING_SCHEMA "org.gnome.Terminal.Legacy.Settings"
+#define TERMINAL_SETTINGS_LIST_SCHEMA "org.gnome.Terminal.SettingsList"
+#define TERMINAL_PROFILES_LIST_SCHEMA "org.gnome.Terminal.ProfilesList"
+
+#define TERMINAL_PROFILE_AUDIBLE_BELL_KEY "audible-bell"
+#define TERMINAL_PROFILE_BOLD_IS_BRIGHT_KEY "bold-is-bright"
+#define TERMINAL_PROFILE_BACKGROUND_COLOR_KEY "background-color"
+#define TERMINAL_PROFILE_BACKSPACE_BINDING_KEY "backspace-binding"
+#define TERMINAL_PROFILE_BOLD_COLOR_KEY "bold-color"
+#define TERMINAL_PROFILE_BOLD_COLOR_SAME_AS_FG_KEY "bold-color-same-as-fg"
+#define TERMINAL_PROFILE_CELL_HEIGHT_SCALE_KEY "cell-height-scale"
+#define TERMINAL_PROFILE_CELL_WIDTH_SCALE_KEY "cell-width-scale"
+#define TERMINAL_PROFILE_CURSOR_COLORS_SET_KEY "cursor-colors-set"
+#define TERMINAL_PROFILE_CURSOR_BACKGROUND_COLOR_KEY "cursor-background-color"
+#define TERMINAL_PROFILE_CURSOR_FOREGROUND_COLOR_KEY "cursor-foreground-color"
+#define TERMINAL_PROFILE_CJK_UTF8_AMBIGUOUS_WIDTH_KEY "cjk-utf8-ambiguous-width"
+#define TERMINAL_PROFILE_CURSOR_BLINK_MODE_KEY "cursor-blink-mode"
+#define TERMINAL_PROFILE_CURSOR_SHAPE_KEY "cursor-shape"
+#define TERMINAL_PROFILE_CUSTOM_COMMAND_KEY "custom-command"
+#define TERMINAL_PROFILE_DEFAULT_SIZE_COLUMNS_KEY "default-size-columns"
+#define TERMINAL_PROFILE_DEFAULT_SIZE_ROWS_KEY "default-size-rows"
+#define TERMINAL_PROFILE_DELETE_BINDING_KEY "delete-binding"
+#define TERMINAL_PROFILE_ENABLE_BIDI_KEY "enable-bidi"
+#define TERMINAL_PROFILE_ENABLE_SHAPING_KEY "enable-shaping"
+#define TERMINAL_PROFILE_ENABLE_SIXEL_KEY "enable-sixel"
+#define TERMINAL_PROFILE_ENCODING_KEY "encoding"
+#define TERMINAL_PROFILE_EXIT_ACTION_KEY "exit-action"
+#define TERMINAL_PROFILE_FONT_KEY "font"
+#define TERMINAL_PROFILE_FOREGROUND_COLOR_KEY "foreground-color"
+#define TERMINAL_PROFILE_HIGHLIGHT_COLORS_SET_KEY "highlight-colors-set"
+#define TERMINAL_PROFILE_HIGHLIGHT_BACKGROUND_COLOR_KEY "highlight-background-color"
+#define TERMINAL_PROFILE_HIGHLIGHT_FOREGROUND_COLOR_KEY "highlight-foreground-color"
+#define TERMINAL_PROFILE_LOGIN_SHELL_KEY "login-shell"
+#define TERMINAL_PROFILE_NAME_KEY "name"
+#define TERMINAL_PROFILE_PALETTE_KEY "palette"
+#define TERMINAL_PROFILE_PRESERVE_WORKING_DIRECTORY_KEY "preserve-working-directory"
+#define TERMINAL_PROFILE_REWRAP_ON_RESIZE_KEY "rewrap-on-resize"
+#define TERMINAL_PROFILE_SCROLLBACK_LINES_KEY "scrollback-lines"
+#define TERMINAL_PROFILE_SCROLLBACK_UNLIMITED_KEY "scrollback-unlimited"
+#define TERMINAL_PROFILE_SCROLLBAR_POLICY_KEY "scrollbar-policy"
+#define TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE_KEY "scroll-on-keystroke"
+#define TERMINAL_PROFILE_SCROLL_ON_OUTPUT_KEY "scroll-on-output"
+#define TERMINAL_PROFILE_TEXT_BLINK_MODE_KEY "text-blink-mode"
+#define TERMINAL_PROFILE_USE_CUSTOM_COMMAND_KEY "use-custom-command"
+#define TERMINAL_PROFILE_USE_SKEY_KEY "use-skey"
+#define TERMINAL_PROFILE_USE_SYSTEM_FONT_KEY "use-system-font"
+#define TERMINAL_PROFILE_USE_THEME_COLORS_KEY "use-theme-colors"
+#define TERMINAL_PROFILE_VISIBLE_NAME_KEY "visible-name"
+#define TERMINAL_PROFILE_WORD_CHAR_EXCEPTIONS_KEY "word-char-exceptions"
+
+#define TERMINAL_SETTING_CONFIRM_CLOSE_KEY "confirm-close"
+#define TERMINAL_SETTING_DEFAULT_SHOW_MENUBAR_KEY "default-show-menubar"
+#define TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY "menu-accelerator-enabled"
+#define TERMINAL_SETTING_ENABLE_MNEMONICS_KEY "mnemonics-enabled"
+#define TERMINAL_SETTING_ENABLE_SHORTCUTS_KEY "shortcuts-enabled"
+#define TERMINAL_SETTING_HEADERBAR_KEY "headerbar"
+#define TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY "new-terminal-mode"
+#define TERMINAL_SETTING_NEW_TAB_POSITION_KEY "new-tab-position"
+#define TERMINAL_SETTING_SCHEMA_VERSION "schema-version"
+#define TERMINAL_SETTING_SHELL_INTEGRATION_KEY "shell-integration-enabled"
+#define TERMINAL_SETTING_TAB_POLICY_KEY "tab-policy"
+#define TERMINAL_SETTING_TAB_POSITION_KEY "tab-position"
+#define TERMINAL_SETTING_THEME_VARIANT_KEY "theme-variant"
+#define TERMINAL_SETTING_UNIFIED_MENU_KEY "unified-menu"
+
+#define TERMINAL_SETTINGS_LIST_LIST_KEY "list"
+#define TERMINAL_SETTINGS_LIST_DEFAULT_KEY "default"
+
+#define TERMINAL_PROFILES_PATH_PREFIX "/org/gnome/terminal/legacy/profiles:/"
+
+G_END_DECLS
+
+#endif /* TERMINAL_SCHEMAS_H */
diff --git a/src/terminal-screen-container.c b/src/terminal-screen-container.c
new file mode 100644
index 0000000..459157b
--- /dev/null
+++ b/src/terminal-screen-container.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright © 2008, 2010, 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-screen-container.h"
+#include "terminal-debug.h"
+
+#if 0
+#define USE_SCROLLED_WINDOW
+#endif
+
+#include <gtk/gtk.h>
+
+#define TERMINAL_SCREEN_CONTAINER_GET_PRIVATE(screen_container)(G_TYPE_INSTANCE_GET_PRIVATE ((screen_container), TERMINAL_TYPE_SCREEN_CONTAINER, TerminalScreenContainerPrivate))
+
+struct _TerminalScreenContainerPrivate
+{
+ TerminalScreen *screen;
+#ifdef USE_SCROLLED_WINDOW
+ GtkWidget *scrolled_window;
+#else
+ GtkWidget *hbox;
+ GtkWidget *vscrollbar;
+#endif
+ GtkPolicyType hscrollbar_policy;
+ GtkPolicyType vscrollbar_policy;
+};
+
+enum
+{
+ PROP_0,
+ PROP_SCREEN,
+ PROP_HSCROLLBAR_POLICY,
+ PROP_VSCROLLBAR_POLICY
+};
+
+G_DEFINE_TYPE (TerminalScreenContainer, terminal_screen_container, GTK_TYPE_OVERLAY)
+
+#define TERMINAL_SCREEN_CONTAINER_CSS_NAME "terminal-screen-container"
+
+/* helper functions */
+
+/* Widget class implementation */
+
+static void
+terminal_screen_container_realize (GtkWidget *widget)
+{
+
+ GTK_WIDGET_CLASS (terminal_screen_container_parent_class)->realize (widget);
+
+ /* We need to realize the screen itself too, see issue #203 */
+ TerminalScreenContainer *container = TERMINAL_SCREEN_CONTAINER (widget);
+ TerminalScreenContainerPrivate *priv = container->priv;
+ gtk_widget_realize (GTK_WIDGET (priv->screen));
+}
+
+#ifndef USE_SCROLLED_WINDOW
+
+static void
+terminal_screen_container_style_updated (GtkWidget *widget)
+{
+ TerminalScreenContainer *container = TERMINAL_SCREEN_CONTAINER (widget);
+ TerminalScreenContainerPrivate *priv = container->priv;
+ GtkCornerType corner;
+ gboolean set;
+
+ GTK_WIDGET_CLASS (terminal_screen_container_parent_class)->style_updated (widget);
+
+ gtk_widget_style_get (widget,
+ "window-placement", &corner,
+ "window-placement-set", &set,
+ NULL);
+
+ if (!set) {
+ g_object_get (gtk_widget_get_settings (widget),
+ "gtk-scrolled-window-placement", &corner,
+ NULL);
+ }
+
+ switch (corner) {
+ case GTK_CORNER_TOP_LEFT:
+ case GTK_CORNER_BOTTOM_LEFT:
+ gtk_box_reorder_child (GTK_BOX (priv->hbox), priv->vscrollbar, -1);
+ break;
+ case GTK_CORNER_TOP_RIGHT:
+ case GTK_CORNER_BOTTOM_RIGHT:
+ gtk_box_reorder_child (GTK_BOX (priv->hbox), priv->vscrollbar, 0);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+#endif /* !USE_SCROLLED_WINDOW */
+
+/* Class implementation */
+
+static void
+terminal_screen_container_init (TerminalScreenContainer *container)
+{
+ TerminalScreenContainerPrivate *priv;
+
+ priv = container->priv = TERMINAL_SCREEN_CONTAINER_GET_PRIVATE (container);
+
+ priv->hscrollbar_policy = GTK_POLICY_AUTOMATIC;
+ priv->vscrollbar_policy = GTK_POLICY_AUTOMATIC;
+}
+
+static void
+terminal_screen_container_constructed (GObject *object)
+{
+ TerminalScreenContainer *container = TERMINAL_SCREEN_CONTAINER (object);
+ TerminalScreenContainerPrivate *priv = container->priv;
+
+ G_OBJECT_CLASS (terminal_screen_container_parent_class)->constructed (object);
+
+ g_assert (priv->screen != NULL);
+
+#ifdef USE_SCROLLED_WINDOW
+{
+ GtkAdjustment *hadjustment;
+ GtkAdjustment *vadjustment;
+
+ hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (priv->screen));
+ vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (priv->screen));
+
+ priv->scrolled_window = gtk_scrolled_window_new (hadjustment, vadjustment);
+ gtk_scrolled_window_set_overlay_scrolling (GTK_SCROLLED_WINDOW (priv->scrolled_window), FALSE);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window),
+ priv->hscrollbar_policy,
+ priv->vscrollbar_policy);
+ gtk_container_add (GTK_CONTAINER (priv->scrolled_window), GTK_WIDGET (priv->screen));
+
+ gtk_container_add (GTK_CONTAINER (container), priv->scrolled_window);
+ gtk_widget_show_all (priv->scrolled_window);
+}
+#else
+ priv->hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ priv->vscrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL,
+ gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (priv->screen)));
+
+ gtk_box_pack_start (GTK_BOX (priv->hbox), GTK_WIDGET (priv->screen), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->hbox), priv->vscrollbar, FALSE, FALSE, 0);
+
+ gtk_container_add (GTK_CONTAINER (container), priv->hbox);
+ gtk_widget_show_all (priv->hbox);
+#endif
+
+ _terminal_screen_update_scrollbar (priv->screen);
+}
+
+static void
+terminal_screen_container_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalScreenContainer *container = TERMINAL_SCREEN_CONTAINER (object);
+ TerminalScreenContainerPrivate *priv = container->priv;
+
+ switch (prop_id) {
+ case PROP_SCREEN:
+ break;
+ case PROP_HSCROLLBAR_POLICY:
+ g_value_set_enum (value, priv->hscrollbar_policy);
+ break;
+ case PROP_VSCROLLBAR_POLICY:
+ g_value_set_enum (value, priv->vscrollbar_policy);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_screen_container_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalScreenContainer *container = TERMINAL_SCREEN_CONTAINER (object);
+ TerminalScreenContainerPrivate *priv = container->priv;
+
+ switch (prop_id) {
+ case PROP_SCREEN:
+ priv->screen = g_value_get_object (value);
+ break;
+ case PROP_HSCROLLBAR_POLICY:
+ terminal_screen_container_set_policy (container,
+ g_value_get_enum (value),
+ priv->vscrollbar_policy);
+ break;
+ case PROP_VSCROLLBAR_POLICY:
+ terminal_screen_container_set_policy (container,
+ priv->hscrollbar_policy,
+ g_value_get_enum (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_screen_container_class_init (TerminalScreenContainerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (gobject_class, sizeof (TerminalScreenContainerPrivate));
+
+ gobject_class->constructed = terminal_screen_container_constructed;
+ gobject_class->get_property = terminal_screen_container_get_property;
+ gobject_class->set_property = terminal_screen_container_set_property;
+
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->realize = terminal_screen_container_realize;
+
+#ifndef USE_SCROLLED_WINDOW
+ widget_class->style_updated = terminal_screen_container_style_updated;
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_enum ("window-placement", NULL, NULL,
+ GTK_TYPE_CORNER_TYPE,
+ GTK_CORNER_BOTTOM_RIGHT,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boolean ("window-placement-set", NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+#endif
+
+ gtk_widget_class_set_css_name(widget_class, TERMINAL_SCREEN_CONTAINER_CSS_NAME);
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_SCREEN,
+ g_param_spec_object ("screen", NULL, NULL,
+ TERMINAL_TYPE_SCREEN,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_HSCROLLBAR_POLICY,
+ g_param_spec_enum ("hscrollbar-policy", NULL, NULL,
+ GTK_TYPE_POLICY_TYPE,
+ GTK_POLICY_AUTOMATIC,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property
+ (gobject_class,
+ PROP_VSCROLLBAR_POLICY,
+ g_param_spec_enum ("vscrollbar-policy", NULL, NULL,
+ GTK_TYPE_POLICY_TYPE,
+ GTK_POLICY_AUTOMATIC,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+}
+
+/* public API */
+
+/**
+ * terminal_screen_container_new:
+ * @screen: a #TerminalScreen
+ *
+ * Returns: a new #TerminalScreenContainer for @screen
+ */
+GtkWidget *
+terminal_screen_container_new (TerminalScreen *screen)
+{
+ return g_object_new (TERMINAL_TYPE_SCREEN_CONTAINER,
+ "screen", screen,
+ NULL);
+}
+
+/**
+ * terminal_screen_container_get_screen:
+ * @container: a #TerminalScreenContainer
+ *
+ * Returns: @container's #TerminalScreen
+ */
+TerminalScreen *
+terminal_screen_container_get_screen (TerminalScreenContainer *container)
+{
+ if (container == NULL)
+ return NULL;
+
+ g_return_val_if_fail (TERMINAL_IS_SCREEN_CONTAINER (container), NULL);
+
+ return container->priv->screen;
+}
+
+/**
+ * terminal_screen_container_get_from_screen:
+ * @screen: a #TerminalScreenContainerPrivate
+ *
+ * Returns the #TerminalScreenContainer containing @screen.
+ */
+TerminalScreenContainer *
+terminal_screen_container_get_from_screen (TerminalScreen *screen)
+{
+ if (screen == NULL)
+ return NULL;
+
+ g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL);
+
+ return TERMINAL_SCREEN_CONTAINER (gtk_widget_get_ancestor (GTK_WIDGET (screen), TERMINAL_TYPE_SCREEN_CONTAINER));
+}
+
+/**
+ * terminal_screen_container_set_policy:
+ * @container: a #TerminalScreenContainer
+ * @hpolicy: a #GtkPolicyType
+ * @vpolicy: a #GtkPolicyType
+ *
+ * Sets @container's scrollbar policy.
+ */
+void
+terminal_screen_container_set_policy (TerminalScreenContainer *container,
+ GtkPolicyType hpolicy,
+ GtkPolicyType vpolicy)
+{
+ TerminalScreenContainerPrivate *priv;
+ GObject *object;
+
+ g_return_if_fail (TERMINAL_IS_SCREEN_CONTAINER (container));
+
+ object = G_OBJECT (container);
+ priv = container->priv;
+
+ g_object_freeze_notify (object);
+
+ if (priv->hscrollbar_policy != hpolicy) {
+ priv->hscrollbar_policy = hpolicy;
+ g_object_notify (object, "hscrollbar-policy");
+ }
+ if (priv->vscrollbar_policy != vpolicy) {
+ priv->vscrollbar_policy = vpolicy;
+ g_object_notify (object, "vscrollbar-policy");
+ }
+
+#ifdef USE_SCROLLED_WINDOW
+ switch (vpolicy) {
+ case GTK_POLICY_NEVER:
+ vpolicy = GTK_POLICY_EXTERNAL;
+ break;
+ case GTK_POLICY_AUTOMATIC:
+ case GTK_POLICY_ALWAYS:
+ vpolicy = GTK_POLICY_ALWAYS;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window), hpolicy, vpolicy);
+#else
+ switch (vpolicy) {
+ case GTK_POLICY_NEVER:
+ gtk_widget_hide (priv->vscrollbar);
+ break;
+ case GTK_POLICY_AUTOMATIC:
+ case GTK_POLICY_ALWAYS:
+ gtk_widget_show (priv->vscrollbar);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+#endif /* USE_SCROLLED_WINDOW */
+
+ g_object_thaw_notify (object);
+}
diff --git a/src/terminal-screen-container.h b/src/terminal-screen-container.h
new file mode 100644
index 0000000..6f816e6
--- /dev/null
+++ b/src/terminal-screen-container.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2008, 2010 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_SCREEN_CONTAINER_H
+#define TERMINAL_SCREEN_CONTAINER_H
+
+#include <gtk/gtk.h>
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_SCREEN_CONTAINER (terminal_screen_container_get_type ())
+#define TERMINAL_SCREEN_CONTAINER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_SCREEN_CONTAINER, TerminalScreenContainer))
+#define TERMINAL_SCREEN_CONTAINER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_SCREEN_CONTAINER, TerminalScreenContainerClass))
+#define TERMINAL_IS_SCREEN_CONTAINER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_SCREEN_CONTAINER))
+#define TERMINAL_IS_SCREEN_CONTAINER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_SCREEN_CONTAINER))
+#define TERMINAL_SCREEN_CONTAINER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_SCREEN_CONTAINER, TerminalScreenContainerClass))
+
+typedef struct _TerminalScreenContainer TerminalScreenContainer;
+typedef struct _TerminalScreenContainerClass TerminalScreenContainerClass;
+typedef struct _TerminalScreenContainerPrivate TerminalScreenContainerPrivate;
+
+struct _TerminalScreenContainer
+{
+ GtkOverlay parent_instance;
+
+ /*< private >*/
+ TerminalScreenContainerPrivate *priv;
+};
+
+struct _TerminalScreenContainerClass
+{
+ GtkOverlayClass parent_class;
+};
+
+GType terminal_screen_container_get_type (void);
+
+GtkWidget *terminal_screen_container_new (TerminalScreen *screen);
+
+TerminalScreen *terminal_screen_container_get_screen (TerminalScreenContainer *container);
+
+TerminalScreenContainer *terminal_screen_container_get_from_screen (TerminalScreen *screen);
+
+void terminal_screen_container_set_policy (TerminalScreenContainer *container,
+ GtkPolicyType hpolicy,
+ GtkPolicyType vpolicy);
+
+G_END_DECLS
+
+#endif /* TERMINAL_SCREEN_CONTAINER_H */
diff --git a/src/terminal-screen.c b/src/terminal-screen.c
new file mode 100644
index 0000000..0c4ee50
--- /dev/null
+++ b/src/terminal-screen.c
@@ -0,0 +1,2324 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2007, 2008, 2010, 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-pcre2.h"
+#include "terminal-regex.h"
+#include "terminal-screen.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <uuid.h>
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
+#include <sys/sysctl.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+#include <gtk/gtk.h>
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+#include "terminal-accels.h"
+#include "terminal-app.h"
+#include "terminal-debug.h"
+#include "terminal-defines.h"
+#include "terminal-enums.h"
+#include "terminal-intl.h"
+#include "terminal-marshal.h"
+#include "terminal-schemas.h"
+#include "terminal-screen-container.h"
+#include "terminal-util.h"
+#include "terminal-window.h"
+#include "terminal-info-bar.h"
+#include "terminal-libgsystem.h"
+
+#include "eggshell.h"
+
+#define URL_MATCH_CURSOR (GDK_HAND2)
+
+typedef struct {
+ volatile int refcount;
+ char **argv; /* as passed */
+ char **exec_argv; /* as processed */
+ char **envv;
+ char *cwd;
+ gboolean as_shell;
+
+ VtePtyFlags pty_flags;
+ GSpawnFlags spawn_flags;
+
+ /* FD passing */
+ GUnixFDList *fd_list;
+ int n_fd_map;
+ int* fd_map;
+
+ /* async exec callback */
+ TerminalScreenExecCallback callback;
+ gpointer callback_data;
+ GDestroyNotify callback_data_destroy_notify;
+
+ /* Cancellable */
+ GCancellable *cancellable;
+} ExecData;
+
+typedef struct
+{
+ int tag;
+ TerminalURLFlavor flavor;
+} TagData;
+
+struct _TerminalScreenPrivate
+{
+ char *uuid;
+ gboolean registered; /* D-Bus interface is registered */
+
+ GSettings *profile; /* never NULL */
+ guint profile_changed_id;
+ guint profile_forgotten_id;
+ int child_pid;
+ GSList *match_tags;
+ gboolean exec_on_realize;
+ guint idle_exec_source;
+ ExecData *exec_data;
+};
+
+enum
+{
+ PROFILE_SET,
+ SHOW_POPUP_MENU,
+ MATCH_CLICKED,
+ CLOSE_SCREEN,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_PROFILE,
+ PROP_TITLE,
+};
+
+enum
+{
+ TARGET_COLOR,
+ TARGET_BGIMAGE,
+ TARGET_RESET_BG,
+ TARGET_MOZ_URL,
+ TARGET_NETSCAPE_URL,
+ TARGET_TAB
+};
+
+static void terminal_screen_constructed (GObject *object);
+static void terminal_screen_dispose (GObject *object);
+static void terminal_screen_finalize (GObject *object);
+static void terminal_screen_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time);
+static void terminal_screen_set_font (TerminalScreen *screen);
+static void terminal_screen_system_font_changed_cb (GSettings *,
+ const char*,
+ TerminalScreen *screen);
+static gboolean terminal_screen_popup_menu (GtkWidget *widget);
+static gboolean terminal_screen_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static void terminal_screen_child_exited (VteTerminal *terminal,
+ int status);
+
+static void terminal_screen_window_title_changed (VteTerminal *vte_terminal,
+ TerminalScreen *screen);
+
+static void update_color_scheme (TerminalScreen *screen);
+
+static char* terminal_screen_check_hyperlink (TerminalScreen *screen,
+ GdkEvent *event);
+static void terminal_screen_check_extra (TerminalScreen *screen,
+ GdkEvent *event,
+ char **number_info);
+static char* terminal_screen_check_match (TerminalScreen *screen,
+ GdkEvent *event,
+ int *flavor);
+
+static void terminal_screen_show_info_bar (TerminalScreen *screen,
+ GError *error,
+ gboolean show_relaunch);
+
+
+static char**terminal_screen_get_child_environment (TerminalScreen *screen,
+ char **initial_envv,
+ char **path,
+ char **shell);
+
+static gboolean terminal_screen_get_child_command (TerminalScreen *screen,
+ char **exec_argv,
+ const char *path_env,
+ const char *shell_env,
+ gboolean shell,
+ gboolean *preserve_cwd_p,
+ GSpawnFlags *spawn_flags_p,
+ char ***argv_p,
+ GError **err);
+
+static void terminal_screen_queue_idle_exec (TerminalScreen *screen);
+
+static guint signals[LAST_SIGNAL];
+
+typedef struct {
+ const char *pattern;
+ TerminalURLFlavor flavor;
+} TerminalRegexPattern;
+
+static const TerminalRegexPattern url_regex_patterns[] = {
+ { REGEX_URL_AS_IS, FLAVOR_AS_IS },
+ { REGEX_URL_HTTP, FLAVOR_DEFAULT_TO_HTTP },
+ { REGEX_URL_FILE, FLAVOR_AS_IS },
+ { REGEX_URL_VOIP, FLAVOR_VOIP_CALL },
+ { REGEX_EMAIL, FLAVOR_EMAIL },
+ { REGEX_NEWS_MAN, FLAVOR_AS_IS },
+};
+
+static const TerminalRegexPattern extra_regex_patterns[] = {
+ { "(0[Xx][[:xdigit:]]+|[[:digit:]]+)", FLAVOR_NUMBER },
+};
+
+static VteRegex **url_regexes;
+static VteRegex **extra_regexes;
+static TerminalURLFlavor *url_regex_flavors;
+static TerminalURLFlavor *extra_regex_flavors;
+static guint n_url_regexes;
+static guint n_extra_regexes;
+
+/* See bug #697024 */
+#ifndef __linux__
+
+#undef dup3
+#define dup3 fake_dup3
+
+static int
+fake_dup3 (int fd, int fd2, int flags)
+{
+ if (dup2 (fd, fd2) == -1)
+ return -1;
+
+ return fcntl (fd2, F_SETFD, flags);
+}
+#endif /* !__linux__ */
+
+static char*
+strv_to_string (char **strv)
+{
+ return strv ? g_strjoinv (" ", strv) : g_strdup ("(null)");
+}
+
+static char*
+exec_data_to_string (ExecData *data)
+{
+ gs_free char *str1 = NULL;
+ gs_free char *str2 = NULL;
+ return data ? g_strdup_printf ("data %p argv:[%s] exec-argv:[%s] envv:%p(%u) as-shell:%s cwd:%s",
+ data,
+ (str1 = strv_to_string (data->argv)),
+ (str2 = strv_to_string (data->exec_argv)),
+ data->envv, data->envv ? g_strv_length (data->envv) : 0,
+ data->as_shell ? "true" : "false",
+ data->cwd)
+ : g_strdup ("(null)");
+}
+
+static ExecData*
+exec_data_new (void)
+{
+ ExecData *data = g_new0 (ExecData, 1);
+ data->refcount = 1;
+
+ return data;
+}
+
+static ExecData *
+exec_data_clone (ExecData *data,
+ gboolean preserve_argv)
+{
+ if (data == NULL)
+ return NULL;
+
+ ExecData *clone = exec_data_new ();
+ clone->envv = g_strdupv (data->envv);
+ clone->cwd = g_strdup (data->cwd);
+
+ /* If FDs were passed, cannot repeat argv. Return data only for env and cwd */
+ if (!preserve_argv ||
+ data->fd_list != NULL) {
+ clone->as_shell = TRUE;
+ return clone;
+ }
+
+ clone->argv = g_strdupv (data->argv);
+ clone->as_shell = data->as_shell;
+
+ return clone;
+}
+
+static void
+exec_data_callback (ExecData *data,
+ GError *error,
+ TerminalScreen *screen)
+{
+ if (data->callback)
+ data->callback (screen, error, data->callback_data);
+}
+
+static ExecData*
+exec_data_ref (ExecData *data)
+{
+ data->refcount++;
+ return data;
+}
+
+static void
+exec_data_unref (ExecData *data)
+{
+ if (data == NULL)
+ return;
+
+ if (--data->refcount > 0)
+ return;
+
+ g_strfreev (data->argv);
+ g_strfreev (data->exec_argv);
+ g_strfreev (data->envv);
+ g_free (data->cwd);
+ g_clear_object (&data->fd_list);
+ g_free (data->fd_map);
+
+ if (data->callback_data_destroy_notify && data->callback_data)
+ data->callback_data_destroy_notify (data->callback_data);
+
+ g_clear_object (&data->cancellable);
+
+ g_free (data);
+}
+
+GS_DEFINE_CLEANUP_FUNCTION0(ExecData*, _terminal_local_unref_exec_data, exec_data_unref)
+#define terminal_unref_exec_data __attribute__((__cleanup__(_terminal_local_unref_exec_data)))
+
+static void
+terminal_screen_clear_exec_data (TerminalScreen *screen,
+ gboolean cancelled)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+
+ if (priv->exec_data == NULL)
+ return;
+
+ if (cancelled) {
+ gs_free_error GError *err = NULL;
+ g_set_error_literal (&err, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ "Spawning was cancelled");
+ exec_data_callback (priv->exec_data, err, screen);
+ }
+
+ exec_data_unref (priv->exec_data);
+ priv->exec_data = NULL;
+}
+
+G_DEFINE_TYPE (TerminalScreen, terminal_screen, VTE_TYPE_TERMINAL)
+
+static void
+free_tag_data (TagData *tagdata)
+{
+ g_slice_free (TagData, tagdata);
+}
+
+static void
+precompile_regexes (const TerminalRegexPattern *regex_patterns,
+ guint n_regexes,
+ VteRegex ***regexes,
+ TerminalURLFlavor **regex_flavors)
+{
+ guint i;
+
+ *regexes = g_new0 (VteRegex*, n_regexes);
+ *regex_flavors = g_new0 (TerminalURLFlavor, n_regexes);
+
+ for (i = 0; i < n_regexes; ++i)
+ {
+ GError *error = NULL;
+
+ (*regexes)[i] = vte_regex_new_for_match (regex_patterns[i].pattern, -1,
+ PCRE2_UTF | PCRE2_NO_UTF_CHECK | PCRE2_UCP | PCRE2_MULTILINE,
+ &error);
+ g_assert_no_error (error);
+
+ if (!vte_regex_jit ((*regexes)[i], PCRE2_JIT_COMPLETE, &error) ||
+ !vte_regex_jit ((*regexes)[i], PCRE2_JIT_PARTIAL_SOFT, &error)) {
+ g_printerr ("Failed to JIT regex '%s': %s\n", regex_patterns[i].pattern, error->message);
+ g_clear_error (&error);
+ }
+
+ (*regex_flavors)[i] = regex_patterns[i].flavor;
+ }
+}
+
+static void
+terminal_screen_class_enable_menu_bar_accel_notify_cb (GSettings *settings,
+ const char *key,
+ TerminalScreenClass *klass)
+{
+ static gboolean is_enabled = TRUE; /* the binding is enabled by default since GtkWidgetClass installs it */
+ gboolean enable;
+ GtkBindingSet *binding_set;
+
+ enable = g_settings_get_boolean (settings, key);
+
+ /* Only remove the 'skip' entry when we have added it previously! */
+ if (enable == is_enabled)
+ return;
+
+ is_enabled = enable;
+
+ binding_set = gtk_binding_set_by_class (klass);
+ if (enable)
+ gtk_binding_entry_remove (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK);
+ else
+ gtk_binding_entry_skip (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK);
+}
+
+static TerminalWindow *
+terminal_screen_get_window (TerminalScreen *screen)
+{
+ GtkWidget *widget = GTK_WIDGET (screen);
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (!gtk_widget_is_toplevel (toplevel))
+ return NULL;
+
+ return TERMINAL_WINDOW (toplevel);
+}
+
+static void
+terminal_screen_realize (GtkWidget *widget)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (widget);
+
+ GTK_WIDGET_CLASS (terminal_screen_parent_class)->realize (widget);
+
+ terminal_screen_set_font (screen);
+
+ TerminalScreenPrivate *priv = screen->priv;
+ if (priv->exec_on_realize)
+ terminal_screen_queue_idle_exec (screen);
+
+ priv->exec_on_realize = FALSE;
+
+}
+
+static void
+terminal_screen_update_style (TerminalScreen *screen)
+{
+ update_color_scheme (screen);
+ terminal_screen_set_font (screen);
+}
+
+static void
+terminal_screen_style_updated (GtkWidget *widget)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (widget);
+
+ GTK_WIDGET_CLASS (terminal_screen_parent_class)->style_updated (widget);
+
+ terminal_screen_update_style (screen);
+}
+
+#ifdef ENABLE_DEBUG
+static void
+size_request (GtkWidget *widget,
+ GtkRequisition *req)
+{
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[screen %p] size-request %d : %d\n",
+ widget, req->width, req->height);
+}
+
+static void
+size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[screen %p] size-alloc %d : %d at (%d, %d)\n",
+ widget, allocation->width, allocation->height, allocation->x, allocation->y);
+}
+#endif
+
+static void
+terminal_screen_init (TerminalScreen *screen)
+{
+ const GtkTargetEntry target_table[] = {
+ { (char *) "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, TARGET_TAB },
+ { (char *) "application/x-color", 0, TARGET_COLOR },
+ { (char *) "x-special/gnome-reset-background", 0, TARGET_RESET_BG },
+ { (char *) "text/x-moz-url", 0, TARGET_MOZ_URL },
+ { (char *) "_NETSCAPE_URL", 0, TARGET_NETSCAPE_URL }
+ };
+ VteTerminal *terminal = VTE_TERMINAL (screen);
+ TerminalScreenPrivate *priv;
+ TerminalApp *app;
+ GtkTargetList *target_list;
+ GtkTargetEntry *targets;
+ int n_targets;
+ guint i;
+ uuid_t u;
+ char uuidstr[37];
+
+ priv = screen->priv = G_TYPE_INSTANCE_GET_PRIVATE (screen, TERMINAL_TYPE_SCREEN, TerminalScreenPrivate);
+
+ uuid_generate (u);
+ uuid_unparse (u, uuidstr);
+ priv->uuid = g_strdup (uuidstr);
+
+ vte_terminal_set_mouse_autohide (terminal, TRUE);
+
+ priv->child_pid = -1;
+
+ vte_terminal_set_allow_hyperlink (terminal, TRUE);
+
+ for (i = 0; i < n_url_regexes; ++i)
+ {
+ TagData *tag_data;
+
+ tag_data = g_slice_new (TagData);
+ tag_data->flavor = url_regex_flavors[i];
+ tag_data->tag = vte_terminal_match_add_regex (terminal, url_regexes[i], 0);
+ vte_terminal_match_set_cursor_type (terminal, tag_data->tag, URL_MATCH_CURSOR);
+
+ priv->match_tags = g_slist_prepend (priv->match_tags, tag_data);
+ }
+
+ /* Setup DND */
+ target_list = gtk_target_list_new (NULL, 0);
+ gtk_target_list_add_uri_targets (target_list, 0);
+ gtk_target_list_add_text_targets (target_list, 0);
+ gtk_target_list_add_table (target_list, target_table, G_N_ELEMENTS (target_table));
+
+ targets = gtk_target_table_new_from_list (target_list, &n_targets);
+
+ gtk_drag_dest_set (GTK_WIDGET (screen),
+ GTK_DEST_DEFAULT_MOTION |
+ GTK_DEST_DEFAULT_HIGHLIGHT |
+ GTK_DEST_DEFAULT_DROP,
+ targets, n_targets,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+ gtk_target_table_free (targets, n_targets);
+ gtk_target_list_unref (target_list);
+
+ g_signal_connect (screen, "window-title-changed",
+ G_CALLBACK (terminal_screen_window_title_changed),
+ screen);
+
+ app = terminal_app_get ();
+ g_signal_connect (terminal_app_get_desktop_interface_settings (app), "changed::" MONOSPACE_FONT_KEY_NAME,
+ G_CALLBACK (terminal_screen_system_font_changed_cb), screen);
+
+#ifdef ENABLE_DEBUG
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_GEOMETRY)
+ {
+ g_signal_connect_after (screen, "size-request", G_CALLBACK (size_request), NULL);
+ g_signal_connect_after (screen, "size-allocate", G_CALLBACK (size_allocate), NULL);
+ }
+#endif
+}
+
+static void
+terminal_screen_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROFILE:
+ g_value_set_object (value, terminal_screen_get_profile (screen));
+ break;
+ case PROP_TITLE:
+ g_value_set_string (value, terminal_screen_get_title (screen));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_screen_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROFILE:
+ terminal_screen_set_profile (screen, g_value_get_object (value));
+ break;
+ case PROP_TITLE:
+ /* not writable */
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_screen_class_init (TerminalScreenClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ VteTerminalClass *terminal_class = VTE_TERMINAL_CLASS (klass);
+ GSettings *settings;
+
+ object_class->constructed = terminal_screen_constructed;
+ object_class->dispose = terminal_screen_dispose;
+ object_class->finalize = terminal_screen_finalize;
+ object_class->get_property = terminal_screen_get_property;
+ object_class->set_property = terminal_screen_set_property;
+
+ widget_class->realize = terminal_screen_realize;
+ widget_class->style_updated = terminal_screen_style_updated;
+ widget_class->drag_data_received = terminal_screen_drag_data_received;
+ widget_class->button_press_event = terminal_screen_button_press;
+ widget_class->popup_menu = terminal_screen_popup_menu;
+
+ terminal_class->child_exited = terminal_screen_child_exited;
+
+ signals[PROFILE_SET] =
+ g_signal_new (I_("profile-set"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalScreenClass, profile_set),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1, G_TYPE_SETTINGS);
+
+ signals[SHOW_POPUP_MENU] =
+ g_signal_new (I_("show-popup-menu"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalScreenClass, show_popup_menu),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER);
+
+ signals[MATCH_CLICKED] =
+ g_signal_new (I_("match-clicked"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalScreenClass, match_clicked),
+ g_signal_accumulator_true_handled, NULL,
+ _terminal_marshal_BOOLEAN__STRING_INT_UINT,
+ G_TYPE_BOOLEAN,
+ 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_UINT);
+
+ signals[CLOSE_SCREEN] =
+ g_signal_new (I_("close-screen"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalScreenClass, close_screen),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ g_object_class_install_property
+ (object_class,
+ PROP_PROFILE,
+ g_param_spec_object ("profile", NULL, NULL,
+ G_TYPE_SETTINGS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property
+ (object_class,
+ PROP_TITLE,
+ g_param_spec_string ("title", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private (object_class, sizeof (TerminalScreenPrivate));
+
+ n_url_regexes = G_N_ELEMENTS (url_regex_patterns);
+ precompile_regexes (url_regex_patterns, n_url_regexes, &url_regexes, &url_regex_flavors);
+ n_extra_regexes = G_N_ELEMENTS (extra_regex_patterns);
+ precompile_regexes (extra_regex_patterns, n_extra_regexes, &extra_regexes, &extra_regex_flavors);
+
+ /* This fixes bug #329827 */
+ settings = terminal_app_get_global_settings (terminal_app_get ());
+ terminal_screen_class_enable_menu_bar_accel_notify_cb (settings, TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY, klass);
+ g_signal_connect (settings, "changed::" TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY,
+ G_CALLBACK (terminal_screen_class_enable_menu_bar_accel_notify_cb), klass);
+}
+
+static void
+terminal_screen_constructed (GObject *object)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (object);
+ TerminalScreenPrivate *priv = screen->priv;
+
+ G_OBJECT_CLASS (terminal_screen_parent_class)->constructed (object);
+
+ terminal_app_register_screen (terminal_app_get (), screen);
+ priv->registered = TRUE;
+}
+
+static void
+terminal_screen_dispose (GObject *object)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (object);
+ TerminalScreenPrivate *priv = screen->priv;
+ GtkSettings *settings;
+
+ /* Unset child PID so that when an eventual child-exited signal arrives,
+ * we don't emit "close".
+ */
+ priv->child_pid = -1;
+
+ settings = gtk_widget_get_settings (GTK_WIDGET (screen));
+ g_signal_handlers_disconnect_matched (settings, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL,
+ screen);
+
+ if (priv->idle_exec_source != 0)
+ {
+ g_source_remove (priv->idle_exec_source);
+ priv->idle_exec_source = 0;
+ }
+
+ terminal_screen_clear_exec_data (screen, TRUE);
+
+ G_OBJECT_CLASS (terminal_screen_parent_class)->dispose (object);
+
+ /* Unregister *after* chaining up to the parent's dispose,
+ * since that will terminate the child process if there still
+ * is any, and we need to get the dbus signal out
+ * from the TerminalReceiver.
+ */
+ if (priv->registered) {
+ terminal_app_unregister_screen (terminal_app_get (), screen);
+ priv->registered = FALSE;
+ }
+}
+
+static void
+terminal_screen_finalize (GObject *object)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (object);
+ TerminalScreenPrivate *priv = screen->priv;
+
+ g_signal_handlers_disconnect_by_func (terminal_app_get_desktop_interface_settings (terminal_app_get ()),
+ G_CALLBACK (terminal_screen_system_font_changed_cb),
+ screen);
+
+ terminal_screen_set_profile (screen, NULL);
+
+ g_slist_free_full (priv->match_tags, (GDestroyNotify) free_tag_data);
+
+ g_free (priv->uuid);
+
+ G_OBJECT_CLASS (terminal_screen_parent_class)->finalize (object);
+}
+
+TerminalScreen *
+terminal_screen_new (GSettings *profile,
+ const char *title,
+ double zoom)
+{
+ g_return_val_if_fail (G_IS_SETTINGS (profile), NULL);
+
+ TerminalScreen *screen = g_object_new (TERMINAL_TYPE_SCREEN, NULL);
+
+ terminal_screen_set_profile (screen, profile);
+
+ vte_terminal_set_size (VTE_TERMINAL (screen),
+ g_settings_get_int (profile, TERMINAL_PROFILE_DEFAULT_SIZE_COLUMNS_KEY),
+ g_settings_get_int (profile, TERMINAL_PROFILE_DEFAULT_SIZE_ROWS_KEY));
+
+ /* If given an initial title, strip it of control characters and
+ * feed it to the terminal.
+ */
+ if (title != NULL) {
+ GString *seq;
+ const char *p;
+
+ seq = g_string_new ("\033]0;");
+ for (p = title; *p; p = g_utf8_next_char (p)) {
+ gunichar c = g_utf8_get_char (p);
+ if (c < 0x20 || (c >= 0x7f && c <= 0x9f))
+ continue;
+ else if (c == ';')
+ break;
+
+ g_string_append_unichar (seq, c);
+ }
+ g_string_append (seq, "\033\\");
+
+ vte_terminal_feed (VTE_TERMINAL (screen), seq->str, seq->len);
+ g_string_free (seq, TRUE);
+ }
+
+ vte_terminal_set_font_scale (VTE_TERMINAL (screen), zoom);
+ terminal_screen_set_font (screen);
+
+ return screen;
+}
+
+static gboolean
+terminal_screen_reexec_from_exec_data (TerminalScreen *screen,
+ ExecData *data,
+ char **envv,
+ const char *cwd,
+ GCancellable *cancellable,
+ GError **error)
+{
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_PROCESSES) {
+ gs_free char *str = exec_data_to_string (data);
+ _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,
+ "[screen %p] reexec_from_data: envv:%p(%u) cwd:%s data:[%s]\n",
+ screen,
+ envv, envv ? g_strv_length (envv) : 0,
+ cwd,
+ str);
+ }
+
+ return terminal_screen_exec (screen,
+ data ? data->argv : NULL,
+ envv ? envv : data ? data->envv : NULL,
+ data ? data->as_shell : TRUE,
+ /* If we have command line args, must always pass the cwd from the command line, too */
+ data && data->argv ? data->cwd : cwd ? cwd : data ? data->cwd : NULL,
+ NULL /* fd list */, NULL /* fd array */,
+ NULL, NULL, NULL, /* callback + data + destroy notify */
+ cancellable,
+ error);
+}
+
+gboolean
+terminal_screen_reexec_from_screen (TerminalScreen *screen,
+ TerminalScreen *parent_screen,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), FALSE);
+
+ if (parent_screen == NULL)
+ return TRUE;
+
+ g_return_val_if_fail (TERMINAL_IS_SCREEN (parent_screen), FALSE);
+
+ terminal_unref_exec_data ExecData* data = exec_data_clone (parent_screen->priv->exec_data, FALSE);
+ gs_free char* cwd = terminal_screen_get_current_dir (parent_screen);
+
+ _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,
+ "[screen %p] reexec_from_screen: parent:%p cwd:%s\n",
+ screen,
+ parent_screen,
+ cwd);
+
+ return terminal_screen_reexec_from_exec_data (screen,
+ data,
+ NULL /* envv */,
+ cwd,
+ cancellable,
+ error);
+}
+
+gboolean
+terminal_screen_reexec (TerminalScreen *screen,
+ char **envv,
+ const char *cwd,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), FALSE);
+
+
+ _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,
+ "[screen %p] reexec: envv:%p(%u) cwd:%s\n",
+ screen,
+ envv, envv ? g_strv_length (envv) : 0,
+ cwd);
+
+ return terminal_screen_reexec_from_exec_data (screen,
+ screen->priv->exec_data,
+ envv,
+ cwd,
+ cancellable,
+ error);
+}
+
+gboolean
+terminal_screen_exec (TerminalScreen *screen,
+ char **argv,
+ char **initial_envv,
+ gboolean as_shell,
+ const char *cwd,
+ GUnixFDList *fd_list,
+ GVariant *fd_array,
+ TerminalScreenExecCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (gtk_widget_get_parent (GTK_WIDGET (screen)) != NULL, FALSE);
+
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_PROCESSES) {
+ gs_free char *argv_str = NULL;
+ _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,
+ "[screen %p] exec: argv:[%s] envv:%p(%u) as-shell:%s cwd:%s\n",
+ screen,
+ (argv_str = strv_to_string(argv)),
+ initial_envv, initial_envv ? g_strv_length (initial_envv) : 0,
+ as_shell ? "true":"false",
+ cwd);
+ }
+
+ TerminalScreenPrivate *priv = screen->priv;
+
+ ExecData *data = exec_data_new ();
+ data->callback = callback;
+ data->callback_data = user_data;
+ data->callback_data_destroy_notify = destroy_notify;
+
+ GError *err = NULL;
+ if (priv->child_pid != -1) {
+ g_set_error_literal (&err, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Cannot launch a new child process while the terminal is still running another child process");
+
+ terminal_screen_show_info_bar (screen, err, FALSE);
+ g_propagate_error (error, err);
+ exec_data_unref (data); /* frees the callback data */
+ return FALSE;
+ }
+
+ gs_free char *path = NULL;
+ gs_free char *shell = NULL;
+ gs_strfreev char **envv = terminal_screen_get_child_environment (screen,
+ initial_envv,
+ &path,
+ &shell);
+
+ gboolean preserve_cwd = FALSE;
+ GSpawnFlags spawn_flags = G_SPAWN_SEARCH_PATH_FROM_ENVP;
+ if (initial_envv)
+ spawn_flags |= VTE_SPAWN_NO_PARENT_ENVV;
+ gs_strfreev char **exec_argv = NULL;
+ if (!terminal_screen_get_child_command (screen,
+ argv,
+ path,
+ shell,
+ as_shell,
+ &preserve_cwd,
+ &spawn_flags,
+ &exec_argv,
+ &err)) {
+ terminal_screen_show_info_bar (screen, err, FALSE);
+ g_propagate_error (error, err);
+ exec_data_unref (data); /* frees the callback data */
+ return FALSE;
+ }
+
+ if (!preserve_cwd) {
+ cwd = g_get_home_dir ();
+ envv = g_environ_unsetenv (envv, "PWD");
+ }
+
+ data->fd_list = fd_list ? g_object_ref(fd_list) : NULL;
+
+ if (fd_array) {
+ g_assert_nonnull(fd_list);
+ int n_fds = g_unix_fd_list_get_length(fd_list);
+
+ gsize fd_array_data_len;
+ const int *fd_array_data = g_variant_get_fixed_array (fd_array, &fd_array_data_len, 2 * sizeof (int));
+
+ data->n_fd_map = fd_array_data_len;
+ data->fd_map = g_new (int, data->n_fd_map);
+ for (gsize i = 0; i < fd_array_data_len; i++) {
+ const int fd = fd_array_data[2 * i];
+ const int idx = fd_array_data[2 * i + 1];
+ g_assert_cmpint(idx, >=, 0);
+ g_assert_cmpuint(idx, <, n_fds);
+
+ data->fd_map[idx] = fd;
+ }
+ } else {
+ data->n_fd_map = 0;
+ data->fd_map = NULL;
+ }
+
+ data->argv = g_strdupv (argv);
+ data->exec_argv = g_strdupv (exec_argv);
+ data->cwd = g_strdup (cwd);
+ data->envv = g_strdupv (envv);
+ data->as_shell = as_shell;
+ data->pty_flags = VTE_PTY_DEFAULT;
+ data->spawn_flags = spawn_flags;
+ data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+ terminal_screen_clear_exec_data (screen, TRUE);
+ priv->exec_data = data;
+
+ terminal_screen_queue_idle_exec (screen);
+
+ return TRUE;
+}
+
+const char*
+terminal_screen_get_title (TerminalScreen *screen)
+{
+ return vte_terminal_get_window_title (VTE_TERMINAL (screen));
+}
+
+static void
+terminal_screen_profile_changed_cb (GSettings *profile,
+ const char *prop_name,
+ TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ GObject *object = G_OBJECT (screen);
+ VteTerminal *vte_terminal = VTE_TERMINAL (screen);
+ TerminalWindow *window;
+
+ g_object_freeze_notify (object);
+
+ if ((window = terminal_screen_get_window (screen)))
+ {
+ /* We need these in line for the set_size in
+ * update_on_realize
+ */
+ terminal_window_update_geometry (window);
+ }
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_SCROLLBAR_POLICY_KEY))
+ _terminal_screen_update_scrollbar (screen);
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_ENCODING_KEY))
+ {
+ gs_free char *charset = g_settings_get_string (profile, TERMINAL_PROFILE_ENCODING_KEY);
+ const char *encoding = terminal_util_translate_encoding (charset);
+ if (encoding != NULL)
+ vte_terminal_set_encoding (vte_terminal, encoding, NULL);
+ }
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_CJK_UTF8_AMBIGUOUS_WIDTH_KEY))
+ {
+ TerminalCJKWidth width;
+
+ width = g_settings_get_enum (profile, TERMINAL_PROFILE_CJK_UTF8_AMBIGUOUS_WIDTH_KEY);
+ vte_terminal_set_cjk_ambiguous_width (vte_terminal, (int) width);
+ }
+
+ if (gtk_widget_get_realized (GTK_WIDGET (screen)) &&
+ (!prop_name ||
+ prop_name == I_(TERMINAL_PROFILE_USE_SYSTEM_FONT_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_FONT_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_CELL_WIDTH_SCALE_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_CELL_HEIGHT_SCALE_KEY)))
+ terminal_screen_set_font (screen);
+
+ if (!prop_name ||
+ prop_name == I_(TERMINAL_PROFILE_USE_THEME_COLORS_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_FOREGROUND_COLOR_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_BACKGROUND_COLOR_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_BOLD_COLOR_SAME_AS_FG_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_BOLD_COLOR_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_CURSOR_COLORS_SET_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_CURSOR_BACKGROUND_COLOR_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_CURSOR_FOREGROUND_COLOR_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_HIGHLIGHT_COLORS_SET_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_HIGHLIGHT_BACKGROUND_COLOR_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_HIGHLIGHT_FOREGROUND_COLOR_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_PALETTE_KEY))
+ update_color_scheme (screen);
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_AUDIBLE_BELL_KEY))
+ vte_terminal_set_audible_bell (vte_terminal, g_settings_get_boolean (profile, TERMINAL_PROFILE_AUDIBLE_BELL_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE_KEY))
+ vte_terminal_set_scroll_on_keystroke (vte_terminal,
+ g_settings_get_boolean (profile, TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE_KEY));
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_SCROLL_ON_OUTPUT_KEY))
+ vte_terminal_set_scroll_on_output (vte_terminal,
+ g_settings_get_boolean (profile, TERMINAL_PROFILE_SCROLL_ON_OUTPUT_KEY));
+ if (!prop_name ||
+ prop_name == I_(TERMINAL_PROFILE_SCROLLBACK_LINES_KEY) ||
+ prop_name == I_(TERMINAL_PROFILE_SCROLLBACK_UNLIMITED_KEY))
+ {
+ glong lines = g_settings_get_boolean (profile, TERMINAL_PROFILE_SCROLLBACK_UNLIMITED_KEY) ?
+ -1 : g_settings_get_int (profile, TERMINAL_PROFILE_SCROLLBACK_LINES_KEY);
+ vte_terminal_set_scrollback_lines (vte_terminal, lines);
+ }
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_BACKSPACE_BINDING_KEY))
+ vte_terminal_set_backspace_binding (vte_terminal,
+ g_settings_get_enum (profile, TERMINAL_PROFILE_BACKSPACE_BINDING_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_DELETE_BINDING_KEY))
+ vte_terminal_set_delete_binding (vte_terminal,
+ g_settings_get_enum (profile, TERMINAL_PROFILE_DELETE_BINDING_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_ENABLE_BIDI_KEY))
+ vte_terminal_set_enable_bidi (vte_terminal,
+ g_settings_get_boolean (profile, TERMINAL_PROFILE_ENABLE_BIDI_KEY));
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_ENABLE_SHAPING_KEY))
+ vte_terminal_set_enable_shaping (vte_terminal,
+ g_settings_get_boolean (profile, TERMINAL_PROFILE_ENABLE_SHAPING_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_ENABLE_SIXEL_KEY))
+ vte_terminal_set_enable_sixel (vte_terminal,
+ g_settings_get_boolean (profile, TERMINAL_PROFILE_ENABLE_SIXEL_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_BOLD_IS_BRIGHT_KEY))
+ vte_terminal_set_bold_is_bright (vte_terminal,
+ g_settings_get_boolean (profile, TERMINAL_PROFILE_BOLD_IS_BRIGHT_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_CURSOR_BLINK_MODE_KEY))
+ vte_terminal_set_cursor_blink_mode (vte_terminal,
+ g_settings_get_enum (priv->profile, TERMINAL_PROFILE_CURSOR_BLINK_MODE_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_CURSOR_SHAPE_KEY))
+ vte_terminal_set_cursor_shape (vte_terminal,
+ g_settings_get_enum (priv->profile, TERMINAL_PROFILE_CURSOR_SHAPE_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_REWRAP_ON_RESIZE_KEY))
+ vte_terminal_set_rewrap_on_resize (vte_terminal,
+ g_settings_get_boolean (profile, TERMINAL_PROFILE_REWRAP_ON_RESIZE_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_TEXT_BLINK_MODE_KEY))
+ vte_terminal_set_text_blink_mode (vte_terminal,
+ g_settings_get_enum (profile, TERMINAL_PROFILE_TEXT_BLINK_MODE_KEY));
+
+ if (!prop_name || prop_name == I_(TERMINAL_PROFILE_WORD_CHAR_EXCEPTIONS_KEY))
+ {
+ gs_free char *word_char_exceptions;
+ g_settings_get (profile, TERMINAL_PROFILE_WORD_CHAR_EXCEPTIONS_KEY, "ms", &word_char_exceptions);
+ vte_terminal_set_word_char_exceptions (vte_terminal, word_char_exceptions);
+ }
+
+ g_object_thaw_notify (object);
+}
+
+static void
+update_color_scheme (TerminalScreen *screen)
+{
+ GtkWidget *widget = GTK_WIDGET (screen);
+ TerminalScreenPrivate *priv = screen->priv;
+ GSettings *profile = priv->profile;
+ gs_free GdkRGBA *colors;
+ gsize n_colors;
+ GdkRGBA fg, bg, bold, theme_fg, theme_bg;
+ GdkRGBA cursor_bg, cursor_fg;
+ GdkRGBA highlight_bg, highlight_fg;
+ GdkRGBA *boldp;
+ GdkRGBA *cursor_bgp = NULL, *cursor_fgp = NULL;
+ GdkRGBA *highlight_bgp = NULL, *highlight_fgp = NULL;
+ GtkStyleContext *context;
+ gboolean use_theme_colors;
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_color (context, gtk_style_context_get_state (context), &theme_fg);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ gtk_style_context_get_background_color (context, gtk_style_context_get_state (context), &theme_bg);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ use_theme_colors = g_settings_get_boolean (profile, TERMINAL_PROFILE_USE_THEME_COLORS_KEY);
+ if (use_theme_colors ||
+ (!terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_FOREGROUND_COLOR_KEY, &fg) ||
+ !terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_BACKGROUND_COLOR_KEY, &bg)))
+ {
+ fg = theme_fg;
+ bg = theme_bg;
+ }
+
+ if (!g_settings_get_boolean (profile, TERMINAL_PROFILE_BOLD_COLOR_SAME_AS_FG_KEY) &&
+ !use_theme_colors &&
+ terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_BOLD_COLOR_KEY, &bold))
+ boldp = &bold;
+ else
+ boldp = NULL;
+
+ if (g_settings_get_boolean (profile, TERMINAL_PROFILE_CURSOR_COLORS_SET_KEY) &&
+ !use_theme_colors)
+ {
+ if (terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_CURSOR_BACKGROUND_COLOR_KEY, &cursor_bg))
+ cursor_bgp = &cursor_bg;
+ if (terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_CURSOR_FOREGROUND_COLOR_KEY, &cursor_fg))
+ cursor_fgp = &cursor_fg;
+ }
+
+ if (g_settings_get_boolean (profile, TERMINAL_PROFILE_HIGHLIGHT_COLORS_SET_KEY) &&
+ !use_theme_colors)
+ {
+ if (terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_HIGHLIGHT_BACKGROUND_COLOR_KEY, &highlight_bg))
+ highlight_bgp = &highlight_bg;
+ if (terminal_g_settings_get_rgba (profile, TERMINAL_PROFILE_HIGHLIGHT_FOREGROUND_COLOR_KEY, &highlight_fg))
+ highlight_fgp = &highlight_fg;
+ }
+
+ colors = terminal_g_settings_get_rgba_palette (priv->profile, TERMINAL_PROFILE_PALETTE_KEY, &n_colors);
+ vte_terminal_set_colors (VTE_TERMINAL (screen), &fg, &bg,
+ colors, n_colors);
+ vte_terminal_set_color_bold (VTE_TERMINAL (screen), boldp);
+ vte_terminal_set_color_cursor (VTE_TERMINAL (screen), cursor_bgp);
+ vte_terminal_set_color_cursor_foreground (VTE_TERMINAL (screen), cursor_fgp);
+ vte_terminal_set_color_highlight (VTE_TERMINAL (screen), highlight_bgp);
+ vte_terminal_set_color_highlight_foreground (VTE_TERMINAL (screen), highlight_fgp);
+}
+
+static void
+terminal_screen_set_font (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ GSettings *profile = priv->profile;
+ PangoFontDescription *desc;
+ int size;
+
+ if (g_settings_get_boolean (profile, TERMINAL_PROFILE_USE_SYSTEM_FONT_KEY))
+ {
+ desc = terminal_app_get_system_font (terminal_app_get ());
+ }
+ else
+ {
+ gs_free char *font;
+ font = g_settings_get_string (profile, TERMINAL_PROFILE_FONT_KEY);
+ desc = pango_font_description_from_string (font);
+ }
+
+ size = pango_font_description_get_size (desc);
+ /* Sanity check */
+ if (size == 0) {
+ if (pango_font_description_get_size_is_absolute (desc))
+ pango_font_description_set_absolute_size (desc, 10);
+ else
+ pango_font_description_set_size (desc, 10);
+ }
+
+ vte_terminal_set_font (VTE_TERMINAL (screen), desc);
+
+ pango_font_description_free (desc);
+
+ vte_terminal_set_cell_width_scale (VTE_TERMINAL (screen),
+ g_settings_get_double (profile, TERMINAL_PROFILE_CELL_WIDTH_SCALE_KEY));
+ vte_terminal_set_cell_height_scale (VTE_TERMINAL (screen),
+ g_settings_get_double (profile, TERMINAL_PROFILE_CELL_HEIGHT_SCALE_KEY));
+}
+
+static void
+terminal_screen_system_font_changed_cb (GSettings *settings,
+ const char *key,
+ TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (screen)))
+ return;
+
+ if (!g_settings_get_boolean (priv->profile, TERMINAL_PROFILE_USE_SYSTEM_FONT_KEY))
+ return;
+
+ terminal_screen_set_font (screen);
+}
+
+void
+terminal_screen_set_profile (TerminalScreen *screen,
+ GSettings *profile)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ GSettings*old_profile;
+
+ old_profile = priv->profile;
+ if (profile == old_profile)
+ return;
+
+ if (priv->profile_changed_id)
+ {
+ g_signal_handler_disconnect (G_OBJECT (priv->profile),
+ priv->profile_changed_id);
+ priv->profile_changed_id = 0;
+ }
+
+ priv->profile = profile;
+ if (profile)
+ {
+ g_object_ref (profile);
+ priv->profile_changed_id =
+ g_signal_connect (profile, "changed",
+ G_CALLBACK (terminal_screen_profile_changed_cb),
+ screen);
+ terminal_screen_profile_changed_cb (profile, NULL, screen);
+
+ g_signal_emit (G_OBJECT (screen), signals[PROFILE_SET], 0, old_profile);
+ }
+
+ if (old_profile)
+ g_object_unref (old_profile);
+
+ g_object_notify (G_OBJECT (screen), "profile");
+}
+
+GSettings*
+terminal_screen_get_profile (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+
+ return priv->profile;
+}
+
+GSettings*
+terminal_screen_ref_profile (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+
+ if (priv->profile != NULL)
+ return g_object_ref (priv->profile);
+ return NULL;
+}
+
+static gboolean
+should_preserve_cwd (TerminalPreserveWorkingDirectory preserve_cwd,
+ const char *path,
+ const char *arg0)
+{
+ switch (preserve_cwd) {
+ case TERMINAL_PRESERVE_WORKING_DIRECTORY_SAFE: {
+ gs_free char *resolved_arg0 = terminal_util_find_program_in_path (path, arg0);
+ return resolved_arg0 != NULL &&
+ terminal_util_get_is_shell (resolved_arg0);
+ }
+
+ case TERMINAL_PRESERVE_WORKING_DIRECTORY_ALWAYS:
+ return TRUE;
+
+ case TERMINAL_PRESERVE_WORKING_DIRECTORY_NEVER:
+ default:
+ return FALSE;
+ }
+}
+
+static gboolean
+terminal_screen_get_child_command (TerminalScreen *screen,
+ char **argv,
+ const char *path_env,
+ const char *shell_env,
+ gboolean as_shell,
+ gboolean *preserve_cwd_p,
+ GSpawnFlags *spawn_flags_p,
+ char ***exec_argv_p,
+ GError **err)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ GSettings *profile = priv->profile;
+ TerminalPreserveWorkingDirectory preserve_cwd;
+ char **exec_argv;
+
+ g_assert (spawn_flags_p != NULL && exec_argv_p != NULL && preserve_cwd_p != NULL);
+
+ *exec_argv_p = exec_argv = NULL;
+
+ preserve_cwd = g_settings_get_enum (profile, TERMINAL_PROFILE_PRESERVE_WORKING_DIRECTORY_KEY);
+
+ if (argv)
+ {
+ exec_argv = g_strdupv (argv);
+
+ /* argv and cwd come from the command line client, so it must always be used */
+ *preserve_cwd_p = TRUE;
+ *spawn_flags_p |= G_SPAWN_SEARCH_PATH_FROM_ENVP;
+ }
+ else if (g_settings_get_boolean (profile, TERMINAL_PROFILE_USE_CUSTOM_COMMAND_KEY))
+ {
+ gs_free char *exec_argv_str;
+
+ exec_argv_str = g_settings_get_string (profile, TERMINAL_PROFILE_CUSTOM_COMMAND_KEY);
+ if (!g_shell_parse_argv (exec_argv_str, NULL, &exec_argv, err))
+ return FALSE;
+
+ *preserve_cwd_p = should_preserve_cwd (preserve_cwd, path_env, exec_argv[0]);
+ *spawn_flags_p |= G_SPAWN_SEARCH_PATH_FROM_ENVP;
+ }
+ else if (as_shell)
+ {
+ const char *only_name;
+ char *shell;
+ int argc = 0;
+
+ shell = egg_shell (shell_env);
+
+ only_name = strrchr (shell, '/');
+ if (only_name != NULL)
+ only_name++;
+ else {
+ only_name = shell;
+ *spawn_flags_p |= G_SPAWN_SEARCH_PATH_FROM_ENVP;
+ }
+
+ exec_argv = g_new (char*, 3);
+
+ exec_argv[argc++] = shell;
+
+ if (g_settings_get_boolean (profile, TERMINAL_PROFILE_LOGIN_SHELL_KEY))
+ exec_argv[argc++] = g_strconcat ("-", only_name, NULL);
+ else
+ exec_argv[argc++] = g_strdup (only_name);
+
+ exec_argv[argc++] = NULL;
+
+ *preserve_cwd_p = should_preserve_cwd (preserve_cwd, path_env, shell);
+ *spawn_flags_p |= G_SPAWN_FILE_AND_ARGV_ZERO;
+ }
+
+ else
+ {
+ g_set_error_literal (err, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ _("No command supplied nor shell requested"));
+ return FALSE;
+ }
+
+ *exec_argv_p = exec_argv;
+
+ return TRUE;
+}
+
+static char**
+terminal_screen_get_child_environment (TerminalScreen *screen,
+ char **initial_envv,
+ char **path,
+ char **shell)
+{
+ TerminalApp *app = terminal_app_get ();
+ char **env;
+ char *e, *v;
+ GHashTable *env_table;
+ GHashTableIter iter;
+ GPtrArray *retval;
+ guint i;
+
+ env_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ env = initial_envv;
+ if (env)
+ {
+ for (i = 0; env[i]; ++i)
+ {
+ v = strchr (env[i], '=');
+ if (v)
+ g_hash_table_replace (env_table, g_strndup (env[i], v - env[i]), g_strdup (v + 1));
+ else
+ g_hash_table_replace (env_table, g_strdup (env[i]), NULL);
+ }
+ }
+
+ g_hash_table_remove (env_table, "COLUMNS");
+ g_hash_table_remove (env_table, "LINES");
+ g_hash_table_remove (env_table, "GNOME_DESKTOP_ICON");
+
+ /* WINDOWID does not work correctly ever since we don't use a native
+ * GdkWindow anymore, and it also becomes incorrect if the screen is
+ * moved to a different window, or the window unrealized and re-realized.
+ * Additionally, it cannot ever work on non-X11 displays like wayland.
+ * And on X11, the only use for this is broken foreign drawing on the
+ * window (w3m etc), and trying to find the focused screen (brltty),
+ * which can now be done correctly using DECSET 1004.
+ * Therefore we do not set WINDOWID, and remove an existing variable.
+ */
+ g_hash_table_remove (env_table, "WINDOWID");
+
+ terminal_util_add_proxy_env (env_table);
+
+ /* Add gnome-terminal private env vars used to communicate back to g-t-server */
+ GDBusConnection *connection = g_application_get_dbus_connection (G_APPLICATION (app));
+ g_hash_table_replace (env_table, g_strdup (TERMINAL_ENV_SERVICE_NAME),
+ g_strdup (g_dbus_connection_get_unique_name (connection)));
+
+ g_hash_table_replace (env_table, g_strdup (TERMINAL_ENV_SCREEN),
+ terminal_app_dup_screen_object_path (app, screen));
+
+ /* Convert to strv */
+ retval = g_ptr_array_sized_new (g_hash_table_size (env_table));
+ g_hash_table_iter_init (&iter, env_table);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &e, (gpointer *) &v))
+ g_ptr_array_add (retval, g_strdup_printf ("%s=%s", e, v ? v : ""));
+ g_ptr_array_add (retval, NULL);
+
+ *path = g_strdup (g_hash_table_lookup (env_table, "PATH"));
+ *shell = g_strdup (g_hash_table_lookup (env_table, "SHELL"));
+
+ g_hash_table_destroy (env_table);
+ return (char **) g_ptr_array_free (retval, FALSE);
+}
+
+enum {
+ RESPONSE_RELAUNCH,
+ RESPONSE_EDIT_PREFERENCES
+};
+
+static void
+info_bar_response_cb (GtkWidget *info_bar,
+ int response,
+ TerminalScreen *screen)
+{
+ gtk_widget_grab_focus (GTK_WIDGET (screen));
+
+ switch (response) {
+ case GTK_RESPONSE_CANCEL:
+ gtk_widget_destroy (info_bar);
+ g_signal_emit (screen, signals[CLOSE_SCREEN], 0);
+ break;
+ case RESPONSE_RELAUNCH:
+ gtk_widget_destroy (info_bar);
+ terminal_screen_reexec (screen, NULL, NULL, NULL, NULL);
+ break;
+ case RESPONSE_EDIT_PREFERENCES:
+ terminal_app_edit_preferences (terminal_app_get (),
+ terminal_screen_get_profile (screen),
+ "custom-command-entry");
+ break;
+ default:
+ gtk_widget_destroy (info_bar);
+ break;
+ }
+}
+
+static void
+terminal_screen_show_info_bar (TerminalScreen *screen,
+ GError *error,
+ gboolean show_relaunch)
+{
+ GtkWidget *info_bar;
+
+ if (!gtk_widget_get_parent (GTK_WIDGET (screen)))
+ return;
+
+ info_bar = terminal_info_bar_new (GTK_MESSAGE_ERROR,
+ _("_Preferences"), RESPONSE_EDIT_PREFERENCES,
+ !show_relaunch ? NULL : _("_Relaunch"), RESPONSE_RELAUNCH,
+ NULL);
+ terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar),
+ _("There was an error creating the child process for this terminal"));
+ terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar),
+ "%s", error->message);
+ g_signal_connect (info_bar, "response",
+ G_CALLBACK (info_bar_response_cb), screen);
+
+ gtk_widget_set_halign (info_bar, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (info_bar, GTK_ALIGN_START);
+ gtk_overlay_add_overlay (GTK_OVERLAY (terminal_screen_container_get_from_screen (screen)),
+ info_bar);
+ gtk_info_bar_set_default_response (GTK_INFO_BAR (info_bar), GTK_RESPONSE_CANCEL);
+ gtk_widget_show (info_bar);
+}
+
+static void
+spawn_result_cb (VteTerminal *terminal,
+ GPid pid,
+ GError *error,
+ gpointer user_data)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (terminal);
+ ExecData *exec_data = user_data;
+
+ /* Terminal was destroyed while the spawn operation was in progress; nothing to do. */
+ if (terminal == NULL)
+ goto out;
+
+ TerminalScreenPrivate *priv = screen->priv;
+
+ priv->child_pid = pid;
+
+ if (error) {
+ // FIXMEchpe should be unnecessary, vte already does this internally
+ vte_terminal_set_pty (terminal, NULL);
+
+ gboolean can_reexec = TRUE; /* FIXME */
+ terminal_screen_show_info_bar (screen, error, can_reexec);
+ }
+
+ /* Retain info for reexec, if possible */
+ ExecData *new_exec_data = exec_data_clone (exec_data, TRUE);
+ terminal_screen_clear_exec_data (screen, FALSE);
+ priv->exec_data = new_exec_data;
+
+out:
+
+ /* Must do this even if the terminal was destroyed */
+ exec_data_callback (exec_data, error, screen);
+
+ exec_data_unref (exec_data);
+}
+
+static gboolean
+idle_exec_cb (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+
+ priv->idle_exec_source = 0;
+
+ ExecData *data = priv->exec_data;
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_PROCESSES) {
+ gs_free char *str = exec_data_to_string (data);
+ _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,
+ "[screen %p] now launching the child process: %s\n",
+ screen, str);
+ }
+
+ int n_fds;
+ int *fds;
+ if (data->fd_list) {
+ fds = g_unix_fd_list_steal_fds(data->fd_list, &n_fds);
+ } else {
+ fds = NULL;
+ n_fds = 0;
+ }
+
+ VteTerminal *terminal = VTE_TERMINAL (screen);
+ vte_terminal_spawn_with_fds_async (terminal,
+ data->pty_flags,
+ data->cwd,
+ (char const* const*)data->exec_argv,
+ (char const* const*)data->envv,
+ fds, n_fds,
+ data->fd_map, data->n_fd_map,
+ data->spawn_flags,
+ NULL, NULL, NULL, /* child setup, data, destroy */
+ -1,
+ data->cancellable,
+ spawn_result_cb,
+ exec_data_ref (data));
+
+ return FALSE; /* don't run again */
+}
+
+static void
+terminal_screen_queue_idle_exec (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+
+ if (priv->idle_exec_source != 0)
+ return;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (screen))) {
+ priv->exec_on_realize = TRUE;
+ return;
+ }
+
+ _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,
+ "[screen %p] scheduling launching the child process on idle\n",
+ screen);
+
+ priv->idle_exec_source = g_idle_add ((GSourceFunc) idle_exec_cb, screen);
+}
+
+static TerminalScreenPopupInfo *
+terminal_screen_popup_info_new (TerminalScreen *screen)
+{
+ TerminalScreenPopupInfo *info;
+
+ info = g_slice_new0 (TerminalScreenPopupInfo);
+ info->ref_count = 1;
+
+ return info;
+}
+
+TerminalScreenPopupInfo *
+terminal_screen_popup_info_ref (TerminalScreenPopupInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ info->ref_count++;
+ return info;
+}
+
+void
+terminal_screen_popup_info_unref (TerminalScreenPopupInfo *info)
+{
+ g_return_if_fail (info != NULL);
+
+ if (--info->ref_count > 0)
+ return;
+
+ g_free (info->hyperlink);
+ g_free (info->url);
+ g_free (info->number_info);
+ g_slice_free (TerminalScreenPopupInfo, info);
+}
+
+static gboolean
+terminal_screen_popup_menu (GtkWidget *widget)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (widget);
+ TerminalScreenPopupInfo *info;
+
+ info = terminal_screen_popup_info_new (screen);
+ info->button = 0;
+ info->timestamp = gtk_get_current_event_time ();
+
+ g_signal_emit (screen, signals[SHOW_POPUP_MENU], 0, info);
+ terminal_screen_popup_info_unref (info);
+
+ return TRUE;
+}
+
+static void
+terminal_screen_do_popup (TerminalScreen *screen,
+ GdkEventButton *event,
+ char *hyperlink,
+ char *url,
+ int url_flavor,
+ char *number_info)
+{
+ TerminalScreenPopupInfo *info;
+
+ info = terminal_screen_popup_info_new (screen);
+ info->button = event->button;
+ info->state = event->state & gtk_accelerator_get_default_mod_mask ();
+ info->timestamp = event->time;
+ info->hyperlink = hyperlink; /* adopted */
+ info->url = url; /* adopted */
+ info->url_flavor = url_flavor;
+ info->number_info = number_info; /* adopted */
+
+ g_signal_emit (screen, signals[SHOW_POPUP_MENU], 0, info);
+ terminal_screen_popup_info_unref (info);
+}
+
+static gboolean
+terminal_screen_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (widget);
+ gboolean (* button_press_event) (GtkWidget*, GdkEventButton*) =
+ GTK_WIDGET_CLASS (terminal_screen_parent_class)->button_press_event;
+ gs_free char *hyperlink = NULL;
+ gs_free char *url = NULL;
+ int url_flavor = 0;
+ gs_free char *number_info = NULL;
+ guint state;
+
+ state = event->state & gtk_accelerator_get_default_mod_mask ();
+
+ hyperlink = terminal_screen_check_hyperlink (screen, (GdkEvent*)event);
+ url = terminal_screen_check_match (screen, (GdkEvent*)event, &url_flavor);
+ terminal_screen_check_extra (screen, (GdkEvent*)event, &number_info);
+
+ if (hyperlink != NULL &&
+ (event->button == 1 || event->button == 2) &&
+ (state & GDK_CONTROL_MASK))
+ {
+ gboolean handled = FALSE;
+
+ g_signal_emit (screen, signals[MATCH_CLICKED], 0,
+ hyperlink,
+ FLAVOR_AS_IS,
+ state,
+ &handled);
+ if (handled)
+ return TRUE; /* don't do anything else such as select with the click */
+ }
+
+ if (url != NULL &&
+ (event->button == 1 || event->button == 2) &&
+ (state & GDK_CONTROL_MASK))
+ {
+ gboolean handled = FALSE;
+
+ g_signal_emit (screen, signals[MATCH_CLICKED], 0,
+ url,
+ url_flavor,
+ state,
+ &handled);
+ if (handled)
+ return TRUE; /* don't do anything else such as select with the click */
+ }
+
+ if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+ {
+ if (!(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)))
+ {
+ /* on right-click, we should first try to send the mouse event to
+ * the client, and popup only if that's not handled. */
+ if (button_press_event && button_press_event (widget, event))
+ return TRUE;
+
+ terminal_screen_do_popup (screen, event, hyperlink, url, url_flavor, number_info);
+ hyperlink = NULL; /* adopted to the popup info */
+ url = NULL; /* ditto */
+ number_info = NULL; /* ditto */
+ return TRUE;
+ }
+ else if (!(event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)))
+ {
+ /* do popup on shift+right-click */
+ terminal_screen_do_popup (screen, event, hyperlink, url, url_flavor, number_info);
+ hyperlink = NULL; /* adopted to the popup info */
+ url = NULL; /* ditto */
+ number_info = NULL; /* ditto */
+ return TRUE;
+ }
+ }
+
+ /* default behavior is to let the terminal widget deal with it */
+ if (button_press_event)
+ return button_press_event (widget, event);
+
+ return FALSE;
+}
+
+/**
+ * terminal_screen_get_current_dir:
+ * @screen:
+ *
+ * Tries to determine the current working directory of the foreground process
+ * in @screen's PTY.
+ *
+ * Returns: a newly allocated string containing the current working directory,
+ * or %NULL on failure
+ */
+char *
+terminal_screen_get_current_dir (TerminalScreen *screen)
+{
+ const char *uri;
+
+ uri = vte_terminal_get_current_directory_uri (VTE_TERMINAL (screen));
+ if (uri != NULL)
+ return g_filename_from_uri (uri, NULL, NULL);
+
+ ExecData *data = screen->priv->exec_data;
+ if (data && data->cwd)
+ return g_strdup (data->cwd);
+
+ return NULL;
+}
+
+static void
+terminal_screen_window_title_changed (VteTerminal *vte_terminal,
+ TerminalScreen *screen)
+{
+ g_object_notify (G_OBJECT (screen), "title");
+}
+
+static void
+terminal_screen_child_exited (VteTerminal *terminal,
+ int status)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (terminal);
+ TerminalScreenPrivate *priv = screen->priv;
+ TerminalExitAction action;
+
+ /* Don't do anything if we don't have a child */
+ if (priv->child_pid == -1)
+ return;
+
+ /* No need to chain up to VteTerminalClass::child_exited since it's NULL */
+
+ _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,
+ "[screen %p] child process exited\n",
+ screen);
+
+ priv->child_pid = -1;
+
+ action = g_settings_get_enum (priv->profile, TERMINAL_PROFILE_EXIT_ACTION_KEY);
+
+ switch (action)
+ {
+ case TERMINAL_EXIT_CLOSE:
+ g_signal_emit (screen, signals[CLOSE_SCREEN], 0);
+ break;
+ case TERMINAL_EXIT_RESTART:
+ terminal_screen_reexec (screen, NULL, NULL, NULL, NULL);
+ break;
+ case TERMINAL_EXIT_HOLD: {
+ GtkWidget *info_bar;
+
+ info_bar = terminal_info_bar_new (GTK_MESSAGE_INFO,
+ _("_Relaunch"), RESPONSE_RELAUNCH,
+ NULL);
+ if (WIFEXITED (status)) {
+ terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar),
+ _("The child process exited normally with status %d."), WEXITSTATUS (status));
+ } else if (WIFSIGNALED (status)) {
+ terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar),
+ _("The child process was aborted by signal %d."), WTERMSIG (status));
+ } else {
+ terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar),
+ _("The child process was aborted."));
+ }
+ g_signal_connect (info_bar, "response",
+ G_CALLBACK (info_bar_response_cb), screen);
+
+ gtk_widget_set_halign (info_bar, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (info_bar, GTK_ALIGN_START);
+ gtk_overlay_add_overlay (GTK_OVERLAY (terminal_screen_container_get_from_screen (screen)),
+ info_bar);
+ gtk_info_bar_set_default_response (GTK_INFO_BAR (info_bar), RESPONSE_RELAUNCH);
+ gtk_widget_show (info_bar);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+static void
+terminal_screen_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint timestamp)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (widget);
+ TerminalScreenPrivate *priv = screen->priv;
+ const guchar *selection_data_data;
+ GdkAtom selection_data_target;
+ gint selection_data_length, selection_data_format;
+
+ selection_data_data = gtk_selection_data_get_data (selection_data);
+ selection_data_target = gtk_selection_data_get_target (selection_data);
+ selection_data_length = gtk_selection_data_get_length (selection_data);
+ selection_data_format = gtk_selection_data_get_format (selection_data);
+
+#if 0
+ {
+ GList *tmp;
+
+ g_print ("info: %d\n", info);
+ tmp = context->targets;
+ while (tmp != NULL)
+ {
+ GdkAtom atom = GDK_POINTER_TO_ATOM (tmp->data);
+
+ g_print ("Target: %s\n", gdk_atom_name (atom));
+
+ tmp = tmp->next;
+ }
+
+ g_print ("Chosen target: %s\n", gdk_atom_name (selection_data->target));
+ }
+#endif
+
+ if (gtk_targets_include_uri (&selection_data_target, 1))
+ {
+ gs_strfreev char **uris;
+ gs_free char *text = NULL;
+ gsize len;
+
+ uris = gtk_selection_data_get_uris (selection_data);
+ if (!uris)
+ return;
+
+ terminal_util_transform_uris_to_quoted_fuse_paths (uris);
+
+ text = terminal_util_concat_uris (uris, &len);
+ vte_terminal_feed_child (VTE_TERMINAL (screen), text, len);
+ }
+ else if (gtk_targets_include_text (&selection_data_target, 1))
+ {
+ gs_free char *text;
+
+ text = (char *) gtk_selection_data_get_text (selection_data);
+ if (text && text[0])
+ vte_terminal_feed_child (VTE_TERMINAL (screen), text, strlen (text));
+ }
+ else switch (info)
+ {
+ case TARGET_COLOR:
+ {
+ guint16 *data = (guint16 *)selection_data_data;
+ GdkRGBA color;
+
+ /* We accept drops with the wrong format, since the KDE color
+ * chooser incorrectly drops application/x-color with format 8.
+ * So just check for the data length.
+ */
+ if (selection_data_length != 8)
+ return;
+
+ color.red = (double) data[0] / 65535.;
+ color.green = (double) data[1] / 65535.;
+ color.blue = (double) data[2] / 65535.;
+ color.alpha = 1.;
+ /* FIXME: use opacity from data[3] */
+
+ terminal_g_settings_set_rgba (priv->profile,
+ TERMINAL_PROFILE_BACKGROUND_COLOR_KEY,
+ &color);
+ g_settings_set_boolean (priv->profile, TERMINAL_PROFILE_USE_THEME_COLORS_KEY, FALSE);
+ }
+ break;
+
+ case TARGET_MOZ_URL:
+ {
+ char *utf8_data, *text;
+ char *uris[2];
+ gsize len;
+
+ /* MOZ_URL is in UCS-2 but in format 8. BROKEN!
+ *
+ * The data contains the URL, a \n, then the
+ * title of the web page.
+ *
+ * Note that some producers (e.g. dolphin) delimit with a \r\n
+ * (see issue#293), so we need to handle that, too.
+ */
+ if (selection_data_format != 8 ||
+ selection_data_length == 0 ||
+ (selection_data_length % 2) != 0)
+ return;
+
+ utf8_data = g_utf16_to_utf8 ((const gunichar2*) selection_data_data,
+ selection_data_length / 2,
+ NULL, NULL, NULL);
+ if (!utf8_data)
+ return;
+
+ uris[0] = g_strdelimit(utf8_data, "\r\n", 0);
+ uris[1] = NULL;
+ terminal_util_transform_uris_to_quoted_fuse_paths (uris); /* This may replace uris[0] */
+
+ text = terminal_util_concat_uris (uris, &len);
+ vte_terminal_feed_child (VTE_TERMINAL (screen), text, len);
+ g_free (text);
+ g_free (uris[0]);
+ }
+ break;
+
+ case TARGET_NETSCAPE_URL:
+ {
+ char *utf8_data, *newline, *text;
+ char *uris[2];
+ gsize len;
+
+ /* The data contains the URL, a \n, then the
+ * title of the web page.
+ */
+ if (selection_data_length < 0 || selection_data_format != 8)
+ return;
+
+ utf8_data = g_strndup ((char *) selection_data_data, selection_data_length);
+ newline = strchr (utf8_data, '\n');
+ if (newline)
+ *newline = '\0';
+
+ uris[0] = utf8_data;
+ uris[1] = NULL;
+ terminal_util_transform_uris_to_quoted_fuse_paths (uris); /* This may replace uris[0] */
+
+ text = terminal_util_concat_uris (uris, &len);
+ vte_terminal_feed_child (VTE_TERMINAL (screen), text, len);
+ g_free (text);
+ g_free (uris[0]);
+ }
+ break;
+
+ case TARGET_RESET_BG:
+ g_settings_reset (priv->profile, TERMINAL_PROFILE_BACKGROUND_COLOR_KEY);
+ break;
+
+ case TARGET_TAB:
+ {
+ GtkWidget *container;
+ TerminalScreen *moving_screen;
+ TerminalWindow *source_window;
+ TerminalWindow *dest_window;
+
+ container = *(GtkWidget**) selection_data_data;
+ if (!GTK_IS_WIDGET (container))
+ return;
+
+ moving_screen = terminal_screen_container_get_screen (TERMINAL_SCREEN_CONTAINER (container));
+ g_warn_if_fail (TERMINAL_IS_SCREEN (moving_screen));
+ if (!TERMINAL_IS_SCREEN (moving_screen))
+ return;
+
+ source_window = terminal_screen_get_window (moving_screen);
+ dest_window = terminal_screen_get_window (screen);
+ terminal_window_move_screen (source_window, dest_window, moving_screen, -1);
+
+ gtk_drag_finish (context, TRUE, TRUE, timestamp);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+void
+_terminal_screen_update_scrollbar (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ TerminalScreenContainer *container;
+ GtkPolicyType vpolicy;
+
+ container = terminal_screen_container_get_from_screen (screen);
+ if (container == NULL)
+ return;
+
+ vpolicy = g_settings_get_enum (priv->profile, TERMINAL_PROFILE_SCROLLBAR_POLICY_KEY);
+
+ terminal_screen_container_set_policy (container, GTK_POLICY_NEVER, vpolicy);
+}
+
+void
+terminal_screen_get_size (TerminalScreen *screen,
+ int *width_chars,
+ int *height_chars)
+{
+ VteTerminal *terminal = VTE_TERMINAL (screen);
+
+ *width_chars = vte_terminal_get_column_count (terminal);
+ *height_chars = vte_terminal_get_row_count (terminal);
+}
+
+void
+terminal_screen_get_cell_size (TerminalScreen *screen,
+ int *cell_width_pixels,
+ int *cell_height_pixels)
+{
+ VteTerminal *terminal = VTE_TERMINAL (screen);
+
+ *cell_width_pixels = vte_terminal_get_char_width (terminal);
+ *cell_height_pixels = vte_terminal_get_char_height (terminal);
+}
+
+static char*
+terminal_screen_check_hyperlink (TerminalScreen *screen,
+ GdkEvent *event)
+{
+ return vte_terminal_hyperlink_check_event (VTE_TERMINAL (screen), event);
+}
+
+static char*
+terminal_screen_check_match (TerminalScreen *screen,
+ GdkEvent *event,
+ int *flavor)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ GSList *tags;
+ int tag;
+ char *match;
+
+ match = vte_terminal_match_check_event (VTE_TERMINAL (screen), event, &tag);
+ for (tags = priv->match_tags; tags != NULL; tags = tags->next)
+ {
+ TagData *tag_data = (TagData*) tags->data;
+ if (tag_data->tag == tag)
+ {
+ if (flavor)
+ *flavor = tag_data->flavor;
+ return match;
+ }
+ }
+
+ g_free (match);
+ return NULL;
+}
+
+static void
+terminal_screen_check_extra (TerminalScreen *screen,
+ GdkEvent *event,
+ char **number_info)
+{
+ guint i;
+ char **matches;
+ gboolean flavor_number_found = FALSE;
+
+ matches = g_newa (char *, n_extra_regexes);
+ memset(matches, 0, sizeof(char*) * n_extra_regexes);
+
+ if (
+ vte_terminal_event_check_regex_simple (VTE_TERMINAL (screen),
+ event,
+ extra_regexes,
+ n_extra_regexes,
+ 0,
+ matches))
+ {
+ for (i = 0; i < n_extra_regexes; i++)
+ {
+ if (matches[i] != NULL)
+ {
+ /* Store the first match for each flavor, free all the others */
+ switch (extra_regex_flavors[i])
+ {
+ case FLAVOR_NUMBER:
+ if (!flavor_number_found)
+ {
+ *number_info = terminal_util_number_info (matches[i]);
+ flavor_number_found = TRUE;
+ }
+ g_free (matches[i]);
+ break;
+ default:
+ g_free (matches[i]);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * terminal_screen_has_foreground_process:
+ * @screen:
+ * @process_name: (out) (allow-none): the basename of the program, or %NULL
+ * @cmdline: (out) (allow-none): the full command line, or %NULL
+ *
+ * Checks whether there's a foreground process running in
+ * this terminal.
+ *
+ * Returns: %TRUE iff there's a foreground process running in @screen
+ */
+gboolean
+terminal_screen_has_foreground_process (TerminalScreen *screen,
+ char **process_name,
+ char **cmdline)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ gs_free char *command = NULL;
+ gs_free char *data_buf = NULL;
+ gs_free char *basename = NULL;
+ gs_free char *name = NULL;
+ VtePty *pty;
+ int fd;
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
+ int mib[4];
+#else
+ char filename[64];
+#endif
+ char *data;
+ gsize i;
+ gsize len;
+ int fgpid;
+
+ if (priv->child_pid == -1)
+ return FALSE;
+
+ pty = vte_terminal_get_pty (VTE_TERMINAL (screen));
+ if (pty == NULL)
+ return FALSE;
+
+ fd = vte_pty_get_fd (pty);
+ if (fd == -1)
+ return FALSE;
+
+ fgpid = tcgetpgrp (fd);
+ if (fgpid == -1 || fgpid == priv->child_pid)
+ return FALSE;
+
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ARGS;
+ mib[3] = fgpid;
+ if (sysctl (mib, G_N_ELEMENTS (mib), NULL, &len, NULL, 0) == -1)
+ return TRUE;
+
+ data_buf = g_malloc0 (len);
+ if (sysctl (mib, G_N_ELEMENTS (mib), data_buf, &len, NULL, 0) == -1)
+ return TRUE;
+ data = data_buf;
+#elif defined(__OpenBSD__)
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC_ARGS;
+ mib[2] = fgpid;
+ mib[3] = KERN_PROC_ARGV;
+ if (sysctl (mib, G_N_ELEMENTS (mib), NULL, &len, NULL, 0) == -1)
+ return TRUE;
+
+ data_buf = g_malloc0 (len);
+ if (sysctl (mib, G_N_ELEMENTS (mib), data_buf, &len, NULL, 0) == -1)
+ return TRUE;
+ data = ((char**)data_buf)[0];
+#else
+ g_snprintf (filename, sizeof (filename), "/proc/%d/cmdline", fgpid);
+ if (!g_file_get_contents (filename, &data_buf, &len, NULL))
+ return TRUE;
+ data = data_buf;
+#endif
+
+ basename = g_path_get_basename (data);
+ if (!basename)
+ return TRUE;
+
+ name = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL);
+ if (!name)
+ return TRUE;
+
+ if (!process_name && !cmdline)
+ return TRUE;
+
+ gs_transfer_out_value (process_name, &name);
+
+ if (len > 0 && data[len - 1] == '\0')
+ len--;
+ for (i = 0; i < len; i++)
+ {
+ if (data[i] == '\0')
+ data[i] = ' ';
+ }
+
+ command = g_filename_to_utf8 (data, -1, NULL, NULL, NULL);
+ if (!command)
+ return TRUE;
+
+ gs_transfer_out_value (cmdline, &command);
+
+ return TRUE;
+}
+
+const char *
+terminal_screen_get_uuid (TerminalScreen *screen)
+{
+ g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL);
+
+ return screen->priv->uuid;
+}
diff --git a/src/terminal-screen.h b/src/terminal-screen.h
new file mode 100644
index 0000000..8ea3378
--- /dev/null
+++ b/src/terminal-screen.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2008, 2010 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_SCREEN_H
+#define TERMINAL_SCREEN_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include <vte/vte.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ FLAVOR_AS_IS,
+ FLAVOR_DEFAULT_TO_HTTP,
+ FLAVOR_VOIP_CALL,
+ FLAVOR_EMAIL,
+ FLAVOR_NUMBER,
+} TerminalURLFlavor;
+
+/* Forward decls */
+typedef struct _TerminalScreenPopupInfo TerminalScreenPopupInfo;
+typedef struct _TerminalWindow TerminalWindow;
+
+#define TERMINAL_TYPE_SCREEN (terminal_screen_get_type ())
+#define TERMINAL_SCREEN(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_SCREEN, TerminalScreen))
+#define TERMINAL_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_SCREEN, TerminalScreenClass))
+#define TERMINAL_IS_SCREEN(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_SCREEN))
+#define TERMINAL_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_SCREEN))
+#define TERMINAL_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_SCREEN, TerminalScreenClass))
+
+typedef struct _TerminalScreen TerminalScreen;
+typedef struct _TerminalScreenClass TerminalScreenClass;
+typedef struct _TerminalScreenPrivate TerminalScreenPrivate;
+
+struct _TerminalScreen
+{
+ VteTerminal parent_instance;
+
+ TerminalScreenPrivate *priv;
+};
+
+struct _TerminalScreenClass
+{
+ VteTerminalClass parent_class;
+
+ void (* profile_set) (TerminalScreen *screen,
+ GSettings *old_profile);
+ void (* show_popup_menu) (TerminalScreen *screen,
+ TerminalScreenPopupInfo *info);
+ gboolean (* match_clicked) (TerminalScreen *screen,
+ const char *url,
+ int flavor,
+ guint state);
+ void (* close_screen) (TerminalScreen *screen);
+};
+
+GType terminal_screen_get_type (void) G_GNUC_CONST;
+
+const char *terminal_screen_get_uuid (TerminalScreen *screen);
+
+TerminalScreen *terminal_screen_new (GSettings *profile,
+ const char *title,
+ double zoom);
+
+typedef void (* TerminalScreenExecCallback) (TerminalScreen *screen,
+ GError *error,
+ gpointer user_data);
+
+gboolean terminal_screen_exec (TerminalScreen *screen,
+ char **argv,
+ char **envv,
+ gboolean as_shell,
+ const char *cwd,
+ GUnixFDList *fd_list,
+ GVariant *fd_array,
+ TerminalScreenExecCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GCancellable *cancellable,
+ GError **error);
+
+
+gboolean terminal_screen_reexec (TerminalScreen *screen,
+ char **envv,
+ const char *cwd,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean terminal_screen_reexec_from_screen (TerminalScreen *screen,
+ TerminalScreen *parent_screen,
+ GCancellable *cancellable,
+ GError **error);
+
+void terminal_screen_set_profile (TerminalScreen *screen,
+ GSettings *profile);
+GSettings* terminal_screen_get_profile (TerminalScreen *screen);
+GSettings* terminal_screen_ref_profile (TerminalScreen *screen);
+
+const char* terminal_screen_get_title (TerminalScreen *screen);
+
+char *terminal_screen_get_current_dir (TerminalScreen *screen);
+
+void terminal_screen_get_size (TerminalScreen *screen,
+ int *width_chars,
+ int *height_chars);
+void terminal_screen_get_cell_size (TerminalScreen *screen,
+ int *width_chars,
+ int *height_chars);
+
+void _terminal_screen_update_scrollbar (TerminalScreen *screen);
+
+void terminal_screen_save_config (TerminalScreen *screen,
+ GKeyFile *key_file,
+ const char *group);
+
+gboolean terminal_screen_has_foreground_process (TerminalScreen *screen,
+ char **process_name,
+ char **cmdline);
+
+/* Allow scales a bit smaller and a bit larger than the usual pango ranges */
+#define TERMINAL_SCALE_XXX_SMALL (PANGO_SCALE_XX_SMALL/1.2)
+#define TERMINAL_SCALE_XXXX_SMALL (TERMINAL_SCALE_XXX_SMALL/1.2)
+#define TERMINAL_SCALE_XXXXX_SMALL (TERMINAL_SCALE_XXXX_SMALL/1.2)
+#define TERMINAL_SCALE_XXX_LARGE (PANGO_SCALE_XX_LARGE*1.2)
+#define TERMINAL_SCALE_XXXX_LARGE (TERMINAL_SCALE_XXX_LARGE*1.2)
+#define TERMINAL_SCALE_XXXXX_LARGE (TERMINAL_SCALE_XXXX_LARGE*1.2)
+#define TERMINAL_SCALE_MINIMUM (TERMINAL_SCALE_XXXXX_SMALL/1.2)
+#define TERMINAL_SCALE_MAXIMUM (TERMINAL_SCALE_XXXXX_LARGE*1.2)
+
+struct _TerminalScreenPopupInfo {
+ int ref_count;
+ char *url;
+ TerminalURLFlavor url_flavor;
+ char *hyperlink;
+ char *number_info;
+ guint button;
+ guint state;
+ guint32 timestamp;
+};
+
+TerminalScreenPopupInfo *terminal_screen_popup_info_ref (TerminalScreenPopupInfo *info);
+
+void terminal_screen_popup_info_unref (TerminalScreenPopupInfo *info);
+
+G_END_DECLS
+
+#endif /* TERMINAL_SCREEN_H */
diff --git a/src/terminal-search-popover.c b/src/terminal-search-popover.c
new file mode 100644
index 0000000..ff18f49
--- /dev/null
+++ b/src/terminal-search-popover.c
@@ -0,0 +1,580 @@
+/*
+ * Copyright © 2015 Christian Persch
+ * Copyright © 2005 Paolo Maggi
+ * Copyright © 2010 Red Hat (Red Hat author: Behdad Esfahbod)
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "terminal-pcre2.h"
+#include "terminal-search-popover.h"
+#include "terminal-intl.h"
+#include "terminal-window.h"
+#include "terminal-app.h"
+#include "terminal-libgsystem.h"
+
+typedef struct _TerminalSearchPopoverPrivate TerminalSearchPopoverPrivate;
+
+struct _TerminalSearchPopover
+{
+ GtkWindow parent_instance;
+};
+
+struct _TerminalSearchPopoverClass
+{
+ GtkWindowClass parent_class;
+
+ /* Signals */
+ void (* search) (TerminalSearchPopover *popover,
+ gboolean backward);
+};
+
+struct _TerminalSearchPopoverPrivate
+{
+ GtkWidget *search_entry;
+ GtkWidget *search_prev_button;
+ GtkWidget *search_next_button;
+ GtkWidget *reveal_button;
+ GtkWidget *close_button;
+ GtkWidget *revealer;
+ GtkWidget *match_case_checkbutton;
+ GtkWidget *entire_word_checkbutton;
+ GtkWidget *regex_checkbutton;
+ GtkWidget *wrap_around_checkbutton;
+
+ gboolean search_text_changed;
+
+ /* Cached regex */
+ gboolean regex_caseless;
+ char *regex_pattern;
+ VteRegex *regex;
+};
+
+enum {
+ PROP_0,
+ PROP_REGEX,
+ PROP_WRAP_AROUND,
+ LAST_PROP
+};
+
+enum {
+ SEARCH,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+static GParamSpec *pspecs[LAST_PROP];
+static GtkListStore *history_store;
+
+G_DEFINE_TYPE_WITH_PRIVATE (TerminalSearchPopover, terminal_search_popover, GTK_TYPE_WINDOW)
+
+#define PRIV(obj) ((TerminalSearchPopoverPrivate *) terminal_search_popover_get_instance_private ((TerminalSearchPopover *)(obj)))
+
+/* history */
+
+#define HISTORY_MIN_ITEM_LEN (3)
+#define HISTORY_LENGTH (10)
+
+static gboolean
+history_enabled (void)
+{
+ gboolean enabled;
+
+ /* not quite an exact setting for this, but close enough… */
+ g_object_get (gtk_settings_get_default (), "gtk-recent-files-enabled", &enabled, NULL);
+ if (!enabled)
+ return FALSE;
+
+ if (history_store == NULL) {
+ history_store = gtk_list_store_new (1, G_TYPE_STRING);
+ g_object_set_data_full (G_OBJECT (terminal_app_get ()), "search-history-store",
+ history_store, (GDestroyNotify) g_object_unref);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+history_remove_item (const char *text)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (history_store);
+ GtkTreeIter iter;
+
+ if (!gtk_tree_model_get_iter_first (model, &iter))
+ return FALSE;
+
+ do {
+ gs_free gchar *item_text;
+
+ gtk_tree_model_get (model, &iter, 0, &item_text, -1);
+
+ if (item_text != NULL && strcmp (item_text, text) == 0) {
+ gtk_list_store_remove (history_store, &iter);
+ return TRUE;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ return FALSE;
+}
+
+static void
+history_clamp (int max)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ /* -1 because TreePath counts from 0 */
+ path = gtk_tree_path_new_from_indices (max - 1, -1);
+
+ if (gtk_tree_model_get_iter (GTK_TREE_MODEL (history_store), &iter, path))
+ while (1)
+ if (!gtk_list_store_remove (history_store, &iter))
+ break;
+
+ gtk_tree_path_free (path);
+}
+
+static void
+history_insert_item (const char *text)
+{
+ GtkTreeIter iter;
+
+ if (!history_enabled () || text == NULL)
+ return;
+
+ if (g_utf8_strlen (text, -1) <= HISTORY_MIN_ITEM_LEN)
+ return;
+
+ /* remove the text from the store if it was already
+ * present. If it wasn't, clamp to max history - 1
+ * before inserting the new row, otherwise appending
+ * would not work */
+ if (!history_remove_item (text))
+ history_clamp (HISTORY_LENGTH - 1);
+
+ gtk_list_store_insert_with_values (history_store, &iter, 0,
+ 0, text,
+ -1);
+}
+
+/* helper functions */
+
+static void
+update_sensitivity (TerminalSearchPopover *popover)
+{
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+ gboolean can_search;
+
+ can_search = priv->regex != NULL;
+
+ gtk_widget_set_sensitive (priv->search_prev_button, can_search);
+ gtk_widget_set_sensitive (priv->search_next_button, can_search);
+}
+
+static void
+perform_search (TerminalSearchPopover *popover,
+ gboolean backward)
+{
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+
+ if (priv->regex == NULL)
+ return;
+
+ /* Add to search history */
+ if (priv->search_text_changed) {
+ const char *search_text;
+
+ search_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
+ history_insert_item (search_text);
+
+ priv->search_text_changed = FALSE;
+ }
+
+ g_signal_emit (popover, signals[SEARCH], 0, backward);
+}
+
+static void
+previous_match_cb (GtkWidget *widget,
+ TerminalSearchPopover *popover)
+{
+ perform_search (popover, TRUE);
+}
+
+static void
+next_match_cb (GtkWidget *widget,
+ TerminalSearchPopover *popover)
+{
+ perform_search (popover, FALSE);
+}
+
+static void
+close_clicked_cb (GtkWidget *widget,
+ GtkWidget *popover)
+{
+ gtk_widget_hide (popover);
+}
+
+static void
+search_button_clicked_cb (GtkWidget *button,
+ TerminalSearchPopover *popover)
+{
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+
+ perform_search (popover, button == priv->search_prev_button);
+}
+
+static gboolean
+key_press_cb (GtkWidget *popover,
+ GdkEventKey *event,
+ gpointer user_data G_GNUC_UNUSED)
+{
+ if (event->keyval == GDK_KEY_Escape) {
+ gtk_widget_hide (popover);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+update_regex (TerminalSearchPopover *popover)
+{
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+ const char *search_text;
+ gboolean caseless;
+ gs_free char *pattern;
+ gs_free_error GError *error = NULL;
+
+ search_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
+
+ caseless = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->match_case_checkbutton));
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->regex_checkbutton))) {
+ pattern = g_strdup (search_text);
+ } else {
+ pattern = g_regex_escape_string (search_text, -1);
+ }
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->entire_word_checkbutton))) {
+ char *new_pattern;
+ new_pattern = g_strdup_printf ("\\b%s\\b", pattern);
+ g_free (pattern);
+ pattern = new_pattern;
+ }
+
+ if (priv->regex_caseless == caseless &&
+ g_strcmp0 (priv->regex_pattern, pattern) == 0)
+ return;
+
+ if (priv->regex) {
+ vte_regex_unref (priv->regex);
+ }
+
+ g_clear_pointer (&priv->regex_pattern, g_free);
+
+ /* FIXME: if comping the regex fails, show the error message somewhere */
+ if (search_text[0] != '\0') {
+ guint32 compile_flags;
+
+ compile_flags = PCRE2_UTF | PCRE2_NO_UTF_CHECK | PCRE2_UCP | PCRE2_MULTILINE;
+ if (caseless)
+ compile_flags |= PCRE2_CASELESS;
+
+ priv->regex = vte_regex_new_for_search (pattern, -1, compile_flags, &error);
+ if (priv->regex != NULL &&
+ (!vte_regex_jit (priv->regex, PCRE2_JIT_COMPLETE, NULL) ||
+ !vte_regex_jit (priv->regex, PCRE2_JIT_PARTIAL_SOFT, NULL))) {
+ }
+
+ if (priv->regex != NULL)
+ gs_transfer_out_value (&priv->regex_pattern, &pattern);
+ } else {
+ priv->regex = NULL;
+ }
+
+ priv->regex_caseless = caseless;
+
+ update_sensitivity (popover);
+
+ g_object_notify_by_pspec (G_OBJECT (popover), pspecs[PROP_REGEX]);
+}
+
+static void
+search_text_changed_cb (GtkToggleButton *button,
+ TerminalSearchPopover *popover)
+{
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+
+ update_regex (popover);
+ priv->search_text_changed = TRUE;
+}
+
+static void
+search_parameters_changed_cb (GtkToggleButton *button,
+ TerminalSearchPopover *popover)
+{
+ update_regex (popover);
+}
+
+static void
+wrap_around_toggled_cb (GtkToggleButton *button,
+ TerminalSearchPopover *popover)
+{
+ g_object_notify_by_pspec (G_OBJECT (popover), pspecs[PROP_WRAP_AROUND]);
+}
+
+/* public functions */
+
+/* Class implementation */
+
+static void
+terminal_search_popover_grab_focus (GtkWidget *widget)
+{
+ TerminalSearchPopover *popover = TERMINAL_SEARCH_POPOVER (widget);
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+
+ gtk_widget_grab_focus (priv->search_entry);
+}
+
+static void
+terminal_search_popover_init (TerminalSearchPopover *popover)
+{
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+ GtkWidget *widget = GTK_WIDGET (popover);
+
+ priv->regex_pattern = 0;
+ priv->regex_caseless = TRUE;
+
+ gtk_widget_init_template (widget);
+
+ /* Make the search entry reasonably wide */
+ gtk_widget_set_size_request (priv->search_entry, 300, -1);
+
+ /* Add entry completion with history */
+#if 0
+ g_object_set (G_OBJECT (priv->search_entry),
+ "model", history_store,
+ "entry-text-column", 0,
+ NULL);
+#endif
+
+ if (history_enabled ()) {
+ gs_unref_object GtkEntryCompletion *completion;
+
+ completion = gtk_entry_completion_new ();
+ gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (history_store));
+ gtk_entry_completion_set_text_column (completion, 0);
+ gtk_entry_completion_set_minimum_key_length (completion, HISTORY_MIN_ITEM_LEN);
+ gtk_entry_completion_set_popup_completion (completion, FALSE);
+ gtk_entry_completion_set_inline_completion (completion, TRUE);
+ gtk_entry_set_completion (GTK_ENTRY (priv->search_entry), completion);
+ }
+
+#if 0
+ gtk_popover_set_default_widget (GTK_POPOVER (popover), priv->search_prev_button);
+#else
+ GtkWindow *window = GTK_WINDOW (popover);
+ gtk_window_set_default (window, priv->search_prev_button);
+#endif
+
+ g_signal_connect (priv->search_entry, "previous-match", G_CALLBACK (previous_match_cb), popover);
+ g_signal_connect (priv->search_entry, "next-match", G_CALLBACK (next_match_cb), popover);
+
+ g_signal_connect (priv->search_prev_button, "clicked", G_CALLBACK (search_button_clicked_cb), popover);
+ g_signal_connect (priv->search_next_button, "clicked", G_CALLBACK (search_button_clicked_cb), popover);
+
+ g_signal_connect (priv->close_button, "clicked", G_CALLBACK (close_clicked_cb), popover);
+
+ g_object_bind_property (priv->reveal_button, "active",
+ priv->revealer, "reveal-child",
+ G_BINDING_DEFAULT);
+
+ update_sensitivity (popover);
+
+ g_signal_connect (priv->search_entry, "search-changed", G_CALLBACK (search_text_changed_cb), popover);
+ g_signal_connect (priv->match_case_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), popover);
+ g_signal_connect (priv->entire_word_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), popover);
+ g_signal_connect (priv->regex_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), popover);
+
+ g_signal_connect (priv->wrap_around_checkbutton, "toggled", G_CALLBACK (wrap_around_toggled_cb), popover);
+
+ g_signal_connect (popover, "key-press-event", G_CALLBACK (key_press_cb), NULL);
+
+ if (terminal_app_get_dialog_use_headerbar (terminal_app_get ())) {
+ GtkWidget *headerbar;
+
+ headerbar = g_object_new (GTK_TYPE_HEADER_BAR,
+ "title", gtk_window_get_title (window),
+ "has-subtitle", FALSE,
+ "show-close-button", TRUE,
+ "visible", TRUE,
+ NULL);
+ gtk_style_context_add_class (gtk_widget_get_style_context (headerbar),
+ "default-decoration");
+ gtk_window_set_titlebar (window, headerbar);
+ }
+}
+
+static void
+terminal_search_popover_finalize (GObject *object)
+{
+ TerminalSearchPopover *popover = TERMINAL_SEARCH_POPOVER (object);
+ TerminalSearchPopoverPrivate *priv = PRIV (popover);
+
+ if (priv->regex) {
+ vte_regex_unref (priv->regex);
+ }
+
+ g_free (priv->regex_pattern);
+
+ G_OBJECT_CLASS (terminal_search_popover_parent_class)->finalize (object);
+}
+
+static void
+terminal_search_popover_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalSearchPopover *popover = TERMINAL_SEARCH_POPOVER (object);
+
+ switch (prop_id) {
+ case PROP_REGEX:
+ g_value_set_boxed (value, terminal_search_popover_get_regex (popover));
+ break;
+ case PROP_WRAP_AROUND:
+ g_value_set_boolean (value, terminal_search_popover_get_wrap_around (popover));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_search_popover_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ case PROP_REGEX:
+ case PROP_WRAP_AROUND:
+ /* not writable */
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_search_popover_class_init (TerminalSearchPopoverClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->finalize = terminal_search_popover_finalize;
+ gobject_class->get_property = terminal_search_popover_get_property;
+ gobject_class->set_property = terminal_search_popover_set_property;
+
+ widget_class->grab_focus = terminal_search_popover_grab_focus;
+
+ signals[SEARCH] =
+ g_signal_new (I_("search"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalSearchPopoverClass, search),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+
+ pspecs[PROP_REGEX] =
+ g_param_spec_boxed ("regex", NULL, NULL,
+ VTE_TYPE_REGEX,
+ G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
+
+ pspecs[PROP_WRAP_AROUND] =
+ g_param_spec_boolean ("wrap-around", NULL, NULL,
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
+
+ g_object_class_install_properties (gobject_class, G_N_ELEMENTS (pspecs), pspecs);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/terminal/ui/search-popover.ui");
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, search_entry);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, search_prev_button);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, search_next_button);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, reveal_button);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, close_button);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, revealer);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, match_case_checkbutton);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, entire_word_checkbutton);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, regex_checkbutton);
+ gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, wrap_around_checkbutton);
+}
+
+/* public API */
+
+/**
+ * terminal_search_popover_new:
+ *
+ * Returns: a new #TerminalSearchPopover
+ */
+TerminalSearchPopover *
+terminal_search_popover_new (GtkWidget *relative_to_widget)
+{
+ return g_object_new (TERMINAL_TYPE_SEARCH_POPOVER,
+#if 0
+ "relative-to", relative_to_widget,
+#else
+ "transient-for", gtk_widget_get_toplevel (relative_to_widget),
+#endif
+ NULL);
+}
+
+/**
+ * terminal_search_popover_get_regex:
+ * @popover: a #TerminalSearchPopover
+ *
+ * Returns: (transfer none): the search regex, or %NULL
+ */
+VteRegex *
+terminal_search_popover_get_regex (TerminalSearchPopover *popover)
+{
+ g_return_val_if_fail (TERMINAL_IS_SEARCH_POPOVER (popover), NULL);
+
+ return PRIV (popover)->regex;
+}
+
+/**
+ * terminal_search_popover_get_wrap_around:
+ * @popover: a #TerminalSearchPopover
+ *
+ * Returns: (transfer none): whether search should wrap around
+ */
+gboolean
+terminal_search_popover_get_wrap_around (TerminalSearchPopover *popover)
+{
+ g_return_val_if_fail (TERMINAL_IS_SEARCH_POPOVER (popover), FALSE);
+
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (PRIV (popover)->wrap_around_checkbutton));
+}
diff --git a/src/terminal-search-popover.h b/src/terminal-search-popover.h
new file mode 100644
index 0000000..10771d9
--- /dev/null
+++ b/src/terminal-search-popover.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2008 Christian Persch
+ *
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_SEARCH_POPOVER_H
+#define TERMINAL_SEARCH_POPOVER_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_SEARCH_POPOVER (terminal_search_popover_get_type ())
+#define TERMINAL_SEARCH_POPOVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_SEARCH_POPOVER, TerminalSearchPopover))
+#define TERMINAL_SEARCH_POPOVER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_SEARCH_POPOVER, TerminalSearchPopoverClass))
+#define TERMINAL_IS_SEARCH_POPOVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_SEARCH_POPOVER))
+#define TERMINAL_IS_SEARCH_POPOVER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_SEARCH_POPOVER))
+#define TERMINAL_SEARCH_POPOVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_SEARCH_POPOVER, TerminalSearchPopoverClass))
+
+typedef struct _TerminalSearchPopover TerminalSearchPopover;
+typedef struct _TerminalSearchPopoverClass TerminalSearchPopoverClass;
+
+GType terminal_search_popover_get_type (void);
+
+TerminalSearchPopover *terminal_search_popover_new (GtkWidget *relative_to_widget);
+
+VteRegex *
+ terminal_search_popover_get_regex (TerminalSearchPopover *popover);
+
+gboolean terminal_search_popover_get_wrap_around (TerminalSearchPopover *popover);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_SEARCH_POPOVER_H */
diff --git a/src/terminal-search-provider.c b/src/terminal-search-provider.c
new file mode 100644
index 0000000..90c063e
--- /dev/null
+++ b/src/terminal-search-provider.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright © 2013, 2014 Red Hat, 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "terminal-app.h"
+#include "terminal-debug.h"
+#include "terminal-libgsystem.h"
+#include "terminal-screen-container.h"
+#include "terminal-search-provider.h"
+#include "terminal-search-provider-gdbus-generated.h"
+#include "terminal-window.h"
+
+struct _TerminalSearchProvider
+{
+ GObject parent;
+
+ TerminalSearchProvider2 *skeleton;
+};
+
+struct _TerminalSearchProviderClass
+{
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (TerminalSearchProvider, terminal_search_provider, G_TYPE_OBJECT)
+
+static char *
+normalize_casefold_and_unaccent (const char *str)
+{
+ gs_free char *casefolded = NULL, *normalized = NULL;
+ char *retval = NULL;
+
+ if (str == NULL)
+ goto out;
+
+ normalized = g_utf8_normalize (str, -1, G_NORMALIZE_ALL_COMPOSE);
+ casefolded = g_utf8_casefold (normalized, -1);
+ retval = g_str_to_ascii (casefolded, NULL);
+
+ out:
+ return retval;
+}
+
+static char **
+normalize_casefold_and_unaccent_terms (const char* const *terms)
+{
+ char **casefolded_terms;
+ guint i, n;
+
+ n = g_strv_length ((char **) terms);
+ casefolded_terms = g_new (char *, n + 1);
+
+ for (i = 0; i < n; i++)
+ casefolded_terms[i] = normalize_casefold_and_unaccent (terms[i]);
+ casefolded_terms[n] = NULL;
+
+ return casefolded_terms;
+}
+
+static gboolean
+match_terms (const char *str,
+ const char* const *terms)
+{
+ gs_free char *casefolded_str = NULL;
+ gboolean matches = TRUE;
+ guint i;
+
+ if (str == NULL)
+ {
+ matches = FALSE;
+ goto out;
+ }
+
+ casefolded_str = normalize_casefold_and_unaccent (str);
+ for (i = 0; terms[i] != NULL; i++)
+ {
+ if (strstr (casefolded_str, terms[i]) == NULL)
+ {
+ matches = FALSE;
+ break;
+ }
+ }
+
+ out:
+ return matches;
+}
+
+static gboolean
+handle_get_initial_result_set_cb (TerminalSearchProvider2 *skeleton,
+ GDBusMethodInvocation *invocation,
+ const char *const *terms,
+ gpointer user_data)
+{
+ GList *l, *screens = NULL, *windows;
+ gs_unref_ptrarray GPtrArray *results;
+ TerminalApp *app;
+ gs_strfreev char **casefolded_terms = NULL;
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "GetInitialResultSet started\n");
+
+ app = terminal_app_get ();
+ windows = gtk_application_get_windows (GTK_APPLICATION (app));
+ for (l = windows; l != NULL; l = l->next)
+ {
+ TerminalWindow *window = (TerminalWindow*)(l->data);
+ GList *c, *containers;
+
+ if (!TERMINAL_IS_WINDOW (l->data))
+ continue;
+
+ containers = terminal_window_list_screen_containers (window);
+ for (c = containers; c != NULL; c = c->next)
+ {
+ TerminalScreenContainer *container = TERMINAL_SCREEN_CONTAINER (c->data);
+ TerminalScreen *screen;
+
+ screen = terminal_screen_container_get_screen (container);
+ screens = g_list_prepend (screens, screen);
+ }
+ }
+
+ casefolded_terms = normalize_casefold_and_unaccent_terms (terms);
+ results = g_ptr_array_new_with_free_func (g_free);
+
+ for (l = screens; l != NULL; l = l->next)
+ {
+ TerminalScreen *screen = TERMINAL_SCREEN (l->data);
+ gs_free char *cmdline = NULL, *process = NULL;
+ const char *cwd, *title;
+
+ cwd = vte_terminal_get_current_directory_uri (VTE_TERMINAL (screen));
+ title = terminal_screen_get_title (screen);
+ terminal_screen_has_foreground_process (screen, &process, &cmdline);
+ if (match_terms (cwd, (const char *const *) casefolded_terms) ||
+ match_terms (title, (const char *const *) casefolded_terms) ||
+ match_terms (process, (const char *const *) casefolded_terms) ||
+ match_terms (cmdline, (const char *const *) casefolded_terms))
+ {
+ const char *uuid;
+
+ uuid = terminal_screen_get_uuid (screen);
+ g_ptr_array_add (results, g_strdup (uuid));
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "Search hit: %s\n", uuid);
+ }
+ }
+
+ g_ptr_array_add (results, NULL);
+ terminal_search_provider2_complete_get_initial_result_set (skeleton,
+ invocation,
+ (const char *const *) results->pdata);
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "GetInitialResultSet completed\n");
+ return TRUE;
+}
+
+static gboolean
+handle_get_subsearch_result_set_cb (TerminalSearchProvider2 *skeleton,
+ GDBusMethodInvocation *invocation,
+ const char *const *previous_results,
+ const char *const *terms,
+ gpointer user_data)
+{
+ gs_unref_ptrarray GPtrArray *results;
+ TerminalApp *app;
+ gs_strfreev char **casefolded_terms = NULL;
+ guint i;
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "GetSubsearchResultSet started\n");
+
+ app = terminal_app_get ();
+ casefolded_terms = normalize_casefold_and_unaccent_terms (terms);
+ results = g_ptr_array_new_with_free_func (g_free);
+
+ for (i = 0; previous_results[i] != NULL; i++)
+ {
+ TerminalScreen *screen;
+ gs_free char *cmdline = NULL, *process = NULL;
+ const char *cwd, *title;
+
+ screen = terminal_app_get_screen_by_uuid (app, previous_results[i]);
+ if (screen == NULL)
+ {
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "Not a screen: %s\n", previous_results[i]);
+ continue;
+ }
+
+ cwd = vte_terminal_get_current_directory_uri (VTE_TERMINAL (screen));
+ title = terminal_screen_get_title (screen);
+ terminal_screen_has_foreground_process (screen, &process, &cmdline);
+ if (match_terms (cwd, (const char *const *) casefolded_terms) ||
+ match_terms (title, (const char *const *) casefolded_terms) ||
+ match_terms (process, (const char *const *) casefolded_terms) ||
+ match_terms (cmdline, (const char *const *) casefolded_terms))
+ {
+ g_ptr_array_add (results, g_strdup (previous_results[i]));
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "Search hit: %s\n", previous_results[i]);
+ }
+ }
+
+ g_ptr_array_add (results, NULL);
+ terminal_search_provider2_complete_get_subsearch_result_set (skeleton,
+ invocation,
+ (const char *const *) results->pdata);
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "GetSubsearchResultSet completed\n");
+ return TRUE;
+}
+
+static gboolean
+handle_get_result_metas_cb (TerminalSearchProvider2 *skeleton,
+ GDBusMethodInvocation *invocation,
+ const char *const *results,
+ gpointer user_data)
+{
+ GVariantBuilder builder;
+ TerminalApp *app;
+ guint i;
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "GetResultMetas started\n");
+
+ app = terminal_app_get ();
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ for (i = 0; results[i] != NULL; i++)
+ {
+ TerminalScreen *screen;
+ const char *title;
+ gs_free char *escaped_text = NULL;
+ gs_free char *text = NULL;
+
+ screen = terminal_app_get_screen_by_uuid (app, results[i]);
+ if (screen == NULL)
+ {
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "Not a screen: %s\n", results[i]);
+ continue;
+ }
+
+ title = terminal_screen_get_title (screen);
+ if (terminal_screen_has_foreground_process (screen, NULL, NULL)) {
+ VteTerminal *terminal = VTE_TERMINAL (screen);
+ long cursor_row;
+
+ vte_terminal_get_cursor_position (terminal, NULL, &cursor_row);
+ text = vte_terminal_get_text_range (terminal,
+ MAX(0, cursor_row - 1),
+ 0,
+ cursor_row + 1,
+ vte_terminal_get_column_count (terminal) - 1,
+ NULL, NULL, NULL);
+ }
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", "id", g_variant_new_string (results[i]));
+ g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string (title));
+ if (text != NULL)
+ {
+ escaped_text = g_markup_escape_text (text, -1);
+ g_variant_builder_add (&builder, "{sv}", "description", g_variant_new_string (escaped_text));
+ }
+ g_variant_builder_close (&builder);
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "Meta for %s: %s\n", results[i], title);
+ }
+
+ terminal_search_provider2_complete_get_result_metas (skeleton, invocation, g_variant_builder_end (&builder));
+
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "GetResultMetas completed\n");
+
+ return TRUE;
+}
+
+static gboolean
+handle_activate_result_cb (TerminalSearchProvider2 *skeleton,
+ GDBusMethodInvocation *invocation,
+ const char *identifier,
+ const char* const *terms,
+ guint timestamp,
+ gpointer user_data)
+{
+ GtkWidget *toplevel;
+ TerminalApp *app;
+ TerminalScreen *screen;
+
+ app = terminal_app_get ();
+ screen = terminal_app_get_screen_by_uuid (app, identifier);
+ if (screen == NULL)
+ goto out;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (screen));
+ if (!gtk_widget_is_toplevel (toplevel))
+ goto out;
+
+ terminal_window_switch_screen (TERMINAL_WINDOW (toplevel), screen);
+ gtk_window_present_with_time (GTK_WINDOW (toplevel), timestamp);
+ _terminal_debug_print (TERMINAL_DEBUG_SEARCH, "ActivateResult: %s\n", identifier);
+
+ out:
+ terminal_search_provider2_complete_activate_result (skeleton, invocation);
+ return TRUE;
+}
+
+static void
+terminal_search_provider_init (TerminalSearchProvider *provider)
+{
+ provider->skeleton = terminal_search_provider2_skeleton_new ();
+
+ g_signal_connect (provider->skeleton, "handle-get-initial-result-set",
+ G_CALLBACK (handle_get_initial_result_set_cb), provider);
+ g_signal_connect (provider->skeleton, "handle-get-subsearch-result-set",
+ G_CALLBACK (handle_get_subsearch_result_set_cb), provider);
+ g_signal_connect (provider->skeleton, "handle-get-result-metas",
+ G_CALLBACK (handle_get_result_metas_cb), provider);
+ g_signal_connect (provider->skeleton, "handle-activate-result",
+ G_CALLBACK (handle_activate_result_cb), provider);
+}
+
+static void
+terminal_search_provider_dispose (GObject *object)
+{
+ TerminalSearchProvider *provider = TERMINAL_SEARCH_PROVIDER (object);
+
+ g_clear_object (&provider->skeleton);
+
+ G_OBJECT_CLASS (terminal_search_provider_parent_class)->dispose (object);
+}
+
+static void
+terminal_search_provider_class_init (TerminalSearchProviderClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = terminal_search_provider_dispose;
+}
+
+TerminalSearchProvider *
+terminal_search_provider_new (void)
+{
+ return g_object_new (TERMINAL_TYPE_SEARCH_PROVIDER, NULL);
+}
+
+gboolean
+terminal_search_provider_dbus_register (TerminalSearchProvider *provider,
+ GDBusConnection *connection,
+ const char *object_path,
+ GError **error)
+{
+ return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (provider->skeleton),
+ connection,
+ object_path,
+ error);
+}
+
+void
+terminal_search_provider_dbus_unregister (TerminalSearchProvider *provider,
+ GDBusConnection *connection,
+ const char *object_path)
+{
+ if (g_dbus_interface_skeleton_has_connection (G_DBUS_INTERFACE_SKELETON (provider->skeleton), connection))
+ g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (provider->skeleton),
+ connection);
+}
diff --git a/src/terminal-search-provider.h b/src/terminal-search-provider.h
new file mode 100644
index 0000000..719bd3e
--- /dev/null
+++ b/src/terminal-search-provider.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2013 Red Hat, 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_SEARCH_PROVIDER_H
+#define TERMINAL_SEARCH_PROVIDER_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_SEARCH_PROVIDER (terminal_search_provider_get_type ())
+#define TERMINAL_SEARCH_PROVIDER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_SEARCH_PROVIDER, TerminalSearchProvider))
+#define TERMINAL_SEARCH_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_SEARCH_PROVIDER, TerminalSearchProviderClass))
+#define TERMINAL_IS_SEARCH_PROVIDER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_SEARCH_PROVIDER))
+#define TERMINAL_IS_SEARCH_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_SEARCH_PROVIDER))
+#define TERMINAL_SEARCH_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_SEARCH_PROVIDER, TerminalSearchProviderClass))
+
+typedef struct _TerminalSearchProvider TerminalSearchProvider;
+typedef struct _TerminalSearchProviderClass TerminalSearchProviderClass;
+
+GType terminal_search_provider_get_type (void);
+
+TerminalSearchProvider *terminal_search_provider_new (void);
+
+gboolean terminal_search_provider_dbus_register (TerminalSearchProvider *provider,
+ GDBusConnection *connection,
+ const char *object_path,
+ GError **error);
+
+void terminal_search_provider_dbus_unregister (TerminalSearchProvider *provider,
+ GDBusConnection *connection,
+ const char *object_path);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_SEARCH_PROVIDER_H */
diff --git a/src/terminal-settings-list.c b/src/terminal-settings-list.c
new file mode 100644
index 0000000..5e52ca1
--- /dev/null
+++ b/src/terminal-settings-list.c
@@ -0,0 +1,938 @@
+/*
+ * Copyright © 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-settings-list.h"
+
+#include <string.h>
+#include <uuid.h>
+#include <dconf.h>
+
+#define G_SETTINGS_ENABLE_BACKEND
+#include <gio/gsettingsbackend.h>
+
+#include "terminal-type-builtins.h"
+#include "terminal-schemas.h"
+#include "terminal-debug.h"
+#include "terminal-libgsystem.h"
+
+struct _TerminalSettingsList {
+ GSettings parent;
+
+ char *path;
+ char *child_schema_id;
+
+ char **uuids;
+ char *default_uuid;
+
+ GHashTable *children;
+
+ TerminalSettingsListFlags flags;
+};
+
+struct _TerminalSettingsListClass {
+ GSettingsClass parent;
+
+ void (* children_changed) (TerminalSettingsList *list);
+ void (* default_changed) (TerminalSettingsList *list);
+};
+
+enum {
+ PROP_CHILD_SCHEMA_ID = 1,
+ PROP_FLAGS
+};
+
+enum {
+ SIGNAL_CHILDREN_CHANGED,
+ SIGNAL_DEFAULT_CHANGED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
+static void
+strv_printerr (char **strv)
+{
+ char **p;
+
+ if (strv == NULL) {
+ g_printerr ("(null)");
+ return;
+ }
+
+ for (p = strv; *p; p++)
+ g_printerr ("%s'%s'", p != strv ? ", " : "", *p);
+}
+
+static char **
+strv_sort (char **strv)
+{
+ // FIXMEchpe
+ return strv;
+}
+
+static gboolean
+strv_equal (char **a,
+ char **b)
+{
+ char **e, **f;
+
+ if (a == NULL || b == NULL)
+ return a == b;
+
+ for (e = a, f = b; *e && *f; e++, f++) {
+ if (!g_str_equal (*e, *f))
+ return FALSE;
+ }
+
+ return *e == *f;
+}
+
+static int
+strv_find (char **strv,
+ const char *str)
+{
+ int i;
+
+ if (strv == NULL || str == NULL)
+ return -1;
+
+ for (i = 0; strv[i]; i++) {
+ if (!g_str_equal (strv[i], str))
+ continue;
+
+ return i;
+ }
+
+ return -1;
+}
+
+static char **
+strv_dupv_insert (char **strv,
+ const char *str)
+{
+ char **nstrv, **p, **q;
+
+ if (strv == NULL) {
+ char *s[2] = { (char *) str, NULL };
+ return g_strdupv (s);
+ }
+
+ /* Is it already in the list? */
+ for (p = strv; *p; p++)
+ if (g_str_equal (*p, str))
+ return g_strdupv (strv);
+
+ /* Not found; append */
+ nstrv = g_new (char *, (p - strv) + 2);
+ for (p = strv, q = nstrv; *p; p++, q++)
+ *q = g_strdup (*p);
+ *q++ = g_strdup (str);
+ *q = NULL;
+
+ return strv_sort (nstrv);
+}
+
+static char **
+strv_dupv_remove (char **strv,
+ const char *str)
+{
+ char **nstrv, **p, **q;
+
+ if (strv == NULL)
+ return NULL;
+
+ nstrv = g_strdupv (strv);
+ for (p = q = nstrv; *p; p++) {
+ if (!g_str_equal (*p, str))
+ *q++ = *p;
+ else
+ g_free (*p);
+ }
+ *q = NULL;
+
+ return nstrv;
+}
+
+gboolean
+terminal_settings_list_valid_uuid (const char *str)
+{
+ uuid_t u;
+
+ if (str == NULL)
+ return FALSE;
+
+ return uuid_parse ((char *) str, u) == 0;
+}
+
+static gboolean
+settings_backend_is_dconf (void)
+{
+ gs_unref_object GSettingsBackend *backend;
+
+ backend = g_settings_backend_get_default ();
+
+ return g_str_equal (G_OBJECT_TYPE_NAME (backend), "DConfSettingsBackend");
+}
+
+static char *
+new_list_entry (void)
+{
+ uuid_t u;
+ char name[37];
+
+ uuid_generate (u);
+ uuid_unparse (u, name);
+
+ return g_strdup (name);
+}
+
+static gboolean
+validate_list (TerminalSettingsList *list,
+ char **entries)
+{
+ gboolean allow_empty = (list->flags & TERMINAL_SETTINGS_LIST_FLAG_ALLOW_EMPTY) != 0;
+ guint i;
+
+ if (entries == NULL)
+ return allow_empty;
+
+ for (i = 0; entries[i]; i++) {
+ if (!terminal_settings_list_valid_uuid (entries[i]))
+ return FALSE;
+ }
+
+ return (i > 0) || allow_empty;
+}
+
+static gboolean
+list_map_func (GVariant *value,
+ gpointer *result,
+ gpointer user_data)
+{
+ TerminalSettingsList *list = user_data;
+ gs_strfreev char **entries;
+
+ entries = strv_sort (g_variant_dup_strv (value, NULL));
+
+ if (validate_list (list, entries)) {
+ gs_transfer_out_value(result, &entries);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static char *
+path_new (TerminalSettingsList *list,
+ const char *uuid)
+{
+ return g_strdup_printf ("%s:%s/", list->path, uuid);
+}
+
+static GSettings *
+terminal_settings_list_ref_child_internal (TerminalSettingsList *list,
+ const char *uuid)
+{
+ GSettings *child;
+ gs_free char *path = NULL;
+
+ if (strv_find (list->uuids, uuid) == -1)
+ return NULL;
+
+ _terminal_debug_print (TERMINAL_DEBUG_SETTINGS_LIST,
+ "%s UUID %s\n", G_STRFUNC, uuid);
+
+ child = g_hash_table_lookup (list->children, uuid);
+ if (child)
+ goto done;
+
+ path = path_new (list, uuid);
+ child = g_settings_new_with_path (list->child_schema_id, path);
+ g_hash_table_insert (list->children, g_strdup (uuid), child /* adopted */);
+
+ done:
+ return g_object_ref (child);
+}
+
+static char *
+new_child (TerminalSettingsList *list,
+ const char *name)
+{
+ char *new_uuid = new_list_entry ();
+
+ if (name != NULL) {
+ gs_free char *new_path = path_new (list, new_uuid);
+ gs_unref_object GSettings *child = g_settings_new_with_path (list->child_schema_id, new_path);
+ g_settings_set_string (child, TERMINAL_PROFILE_VISIBLE_NAME_KEY, name);
+ }
+
+ return new_uuid;
+}
+
+static char *
+clone_child (TerminalSettingsList *list,
+ const char *uuid,
+ const char *name)
+{
+ char *new_uuid;
+ gs_free char *path;
+ gs_free char *new_path;
+ guint i;
+ gs_unref_object DConfClient *client;
+ DConfChangeset *changeset;
+
+ new_uuid = new_list_entry ();
+
+ _terminal_debug_print (TERMINAL_DEBUG_SETTINGS_LIST,
+ "%s UUID %s NEW UUID %s \n", G_STRFUNC, uuid ? uuid : "(null)", new_uuid);
+
+ path = path_new (list, uuid);
+ new_path = path_new (list, new_uuid);
+
+ client = dconf_client_new ();
+ changeset = dconf_changeset_new ();
+
+ GSettingsSchemaSource *source = g_settings_schema_source_get_default (); /* unowned */
+ gs_unref_settings_schema GSettingsSchema* schema = g_settings_schema_source_lookup (source,
+ list->child_schema_id,
+ TRUE);
+ /* shouldn't really happen ever */
+ if (schema == NULL)
+ return new_uuid;
+
+ gs_strfreev char **keys = g_settings_schema_list_keys (schema);
+
+ for (i = 0; keys[i]; i++) {
+ gs_free char *rkey;
+ gs_unref_variant GVariant *value;
+
+ rkey = g_strconcat (path, keys[i], NULL);
+ value = dconf_client_read (client, rkey);
+ if (value) {
+ gs_free char *wkey;
+ wkey = g_strconcat (new_path, keys[i], NULL);
+ dconf_changeset_set (changeset, wkey, value);
+ }
+ }
+
+ if (name != NULL) {
+ GVariant *value;
+ value = g_variant_new_string (name);
+ if (value) {
+ gs_free char *wkey;
+ wkey = g_strconcat (new_path, TERMINAL_PROFILE_VISIBLE_NAME_KEY, NULL);
+ dconf_changeset_set (changeset, wkey, value);
+ }
+ }
+
+ dconf_client_change_sync (client, changeset, NULL, NULL, NULL);
+ dconf_changeset_unref (changeset);
+
+ return new_uuid;
+}
+
+static char *
+terminal_settings_list_add_child_internal (TerminalSettingsList *list,
+ const char *uuid,
+ const char *name)
+{
+ char *new_uuid;
+ gs_strfreev char **new_uuids;
+
+ if (uuid && settings_backend_is_dconf ())
+ new_uuid = clone_child (list, uuid, name);
+ else
+ new_uuid = new_child (list, name);
+
+ _terminal_debug_print (TERMINAL_DEBUG_SETTINGS_LIST,
+ "%s NEW UUID %s\n", G_STRFUNC, new_uuid);
+
+ new_uuids = strv_dupv_insert (list->uuids, new_uuid);
+ g_settings_set_strv (&list->parent, TERMINAL_SETTINGS_LIST_LIST_KEY,
+ (const char * const *) new_uuids);
+
+ return new_uuid;
+}
+
+static void
+terminal_settings_list_remove_child_internal (TerminalSettingsList *list,
+ const char *uuid)
+{
+ gs_strfreev char **new_uuids;
+
+ _terminal_debug_print (TERMINAL_DEBUG_SETTINGS_LIST,
+ "%s UUID %s\n", G_STRFUNC, uuid);
+
+ new_uuids = strv_dupv_remove (list->uuids, uuid);
+
+ if ((new_uuids == NULL || new_uuids[0] == NULL) &&
+ (list->flags & TERMINAL_SETTINGS_LIST_FLAG_ALLOW_EMPTY) == 0)
+ return;
+
+ g_settings_set_strv (&list->parent, TERMINAL_SETTINGS_LIST_LIST_KEY, (const char * const *) new_uuids);
+
+ if (list->default_uuid != NULL &&
+ g_str_equal (list->default_uuid, uuid))
+ g_settings_set_string (&list->parent, TERMINAL_SETTINGS_LIST_DEFAULT_KEY, "");
+
+ /* Now we unset all keys under the child */
+ if (settings_backend_is_dconf ()) {
+ gs_free char *path;
+ gs_unref_object DConfClient *client;
+
+ path = path_new (list, uuid);
+ client = dconf_client_new ();
+ dconf_client_write_sync (client, path, NULL, NULL, NULL, NULL);
+ }
+}
+
+static void
+terminal_settings_list_update_list (TerminalSettingsList *list)
+{
+ char **uuids, *uuid;
+ GSettings *child;
+ GHashTable *new_children;
+ guint i;
+ gboolean changed;
+
+ uuids = g_settings_get_mapped (&list->parent,
+ TERMINAL_SETTINGS_LIST_LIST_KEY,
+ list_map_func, list);
+
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_SETTINGS_LIST) {
+ g_printerr ("%s: current UUIDs [", G_STRFUNC);
+ strv_printerr (list->uuids);
+ g_printerr ("]\n new UUIDs [");
+ strv_printerr (uuids);
+ g_printerr ("]\n");
+ }
+
+ if (strv_equal (uuids, list->uuids) &&
+ ((list->flags & TERMINAL_SETTINGS_LIST_FLAG_HAS_DEFAULT) == 0 ||
+ strv_find (list->uuids, list->default_uuid) != -1)) {
+ g_strfreev (uuids);
+ return;
+ }
+
+ new_children = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+
+ if (uuids) {
+ for (i = 0; uuids[i] != NULL; i++) {
+ uuid = uuids[i];
+
+ child = g_hash_table_lookup (list->children, uuid);
+
+ if (child) {
+ g_object_ref (child);
+ g_hash_table_remove (list->children, uuid);
+ g_hash_table_insert (new_children, g_strdup (uuid), child /* adopted */);
+ }
+ }
+
+ changed = !strv_equal (uuids, list->uuids);
+ } else {
+ changed = g_strv_length (list->uuids) != 0;
+ }
+
+ g_hash_table_unref (list->children);
+ list->children = new_children;
+
+ g_strfreev (list->uuids);
+ list->uuids = uuids; /* adopts */
+
+ if (changed)
+ g_signal_emit (list, signals[SIGNAL_CHILDREN_CHANGED], 0);
+}
+
+static void
+terminal_settings_list_update_default (TerminalSettingsList *list)
+{
+ if ((list->flags & TERMINAL_SETTINGS_LIST_FLAG_HAS_DEFAULT) == 0)
+ return;
+
+ g_free (list->default_uuid);
+ list->default_uuid = g_settings_get_string (&list->parent,
+ TERMINAL_SETTINGS_LIST_DEFAULT_KEY);
+
+ _terminal_debug_print (TERMINAL_DEBUG_SETTINGS_LIST,
+ "%s new default UUID %s\n", G_STRFUNC, list->default_uuid);
+
+ g_signal_emit (list, signals[SIGNAL_DEFAULT_CHANGED], 0);
+}
+
+G_DEFINE_TYPE (TerminalSettingsList, terminal_settings_list, G_TYPE_SETTINGS);
+
+static void
+terminal_settings_list_changed (GSettings *list_settings,
+ const char *key)
+{
+ TerminalSettingsList *list = TERMINAL_SETTINGS_LIST (list_settings);
+
+ _terminal_debug_print (TERMINAL_DEBUG_SETTINGS_LIST,
+ "%s key %s", G_STRFUNC, key ? key : "(null)");
+
+ if (key == NULL ||
+ g_str_equal (key, TERMINAL_SETTINGS_LIST_LIST_KEY)) {
+ terminal_settings_list_update_list (list);
+ terminal_settings_list_update_default (list);
+ }
+
+ if (key == NULL)
+ return;
+
+ if (g_str_equal (key, TERMINAL_SETTINGS_LIST_DEFAULT_KEY)) {
+ terminal_settings_list_update_default (list);
+ }
+}
+
+static void
+terminal_settings_list_init (TerminalSettingsList *list)
+{
+ list->flags = TERMINAL_SETTINGS_LIST_FLAG_NONE;
+}
+
+static void
+terminal_settings_list_constructed (GObject *object)
+{
+ TerminalSettingsList *list = TERMINAL_SETTINGS_LIST (object);
+
+ G_OBJECT_CLASS (terminal_settings_list_parent_class)->constructed (object);
+
+ g_assert (list->child_schema_id != NULL);
+
+ g_object_get (object, "path", &list->path, NULL);
+
+ list->children = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+
+ terminal_settings_list_changed (&list->parent, NULL);
+}
+
+static void
+terminal_settings_list_finalize (GObject *object)
+{
+ TerminalSettingsList *list = TERMINAL_SETTINGS_LIST (object);
+
+ g_free (list->path);
+ g_free (list->child_schema_id);
+ g_strfreev (list->uuids);
+ g_free (list->default_uuid);
+ g_hash_table_unref (list->children);
+
+ G_OBJECT_CLASS (terminal_settings_list_parent_class)->finalize (object);
+}
+
+static void
+terminal_settings_list_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalSettingsList *list = TERMINAL_SETTINGS_LIST (object);
+
+ switch (prop_id) {
+ case PROP_CHILD_SCHEMA_ID:
+ list->child_schema_id = g_value_dup_string (value);
+ break;
+ case PROP_FLAGS:
+ list->flags = g_value_get_flags (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_settings_list_class_init (TerminalSettingsListClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GSettingsClass *settings_class = G_SETTINGS_CLASS (klass);
+
+ object_class->set_property = terminal_settings_list_set_property;
+ object_class->constructed = terminal_settings_list_constructed;
+ object_class->finalize = terminal_settings_list_finalize;
+
+ /**
+ * TerminalSettingsList:child-schema-id:
+ *
+ * The name of the schema of the children of this list.
+ */
+ g_object_class_install_property (object_class, PROP_CHILD_SCHEMA_ID,
+ g_param_spec_string ("child-schema-id", NULL,NULL,
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * TerminalSettingsList:flags:
+ *
+ * Flags from #TerminalSettingsListFlags.
+ */
+ g_object_class_install_property (object_class, PROP_FLAGS,
+ g_param_spec_flags ("flags", NULL,NULL,
+ TERMINAL_TYPE_SETTINGS_LIST_FLAGS,
+ TERMINAL_SETTINGS_LIST_FLAG_NONE,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * TerminalSettingsList::children-changed:
+ * @list: the object on which the signal was emitted
+ *
+ * The "children-changed" signal is emitted when the list of children
+ * has potentially changed.
+ */
+ signals[SIGNAL_CHILDREN_CHANGED] =
+ g_signal_new ("children-changed", TERMINAL_TYPE_SETTINGS_LIST,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalSettingsListClass, children_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * TerminalSettingsList::default-changed:
+ * @list: the object on which the signal was emitted
+ *
+ * The "default-changed" signal is emitted when the default child
+ * has potentially changed.
+ */
+ signals[SIGNAL_DEFAULT_CHANGED] =
+ g_signal_new ("default-changed", TERMINAL_TYPE_SETTINGS_LIST,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalSettingsListClass, default_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ settings_class->changed = terminal_settings_list_changed;
+}
+
+
+/**
+ * terminal_settings_list_new:
+ * @path: the settings path for the list
+ * @schema_id: the schema of the list, equal to or derived from "org.gnome.Terminal.SettingsList"
+ * @child_schema_id: the schema of the list children
+ * @flags: list flags
+ *
+ * Returns: (transfer full): the newly created #TerminalSettingsList
+ */
+TerminalSettingsList *
+terminal_settings_list_new (const char *path,
+ const char *schema_id,
+ const char *child_schema_id,
+ TerminalSettingsListFlags flags)
+{
+ g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (schema_id != NULL, NULL);
+ g_return_val_if_fail (child_schema_id != NULL, NULL);
+ g_return_val_if_fail (g_str_has_suffix (path, ":/"), NULL);
+
+ return g_object_new (TERMINAL_TYPE_SETTINGS_LIST,
+ "schema-id", schema_id,
+ "child-schema-id", child_schema_id,
+ "path", path,
+ "flags", flags,
+ NULL);
+}
+
+/**
+ * terminal_settings_list_dupv_children:
+ * @list: a #TerminalSettingsList
+ *
+ * Returns: (transfer full): the UUIDs of the children in the settings list, or %NULL
+ * if the list is empty
+ */
+char **
+terminal_settings_list_dupv_children (TerminalSettingsList *list)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+
+ return g_strdupv (list->uuids);
+}
+
+/**
+ * terminal_settings_list_dup_default_child:
+ * @list: a #TerminalSettingsList
+ *
+ * Returns: (transfer full): the UUID of the default child in the settings list
+ */
+char *
+terminal_settings_list_dup_default_child (TerminalSettingsList *list)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+
+ if ((list->flags & TERMINAL_SETTINGS_LIST_FLAG_HAS_DEFAULT) == 0)
+ return NULL;
+
+ if ((strv_find (list->uuids, list->default_uuid)) != -1)
+ return g_strdup (list->default_uuid);
+
+ /* Just randomly designate the first child as default, but don't write that
+ * to dconf.
+ */
+ if (list->uuids == NULL || list->uuids[0] == NULL) {
+ g_warn_if_fail ((list->flags & TERMINAL_SETTINGS_LIST_FLAG_ALLOW_EMPTY));
+ return NULL;
+ }
+
+ return g_strdup (list->uuids[0]);
+}
+
+/**
+ * terminal_settings_list_has_child:
+ * @list: a #TerminalSettingsList
+ * @uuid: the UUID of a list child
+ *
+ * Returns: %TRUE iff the child with @uuid exists
+ */
+gboolean
+terminal_settings_list_has_child (TerminalSettingsList *list,
+ const char *uuid)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), FALSE);
+ g_return_val_if_fail (terminal_settings_list_valid_uuid (uuid), FALSE);
+
+ return strv_find (list->uuids, uuid) != -1;
+}
+
+/**
+ * terminal_settings_list_ref_child:
+ * @list: a #TerminalSettingsList
+ * @uuid: the UUID of a list child
+ *
+ * Returns the child #GSettings for the list child with UUID @uuid, or %NULL
+ * if @list has no such child.
+ *
+ * Returns: (transfer full): a reference to the #GSettings for the child, or %NULL
+ */
+GSettings *
+terminal_settings_list_ref_child (TerminalSettingsList *list,
+ const char *uuid)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+ g_return_val_if_fail (terminal_settings_list_valid_uuid (uuid), NULL);
+
+ return terminal_settings_list_ref_child_internal (list, uuid);
+}
+
+/**
+ * terminal_settings_list_ref_children:
+ * @list: a #TerminalSettingsList
+ *
+ * Returns the list of children #GSettings or @list.
+ *
+ * Returns: (transfer full): a list of child #GSettings of @list
+ */
+GList *
+terminal_settings_list_ref_children (TerminalSettingsList *list)
+{
+ GList *l;
+ guint i;
+
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+
+ if (list->uuids == NULL)
+ return NULL;
+
+ l = NULL;
+ for (i = 0; list->uuids[i]; i++)
+ l = g_list_prepend (l, terminal_settings_list_ref_child (list, list->uuids[i]));
+
+ return g_list_reverse (l);
+}
+
+/**
+ * terminal_settings_list_ref_default_child:
+ * @list: a #TerminalSettingsList
+ *
+ * Returns the default child #GSettings for the list, or %NULL if @list has no
+ * children.
+ *
+ * Returns: (transfer full): a reference to the #GSettings for the default child, or %NULL
+ */
+GSettings *
+terminal_settings_list_ref_default_child (TerminalSettingsList *list)
+{
+ gs_free char *uuid = NULL;
+
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+
+ uuid = terminal_settings_list_dup_default_child (list);
+ if (uuid == NULL)
+ return NULL;
+
+ return terminal_settings_list_ref_child_internal (list, uuid);
+}
+
+/**
+ * terminal_settings_list_add_child:
+ * @list: a #TerminalSettingsList
+ * @name: the name of the new profile
+ *
+ * Adds a new child to the list, and returns a reference to its #GSettings.
+ *
+ * Returns: (transfer full): the UUID of new child
+ */
+char *
+terminal_settings_list_add_child (TerminalSettingsList *list,
+ const char *name)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+
+ return terminal_settings_list_add_child_internal (list, NULL, name);
+}
+
+/**
+ * terminal_settings_list_clone_child:
+ * @list: a #TerminalSettingsList
+ * @uuid: the UUID of the child to clone
+ * @name: the name of the new child
+ *
+ * Adds a new child to the list, and returns a reference to its #GSettings.
+ * All keys of the new child will have the same value as @uuid's.
+ *
+ * Returns: (transfer full): the UUID of new child
+ */
+char *
+terminal_settings_list_clone_child (TerminalSettingsList *list,
+ const char *uuid,
+ const char *name)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+ g_return_val_if_fail (terminal_settings_list_valid_uuid (uuid), NULL);
+
+ return terminal_settings_list_add_child_internal (list, uuid, name);
+}
+
+/**
+ * terminal_settings_list_remove_child:
+ * @list: a #TerminalSettingsList
+ * @uuid: the UUID of a list child
+ *
+ * Removes the child with UUID @uuid from the list.
+ */
+void
+terminal_settings_list_remove_child (TerminalSettingsList *list,
+ const char *uuid)
+{
+ g_return_if_fail (TERMINAL_IS_SETTINGS_LIST (list));
+ g_return_if_fail (terminal_settings_list_valid_uuid (uuid));
+
+ terminal_settings_list_remove_child_internal (list, uuid);
+}
+
+/**
+ * terminal_settings_list_dup_uuid_from_child:
+ * @list: a #TerminalSettingsList
+ * @child: a #GSettings of a child in the list
+ *
+ * Returns the UUID of @child in the list, or %NULL if @child is not in the list.
+ *
+ * Returns: (transfer full): the UUID of the child in the settings list, or %NULL
+ */
+char *
+terminal_settings_list_dup_uuid_from_child (TerminalSettingsList *list,
+ GSettings *child)
+{
+ gs_free char *path;
+ char *p;
+
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), NULL);
+
+ g_object_get (child, "path", &path, NULL);
+ g_return_val_if_fail (g_str_has_prefix (path, list->path), NULL);
+
+ p = path + strlen (list->path);
+ g_return_val_if_fail (p[0] == ':', NULL);
+ p++;
+ g_return_val_if_fail (strlen (p) == 37, NULL);
+ g_return_val_if_fail (p[36] == '/', NULL);
+ p[36] = '\0';
+ g_assert (terminal_settings_list_valid_uuid (p));
+
+ return g_strdup (p);
+}
+
+/**
+ * terminal_settings_list_get_set_default_child:
+ * @list: a #TerminalSettingsList
+ * @uuid: the UUID of a child in the list
+ *
+ * Sets @uuid as the default child.
+ */
+void
+terminal_settings_list_set_default_child (TerminalSettingsList *list,
+ const char *uuid)
+{
+ g_return_if_fail (TERMINAL_IS_SETTINGS_LIST (list));
+ g_return_if_fail (terminal_settings_list_valid_uuid (uuid));
+
+ if (!terminal_settings_list_has_child (list, uuid))
+ return;
+
+ g_settings_set_string (&list->parent, TERMINAL_SETTINGS_LIST_DEFAULT_KEY, uuid);
+}
+
+/**
+ * terminal_settings_list_foreach_child:
+ * @list: a #TerminalSettingsList
+ * @callback: a #TerminalSettingsListForeachFunc
+ * @user_data: user data for @callback
+ *
+ * Calls @callback for each child of @list.
+ *
+ * NOTE: No changes to @list must be made from @callback.
+ */
+void
+terminal_settings_list_foreach_child (TerminalSettingsList *list,
+ TerminalSettingsListForeachFunc callback,
+ gpointer user_data)
+{
+ g_return_if_fail (TERMINAL_IS_SETTINGS_LIST (list));
+ g_return_if_fail (callback);
+
+ for (char **p = list->uuids; *p; p++) {
+ const char *uuid = *p;
+ gs_unref_object GSettings *child = terminal_settings_list_ref_child_internal (list, uuid);
+ if (child != NULL)
+ callback (list, uuid, child, user_data);
+ }
+}
+
+/**
+ * terminal_settings_list_foreach_child:
+ * @list: a #TerminalSettingsList
+ *
+ * Returns: the number of children of @list.
+ */
+guint
+terminal_settings_list_get_n_children (TerminalSettingsList *list)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), 0);
+
+ return g_hash_table_size (list->children);
+}
diff --git a/src/terminal-settings-list.h b/src/terminal-settings-list.h
new file mode 100644
index 0000000..ecf8950
--- /dev/null
+++ b/src/terminal-settings-list.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2013 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_SETTINGS_LIST_H
+#define TERMINAL_SETTINGS_LIST_H
+
+#include <gio/gio.h>
+
+#include "terminal-enums.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_SETTINGS_LIST (terminal_settings_list_get_type ())
+#define TERMINAL_SETTINGS_LIST(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_SETTINGS_LIST, TerminalSettingsList))
+#define TERMINAL_SETTINGS_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_SETTINGS_LIST, TerminalSettingsListClass))
+#define TERMINAL_IS_SETTINGS_LIST(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_SETTINGS_LIST))
+#define TERMINAL_IS_SETTINGS_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_SETTINGS_LIST))
+#define TERMINAL_SETTINGS_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_SETTINGS_LIST, TerminalSettingsListClass))
+
+typedef struct _TerminalSettingsList TerminalSettingsList;
+typedef struct _TerminalSettingsListClass TerminalSettingsListClass;
+
+GType terminal_settings_list_get_type (void);
+
+TerminalSettingsList *terminal_settings_list_new (const char *path,
+ const char *schema_id,
+ const char *child_schema_id,
+ TerminalSettingsListFlags flags);
+
+char **terminal_settings_list_dupv_children (TerminalSettingsList *list);
+
+GList *terminal_settings_list_ref_children (TerminalSettingsList *list);
+
+gboolean terminal_settings_list_has_child (TerminalSettingsList *list,
+ const char *uuid);
+
+GSettings *terminal_settings_list_ref_child (TerminalSettingsList *list,
+ const char *uuid);
+
+char *terminal_settings_list_add_child (TerminalSettingsList *list,
+ const char *name);
+
+char *terminal_settings_list_clone_child (TerminalSettingsList *list,
+ const char *uuid,
+ const char *name);
+
+void terminal_settings_list_remove_child (TerminalSettingsList *list,
+ const char *uuid);
+
+char *terminal_settings_list_dup_uuid_from_child (TerminalSettingsList *list,
+ GSettings *child);
+
+GSettings *terminal_settings_list_ref_default_child (TerminalSettingsList *list);
+
+char *terminal_settings_list_dup_default_child (TerminalSettingsList *list);
+
+void terminal_settings_list_set_default_child (TerminalSettingsList *list,
+ const char *uuid);
+
+typedef void (* TerminalSettingsListForeachFunc) (TerminalSettingsList *list,
+ const char *uuid,
+ GSettings *child,
+ gpointer user_data);
+
+void terminal_settings_list_foreach_child (TerminalSettingsList *list,
+ TerminalSettingsListForeachFunc callback,
+ gpointer user_data);
+
+guint terminal_settings_list_get_n_children (TerminalSettingsList *list);
+
+gboolean terminal_settings_list_valid_uuid (const char *str);
+
+G_END_DECLS
+
+#endif /* TERMINAL_SETTINGS_LIST_H */
diff --git a/src/terminal-tab-label.c b/src/terminal-tab-label.c
new file mode 100644
index 0000000..7b4b084
--- /dev/null
+++ b/src/terminal-tab-label.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2007, 2008 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "terminal-intl.h"
+#include "terminal-tab-label.h"
+#include "terminal-icon-button.h"
+#include "terminal-window.h"
+
+#define TERMINAL_TAB_LABEL_GET_PRIVATE(tab_label)(G_TYPE_INSTANCE_GET_PRIVATE ((tab_label), TERMINAL_TYPE_TAB_LABEL, TerminalTabLabelPrivate))
+
+#define SPACING (4)
+
+struct _TerminalTabLabelPrivate
+{
+ TerminalScreen *screen;
+ GtkWidget *label;
+ GtkWidget *close_button;
+ gboolean bold;
+ GtkPositionType tab_pos;
+};
+
+enum
+{
+ PROP_0,
+ PROP_SCREEN
+};
+
+enum
+{
+ CLOSE_BUTTON_CLICKED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (TerminalTabLabel, terminal_tab_label, GTK_TYPE_BOX);
+
+/* helper functions */
+
+static void
+close_button_clicked_cb (GtkWidget *widget,
+ TerminalTabLabel *tab_label)
+{
+ g_signal_emit (tab_label, signals[CLOSE_BUTTON_CLICKED], 0);
+}
+
+static void
+sync_tab_label (TerminalScreen *screen,
+ GParamSpec *pspec,
+ GtkWidget *label)
+{
+ GtkWidget *hbox;
+ const char *title;
+ TerminalWindow *window;
+
+ title = terminal_screen_get_title (screen);
+ hbox = gtk_widget_get_parent (label);
+
+ gtk_label_set_text (GTK_LABEL (label),
+ title && title[0] ? title : _("Terminal"));
+
+ gtk_widget_set_tooltip_text (hbox, title);
+
+ /* This call updates the window size: bug 732588.
+ * FIXMEchpe: This is probably a GTK+ bug, should get them fix it.
+ */
+ window = TERMINAL_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (label),
+ TERMINAL_TYPE_WINDOW));
+ if (window != NULL)
+ terminal_window_update_size (window);
+}
+
+static void
+notify_tab_pos_cb (GtkNotebook *notebook,
+ GParamSpec *pspec G_GNUC_UNUSED,
+ TerminalTabLabel *label)
+{
+ TerminalTabLabelPrivate *priv = label->priv;
+ GtkPositionType pos;
+
+ pos = gtk_notebook_get_tab_pos (notebook);
+ if (pos == priv->tab_pos)
+ return;
+
+ priv->tab_pos = pos;
+
+ switch (pos) {
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ gtk_widget_hide (priv->close_button);
+ break;
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ gtk_widget_show (priv->close_button);
+ break;
+ }
+}
+
+/* public functions */
+
+/* Class implementation */
+
+static void
+terminal_tab_label_parent_set (GtkWidget *widget,
+ GtkWidget *old_parent)
+{
+ GtkWidget *parent;
+ void (* parent_set) (GtkWidget *, GtkWidget *) = GTK_WIDGET_CLASS (terminal_tab_label_parent_class)->parent_set;
+
+ if (GTK_IS_NOTEBOOK (old_parent)) {
+ g_signal_handlers_disconnect_by_func (old_parent,
+ G_CALLBACK (notify_tab_pos_cb),
+ widget);
+ }
+
+ if (parent_set)
+ parent_set (widget, old_parent);
+
+ parent = gtk_widget_get_parent (widget);
+ if (GTK_IS_NOTEBOOK (parent)) {
+ notify_tab_pos_cb (GTK_NOTEBOOK (parent), NULL, TERMINAL_TAB_LABEL (widget));
+ g_signal_connect (parent, "notify::tab-pos",
+ G_CALLBACK (notify_tab_pos_cb), widget);
+ }
+}
+
+static void
+terminal_tab_label_get_preferred_width (GtkWidget *widget,
+ int *minimum_width,
+ int *natural_width)
+{
+ TerminalTabLabel *tab_label = TERMINAL_TAB_LABEL (widget);
+ TerminalTabLabelPrivate *priv = tab_label->priv;
+
+ if (priv->tab_pos == GTK_POS_LEFT ||
+ priv->tab_pos == GTK_POS_RIGHT) {
+ if (natural_width)
+ *natural_width = 160;
+ if (minimum_width)
+ *minimum_width = 160;
+ }
+ else
+ GTK_WIDGET_CLASS (terminal_tab_label_parent_class)->get_preferred_width (widget, minimum_width, natural_width);
+}
+
+static void
+terminal_tab_label_init (TerminalTabLabel *tab_label)
+{
+ TerminalTabLabelPrivate *priv;
+
+ priv = tab_label->priv = TERMINAL_TAB_LABEL_GET_PRIVATE (tab_label);
+
+ priv->tab_pos = (GtkPositionType) -1; /* invalid */
+}
+
+static void
+terminal_tab_label_constructed (GObject *object)
+{
+ TerminalTabLabel *tab_label = TERMINAL_TAB_LABEL (object);
+ TerminalTabLabelPrivate *priv = tab_label->priv;
+ GtkWidget *hbox, *label, *close_button;
+
+ G_OBJECT_CLASS (terminal_tab_label_parent_class)->constructed (object);
+
+ hbox = GTK_WIDGET (tab_label);
+
+ g_assert (priv->screen != NULL);
+
+ gtk_box_set_spacing (GTK_BOX (hbox), SPACING);
+
+ priv->label = label = gtk_label_new (NULL);
+ gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
+ gtk_widget_set_margin_start (label, 0);
+ gtk_widget_set_margin_end (label, 0);
+ gtk_widget_set_margin_top (label, 0);
+ gtk_widget_set_margin_bottom (label, 0);
+
+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+ gtk_label_set_single_line_mode (GTK_LABEL (label), TRUE);
+
+ gtk_box_set_center_widget (GTK_BOX (hbox), label);
+
+ priv->close_button = close_button = terminal_close_button_new ();
+ gtk_widget_set_tooltip_text (close_button, _("Close tab"));
+ gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0);
+
+ sync_tab_label (priv->screen, NULL, label);
+ g_signal_connect (priv->screen, "notify::title",
+ G_CALLBACK (sync_tab_label), label);
+
+ g_signal_connect (close_button, "clicked",
+ G_CALLBACK (close_button_clicked_cb), tab_label);
+
+ gtk_widget_show_all (hbox);
+}
+
+static void
+terminal_tab_label_dispose (GObject *object)
+{
+ TerminalTabLabel *tab_label = TERMINAL_TAB_LABEL (object);
+ TerminalTabLabelPrivate *priv = tab_label->priv;
+
+ if (priv->screen != NULL) {
+ g_signal_handlers_disconnect_by_func (priv->screen,
+ G_CALLBACK (sync_tab_label),
+ priv->label);
+ g_object_unref (priv->screen);
+ priv->screen = NULL;
+ }
+
+ G_OBJECT_CLASS (terminal_tab_label_parent_class)->dispose (object);
+}
+
+static void
+terminal_tab_label_finalize (GObject *object)
+{
+// TerminalTabLabel *tab_label = TERMINAL_TAB_LABEL (object);
+
+ G_OBJECT_CLASS (terminal_tab_label_parent_class)->finalize (object);
+}
+
+static void
+terminal_tab_label_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalTabLabel *tab_label = TERMINAL_TAB_LABEL (object);
+
+ switch (prop_id) {
+ case PROP_SCREEN:
+ g_value_set_object (value, terminal_tab_label_get_screen (tab_label));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_tab_label_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TerminalTabLabel *tab_label = TERMINAL_TAB_LABEL (object);
+ TerminalTabLabelPrivate *priv = tab_label->priv;
+
+ switch (prop_id) {
+ case PROP_SCREEN:
+ priv->screen = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+terminal_tab_label_class_init (TerminalTabLabelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->constructed = terminal_tab_label_constructed;
+ gobject_class->dispose = terminal_tab_label_dispose;
+ gobject_class->finalize = terminal_tab_label_finalize;
+ gobject_class->get_property = terminal_tab_label_get_property;
+ gobject_class->set_property = terminal_tab_label_set_property;
+
+ widget_class->parent_set = terminal_tab_label_parent_set;
+ widget_class->get_preferred_width = terminal_tab_label_get_preferred_width;
+
+ signals[CLOSE_BUTTON_CLICKED] =
+ g_signal_new (I_("close-button-clicked"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalTabLabelClass, close_button_clicked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_SCREEN,
+ g_param_spec_object ("screen", NULL, NULL,
+ TERMINAL_TYPE_SCREEN,
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (gobject_class, sizeof (TerminalTabLabelPrivate));
+}
+
+/* public API */
+
+/**
+ * terminal_tab_label_new:
+ * @screen: a #TerminalScreen
+ *
+ * Returns: a new #TerminalTabLabel for @screen
+ */
+GtkWidget *
+terminal_tab_label_new (TerminalScreen *screen)
+{
+ return g_object_new (TERMINAL_TYPE_TAB_LABEL,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "screen", screen,
+ NULL);
+}
+
+/**
+ * terminal_tab_label_set_bold:
+ * @tab_label: a #TerminalTabLabel
+ * @bold: whether to enable label bolding
+ *
+ * Sets the tab label text bold, or unbolds it.
+ */
+void
+terminal_tab_label_set_bold (TerminalTabLabel *tab_label,
+ gboolean bold)
+{
+ TerminalTabLabelPrivate *priv = tab_label->priv;
+ PangoAttrList *attr_list;
+ PangoAttribute *weight_attr;
+ gboolean free_list = FALSE;
+
+ bold = bold != FALSE;
+ if (priv->bold == bold)
+ return;
+
+ priv->bold = bold;
+
+ attr_list = gtk_label_get_attributes (GTK_LABEL (priv->label));
+ if (!attr_list) {
+ attr_list = pango_attr_list_new ();
+ free_list = TRUE;
+ }
+
+ if (bold)
+ weight_attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+ else
+ weight_attr = pango_attr_weight_new (PANGO_WEIGHT_NORMAL);
+
+ /* gtk_label_get_attributes() returns the label's internal list,
+ * which we're probably not supposed to modify directly.
+ * It seems to work ok however.
+ */
+ pango_attr_list_change (attr_list, weight_attr);
+
+ gtk_label_set_attributes (GTK_LABEL (priv->label), attr_list);
+
+ if (free_list)
+ pango_attr_list_unref (attr_list);
+}
+
+/**
+ * terminal_tab_label_get_screen:
+ * @tab_label: a #TerminalTabLabel
+ *
+ * Returns: (transfer none): the #TerminalScreen for @tab_label
+ */
+TerminalScreen *
+terminal_tab_label_get_screen (TerminalTabLabel *tab_label)
+{
+ g_return_val_if_fail (TERMINAL_IS_TAB_LABEL (tab_label), NULL);
+
+ return tab_label->priv->screen;
+}
diff --git a/src/terminal-tab-label.h b/src/terminal-tab-label.h
new file mode 100644
index 0000000..20cfbce
--- /dev/null
+++ b/src/terminal-tab-label.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2008 Christian Persch
+ *
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_TAB_LABEL_H
+#define TERMINAL_TAB_LABEL_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_TAB_LABEL (terminal_tab_label_get_type ())
+#define TERMINAL_TAB_LABEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_TAB_LABEL, TerminalTabLabel))
+#define TERMINAL_TAB_LABEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_TAB_LABEL, TerminalTabLabelClass))
+#define TERMINAL_IS_TAB_LABEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_TAB_LABEL))
+#define TERMINAL_IS_TAB_LABEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_TAB_LABEL))
+#define TERMINAL_TAB_LABEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_TAB_LABEL, TerminalTabLabelClass))
+
+typedef struct _TerminalTabLabel TerminalTabLabel;
+typedef struct _TerminalTabLabelClass TerminalTabLabelClass;
+typedef struct _TerminalTabLabelPrivate TerminalTabLabelPrivate;
+
+struct _TerminalTabLabel
+{
+ GtkBox parent_instance;
+
+ /*< private >*/
+ TerminalTabLabelPrivate *priv;
+};
+
+struct _TerminalTabLabelClass
+{
+ GtkBoxClass parent_class;
+
+ /* Signals */
+ void (* close_button_clicked) (TerminalTabLabel *tab_label);
+};
+
+GType terminal_tab_label_get_type (void);
+
+GtkWidget * terminal_tab_label_new (TerminalScreen *screen);
+
+void terminal_tab_label_set_bold (TerminalTabLabel *tab_label,
+ gboolean bold);
+
+TerminalScreen *terminal_tab_label_get_screen (TerminalTabLabel *tab_label);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_TAB_LABEL_H */
diff --git a/src/terminal-type-builtins.c.template b/src/terminal-type-builtins.c.template
new file mode 100644
index 0000000..eb8fe99
--- /dev/null
+++ b/src/terminal-type-builtins.c.template
@@ -0,0 +1,45 @@
+/*** BEGIN file-header ***/
+#include <config.h>
+
+#include "terminal-type-builtins.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+
+#include "@filename@"
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+@enum_name@_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id = \
+ g_@type@_register_static (/* g_intern_static_string */ ("@EnumName@"), values);
+
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+/*** END value-tail ***/
+
+/*** BEGIN file-tail ***/
+
+/*** END file-tail ***/
diff --git a/src/terminal-type-builtins.h.template b/src/terminal-type-builtins.h.template
new file mode 100644
index 0000000..c454d05
--- /dev/null
+++ b/src/terminal-type-builtins.h.template
@@ -0,0 +1,25 @@
+/*** BEGIN file-header ***/
+#ifndef TERMINAL_TYPE_BUILTINS_H
+#define TERMINAL_TYPE_BUILTINS_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void);
+#define TERMINAL_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+
+G_END_DECLS
+
+#endif /* !TERMINAL_TYPE_BUILTINS_H */
+/*** END file-tail ***/
diff --git a/src/terminal-util.c b/src/terminal-util.c
new file mode 100644
index 0000000..3155e3f
--- /dev/null
+++ b/src/terminal-util.c
@@ -0,0 +1,1580 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2008, 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <langinfo.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include <gdesktop-enums.h>
+
+#include "terminal-accels.h"
+#include "terminal-app.h"
+#include "terminal-intl.h"
+#include "terminal-util.h"
+#include "terminal-libgsystem.h"
+
+/**
+ * terminal_util_show_error_dialog:
+ * @transient_parent: parent of the future dialog window;
+ * @weap_ptr: pointer to a #Widget pointer, to control the population.
+ * @error: a #GError, or %NULL
+ * @message_format: printf() style format string
+ *
+ * Create a #GtkMessageDialog window with the message, and present it, handling its buttons.
+ * If @weap_ptr is not #NULL, only create the dialog if <literal>*weap_ptr</literal> is #NULL
+ * (and in that * case, set @weap_ptr to be a weak pointer to the new dialog), otherwise just
+ * present <literal>*weak_ptr</literal>. Note that in this last case, the message <emph>will</emph>
+ * be changed.
+ */
+void
+terminal_util_show_error_dialog (GtkWindow *transient_parent,
+ GtkWidget **weak_ptr,
+ GError *error,
+ const char *message_format,
+ ...)
+{
+ gs_free char *message;
+ va_list args;
+
+ if (message_format)
+ {
+ va_start (args, message_format);
+ message = g_strdup_vprintf (message_format, args);
+ va_end (args);
+ }
+ else message = NULL;
+
+ if (weak_ptr == NULL || *weak_ptr == NULL)
+ {
+ GtkWidget *dialog;
+ dialog = gtk_message_dialog_new (transient_parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ message ? "%s" : NULL,
+ message);
+
+ if (error != NULL)
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", error->message);
+
+ g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL);
+
+ if (weak_ptr != NULL)
+ {
+ *weak_ptr = dialog;
+ g_object_add_weak_pointer (G_OBJECT (dialog), (void**)weak_ptr);
+ }
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+ gtk_widget_show_all (dialog);
+ }
+ else
+ {
+ g_return_if_fail (GTK_IS_MESSAGE_DIALOG (*weak_ptr));
+
+ /* Sucks that there's no direct accessor for "text" property */
+ g_object_set (G_OBJECT (*weak_ptr), "text", message, NULL);
+
+ gtk_window_present (GTK_WINDOW (*weak_ptr));
+ }
+}
+
+static gboolean
+open_url (GtkWindow *parent,
+ const char *uri,
+ guint32 user_time,
+ GError **error)
+{
+ GdkScreen *screen;
+ gs_free char *uri_fixed;
+
+ if (parent)
+ screen = gtk_widget_get_screen (GTK_WIDGET (parent));
+ else
+ screen = gdk_screen_get_default ();
+
+ uri_fixed = terminal_util_uri_fixup (uri, error);
+ if (uri_fixed == NULL)
+ return FALSE;
+
+ return gtk_show_uri (screen, uri_fixed, user_time, error);
+}
+
+void
+terminal_util_show_help (const char *topic)
+{
+ gs_free_error GError *error = NULL;
+ gs_free char *uri;
+
+ if (topic) {
+ uri = g_strdup_printf ("help:gnome-terminal/%s", topic);
+ } else {
+ uri = g_strdup ("help:gnome-terminal");
+ }
+
+ if (!open_url (NULL, uri, gtk_get_current_event_time (), &error))
+ {
+ terminal_util_show_error_dialog (NULL, NULL, error,
+ _("There was an error displaying help"));
+ }
+}
+
+#define ABOUT_GROUP "About"
+#define ABOUT_URL "https://wiki.gnome.org/Apps/Terminal"
+#define EMAILIFY(string) (g_strdelimit ((string), "%", '@'))
+
+void
+terminal_util_show_about (void)
+{
+ static const char copyright[] =
+ "Copyright © 2002–2004 Havoc Pennington\n"
+ "Copyright © 2003–2004, 2007 Mariano Suárez-Alvarez\n"
+ "Copyright © 2006 Guilherme de S. Pastore\n"
+ "Copyright © 2007–2019 Christian Persch\n"
+ "Copyright © 2013–2019 Egmont Koblinger";
+ char *licence_text;
+ GKeyFile *key_file;
+ GBytes *bytes;
+ const guint8 *data;
+ gsize data_len;
+ GError *error = NULL;
+ char **authors, **contributors, **artists, **documenters, **array_strv;
+ gsize n_authors = 0, n_contributors = 0, n_artists = 0, n_documenters = 0 , i;
+ GPtrArray *array;
+ gs_free char *comment;
+ gs_free char *vte_version;
+ GtkWindow *dialog;
+
+ bytes = g_resources_lookup_data (TERMINAL_RESOURCES_PATH_PREFIX "/ui/terminal.about",
+ G_RESOURCE_LOOKUP_FLAGS_NONE,
+ &error);
+ g_assert_no_error (error);
+
+ data = g_bytes_get_data (bytes, &data_len);
+ key_file = g_key_file_new ();
+ g_key_file_load_from_data (key_file, (const char *) data, data_len, 0, &error);
+ g_assert_no_error (error);
+
+ authors = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Authors", &n_authors, NULL);
+ contributors = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Contributors", &n_contributors, NULL);
+ artists = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Artists", &n_artists, NULL);
+ documenters = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Documenters", &n_documenters, NULL);
+
+ g_key_file_free (key_file);
+ g_bytes_unref (bytes);
+
+ array = g_ptr_array_new ();
+
+ for (i = 0; i < n_authors; ++i)
+ g_ptr_array_add (array, EMAILIFY (authors[i]));
+ g_free (authors); /* strings are now owned by the array */
+
+ if (n_contributors > 0)
+ {
+ g_ptr_array_add (array, g_strdup (""));
+ g_ptr_array_add (array, g_strdup (_("Contributors:")));
+ for (i = 0; i < n_contributors; ++i)
+ g_ptr_array_add (array, EMAILIFY (contributors[i]));
+ }
+ g_free (contributors); /* strings are now owned by the array */
+
+ g_ptr_array_add (array, NULL);
+ array_strv = (char **) g_ptr_array_free (array, FALSE);
+
+ for (i = 0; i < n_artists; ++i)
+ artists[i] = EMAILIFY (artists[i]);
+ for (i = 0; i < n_documenters; ++i)
+ documenters[i] = EMAILIFY (documenters[i]);
+
+ licence_text = terminal_util_get_licence_text ();
+
+ vte_version = g_strdup_printf (_("Using VTE version %u.%u.%u"),
+ vte_get_major_version (),
+ vte_get_minor_version (),
+ vte_get_micro_version ());
+
+ comment = g_strdup_printf("%s\n%s %s",
+ _("A terminal emulator for the GNOME desktop"),
+ vte_version,
+ vte_get_features ());
+
+ dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG,
+ /* Hold the application while the window is shown */
+ "application", terminal_app_get (),
+ "program-name", _("GNOME Terminal"),
+ "copyright", copyright,
+ "comments", comment,
+ "version", VERSION,
+ "authors", array_strv,
+ "artists", artists,
+ "documenters", documenters,
+ "license", licence_text,
+ "wrap-license", TRUE,
+ "website", ABOUT_URL,
+ "translator-credits", _("translator-credits"),
+ "logo-icon-name", GNOME_TERMINAL_ICON_NAME,
+ NULL);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_window_present (dialog);
+
+ g_strfreev (array_strv);
+ g_strfreev (artists);
+ g_strfreev (documenters);
+ g_free (licence_text);
+}
+
+/* sets accessible name and description for the widget */
+
+void
+terminal_util_set_atk_name_description (GtkWidget *widget,
+ const char *name,
+ const char *desc)
+{
+ AtkObject *obj;
+
+ obj = gtk_widget_get_accessible (widget);
+
+ if (obj == NULL)
+ {
+ g_warning ("%s: for some reason widget has no GtkAccessible",
+ G_STRFUNC);
+ return;
+ }
+
+ if (!GTK_IS_ACCESSIBLE (obj))
+ return; /* This means GAIL is not loaded so we have the NoOp accessible */
+
+ g_return_if_fail (GTK_IS_ACCESSIBLE (obj));
+ if (desc)
+ atk_object_set_description (obj, desc);
+ if (name)
+ atk_object_set_name (obj, name);
+}
+
+void
+terminal_util_open_url (GtkWidget *parent,
+ const char *orig_url,
+ TerminalURLFlavor flavor,
+ guint32 user_time)
+{
+ gs_free_error GError *error = NULL;
+ gs_free char *uri = NULL;
+
+ g_return_if_fail (orig_url != NULL);
+
+ switch (flavor)
+ {
+ case FLAVOR_DEFAULT_TO_HTTP:
+ uri = g_strdup_printf ("http://%s", orig_url);
+ break;
+ case FLAVOR_EMAIL:
+ if (g_ascii_strncasecmp ("mailto:", orig_url, 7) != 0)
+ uri = g_strdup_printf ("mailto:%s", orig_url);
+ else
+ uri = g_strdup (orig_url);
+ break;
+ case FLAVOR_VOIP_CALL:
+ case FLAVOR_AS_IS:
+ uri = g_strdup (orig_url);
+ break;
+ default:
+ uri = NULL;
+ g_assert_not_reached ();
+ }
+
+ if (!open_url (GTK_WINDOW (parent), uri, user_time, &error))
+ {
+ terminal_util_show_error_dialog (GTK_WINDOW (parent), NULL, error,
+ _("Could not open the address “%s”"),
+ uri);
+ }
+}
+
+/**
+ * terminal_util_transform_uris_to_quoted_fuse_paths:
+ * @uris:
+ *
+ * Transforms those URIs in @uris to shell-quoted paths that point to
+ * GIO fuse paths.
+ */
+void
+terminal_util_transform_uris_to_quoted_fuse_paths (char **uris)
+{
+ guint i;
+
+ if (!uris)
+ return;
+
+ for (i = 0; uris[i]; ++i)
+ {
+ gs_unref_object GFile *file;
+ gs_free char *path;
+
+ file = g_file_new_for_uri (uris[i]);
+
+ path = g_file_get_path (file);
+ if (path)
+ {
+ char *quoted;
+
+ quoted = g_shell_quote (path);
+ g_free (uris[i]);
+
+ uris[i] = quoted;
+ }
+ }
+}
+
+char *
+terminal_util_concat_uris (char **uris,
+ gsize *length)
+{
+ GString *string;
+ gsize len;
+ guint i;
+
+ len = 0;
+ for (i = 0; uris[i]; ++i)
+ len += strlen (uris[i]) + 1;
+
+ if (length)
+ *length = len;
+
+ string = g_string_sized_new (len + 1);
+ for (i = 0; uris[i]; ++i)
+ {
+ g_string_append (string, uris[i]);
+ g_string_append_c (string, ' ');
+ }
+
+ return g_string_free (string, FALSE);
+}
+
+char *
+terminal_util_get_licence_text (void)
+{
+ const gchar *license[] = {
+ N_("GNOME Terminal 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 3 of the License, or "
+ "(at your option) any later version."),
+ N_("GNOME Terminal 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."),
+ N_("You should have received a copy of the GNU General Public License "
+ "along with GNOME Terminal. If not, see <http://www.gnu.org/licenses/>.")
+ };
+
+ return g_strjoin ("\n\n", _(license[0]), _(license[1]), _(license[2]), NULL);
+}
+
+static void
+main_object_destroy_cb (GtkWidget *widget)
+{
+ g_object_set_data (G_OBJECT (widget), "builder", NULL);
+}
+
+GtkBuilder *
+terminal_util_load_widgets_resource (const char *path,
+ const char *main_object_name,
+ const char *object_name,
+ ...)
+{
+ GtkBuilder *builder;
+ GError *error = NULL;
+ va_list args;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_resource (builder, path, &error);
+ g_assert_no_error (error);
+
+ va_start (args, object_name);
+
+ while (object_name) {
+ GObject **objectptr;
+
+ objectptr = va_arg (args, GObject**);
+ *objectptr = gtk_builder_get_object (builder, object_name);
+ if (!*objectptr)
+ g_error ("Failed to fetch object \"%s\" from resource \"%s\"\n", object_name, path);
+
+ object_name = va_arg (args, const char*);
+ }
+
+ va_end (args);
+
+ if (main_object_name) {
+ GObject *main_object;
+ GtkWidget *action_area;
+
+ main_object = gtk_builder_get_object (builder, main_object_name);
+ g_object_set_data_full (main_object, "builder", g_object_ref (builder), (GDestroyNotify) g_object_unref);
+ g_signal_connect (main_object, "destroy", G_CALLBACK (main_object_destroy_cb), NULL);
+
+ /* Fixup dialogue padding, #735242 */
+ if (GTK_IS_DIALOG (main_object) &&
+ (action_area = (GtkWidget *) gtk_builder_get_object (builder, "dialog-action-area"))) {
+ gtk_widget_set_margin_start (action_area, 5);
+ gtk_widget_set_margin_end (action_area, 5);
+ gtk_widget_set_margin_top (action_area, 5);
+ gtk_widget_set_margin_bottom (action_area, 5);
+ }
+ }
+ return builder;
+}
+
+void
+terminal_util_load_objects_resource (const char *path,
+ const char *object_name,
+ ...)
+{
+ gs_unref_object GtkBuilder *builder;
+ GError *error = NULL;
+ va_list args;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_resource (builder, path, &error);
+ g_assert_no_error (error);
+
+ va_start (args, object_name);
+
+ while (object_name) {
+ GObject **objectptr;
+
+ objectptr = va_arg (args, GObject**);
+ *objectptr = gtk_builder_get_object (builder, object_name);
+ if (*objectptr)
+ g_object_ref (*objectptr);
+ else
+ g_error ("Failed to fetch object \"%s\" from resource \"%s\"\n", object_name, path);
+
+ object_name = va_arg (args, const char*);
+ }
+
+ va_end (args);
+}
+
+gboolean
+terminal_util_dialog_response_on_delete (GtkWindow *widget)
+{
+ gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_DELETE_EVENT);
+ return TRUE;
+}
+
+void
+terminal_util_dialog_focus_widget (GtkBuilder *builder,
+ const char *widget_name)
+{
+ GtkWidget *widget, *page, *page_parent;
+
+ if (widget_name == NULL)
+ return;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, widget_name));
+ if (widget == NULL)
+ return;
+
+ page = widget;
+ while (page != NULL &&
+ (page_parent = gtk_widget_get_parent (page)) != NULL &&
+ !GTK_IS_NOTEBOOK (page_parent))
+ page = page_parent;
+
+ page_parent = gtk_widget_get_parent (page);
+ if (page != NULL && GTK_IS_NOTEBOOK (page_parent)) {
+ GtkNotebook *notebook;
+
+ notebook = GTK_NOTEBOOK (page_parent);
+ gtk_notebook_set_current_page (notebook, gtk_notebook_page_num (notebook, page));
+ }
+
+ if (gtk_widget_is_sensitive (widget))
+ gtk_widget_grab_focus (widget);
+}
+
+/* Proxy stuff */
+
+/*
+ * set_proxy_env:
+ * @env_table: a #GHashTable
+ * @key: the env var name
+ * @value: the env var value
+ *
+ * Adds @value for @key to @env_table, taking care to never overwrite an
+ * existing value for @key. @value is consumed.
+ */
+static void
+set_proxy_env (GHashTable *env_table,
+ const char *key,
+ char *value /* consumed */)
+{
+ char *key1 = NULL, *key2 = NULL;
+ char *value1 = NULL, *value2 = NULL;
+
+ if (!value)
+ return;
+
+ if (g_hash_table_lookup (env_table, key) == NULL)
+ key1 = g_strdup (key);
+
+ key2 = g_ascii_strup (key, -1);
+ if (g_hash_table_lookup (env_table, key) != NULL)
+ {
+ g_free (key2);
+ key2 = NULL;
+ }
+
+ if (key1 && key2)
+ {
+ value1 = value;
+ value2 = g_strdup (value);
+ }
+ else if (key1)
+ value1 = value;
+ else if (key2)
+ value2 = value;
+ else
+ g_free (value);
+
+ if (key1)
+ g_hash_table_replace (env_table, key1, value1);
+ if (key2)
+ g_hash_table_replace (env_table, key2, value2);
+}
+
+static void
+setup_proxy_env (GSettings *proxy_settings,
+ const char *child_schema_id,
+ const char *proxy_scheme,
+ const char *env_name,
+ GHashTable *env_table)
+{
+ gs_unref_object GSettings *child_settings;
+ GString *buf;
+ gs_free char *host;
+ int port;
+ gboolean is_http;
+
+ is_http = (strcmp (child_schema_id, "http") == 0);
+
+ child_settings = g_settings_get_child (proxy_settings, child_schema_id);
+
+ host = g_settings_get_string (child_settings, "host");
+ port = g_settings_get_int (child_settings, "port");
+ if (host[0] == '\0' || port == 0)
+ return;
+
+ buf = g_string_sized_new (64);
+
+ g_string_append_printf (buf, "%s://", proxy_scheme);
+
+ if (is_http &&
+ g_settings_get_boolean (child_settings, "use-authentication"))
+ {
+ gs_free char *user;
+
+ user = g_settings_get_string (child_settings, "authentication-user");
+ if (user[0])
+ {
+ gs_free char *password;
+
+ g_string_append_uri_escaped (buf, user, NULL, TRUE);
+
+ password = g_settings_get_string (child_settings, "authentication-password");
+ if (password[0])
+ {
+ g_string_append_c (buf, ':');
+ g_string_append_uri_escaped (buf, password, NULL, TRUE);
+ }
+ g_string_append_c (buf, '@');
+ }
+ }
+
+ g_string_append_printf (buf, "%s:%d/", host, port);
+ set_proxy_env (env_table, env_name, g_string_free (buf, FALSE));
+}
+
+static void
+setup_autoconfig_proxy_env (GSettings *proxy_settings,
+ GHashTable *env_table)
+{
+ /* XXX Not sure what to do with this. See bug #596688.
+ gs_free char *url;
+
+ url = g_settings_get_string (proxy_settings, "autoconfig-url");
+ if (url[0])
+ {
+ char *proxy;
+ proxy = g_strdup_printf ("pac+%s", url);
+ set_proxy_env (env_table, "http_proxy", proxy);
+ }
+ */
+}
+
+static void
+setup_ignore_proxy_env (GSettings *proxy_settings,
+ GHashTable *env_table)
+{
+ GString *buf;
+ gs_strfreev char **ignore;
+ int i;
+
+ g_settings_get (proxy_settings, "ignore-hosts", "^as", &ignore);
+ if (ignore == NULL)
+ return;
+
+ buf = g_string_sized_new (64);
+ for (i = 0; ignore[i] != NULL; ++i)
+ {
+ if (buf->len)
+ g_string_append_c (buf, ',');
+ g_string_append (buf, ignore[i]);
+ }
+
+ set_proxy_env (env_table, "no_proxy", g_string_free (buf, FALSE));
+}
+
+/**
+ * terminal_util_add_proxy_env:
+ * @env_table: a #GHashTable
+ *
+ * Adds the proxy env variables to @env_table.
+ */
+void
+terminal_util_add_proxy_env (GHashTable *env_table)
+{
+ GSettings *proxy_settings;
+ GDesktopProxyMode mode;
+
+ proxy_settings = terminal_app_get_proxy_settings (terminal_app_get ());
+ mode = g_settings_get_enum (proxy_settings, "mode");
+
+ if (mode == G_DESKTOP_PROXY_MODE_MANUAL)
+ {
+ setup_proxy_env (proxy_settings, "http", "http", "http_proxy", env_table);
+ /* Even though it's https, the proxy scheme is 'http'. See bug #624440. */
+ setup_proxy_env (proxy_settings, "https", "http", "https_proxy", env_table);
+ /* Even though it's ftp, the proxy scheme is 'http'. See bug #624440. */
+ setup_proxy_env (proxy_settings, "ftp", "http", "ftp_proxy", env_table);
+ setup_proxy_env (proxy_settings, "socks", "socks", "all_proxy", env_table);
+ setup_ignore_proxy_env (proxy_settings, env_table);
+ }
+ else if (mode == G_DESKTOP_PROXY_MODE_AUTO)
+ {
+ setup_autoconfig_proxy_env (proxy_settings, env_table);
+ }
+}
+
+/**
+ * terminal_util_get_etc_shells:
+ *
+ * Returns: (transfer full) the contents of /etc/shells
+ */
+char **
+terminal_util_get_etc_shells (void)
+{
+ GError *err = NULL;
+ gsize len;
+ gs_free char *contents = NULL;
+ char *str, *nl, *end;
+ GPtrArray *arr;
+
+ if (!g_file_get_contents ("/etc/shells", &contents, &len, &err) || len == 0) {
+ /* Defaults as per man:getusershell(3) */
+ char *default_shells[3] = {
+ (char*) "/bin/sh",
+ (char*) "/bin/csh",
+ NULL
+ };
+ return g_strdupv (default_shells);
+ }
+
+ arr = g_ptr_array_new ();
+ str = contents;
+ end = contents + len;
+ while (str < end && (nl = strchr (str, '\n')) != NULL) {
+ if (str != nl) /* non-empty? */
+ g_ptr_array_add (arr, g_strndup (str, nl - str));
+ str = nl + 1;
+ }
+ /* Anything non-empty left? */
+ if (str < end && str[0])
+ g_ptr_array_add (arr, g_strdup (str));
+
+ g_ptr_array_add (arr, NULL);
+ return (char **) g_ptr_array_free (arr, FALSE);
+}
+
+/**
+ * terminal_util_get_is_shell:
+ * @command: a string
+ *
+ * Returns wether @command is a valid shell as defined by the contents of /etc/shells.
+ *
+ * Returns: whether @command is a shell
+ */
+gboolean
+terminal_util_get_is_shell (const char *command)
+{
+ gs_strfreev char **shells;
+ guint i;
+
+ shells = terminal_util_get_etc_shells ();
+ if (shells == NULL)
+ return FALSE;
+
+ for (i = 0; shells[i]; i++)
+ if (g_str_equal (command, shells[i]))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+s_to_rgba (GVariant *variant,
+ gpointer *result,
+ gpointer user_data)
+{
+ GdkRGBA *color = user_data;
+ const char *str;
+
+ if (variant == NULL) {
+ /* Fallback */
+ *result = NULL;
+ return TRUE;
+ }
+
+ g_variant_get (variant, "&s", &str);
+ if (!gdk_rgba_parse (color, str))
+ return FALSE;
+
+ color->alpha = 1.0;
+ *result = color;
+ return TRUE;
+}
+
+/**
+ * terminal_g_settings_new:
+ * @schema_id: a settings schema ID
+ * @mandatory_key: the name of a key that must exist in the schema
+ * @mandatory_key_type: the expected value type of @mandatory_key
+ *
+ * Creates a #GSettings for @schema_id, if this schema exists and
+ * has a key named @mandatory_key (if non-%NULL) with the value type
+ * @mandatory_key_type.
+ *
+ * Returns: (transfer full): a new #GSettings, or %NULL
+ */
+GSettings *
+terminal_g_settings_new (const char *schema_id,
+ const char *mandatory_key,
+ const GVariantType *mandatory_key_type)
+{
+ gs_unref_settings_schema GSettingsSchema *schema;
+
+ schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
+ schema_id,
+ TRUE);
+ if (schema == NULL)
+ return NULL;
+
+ if (mandatory_key) {
+ gs_unref_settings_schema_key GSettingsSchemaKey *key;
+
+ key = g_settings_schema_get_key (schema, mandatory_key);
+ if (key == NULL)
+ return NULL;
+
+ if (!g_variant_type_equal (g_settings_schema_key_get_value_type (key),
+ mandatory_key_type))
+ return NULL;
+ }
+
+ return g_settings_new_full (schema, NULL, NULL);
+}
+
+/**
+ * terminal_g_settings_get_rgba:
+ * @settings: a #GSettings
+ * @key: a valid key in @settings of type "s"
+ * @color: location to store the parsed color
+ *
+ * Gets a color from @key in @settings.
+ *
+ * Returns: @color if parsing succeeded, or %NULL otherwise
+ */
+const GdkRGBA *
+terminal_g_settings_get_rgba (GSettings *settings,
+ const char *key,
+ GdkRGBA *color)
+{
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ return g_settings_get_mapped (settings, key,
+ (GSettingsGetMapping) s_to_rgba,
+ color);
+}
+
+/**
+ * terminal_g_settings_set_rgba:
+ * @settings: a #GSettings
+ * @key: a valid key in @settings of type "s"
+ * @color: a #GdkRGBA
+ *
+ * Sets a color in @key in @settings.
+ */
+void
+terminal_g_settings_set_rgba (GSettings *settings,
+ const char *key,
+ const GdkRGBA *color)
+{
+ gs_free char *str;
+
+ str = gdk_rgba_to_string (color);
+ g_settings_set_string (settings, key, str);
+}
+
+static gboolean
+as_to_rgba_palette (GVariant *variant,
+ gpointer *result,
+ gpointer user_data)
+{
+ gsize *n_colors = user_data;
+ gs_free GdkRGBA *colors = NULL;
+ gsize n = 0;
+ GVariantIter iter;
+ const char *str;
+ gsize i;
+
+ /* Fallback */
+ if (variant == NULL)
+ goto out;
+
+ g_variant_iter_init (&iter, variant);
+ n = g_variant_iter_n_children (&iter);
+ colors = g_new (GdkRGBA, n);
+
+ i = 0;
+ while (g_variant_iter_next (&iter, "&s", &str)) {
+ if (!gdk_rgba_parse (&colors[i++], str)) {
+ return FALSE;
+ }
+ }
+
+ out:
+ gs_transfer_out_value (result, &colors);
+ if (n_colors)
+ *n_colors = n;
+
+ return TRUE;
+}
+
+/**
+ * terminal_g_settings_get_rgba_palette:
+ * @settings: a #GSettings
+ * @key: a valid key in @settings or type "s"
+ * @n_colors: (allow-none): location to store the number of palette entries, or %NULL
+ *
+ * Returns: (transfer full):
+ */
+GdkRGBA *
+terminal_g_settings_get_rgba_palette (GSettings *settings,
+ const char *key,
+ gsize *n_colors)
+{
+ return g_settings_get_mapped (settings, key,
+ (GSettingsGetMapping) as_to_rgba_palette,
+ n_colors);
+}
+
+void
+terminal_g_settings_set_rgba_palette (GSettings *settings,
+ const char *key,
+ const GdkRGBA *colors,
+ gsize n_colors)
+{
+ gs_strfreev char **strv;
+ gsize i;
+
+ strv = g_new (char *, n_colors + 1);
+ for (i = 0; i < n_colors; ++i)
+ strv[i] = gdk_rgba_to_string (&colors[i]);
+ strv[n_colors] = NULL;
+
+ g_settings_set (settings, key, "^as", strv);
+}
+
+static void
+mnemonic_label_set_sensitive_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GtkWidget *label)
+{
+ gtk_widget_set_sensitive (label, gtk_widget_get_sensitive (widget));
+}
+
+/**
+ * terminal_util_bind_mnemonic_label_sensitivity:
+ * @container: a #GtkContainer
+ */
+void
+terminal_util_bind_mnemonic_label_sensitivity (GtkWidget *widget)
+{
+ GList *list, *l;
+
+ list = gtk_widget_list_mnemonic_labels (widget);
+ for (l = list; l != NULL; l = l->next) {
+ GtkWidget *label = l->data;
+
+ if (gtk_widget_is_ancestor (label, widget))
+ continue;
+
+#if 0
+ g_print ("Widget %s has mnemonic label %s\n",
+ gtk_buildable_get_name (GTK_BUILDABLE (widget)),
+ gtk_buildable_get_name (GTK_BUILDABLE (label)));
+#endif
+
+ mnemonic_label_set_sensitive_cb (widget, NULL, label);
+ g_signal_connect (widget, "notify::sensitive",
+ G_CALLBACK (mnemonic_label_set_sensitive_cb),
+ label);
+ }
+ g_list_free (list);
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ /* See #96 for double casting. */
+ (GtkCallback) (GCallback) terminal_util_bind_mnemonic_label_sensitivity,
+ NULL);
+}
+
+/*
+ * "1234567", "'", 3 -> "1'234'567"
+ */
+static char *
+add_separators (const char *in, const char *sep, int groupby)
+{
+ int inlen, outlen, seplen, firstgrouplen;
+ char *out, *ret;
+
+ if (in[0] == '\0')
+ return g_strdup("");
+
+ inlen = strlen(in);
+ seplen = strlen(sep);
+ outlen = inlen + (inlen - 1) / groupby * seplen;
+ ret = out = g_malloc(outlen + 1);
+
+ firstgrouplen = (inlen - 1) % groupby + 1;
+ memcpy(out, in, firstgrouplen);
+ in += firstgrouplen;
+ out += firstgrouplen;
+
+ while (*in != '\0') {
+ memcpy(out, sep, seplen);
+ out += seplen;
+ memcpy(out, in, groupby);
+ in += groupby;
+ out += groupby;
+ }
+
+ g_assert(out - ret == outlen);
+ *out = '\0';
+ return ret;
+}
+
+/**
+ * terminal_util_number_info:
+ * @str: a dec or hex number as string
+ *
+ * Returns: (transfer full): Useful info about @str, or %NULL if it's too large
+ */
+char *
+terminal_util_number_info (const char *str)
+{
+ gs_free char *decstr = NULL;
+ gs_free char *hextmp = NULL;
+ gs_free char *hexstr = NULL;
+ gs_free char *magnitudestr = NULL;
+ unsigned long long num;
+ gboolean exact = TRUE;
+ gboolean hex = FALSE;
+ const char *thousep;
+
+ errno = 0;
+ /* Deliberately not handle octal */
+ if (str[1] == 'x' || str[1] == 'X') {
+ num = strtoull(str + 2, NULL, 16);
+ hex = TRUE;
+ } else {
+ num = strtoull(str, NULL, 10);
+ }
+ if (errno) {
+ return NULL;
+ }
+
+ /* No use in dec-hex conversion for so small numbers */
+ if (num < 10) {
+ return NULL;
+ }
+
+ /* Group the decimal digits */
+ thousep = nl_langinfo(THOUSEP);
+ if (thousep[0] != '\0') {
+ /* If thousep is nonempty, use printf's magic which can handle
+ more complex separating logics, e.g. 2+2+2+3 for some locales */
+ decstr = g_strdup_printf("%'llu", num);
+ } else {
+ /* If, however, thousep is empty, override it with a space so that we
+ do always group the digits (that's the whole point of this feature;
+ the choice of space guarantees not conflicting with the decimal separator) */
+ gs_free char *tmp = g_strdup_printf("%llu", num);
+ thousep = " ";
+ decstr = add_separators(tmp, thousep, 3);
+ }
+
+ /* Group the hex digits by 4 using the same nonempty separator */
+ hextmp = g_strdup_printf("%llx", num);
+ hexstr = add_separators(hextmp, thousep, 4);
+
+ /* Find out the human-readable magnitude, e.g. 15.99 Mi */
+ if (num >= 1024) {
+ int power = 0;
+ while (num >= 1024 * 1024) {
+ power++;
+ if (num % 1024 != 0)
+ exact = FALSE;
+ num /= 1024;
+ }
+ /* Show 2 fraction digits, always rounding downwards. Printf rounds floats to the nearest representable value,
+ so do the calculation with integers until we get 100-fold the desired value, and then switch to float. */
+ if (100 * num % 1024 != 0)
+ exact = FALSE;
+ num = 100 * num / 1024;
+ magnitudestr = g_strdup_printf(" %s %.2f %ci", exact ? "=" : "≈", (double) num / 100, "KMGTPE"[power]);
+ } else {
+ magnitudestr = g_strdup("");
+ }
+
+ return g_strdup_printf(hex ? "0x%2$s = %1$s%3$s" : "%s = 0x%s%s", decstr, hexstr, magnitudestr);
+}
+
+/**
+ * terminal_util_uri_fixup:
+ * @uri: The URI to verify and maybe fixup
+ * @error: a #GError that is returned in case of errors
+ *
+ * Checks if gnome-terminal should attempt to handle the given URI,
+ * and rewrites if necessary.
+ *
+ * Currently URIs of "file://some-other-host/..." are refused because
+ * GIO (e.g. gtk_show_uri()) silently strips off the remote hostname
+ * and opens the local counterpart which is incorrect and misleading.
+ *
+ * Furthermore, once the hostname is verified, it is stripped off to
+ * avoid potential confusion around short hostname vs. fqdn, and to
+ * work around bug 781800 (LibreOffice bug 107461).
+ *
+ * Returns: The possibly rewritten URI if gnome-terminal should attempt
+ * to handle it, NULL if it should refuse to handle.
+ */
+char *
+terminal_util_uri_fixup (const char *uri,
+ GError **error)
+{
+ gs_free char *filename;
+ gs_free char *hostname;
+
+ filename = g_filename_from_uri (uri, &hostname, NULL);
+ if (filename != NULL &&
+ hostname != NULL &&
+ hostname[0] != '\0') {
+ /* "file" scheme and nonempty hostname */
+ if (g_ascii_strcasecmp (hostname, "localhost") == 0 ||
+ g_ascii_strcasecmp (hostname, g_get_host_name()) == 0) {
+ /* hostname corresponds to localhost */
+ char *slash1, *slash2, *slash3;
+
+ /* We shouldn't enter this branch in case of URIs like
+ * "file:/etc/passwd", but just in case we do, or encounter
+ * something else unexpected, leave the URI unchanged. */
+ slash1 = strchr(uri, '/');
+ if (slash1 == NULL)
+ return g_strdup (uri);
+
+ slash2 = slash1 + 1;
+ if (*slash2 != '/')
+ return g_strdup (uri);
+
+ slash3 = strchr(slash2 + 1, '/');
+ if (slash3 == NULL)
+ return g_strdup (uri);
+
+ return g_strdup_printf("%.*s%s",
+ (int) (slash2 + 1 - uri),
+ uri,
+ slash3);
+ } else {
+ /* hostname refers to another host (e.g. the OSC 8 escape sequence
+ * was correctly emitted by a utility inside an ssh session) */
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("“file” scheme with remote hostname not supported"));
+ return NULL;
+ }
+ } else {
+ /* "file" scheme without hostname, or some other scheme */
+ return g_strdup (uri);
+ }
+}
+
+/**
+ * terminal_util_hyperlink_uri_label:
+ * @uri: a URI
+ *
+ * Formats @uri to be displayed in a tooltip.
+ * Performs URI-decoding and converts IDN hostname to UTF-8.
+ *
+ * Returns: (transfer full): The human readable URI as plain text
+ */
+char *terminal_util_hyperlink_uri_label (const char *uri)
+{
+ gs_free char *unesc = NULL;
+ gboolean replace_hostname;
+
+ if (uri == NULL)
+ return NULL;
+
+ unesc = g_uri_unescape_string(uri, NULL);
+ if (unesc == NULL)
+ unesc = g_strdup(uri);
+
+ if (g_ascii_strncasecmp(unesc, "ftp://", 6) == 0 ||
+ g_ascii_strncasecmp(unesc, "http://", 7) == 0 ||
+ g_ascii_strncasecmp(unesc, "https://", 8) == 0) {
+ gs_free char *unidn = NULL;
+ char *hostname = strchr(unesc, '/') + 2;
+ char *hostname_end = strchrnul(hostname, '/');
+ char save = *hostname_end;
+ *hostname_end = '\0';
+ unidn = g_hostname_to_unicode(hostname);
+ replace_hostname = unidn != NULL && g_ascii_strcasecmp(unidn, hostname) != 0;
+ *hostname_end = save;
+ if (replace_hostname) {
+ char *new_unesc = g_strdup_printf("%.*s%s%s",
+ (int) (hostname - unesc),
+ unesc,
+ unidn,
+ hostname_end);
+ g_free(unesc);
+ unesc = new_unesc;
+ }
+ }
+
+ return g_utf8_make_valid (unesc, -1);
+}
+
+#define TERMINAL_CACHE_DIR "gnome-terminal"
+#define TERMINAL_PRINT_SETTINGS_FILENAME "print-settings.ini"
+#define TERMINAL_PRINT_SETTINGS_GROUP_NAME "Print Settings"
+#define TERMINAL_PAGE_SETUP_GROUP_NAME "Page Setup"
+
+#define KEYFILE_FLAGS_FOR_LOAD (G_KEY_FILE_NONE)
+#define KEYFILE_FLAGS_FOR_SAVE (G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS)
+
+static char *
+get_cache_dir (void)
+{
+ return g_build_filename (g_get_user_cache_dir (), TERMINAL_CACHE_DIR, NULL);
+}
+
+static gboolean
+ensure_cache_dir (void)
+{
+ gs_free char *cache_dir;
+ int r;
+
+ cache_dir = get_cache_dir ();
+ errno = 0;
+ r = g_mkdir_with_parents (cache_dir, 0700);
+ if (r == -1 && errno != EEXIST)
+ g_printerr ("Failed to create cache dir: %m\n");
+ return r == 0;
+}
+
+static char *
+get_cache_filename (const char *filename)
+{
+ gs_free char *cache_dir = get_cache_dir ();
+ return g_build_filename (cache_dir, filename, NULL);
+}
+
+static GKeyFile *
+load_cache_keyfile (const char *filename,
+ GKeyFileFlags flags,
+ gboolean ignore_error)
+{
+ gs_free char *path;
+ GKeyFile *keyfile;
+
+ path = get_cache_filename (filename);
+ keyfile = g_key_file_new ();
+ if (g_key_file_load_from_file (keyfile, path, flags, NULL) || ignore_error)
+ return keyfile;
+
+ g_key_file_unref (keyfile);
+ return NULL;
+}
+
+static void
+save_cache_keyfile (GKeyFile *keyfile,
+ const char *filename)
+{
+ gs_free char *path = NULL;
+ gs_free char *data = NULL;
+ gsize len = 0;
+
+ if (!ensure_cache_dir ())
+ return;
+
+ data = g_key_file_to_data (keyfile, &len, NULL);
+ if (data == NULL || len == 0)
+ return;
+
+ path = get_cache_filename (filename);
+
+ /* Ignore errors */
+ GError *err = NULL;
+ if (!g_file_set_contents (path, data, len, &err)) {
+ g_printerr ("Error saving print settings: %s\n", err->message);
+ g_error_free (err);
+ }
+}
+
+static void
+keyfile_remove_keys (GKeyFile *keyfile,
+ const char *group_name,
+ ...)
+{
+ va_list args;
+ const char *key;
+
+ va_start (args, group_name);
+ while ((key = va_arg (args, const char *)) != NULL) {
+ g_key_file_remove_key (keyfile, group_name, key, NULL);
+ }
+ va_end (args);
+}
+
+/**
+ * terminal_util_load_print_settings:
+ *
+ * Loads the saved print settings, if any.
+ */
+void
+terminal_util_load_print_settings (GtkPrintSettings **settings,
+ GtkPageSetup **page_setup)
+{
+ gs_unref_key_file GKeyFile *keyfile = load_cache_keyfile (TERMINAL_PRINT_SETTINGS_FILENAME,
+ KEYFILE_FLAGS_FOR_LOAD,
+ FALSE);
+ if (keyfile == NULL) {
+ *settings = NULL;
+ *page_setup = NULL;
+ return;
+ }
+
+ /* Ignore errors */
+ *settings = gtk_print_settings_new_from_key_file (keyfile,
+ TERMINAL_PRINT_SETTINGS_GROUP_NAME,
+ NULL);
+ *page_setup = gtk_page_setup_new_from_key_file (keyfile,
+ TERMINAL_PAGE_SETUP_GROUP_NAME,
+ NULL);
+}
+
+/**
+ * terminal_util_save_print_settings:
+ * @settings: (allow-none): a #GtkPrintSettings
+ * @page_setup: (allow-none): a #GtkPageSetup
+ *
+ * Saves the print settings.
+ */
+void
+terminal_util_save_print_settings (GtkPrintSettings *settings,
+ GtkPageSetup *page_setup)
+{
+ gs_unref_key_file GKeyFile *keyfile = NULL;
+
+ keyfile = load_cache_keyfile (TERMINAL_PRINT_SETTINGS_FILENAME,
+ KEYFILE_FLAGS_FOR_SAVE,
+ TRUE);
+ g_assert (keyfile != NULL);
+
+ if (settings != NULL)
+ gtk_print_settings_to_key_file (settings, keyfile,
+ TERMINAL_PRINT_SETTINGS_GROUP_NAME);
+
+ /* Some keys are not desirable to persist; remove these.
+ * This list comes from evince.
+ */
+ keyfile_remove_keys (keyfile,
+ TERMINAL_PRINT_SETTINGS_GROUP_NAME,
+ GTK_PRINT_SETTINGS_COLLATE,
+ GTK_PRINT_SETTINGS_NUMBER_UP,
+ GTK_PRINT_SETTINGS_N_COPIES,
+ GTK_PRINT_SETTINGS_OUTPUT_URI,
+ GTK_PRINT_SETTINGS_PAGE_RANGES,
+ GTK_PRINT_SETTINGS_PAGE_SET,
+ GTK_PRINT_SETTINGS_PRINT_PAGES,
+ GTK_PRINT_SETTINGS_REVERSE,
+ GTK_PRINT_SETTINGS_SCALE,
+ NULL);
+
+ if (page_setup != NULL)
+ gtk_page_setup_to_key_file (page_setup, keyfile,
+ TERMINAL_PAGE_SETUP_GROUP_NAME);
+
+ /* Some keys are not desirable to persist; remove these.
+ * This list comes from evince.
+ */
+ keyfile_remove_keys (keyfile,
+ TERMINAL_PAGE_SETUP_GROUP_NAME,
+ "page-setup-orientation",
+ "page-setup-margin-bottom",
+ "page-setup-margin-left",
+ "page-setup-margin-right",
+ "page-setup-margin-top",
+ NULL);
+
+ save_cache_keyfile (keyfile, TERMINAL_PRINT_SETTINGS_FILENAME);
+}
+
+/*
+ * terminal_util_translate_encoding:
+ * @encoding: the encoding name
+ *
+ * Translates old encoding name to the one supported by ICU, or
+ * to %NULL if the encoding is not known to ICU.
+ *
+ * Returns: (transfer none): the translated encoding, or %NULL if
+ * not translation was possible.
+ */
+const char*
+terminal_util_translate_encoding (const char *encoding)
+{
+ if (vte_get_encoding_supported (encoding))
+ return encoding;
+
+ /* ICU knows (or has aliases for) most of the old names, except the following */
+ struct {
+ const char *name;
+ const char *replacement;
+ } translations[] = {
+ { "ARMSCII-8", NULL }, /* apparently not supported by ICU */
+ { "GEORGIAN-PS", NULL }, /* no idea which charset this even is */
+ { "ISO-IR-111", NULL }, /* ISO-IR-111 refers to ECMA-94, but that
+ * standard does not contain cyrillic letters.
+ * ECMA-94 refers to ECMA-113 (ISO-IR-144),
+ * whose assignment differs greatly from ISO-IR-111,
+ * so it cannot be that either.
+ */
+ /* All the MAC_* charsets appear to be unknown to even glib iconv, so
+ * why did we have them in our list in the first place?
+ */
+ { "MAC_DEVANAGARI", NULL }, /* apparently not supported by ICU */
+ { "MAC_FARSI", NULL }, /* apparently not supported by ICU */
+ { "MAC_GREEK", "x-MacGreek" },
+ { "MAC_GUJARATI", NULL }, /* apparently not supported by ICU */
+ { "MAC_GURMUKHI", NULL }, /* apparently not supported by ICU */
+ { "MAC_ICELANDIC", NULL }, /* apparently not supported by ICU */
+ { "MAC_ROMANIAN", "x-macroman" }, /* not sure this is the right one */
+ { "MAC_TURKISH", "x-MacTurkish" },
+ { "MAC_UKRAINIAN", "x-MacUkraine" },
+
+ { "TCVN", NULL }, /* apparently not supported by ICU */
+ { "UHC", "cp949" },
+ { "VISCII", NULL }, /* apparently not supported by ICU */
+
+ /* ISO-2022-* are known to ICU, but they simply cannot work in vte as
+ * I/O encoding, so don't even try.
+ */
+ { "ISO-2022-JP", NULL },
+ { "ISO-2022-KR", NULL },
+ };
+
+ const char *replacement = NULL;
+ for (guint i = 0; i < G_N_ELEMENTS (translations); ++i) {
+ if (g_str_equal (encoding, translations[i].name)) {
+ replacement = translations[i].replacement;
+ break;
+ }
+ }
+
+ return replacement;
+}
+
+/* BEGIN code copied from glib
+ *
+ * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * Code originally under LGPL2+; used and modified here under GPL3+
+ * Changes:
+ * Remove win32 support.
+ * Make @program nullable.
+ * Use @path instead of getenv("PATH").
+ * Use strchrnul
+ */
+
+/**
+ * terminal_util_find_program_in_path:
+ * @path: (type filename) (nullable): the search path (delimited by G_SEARCHPATH_SEPARATOR)
+ * @program: (type filename) (nullable): the programme to find in @path
+ *
+ * Like g_find_program_in_path(), but uses @path instead of the
+ * PATH environment variable as the search path.
+ *
+ * Returns: (type filename) (transfer full) (nullable): a newly allocated
+ * string containing the full path to @program, or %NULL if @program
+ * could not be found in @path.
+ */
+char *
+terminal_util_find_program_in_path (const char *path,
+ const char *program)
+{
+ const gchar *p;
+ gchar *name, *freeme;
+ gsize len;
+ gsize pathlen;
+
+ if (program == NULL)
+ return NULL;
+
+ /* If it is an absolute path, or a relative path including subdirectories,
+ * don't look in PATH.
+ */
+ if (g_path_is_absolute (program)
+ || strchr (program, G_DIR_SEPARATOR) != NULL
+ )
+ {
+ if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) &&
+ !g_file_test (program, G_FILE_TEST_IS_DIR))
+ return g_strdup (program);
+ else
+ return NULL;
+ }
+
+ if (path == NULL)
+ {
+ /* There is no 'PATH' in the environment. The default
+ * search path in GNU libc is the current directory followed by
+ * the path 'confstr' returns for '_CS_PATH'.
+ */
+
+ /* In GLib we put . last, for security, and don't use the
+ * unportable confstr(); UNIX98 does not actually specify
+ * what to search if PATH is unset. POSIX may, dunno.
+ */
+
+ path = "/bin:/usr/bin:.";
+ }
+
+ len = strlen (program) + 1;
+ pathlen = strlen (path);
+ freeme = name = g_malloc (pathlen + len + 1);
+
+ /* Copy the file name at the top, including '\0' */
+ memcpy (name + pathlen + 1, program, len);
+ name = name + pathlen;
+ /* And add the slash before the filename */
+ *name = G_DIR_SEPARATOR;
+
+ p = path;
+ do
+ {
+ char *startp;
+
+ path = p;
+ p = strchrnul (path, G_SEARCHPATH_SEPARATOR);
+
+ if (p == path)
+ /* Two adjacent colons, or a colon at the beginning or the end
+ * of 'PATH' means to search the current directory.
+ */
+ startp = name + 1;
+ else
+ startp = memcpy (name - (p - path), path, p - path);
+
+ if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE) &&
+ !g_file_test (startp, G_FILE_TEST_IS_DIR))
+ {
+ gchar *ret;
+ ret = g_strdup (startp);
+ g_free (freeme);
+ return ret;
+ }
+ }
+ while (*p++ != '\0');
+
+ g_free (freeme);
+ return NULL;
+}
+
+/* END code copied from glib */
+
+/*
+ * terminal_util_check_envv:
+ * @strv:
+ *
+ * Validates that each element is of the form 'KEY=VALUE'.
+ */
+gboolean
+terminal_util_check_envv(char const* const* strv)
+{
+ if (!strv)
+ return TRUE;
+
+ for (int i = 0; strv[i]; ++i) {
+ const char *str = strv[i];
+ const char *equal = strchr(str, '=');
+ if (equal == NULL || equal == str)
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/terminal-util.h b/src/terminal-util.h
new file mode 100644
index 0000000..0f3e6bf
--- /dev/null
+++ b/src/terminal-util.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2008, 2010 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_UTIL_H
+#define TERMINAL_UTIL_H
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void terminal_util_show_error_dialog (GtkWindow *transient_parent,
+ GtkWidget **weap_ptr,
+ GError *error,
+ const char *message_format, ...) G_GNUC_PRINTF(4, 5);
+
+void terminal_util_show_help (const char *topic);
+
+void terminal_util_show_about (void);
+
+void terminal_util_set_labelled_by (GtkWidget *widget,
+ GtkLabel *label);
+void terminal_util_set_atk_name_description (GtkWidget *widget,
+ const char *name,
+ const char *desc);
+
+void terminal_util_open_url (GtkWidget *parent,
+ const char *orig_url,
+ TerminalURLFlavor flavor,
+ guint32 user_time);
+
+void terminal_util_transform_uris_to_quoted_fuse_paths (char **uris);
+
+char *terminal_util_concat_uris (char **uris,
+ gsize *length);
+
+char *terminal_util_get_licence_text (void);
+
+GtkBuilder *terminal_util_load_widgets_resource (const char *path,
+ const char *main_object_name,
+ const char *object_name,
+ ...);
+
+void terminal_util_load_objects_resource (const char *path,
+ const char *object_name,
+ ...);
+
+void terminal_util_dialog_focus_widget (GtkBuilder *builder,
+ const char *widget_name);
+
+gboolean terminal_util_dialog_response_on_delete (GtkWindow *widget);
+
+void terminal_util_add_proxy_env (GHashTable *env_table);
+
+char **terminal_util_get_etc_shells (void);
+
+gboolean terminal_util_get_is_shell (const char *command);
+
+GSettings *terminal_g_settings_new (const char *schema_id,
+ const char *mandatory_key,
+ const GVariantType *mandatory_key_type);
+
+const GdkRGBA *terminal_g_settings_get_rgba (GSettings *settings,
+ const char *key,
+ GdkRGBA *rgba);
+void terminal_g_settings_set_rgba (GSettings *settings,
+ const char *key,
+ const GdkRGBA *rgba);
+
+GdkRGBA *terminal_g_settings_get_rgba_palette (GSettings *settings,
+ const char *key,
+ gsize *n_colors);
+void terminal_g_settings_set_rgba_palette (GSettings *settings,
+ const char *key,
+ const GdkRGBA *colors,
+ gsize n_colors);
+
+void terminal_util_bind_mnemonic_label_sensitivity (GtkWidget *widget);
+
+char *terminal_util_number_info (const char *str);
+
+char *terminal_util_uri_fixup (const char *uri,
+ GError **error);
+
+char *terminal_util_hyperlink_uri_label (const char *str);
+
+void terminal_util_load_print_settings (GtkPrintSettings **settings,
+ GtkPageSetup **page_setup);
+
+void terminal_util_save_print_settings (GtkPrintSettings *settings,
+ GtkPageSetup *page_setup);
+
+const char *terminal_util_translate_encoding (const char *encoding);
+
+char *terminal_util_find_program_in_path (const char *path,
+ const char *program);
+
+gboolean terminal_util_check_envv(char const* const* strv);
+
+G_END_DECLS
+
+#endif /* TERMINAL_UTIL_H */
diff --git a/src/terminal-version.h b/src/terminal-version.h
new file mode 100644
index 0000000..cc336a4
--- /dev/null
+++ b/src/terminal-version.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2009 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__TERMINAL_TERMINAL_H_INSIDE__) && !defined (TERMINAL_COMPILATION)
+#error "Only <terminal/terminal.h> can be included directly."
+#endif
+
+#ifndef TERMINAL_VERSION_H
+#define TERMINAL_VERSION_H
+
+#define TERMINAL_MAJOR_VERSION (3)
+#define TERMINAL_MINOR_VERSION (38)
+#define TERMINAL_MICRO_VERSION (3)
+
+#define TERMINAL_CHECK_VERSION(major,minor,micro) \
+ (TERMINAL_MAJOR_VERSION > (major) || \
+ (TERMINAL_MAJOR_VERSION == (major) && TERMINAL_MINOR_VERSION > (minor)) || \
+ (TERMINAL_MAJOR_VERSION == (major) && TERMINAL_MINOR_VERSION == (minor) && TERMINAL_MICRO_VERSION >= (micro)))
+
+#endif /* !TERMINAL_VERSION_H */
diff --git a/src/terminal-version.h.in b/src/terminal-version.h.in
new file mode 100644
index 0000000..154a3a1
--- /dev/null
+++ b/src/terminal-version.h.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2009 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__TERMINAL_TERMINAL_H_INSIDE__) && !defined (TERMINAL_COMPILATION)
+#error "Only <terminal/terminal.h> can be included directly."
+#endif
+
+#ifndef TERMINAL_VERSION_H
+#define TERMINAL_VERSION_H
+
+#define TERMINAL_MAJOR_VERSION (@TERMINAL_MAJOR_VERSION@)
+#define TERMINAL_MINOR_VERSION (@TERMINAL_MINOR_VERSION@)
+#define TERMINAL_MICRO_VERSION (@TERMINAL_MICRO_VERSION@)
+
+#define TERMINAL_CHECK_VERSION(major,minor,micro) \
+ (TERMINAL_MAJOR_VERSION > (major) || \
+ (TERMINAL_MAJOR_VERSION == (major) && TERMINAL_MINOR_VERSION > (minor)) || \
+ (TERMINAL_MAJOR_VERSION == (major) && TERMINAL_MINOR_VERSION == (minor) && TERMINAL_MICRO_VERSION >= (micro)))
+
+#endif /* !TERMINAL_VERSION_H */
diff --git a/src/terminal-window.c b/src/terminal-window.c
new file mode 100644
index 0000000..8adb134
--- /dev/null
+++ b/src/terminal-window.c
@@ -0,0 +1,3259 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2007, 2008, 2009, 2011, 2017 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+#include <uuid.h>
+
+#include "terminal-app.h"
+#include "terminal-debug.h"
+#include "terminal-enums.h"
+#include "terminal-headerbar.h"
+#include "terminal-icon-button.h"
+#include "terminal-intl.h"
+#include "terminal-mdi-container.h"
+#include "terminal-menu-button.h"
+#include "terminal-notebook.h"
+#include "terminal-schemas.h"
+#include "terminal-screen-container.h"
+#include "terminal-search-popover.h"
+#include "terminal-tab-label.h"
+#include "terminal-util.h"
+#include "terminal-window.h"
+#include "terminal-libgsystem.h"
+
+struct _TerminalWindowPrivate
+{
+ char *uuid;
+
+ GtkClipboard *clipboard;
+
+ TerminalScreenPopupInfo *popup_info;
+
+ GtkWidget *menubar;
+ TerminalMdiContainer *mdi_container;
+ GtkWidget *main_vbox;
+ TerminalScreen *active_screen;
+
+ /* Size of a character cell in pixels */
+ int old_char_width;
+ int old_char_height;
+
+ /* Width and height added to the actual terminal grid by "chrome" inside
+ * what was traditionally the X11 window: menu bar, title bar,
+ * style-provided padding. This must be included when resizing the window
+ * and also included in geometry hints. */
+ int old_chrome_width;
+ int old_chrome_height;
+
+ /* Width and height added to the window by client-side decorations.
+ * This must be included in geometry hints but must not be included when
+ * resizing the window. */
+ int old_csd_width;
+ int old_csd_height;
+
+ /* Width and height of the padding around the geometry widget. */
+ int old_padding_width;
+ int old_padding_height;
+
+ void *old_geometry_widget; /* only used for pointer value as it may be freed */
+
+ GtkWidget *confirm_close_dialog;
+ TerminalSearchPopover *search_popover;
+
+ guint use_default_menubar_visibility : 1;
+
+ guint disposed : 1;
+ guint present_on_insert : 1;
+
+ guint realized : 1;
+};
+
+#define TERMINAL_WINDOW_CSS_NAME "terminal-window"
+
+#define MIN_WIDTH_CHARS 4
+#define MIN_HEIGHT_CHARS 1
+
+#if 1
+/*
+ * We don't want to enable content saving until vte supports it async.
+ * So we disable this code for stable versions.
+ */
+#include "terminal-version.h"
+
+#if (TERMINAL_MINOR_VERSION & 1) != 0
+#define ENABLE_SAVE
+#else
+#undef ENABLE_SAVE
+#endif
+#endif
+
+/* See bug #789356 */
+#define WINDOW_STATE_TILED (GDK_WINDOW_STATE_TILED | \
+ GDK_WINDOW_STATE_LEFT_TILED | \
+ GDK_WINDOW_STATE_RIGHT_TILED | \
+ GDK_WINDOW_STATE_TOP_TILED | \
+ GDK_WINDOW_STATE_BOTTOM_TILED)
+
+static void terminal_window_dispose (GObject *object);
+static void terminal_window_finalize (GObject *object);
+static gboolean terminal_window_state_event (GtkWidget *widget,
+ GdkEventWindowState *event);
+
+static gboolean terminal_window_delete_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data);
+
+static gboolean notebook_button_press_cb (GtkWidget *notebook,
+ GdkEventButton *event,
+ TerminalWindow *window);
+static gboolean notebook_popup_menu_cb (GtkWidget *notebook,
+ TerminalWindow *window);
+static void mdi_screen_switched_cb (TerminalMdiContainer *container,
+ TerminalScreen *old_active_screen,
+ TerminalScreen *screen,
+ TerminalWindow *window);
+static void mdi_screen_added_cb (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ TerminalWindow *window);
+static void mdi_screen_removed_cb (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ TerminalWindow *window);
+static void mdi_screens_reordered_cb (TerminalMdiContainer *container,
+ TerminalWindow *window);
+static void screen_close_request_cb (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ TerminalWindow *window);
+
+/* Menu action callbacks */
+static gboolean find_larger_zoom_factor (double *zoom);
+static gboolean find_smaller_zoom_factor (double *zoom);
+static void terminal_window_update_zoom_sensitivity (TerminalWindow *window);
+static void terminal_window_update_search_sensitivity (TerminalScreen *screen,
+ TerminalWindow *window);
+static void terminal_window_update_paste_sensitivity (TerminalWindow *window);
+
+static void terminal_window_show (GtkWidget *widget);
+
+static gboolean confirm_close_window_or_tab (TerminalWindow *window,
+ TerminalScreen *screen);
+
+G_DEFINE_TYPE (TerminalWindow, terminal_window, GTK_TYPE_APPLICATION_WINDOW)
+
+/* Zoom helpers */
+
+static const double zoom_factors[] = {
+ TERMINAL_SCALE_MINIMUM,
+ TERMINAL_SCALE_XXXXX_SMALL,
+ TERMINAL_SCALE_XXXX_SMALL,
+ TERMINAL_SCALE_XXX_SMALL,
+ PANGO_SCALE_XX_SMALL,
+ PANGO_SCALE_X_SMALL,
+ PANGO_SCALE_SMALL,
+ PANGO_SCALE_MEDIUM,
+ PANGO_SCALE_LARGE,
+ PANGO_SCALE_X_LARGE,
+ PANGO_SCALE_XX_LARGE,
+ TERMINAL_SCALE_XXX_LARGE,
+ TERMINAL_SCALE_XXXX_LARGE,
+ TERMINAL_SCALE_XXXXX_LARGE,
+ TERMINAL_SCALE_MAXIMUM
+};
+
+static gboolean
+find_larger_zoom_factor (double *zoom)
+{
+ double current = *zoom;
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (zoom_factors); ++i)
+ {
+ /* Find a font that's larger than this one */
+ if ((zoom_factors[i] - current) > 1e-6)
+ {
+ *zoom = zoom_factors[i];
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+find_smaller_zoom_factor (double *zoom)
+{
+ double current = *zoom;
+ int i;
+
+ i = (int) G_N_ELEMENTS (zoom_factors) - 1;
+ while (i >= 0)
+ {
+ /* Find a font that's smaller than this one */
+ if ((current - zoom_factors[i]) > 1e-6)
+ {
+ *zoom = zoom_factors[i];
+ return TRUE;
+ }
+
+ --i;
+ }
+
+ return FALSE;
+}
+
+static inline GSimpleAction *
+lookup_action (TerminalWindow *window,
+ const char *name)
+{
+ GAction *action;
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (window), name);
+ g_return_val_if_fail (action != NULL, NULL);
+
+ return G_SIMPLE_ACTION (action);
+}
+
+/* Context menu helpers */
+
+/* We don't want context menus to show accelerators.
+ * Setting the menu's accel group and/or accel path to NULL
+ * unfortunately doesn't hide accelerators; we need to walk
+ * the menu items and remove the accelerators on each,
+ * manually.
+ */
+static void
+popup_menu_remove_accelerators (GtkWidget *menu)
+{
+ gs_free_list GList *menu_items;
+ GList *l;
+
+ menu_items = gtk_container_get_children (GTK_CONTAINER (menu));
+ for (l = menu_items; l != NULL; l = l ->next) {
+ GtkMenuItem *item = (GtkMenuItem*) (l->data);
+ GtkWidget *label, *submenu;
+
+ if (!GTK_IS_MENU_ITEM (item))
+ continue;
+
+ if (GTK_IS_ACCEL_LABEL ((label = gtk_bin_get_child (GTK_BIN (item)))))
+ gtk_accel_label_set_accel (GTK_ACCEL_LABEL (label), 0, 0);
+
+ /* Recurse into submenus */
+ if ((submenu = gtk_menu_item_get_submenu (item)))
+ popup_menu_remove_accelerators (submenu);
+ }
+}
+
+/* Because we're using gtk_menu_attach_to_widget(), the attach
+ * widget holds a strong reference to the menu, causing it not to
+ * be automatically destroyed once popped down. So we need to
+ * detach the menu from the attach widget manually, which will
+ * cause the menu to be destroyed. We cannot do so in the
+ * "deactivate" handler however, since that causes the menu
+ * item activation to be lost. The "selection-done" signal
+ * appears to be the right place.
+ */
+
+static void
+popup_menu_destroy_cb (GtkWidget *menu,
+ gpointer user_data)
+{
+ /* g_printerr ("Menu %p destroyed!\n", menu); */
+}
+
+static void
+popup_menu_selection_done_cb (GtkMenu *menu,
+ gpointer user_data)
+{
+ g_signal_handlers_disconnect_by_func
+ (menu, G_CALLBACK (popup_menu_selection_done_cb), user_data);
+
+ /* g_printerr ("selection-done %p\n", menu); */
+
+ /* This will remove the ref from the attach widget widget, and destroy the menu */
+ if (gtk_menu_get_attach_widget (menu) != NULL)
+ gtk_menu_detach (menu);
+}
+
+static void
+popup_menu_detach_cb (GtkWidget *attach_widget,
+ GtkMenu *menu)
+{
+ gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu));
+}
+
+static GtkWidget *
+context_menu_new (GMenuModel *menu,
+ GtkWidget *widget)
+{
+ GtkWidget *popup_menu;
+
+ popup_menu = gtk_menu_new_from_model (menu);
+ gtk_style_context_add_class (gtk_widget_get_style_context (popup_menu),
+ GTK_STYLE_CLASS_CONTEXT_MENU);
+ gtk_menu_attach_to_widget (GTK_MENU (popup_menu), widget,
+ (GtkMenuDetachFunc)popup_menu_detach_cb);
+
+ popup_menu_remove_accelerators (popup_menu);
+
+ /* Staggered destruction */
+ g_signal_connect (popup_menu, "selection-done",
+ G_CALLBACK (popup_menu_selection_done_cb), widget);
+ g_signal_connect (popup_menu, "destroy",
+ G_CALLBACK (popup_menu_destroy_cb), widget);
+
+ return popup_menu;
+}
+
+/* GAction callbacks */
+
+static void
+action_new_terminal_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalApp *app;
+ TerminalSettingsList *profiles_list;
+ gs_unref_object GSettings *profile = NULL;
+ gboolean can_toggle = FALSE;
+
+ g_assert (TERMINAL_IS_WINDOW (window));
+
+ app = terminal_app_get ();
+
+ const char *mode_str, *uuid_str;
+ g_variant_get (parameter, "(&s&s)", &mode_str, &uuid_str);
+
+ TerminalNewTerminalMode mode;
+ if (g_str_equal (mode_str, "tab"))
+ mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
+ else if (g_str_equal (mode_str, "window"))
+ mode = TERMINAL_NEW_TERMINAL_MODE_WINDOW;
+ else if (g_str_equal (mode_str, "tab-default")) {
+ mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
+ can_toggle = TRUE;
+ } else {
+ mode = g_settings_get_enum (terminal_app_get_global_settings (app),
+ TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY);
+ can_toggle = TRUE;
+ }
+
+ if (can_toggle) {
+ GdkEvent *event = gtk_get_current_event ();
+ if (event != NULL) {
+ GdkModifierType modifiers;
+
+ if ((gdk_event_get_state (event, &modifiers) &&
+ (modifiers & gtk_accelerator_get_default_mod_mask () & GDK_CONTROL_MASK))) {
+ /* Invert */
+ if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
+ mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
+ else
+ mode = TERMINAL_NEW_TERMINAL_MODE_WINDOW;
+ }
+ gdk_event_free (event);
+ }
+ }
+
+ TerminalScreen *parent_screen = priv->active_screen;
+
+ profiles_list = terminal_app_get_profiles_list (app);
+ if (g_str_equal (uuid_str, "current"))
+ profile = terminal_screen_ref_profile (parent_screen);
+ else if (g_str_equal (uuid_str, "default"))
+ profile = terminal_settings_list_ref_default_child (profiles_list);
+ else
+ profile = terminal_settings_list_ref_child (profiles_list, uuid_str);
+
+ if (profile == NULL)
+ return;
+
+ if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
+ window = terminal_window_new (G_APPLICATION (app));
+
+ TerminalScreen *screen = terminal_screen_new (profile,
+ NULL /* title */,
+ 1.0);
+
+ /* Now add the new screen to the window */
+ terminal_window_add_screen (window, screen, -1);
+ terminal_window_switch_screen (window, screen);
+ gtk_widget_grab_focus (GTK_WIDGET (screen));
+
+ /* Start child process, if possible by using the same args as the parent screen */
+ terminal_screen_reexec_from_screen (screen, parent_screen, NULL, NULL);
+
+ if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
+ gtk_window_present (GTK_WINDOW (window));
+}
+
+#ifdef ENABLE_SAVE
+
+static void
+save_contents_dialog_on_response (GtkDialog *dialog, gint response_id, gpointer terminal)
+{
+ GtkWindow *parent;
+ gs_free gchar *filename_uri = NULL;
+ gs_unref_object GFile *file = NULL;
+ GOutputStream *stream;
+ gs_free_error GError *error = NULL;
+
+ if (response_id != GTK_RESPONSE_ACCEPT)
+ {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ return;
+ }
+
+ parent = (GtkWindow*) gtk_widget_get_ancestor (GTK_WIDGET (terminal), GTK_TYPE_WINDOW);
+ filename_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ if (filename_uri == NULL)
+ return;
+
+ file = g_file_new_for_uri (filename_uri);
+ stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error));
+
+ if (stream)
+ {
+ /* XXX
+ * FIXME
+ * This is a sync operation.
+ * Should be replaced with the async version when vte implements that.
+ */
+ vte_terminal_write_contents_sync (terminal, stream,
+ VTE_WRITE_DEFAULT,
+ NULL, &error);
+ g_object_unref (stream);
+ }
+
+ if (error)
+ {
+ terminal_util_show_error_dialog (parent, NULL, error,
+ "%s", _("Could not save contents"));
+ }
+}
+
+static void
+action_save_contents_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ GtkWidget *dialog = NULL;
+ TerminalWindowPrivate *priv = window->priv;
+ VteTerminal *terminal;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ terminal = VTE_TERMINAL (priv->active_screen);
+ g_return_if_fail (VTE_IS_TERMINAL (terminal));
+
+ dialog = gtk_file_chooser_dialog_new (_("Save as…"),
+ GTK_WINDOW(window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (save_contents_dialog_on_response), terminal);
+ g_signal_connect (dialog, "delete_event", G_CALLBACK (terminal_util_dialog_response_on_delete), NULL);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+#endif /* ENABLE_SAVE */
+
+#ifdef ENABLE_PRINT
+
+static void
+print_begin_cb (GtkPrintOperation *op,
+ GtkPrintContext *context,
+ TerminalApp *app)
+{
+ GtkPrintSettings *settings;
+ GtkPageSetup *page_setup;
+
+ /* Don't save if the print dialogue was cancelled */
+ if (gtk_print_operation_get_status(op) == GTK_PRINT_STATUS_FINISHED_ABORTED)
+ return;
+
+ settings = gtk_print_operation_get_print_settings (op);
+ page_setup = gtk_print_operation_get_default_page_setup (op);
+ terminal_util_save_print_settings (settings, page_setup);
+}
+
+static void
+print_done_cb (GtkPrintOperation *op,
+ GtkPrintOperationResult result,
+ TerminalWindow *window)
+{
+ if (result != GTK_PRINT_OPERATION_RESULT_ERROR)
+ return;
+
+ /* FIXME: show error */
+}
+
+static void
+action_print_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ gs_unref_object GtkPrintSettings *settings = NULL;
+ gs_unref_object GtkPageSetup *page_setup = NULL;
+ gs_unref_object GtkPrintOperation *op = NULL;
+ gs_free_error GError *error = NULL;
+ GtkPrintOperationResult result;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ op = vte_print_operation_new (VTE_TERMINAL (priv->active_screen),
+ VTE_PRINT_OPERATION_DEFAULT /* flags */);
+ if (op == NULL)
+ return;
+
+ terminal_util_load_print_settings (&settings, &page_setup);
+ if (settings != NULL)
+ gtk_print_operation_set_print_settings (op, settings);
+ if (page_setup != NULL)
+ gtk_print_operation_set_default_page_setup (op, page_setup);
+
+ g_signal_connect (op, "begin-print", G_CALLBACK (print_begin_cb), window);
+ g_signal_connect (op, "done", G_CALLBACK (print_done_cb), window);
+
+ /* FIXME: show progress better */
+
+ result = gtk_print_operation_run (op,
+ /* this is the only supported one: */
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ GTK_WINDOW (window),
+ &error);
+ /* VtePrintOperation always runs async */
+ g_assert_cmpint (result, ==, GTK_PRINT_OPERATION_RESULT_IN_PROGRESS);
+}
+
+#endif /* ENABLE_PRINT */
+
+#ifdef ENABLE_EXPORT
+
+static void
+action_export_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ gs_unref_object VteExportOperation *op = NULL;
+ gs_free_error GError *error = NULL;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ op = vte_export_operation_new (VTE_TERMINAL (priv->active_screen),
+ TRUE /* interactive */,
+ VTE_EXPORT_FORMAT_ASK /* allow user to choose export format */,
+ NULL, NULL /* GSettings & key to load/store default directory from, FIXME */,
+ NULL, NULL /* progress callback & user data, FIXME */);
+ if (op == NULL)
+ return;
+
+ /* FIXME: show progress better */
+
+ vte_export_operation_run_async (op, GTK_WINDOW (window), NULL /* cancellable */);
+}
+
+#endif /* ENABLE_EXPORT */
+
+static void
+action_close_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreen *screen;
+ const char *mode_str;
+
+ g_assert_nonnull (parameter);
+ g_variant_get (parameter, "&s", &mode_str);
+
+ if (g_str_equal (mode_str, "tab"))
+ screen = priv->active_screen;
+ else if (g_str_equal (mode_str, "window"))
+ screen = NULL;
+ else
+ return;
+
+ if (confirm_close_window_or_tab (window, screen))
+ return;
+
+ if (screen)
+ terminal_window_remove_screen (window, screen);
+ else
+ gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+static void
+action_copy_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ const char *format_str;
+ VteFormat format;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ g_assert_nonnull (parameter);
+ g_variant_get (parameter, "&s", &format_str);
+
+ if (g_str_equal (format_str, "text"))
+ format = VTE_FORMAT_TEXT;
+ else if (g_str_equal (format_str, "html"))
+ format = VTE_FORMAT_HTML;
+ else
+ return;
+
+ vte_terminal_copy_clipboard_format (VTE_TERMINAL (priv->active_screen), format);
+}
+
+/* Clipboard helpers */
+
+typedef struct {
+ GWeakRef screen_weak_ref;
+} PasteData;
+
+static void
+clipboard_uris_received_cb (GtkClipboard *clipboard,
+ /* const */ char **uris,
+ PasteData *data)
+{
+ gs_unref_object TerminalScreen *screen = NULL;
+
+ if (uris != NULL && uris[0] != NULL &&
+ (screen = g_weak_ref_get (&data->screen_weak_ref))) {
+ gs_free char *text;
+ gsize len;
+
+ /* This potentially modifies the strings in |uris| but that's ok */
+ terminal_util_transform_uris_to_quoted_fuse_paths (uris);
+ text = terminal_util_concat_uris (uris, &len);
+
+ vte_terminal_feed_child (VTE_TERMINAL (screen), text, len);
+ }
+
+ g_weak_ref_clear (&data->screen_weak_ref);
+ g_slice_free (PasteData, data);
+}
+
+static void
+request_clipboard_contents_for_paste (TerminalWindow *window,
+ gboolean paste_as_uris)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GdkAtom *targets;
+ int n_targets;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ targets = terminal_app_get_clipboard_targets (terminal_app_get (),
+ priv->clipboard,
+ &n_targets);
+ if (targets == NULL)
+ return;
+
+ if (paste_as_uris && gtk_targets_include_uri (targets, n_targets)) {
+ PasteData *data = g_slice_new (PasteData);
+ g_weak_ref_init (&data->screen_weak_ref, priv->active_screen);
+
+ gtk_clipboard_request_uris (priv->clipboard,
+ (GtkClipboardURIReceivedFunc) clipboard_uris_received_cb,
+ data);
+ return;
+ } else if (gtk_targets_include_text (targets, n_targets)) {
+ vte_terminal_paste_clipboard (VTE_TERMINAL (priv->active_screen));
+ }
+}
+
+static void
+action_paste_text_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ request_clipboard_contents_for_paste (window, FALSE);
+}
+
+static void
+action_paste_uris_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ request_clipboard_contents_for_paste (window, TRUE);
+}
+
+static void
+action_select_all_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_select_all (VTE_TERMINAL (priv->active_screen));
+}
+
+static void
+action_reset_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ g_assert_nonnull (parameter);
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_reset (VTE_TERMINAL (priv->active_screen),
+ TRUE,
+ g_variant_get_boolean (parameter));
+}
+
+static void
+tab_switch_relative (TerminalWindow *window,
+ int change)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ int n_screens, value;
+
+ n_screens = terminal_mdi_container_get_n_screens (priv->mdi_container);
+ value = terminal_mdi_container_get_active_screen_num (priv->mdi_container) + change;
+
+ gboolean keynav_wrap_around;
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+ "gtk-keynav-wrap-around", &keynav_wrap_around,
+ NULL);
+ if (keynav_wrap_around) {
+ if (value < 0)
+ value += n_screens;
+ else if (value >= n_screens)
+ value -= n_screens;
+ }
+
+ if (value < 0 || value >= n_screens)
+ return;
+
+ g_action_change_state (G_ACTION (lookup_action (window, "active-tab")),
+ g_variant_new_int32 (value));
+}
+
+static void
+action_tab_switch_left_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ tab_switch_relative (window, -1);
+}
+
+static void
+action_tab_switch_right_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ tab_switch_relative (window, 1);
+}
+
+static void
+action_tab_move_left_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ int change;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ change = gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL ? 1 : -1;
+ terminal_mdi_container_reorder_screen (priv->mdi_container,
+ terminal_mdi_container_get_active_screen (priv->mdi_container),
+ change);
+}
+
+static void
+action_tab_move_right_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ int change;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ change = gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL ? -1 : 1;
+ terminal_mdi_container_reorder_screen (priv->mdi_container,
+ terminal_mdi_container_get_active_screen (priv->mdi_container),
+ change);
+}
+
+static void
+action_zoom_in_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ double zoom;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ zoom = vte_terminal_get_font_scale (VTE_TERMINAL (priv->active_screen));
+ if (!find_larger_zoom_factor (&zoom))
+ return;
+
+ vte_terminal_set_font_scale (VTE_TERMINAL (priv->active_screen), zoom);
+ terminal_window_update_zoom_sensitivity (window);
+}
+
+static void
+action_zoom_out_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ double zoom;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ zoom = vte_terminal_get_font_scale (VTE_TERMINAL (priv->active_screen));
+ if (!find_smaller_zoom_factor (&zoom))
+ return;
+
+ vte_terminal_set_font_scale (VTE_TERMINAL (priv->active_screen), zoom);
+ terminal_window_update_zoom_sensitivity (window);
+}
+
+static void
+action_zoom_normal_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_set_font_scale (VTE_TERMINAL (priv->active_screen), PANGO_SCALE_MEDIUM);
+ terminal_window_update_zoom_sensitivity (window);
+}
+
+static void
+action_tab_detach_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalApp *app;
+ TerminalWindow *new_window;
+ TerminalScreen *screen;
+ char geometry[32];
+ int width, height;
+
+ app = terminal_app_get ();
+
+ screen = priv->active_screen;
+
+ terminal_screen_get_size (screen, &width, &height);
+ g_snprintf (geometry, sizeof (geometry), "%dx%d", width, height);
+
+ new_window = terminal_window_new (G_APPLICATION (app));
+
+ terminal_window_move_screen (window, new_window, screen, -1);
+
+ terminal_window_parse_geometry (new_window, geometry);
+
+ gtk_window_present_with_time (GTK_WINDOW (new_window), gtk_get_current_event_time ());
+}
+
+static void
+action_help_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ terminal_util_show_help (NULL);
+}
+
+static void
+action_about_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ terminal_util_show_about ();
+}
+
+static void
+action_edit_preferences_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ terminal_app_edit_preferences (terminal_app_get (),
+ terminal_screen_get_profile (priv->active_screen),
+ NULL);
+}
+
+static void
+action_size_to_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ guint width, height;
+
+ g_assert_nonnull (parameter);
+
+ if (priv->active_screen == NULL)
+ return;
+
+ g_variant_get (parameter, "(uu)", &width, &height);
+ if (width < MIN_WIDTH_CHARS || height < MIN_HEIGHT_CHARS ||
+ width > 256 || height > 256)
+ return;
+
+ vte_terminal_set_size (VTE_TERMINAL (priv->active_screen), width, height);
+ terminal_window_update_size (window);
+}
+
+static void
+action_open_match_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->url == NULL)
+ return;
+
+ terminal_util_open_url (GTK_WIDGET (window), info->url, info->url_flavor,
+ gtk_get_current_event_time ());
+}
+
+static void
+action_copy_match_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->url == NULL)
+ return;
+
+ gtk_clipboard_set_text (priv->clipboard, info->url, -1);
+}
+
+static void
+action_open_hyperlink_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->hyperlink == NULL)
+ return;
+
+ terminal_util_open_url (GTK_WIDGET (window), info->hyperlink, FLAVOR_AS_IS,
+ gtk_get_current_event_time ());
+}
+
+static void
+action_copy_hyperlink_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->hyperlink == NULL)
+ return;
+
+ gtk_clipboard_set_text (priv->clipboard, info->hyperlink, -1);
+}
+
+static void
+action_enter_fullscreen_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ g_action_group_change_action_state (G_ACTION_GROUP (window), "fullscreen",
+ g_variant_new_boolean (TRUE));
+}
+
+static void
+action_leave_fullscreen_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ g_action_group_change_action_state (G_ACTION_GROUP (window), "fullscreen",
+ g_variant_new_boolean (FALSE));
+}
+
+static void
+action_inspector_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ gtk_window_set_interactive_debugging (TRUE);
+}
+
+static void
+search_popover_search_cb (TerminalSearchPopover *popover,
+ gboolean backward,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (G_UNLIKELY (priv->active_screen == NULL))
+ return;
+
+ if (backward)
+ vte_terminal_search_find_previous (VTE_TERMINAL (priv->active_screen));
+ else
+ vte_terminal_search_find_next (VTE_TERMINAL (priv->active_screen));
+}
+
+static void
+search_popover_notify_regex_cb (TerminalSearchPopover *popover,
+ GParamSpec *pspec G_GNUC_UNUSED,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ VteRegex *regex;
+
+ if (G_UNLIKELY (priv->active_screen == NULL))
+ return;
+
+ regex = terminal_search_popover_get_regex (popover);
+ vte_terminal_search_set_regex (VTE_TERMINAL (priv->active_screen), regex, 0);
+
+ terminal_window_update_search_sensitivity (priv->active_screen, window);
+}
+
+static void
+search_popover_notify_wrap_around_cb (TerminalSearchPopover *popover,
+ GParamSpec *pspec G_GNUC_UNUSED,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ gboolean wrap;
+
+ if (G_UNLIKELY (priv->active_screen == NULL))
+ return;
+
+ wrap = terminal_search_popover_get_wrap_around (popover);
+ vte_terminal_search_set_wrap_around (VTE_TERMINAL (priv->active_screen), wrap);
+}
+
+static void
+action_find_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (G_UNLIKELY(priv->active_screen == NULL))
+ return;
+
+ if (priv->search_popover != NULL) {
+ search_popover_notify_regex_cb (priv->search_popover, NULL, window);
+ search_popover_notify_wrap_around_cb (priv->search_popover, NULL, window);
+
+ gtk_window_present_with_time (GTK_WINDOW (priv->search_popover),
+ gtk_get_current_event_time ());
+ gtk_widget_grab_focus (GTK_WIDGET (priv->search_popover));
+ return;
+ }
+
+ if (priv->active_screen == NULL)
+ return;
+
+ priv->search_popover = terminal_search_popover_new (GTK_WIDGET (window));
+
+ g_signal_connect (priv->search_popover, "search", G_CALLBACK (search_popover_search_cb), window);
+
+ search_popover_notify_regex_cb (priv->search_popover, NULL, window);
+ g_signal_connect (priv->search_popover, "notify::regex", G_CALLBACK (search_popover_notify_regex_cb), window);
+
+ search_popover_notify_wrap_around_cb (priv->search_popover, NULL, window);
+ g_signal_connect (priv->search_popover, "notify::wrap-around", G_CALLBACK (search_popover_notify_wrap_around_cb), window);
+
+ g_signal_connect (priv->search_popover, "destroy", G_CALLBACK (gtk_widget_destroyed), &priv->search_popover);
+
+ gtk_window_present_with_time (GTK_WINDOW (priv->search_popover), gtk_get_current_event_time ());
+ gtk_widget_grab_focus (GTK_WIDGET (priv->search_popover));
+}
+
+static void
+action_find_forward_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_search_find_next (VTE_TERMINAL (priv->active_screen));
+}
+
+static void
+action_find_backward_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_search_find_previous (VTE_TERMINAL (priv->active_screen));
+}
+
+static void
+action_find_clear_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_search_set_regex (VTE_TERMINAL (priv->active_screen), NULL, 0);
+ vte_terminal_unselect_all (VTE_TERMINAL (priv->active_screen));
+}
+
+static void
+action_shadow_activate_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ gs_free char *param = g_variant_print(parameter, TRUE);
+
+ _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+ "Window %p shadow action activated for %s\n",
+ window, param);
+
+ /* We make sure in terminal-accels to always install the keybinding
+ * for the real action first, so that it's first in line for activation.
+ * That means we can make this here a NOP, instead of forwarding the
+ * activation to the shadowed action.
+ */
+}
+
+static void
+action_menubar_visible_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ gboolean active;
+
+ active = g_variant_get_boolean (state);
+ terminal_window_set_menubar_visible (window, active); /* this also sets the action state */
+}
+
+static void
+action_fullscreen_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (window)))
+ return;
+
+ if (g_variant_get_boolean (state))
+ gtk_window_fullscreen (GTK_WINDOW (window));
+ else
+ gtk_window_unfullscreen (GTK_WINDOW (window));
+
+ /* The window-state-changed callback will update the action's actual state */
+}
+
+static void
+action_read_only_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ g_assert_nonnull (state);
+
+ g_simple_action_set_state (action, state);
+
+ terminal_window_update_paste_sensitivity (window);
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_set_input_enabled (VTE_TERMINAL (priv->active_screen),
+ !g_variant_get_boolean (state));
+}
+
+static void
+action_profile_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalSettingsList *profiles_list;
+ const gchar *uuid;
+ gs_unref_object GSettings *profile;
+
+ g_assert_nonnull (state);
+
+ uuid = g_variant_get_string (state, NULL);
+ profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
+ profile = terminal_settings_list_ref_child (profiles_list, uuid);
+ if (profile == NULL)
+ return;
+
+ g_simple_action_set_state (action, state);
+
+ terminal_screen_set_profile (priv->active_screen, profile);
+}
+
+static void
+action_active_tab_set_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ int value, n_screens;
+
+ g_assert_nonnull (parameter);
+
+ n_screens = terminal_mdi_container_get_n_screens (priv->mdi_container);
+
+ value = g_variant_get_int32 (parameter);
+ if (value < 0)
+ value += n_screens;
+ if (value < 0 || value >= n_screens)
+ return;
+
+ g_action_change_state (G_ACTION (action), g_variant_new_int32 (value));
+}
+
+static void
+action_active_tab_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ g_assert_nonnull (state);
+
+ g_simple_action_set_state (action, state);
+
+ terminal_mdi_container_set_active_screen_num (priv->mdi_container, g_variant_get_int32 (state));
+}
+
+/* Menubar mnemonics & accel settings handling */
+
+static void
+enable_menubar_accel_changed_cb (GSettings *settings,
+ const char *key,
+ GtkSettings *gtk_settings)
+{
+ if (g_settings_get_boolean (settings, key))
+ gtk_settings_reset_property (gtk_settings, "gtk-menu-bar-accel");
+ else
+ g_object_set (gtk_settings, "gtk-menu-bar-accel", NULL, NULL);
+}
+
+/* The menubar is shown by the app, and the use of mnemonics (e.g. Alt+F for File) is toggled.
+ * The mnemonic modifier is per window, so it doesn't affect the Find or Preferences windows.
+ * If the menubar is shown by the shell, a non-mnemonic variant of the menu is loaded instead
+ * in terminal-app.c. See over there for further details. */
+static void
+enable_mnemonics_changed_cb (GSettings *settings,
+ const char *key,
+ TerminalWindow *window)
+{
+ gboolean enabled = g_settings_get_boolean (settings, key);
+
+ if (enabled)
+ gtk_window_set_mnemonic_modifier (GTK_WINDOW (window), GDK_MOD1_MASK);
+ else
+ gtk_window_set_mnemonic_modifier (GTK_WINDOW (window), GDK_MODIFIER_MASK & ~GDK_RELEASE_MASK);
+}
+
+static void
+app_setting_notify_destroy_cb (GtkSettings *gtk_settings)
+{
+ g_signal_handlers_disconnect_by_func (terminal_app_get_global_settings (terminal_app_get ()),
+ G_CALLBACK (enable_menubar_accel_changed_cb),
+ gtk_settings);
+}
+
+/* utility functions */
+
+static int
+find_tab_num_at_pos (GtkNotebook *notebook,
+ int screen_x,
+ int screen_y)
+{
+ GtkPositionType tab_pos;
+ int page_num = 0;
+ GtkNotebook *nb = GTK_NOTEBOOK (notebook);
+ GtkWidget *page;
+ GtkAllocation tab_allocation;
+
+ tab_pos = gtk_notebook_get_tab_pos (GTK_NOTEBOOK (notebook));
+
+ while ((page = gtk_notebook_get_nth_page (nb, page_num)))
+ {
+ GtkWidget *tab;
+ int max_x, max_y, x_root, y_root;
+
+ tab = gtk_notebook_get_tab_label (nb, page);
+ g_return_val_if_fail (tab != NULL, -1);
+
+ if (!gtk_widget_get_mapped (GTK_WIDGET (tab)))
+ {
+ page_num++;
+ continue;
+ }
+
+ gdk_window_get_origin (gtk_widget_get_window (tab), &x_root, &y_root);
+
+ gtk_widget_get_allocation (tab, &tab_allocation);
+ 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) && screen_x <= max_x)
+ return page_num;
+
+ if ((tab_pos == GTK_POS_LEFT || tab_pos == GTK_POS_RIGHT) && screen_y <= max_y)
+ return page_num;
+
+ page_num++;
+ }
+
+ return -1;
+}
+
+static void
+terminal_window_update_set_profile_menu_active_profile (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GSettings *new_active_profile;
+ TerminalSettingsList *profiles_list;
+ char *uuid;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ new_active_profile = terminal_screen_get_profile (priv->active_screen);
+
+ profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
+ uuid = terminal_settings_list_dup_uuid_from_child (profiles_list, new_active_profile);
+
+ g_simple_action_set_state (lookup_action (window, "profile"),
+ g_variant_new_take_string (uuid));
+}
+
+static void
+terminal_window_update_terminal_menu (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ gboolean read_only = !vte_terminal_get_input_enabled (VTE_TERMINAL (priv->active_screen));
+ g_simple_action_set_state (lookup_action (window, "read-only"),
+ g_variant_new_boolean (read_only));
+}
+
+/* Actions stuff */
+
+static void
+terminal_window_update_copy_sensitivity (TerminalScreen *screen,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ gboolean can_copy;
+
+ if (screen != priv->active_screen)
+ return;
+
+ can_copy = vte_terminal_get_has_selection (VTE_TERMINAL (screen));
+ g_simple_action_set_enabled (lookup_action (window, "copy"), can_copy);
+}
+
+static void
+terminal_window_update_zoom_sensitivity (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreen *screen;
+
+ screen = priv->active_screen;
+ if (screen == NULL)
+ return;
+
+ double v;
+ double zoom = v = vte_terminal_get_font_scale (VTE_TERMINAL (screen));
+ g_simple_action_set_enabled (lookup_action (window, "zoom-in"),
+ find_larger_zoom_factor (&v));
+
+ v = zoom;
+ g_simple_action_set_enabled (lookup_action (window, "zoom-out"),
+ find_smaller_zoom_factor (&v));
+}
+
+static void
+terminal_window_update_search_sensitivity (TerminalScreen *screen,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (screen != priv->active_screen)
+ return;
+
+ gboolean can_search = vte_terminal_search_get_regex (VTE_TERMINAL (screen)) != NULL;
+
+ g_simple_action_set_enabled (lookup_action (window, "find-forward"), can_search);
+ g_simple_action_set_enabled (lookup_action (window, "find-backward"), can_search);
+ g_simple_action_set_enabled (lookup_action (window, "find-clear"), can_search);
+}
+
+static void
+clipboard_targets_changed_cb (TerminalApp *app,
+ GtkClipboard *clipboard,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (clipboard != priv->clipboard)
+ return;
+
+ terminal_window_update_paste_sensitivity (window);
+}
+
+static void
+terminal_window_update_paste_sensitivity (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ GdkAtom *targets;
+ int n_targets;
+ targets = terminal_app_get_clipboard_targets (terminal_app_get(), priv->clipboard, &n_targets);
+
+ gboolean can_paste;
+ gboolean can_paste_uris;
+ if (n_targets) {
+ can_paste = gtk_targets_include_text (targets, n_targets);
+ can_paste_uris = gtk_targets_include_uri (targets, n_targets);
+ } else {
+ can_paste = can_paste_uris = FALSE;
+ }
+
+ gs_unref_variant GVariant *ro_state = g_action_get_state (g_action_map_lookup_action (G_ACTION_MAP (window), "read-only"));
+ gboolean read_only = g_variant_get_boolean (ro_state);
+
+ g_simple_action_set_enabled (lookup_action (window, "paste-text"), can_paste && !read_only);
+ g_simple_action_set_enabled (lookup_action (window, "paste-uris"), can_paste_uris && !read_only);
+}
+
+static void
+screen_resize_window_cb (TerminalScreen *screen,
+ guint columns,
+ guint rows,
+ TerminalWindow* window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GtkWidget *widget = GTK_WIDGET (screen);
+
+ if (gtk_widget_get_realized (widget) &&
+ (gdk_window_get_state (gtk_widget_get_window (widget)) & (GDK_WINDOW_STATE_MAXIMIZED |
+ GDK_WINDOW_STATE_FULLSCREEN |
+ WINDOW_STATE_TILED)) != 0)
+ return;
+
+ vte_terminal_set_size (VTE_TERMINAL (priv->active_screen), columns, rows);
+
+ if (screen == priv->active_screen)
+ terminal_window_update_size (window);
+}
+
+static void
+terminal_window_update_tabs_actions_sensitivity (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->disposed)
+ return;
+
+ int num_pages = terminal_mdi_container_get_n_screens (priv->mdi_container);
+ int page_num = terminal_mdi_container_get_active_screen_num (priv->mdi_container);
+
+ gboolean not_only = num_pages > 1;
+ gboolean not_first = page_num > 0;
+ gboolean not_last = page_num + 1 < num_pages;
+
+ gboolean not_first_lr, not_last_lr;
+ if (gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL) {
+ not_first_lr = not_last;
+ not_last_lr = not_first;
+ } else {
+ not_first_lr = not_first;
+ not_last_lr = not_last;
+ }
+
+ /* Hide the tabs menu in single-tab windows */
+ g_simple_action_set_enabled (lookup_action (window, "tabs-menu"), not_only);
+
+ /* Disable shadowing of MDI actions in SDI windows */
+ g_simple_action_set_enabled (lookup_action (window, "shadow-mdi"), not_only);
+
+ /* Disable tab switching (and all its shortcuts) in SDI windows */
+ g_simple_action_set_enabled (lookup_action (window, "active-tab"), not_only);
+
+ /* Set the active tab */
+ g_simple_action_set_state (lookup_action (window, "active-tab"),
+ g_variant_new_int32 (page_num));
+
+ /* Keynav wraps around? See bug #92139 */
+ gboolean keynav_wrap_around;
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+ "gtk-keynav-wrap-around", &keynav_wrap_around,
+ NULL);
+
+ gboolean wrap = keynav_wrap_around && not_only;
+ g_simple_action_set_enabled (lookup_action (window, "tab-switch-left"), not_first || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-switch-right"), not_last || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-move-left"), not_first_lr || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-move-right"), not_last_lr || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-detach"), not_only);
+}
+
+static GtkNotebook *
+handle_tab_droped_on_desktop (GtkNotebook *source_notebook,
+ GtkWidget *container,
+ gint x,
+ gint y,
+ gpointer data G_GNUC_UNUSED)
+{
+ TerminalWindow *source_window;
+ TerminalWindow *new_window;
+ TerminalWindowPrivate *new_priv;
+
+ source_window = TERMINAL_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (source_notebook)));
+ g_return_val_if_fail (TERMINAL_IS_WINDOW (source_window), NULL);
+
+ new_window = terminal_window_new (G_APPLICATION (terminal_app_get ()));
+ new_priv = new_window->priv;
+ new_priv->present_on_insert = TRUE;
+
+ return GTK_NOTEBOOK (new_priv->mdi_container);
+}
+
+/* Terminal screen popup menu handling */
+
+static void
+remove_popup_info (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->popup_info != NULL)
+ {
+ terminal_screen_popup_info_unref (priv->popup_info);
+ priv->popup_info = NULL;
+ }
+}
+
+static void
+screen_popup_menu_selection_done_cb (GtkWidget *popup,
+ GtkWidget *window)
+{
+ g_signal_handlers_disconnect_by_func
+ (popup, G_CALLBACK (screen_popup_menu_selection_done_cb), window);
+
+ GtkWidget *attach_widget = gtk_menu_get_attach_widget (GTK_MENU (popup));
+ if (attach_widget != window || !TERMINAL_IS_WINDOW (attach_widget))
+ return;
+
+ remove_popup_info (TERMINAL_WINDOW (attach_widget));
+}
+
+static void
+screen_show_popup_menu_cb (TerminalScreen *screen,
+ TerminalScreenPopupInfo *info,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalApp *app = terminal_app_get ();
+
+ if (screen != priv->active_screen)
+ return;
+
+ remove_popup_info (window);
+ priv->popup_info = terminal_screen_popup_info_ref (info);
+
+ gs_unref_object GMenu *menu = g_menu_new ();
+
+ /* Hyperlink section */
+ if (info->hyperlink != NULL) {
+ gs_unref_object GMenu *section1 = g_menu_new ();
+
+ g_menu_append (section1, _("Open _Hyperlink"), "win.open-hyperlink");
+ g_menu_append (section1, _("Copy Hyperlink _Address"), "win.copy-hyperlink");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section1));
+ }
+ /* Matched link section */
+ else if (info->url != NULL) {
+ gs_unref_object GMenu *section2 = g_menu_new ();
+
+ const char *open_label = NULL, *copy_label = NULL;
+ switch (info->url_flavor) {
+ case FLAVOR_EMAIL:
+ open_label = _("Send Mail _To…");
+ copy_label = _("Copy Mail _Address");
+ break;
+ case FLAVOR_VOIP_CALL:
+ open_label = _("Call _To…");
+ copy_label = _("Copy Call _Address ");
+ break;
+ case FLAVOR_AS_IS:
+ case FLAVOR_DEFAULT_TO_HTTP:
+ default:
+ open_label = _("_Open Link");
+ copy_label = _("Copy _Link");
+ break;
+ }
+
+ g_menu_append (section2, open_label, "win.open-match");
+ g_menu_append (section2, copy_label, "win.copy-match");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section2));
+ }
+
+ /* Info section */
+ if (info->number_info != NULL) {
+ gs_unref_object GMenu *section3 = g_menu_new ();
+ /* Non-existent action will make this item insensitive */
+ gs_unref_object GMenuItem *item3 = g_menu_item_new (info->number_info, "win.notexist");
+ g_menu_append_item (section3, item3);
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section3));
+ }
+
+ /* Clipboard section */
+ gs_unref_object GMenu *section4 = g_menu_new ();
+
+ g_menu_append (section4, _("_Copy"), "win.copy::text");
+ g_menu_append (section4, _("Copy as _HTML"), "win.copy::html");
+ g_menu_append (section4, _("_Paste"), "win.paste-text");
+ if (g_action_get_enabled (G_ACTION (lookup_action (window, "paste-uris"))))
+ g_menu_append (section4, _("Paste as _Filenames"), "win.paste-uris");
+
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section4));
+
+ /* Profile and property section */
+ gs_unref_object GMenu *section5 = g_menu_new ();
+ g_menu_append (section5, _("Read-_Only"), "win.read-only");
+
+ GMenuModel *profiles_menu = terminal_app_get_profile_section (app);
+ if (profiles_menu != NULL && g_menu_model_get_n_items (profiles_menu) > 1) {
+ gs_unref_object GMenu *submenu5 = g_menu_new ();
+ g_menu_append_section (submenu5, NULL, profiles_menu);
+
+ gs_unref_object GMenuItem *item5 = g_menu_item_new (_("P_rofiles"), NULL);
+ g_menu_item_set_submenu (item5, G_MENU_MODEL (submenu5));
+ g_menu_append_item (section5, item5);
+ }
+
+ g_menu_append (section5, _("_Preferences"), "win.edit-preferences");
+
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section5));
+
+ /* New Terminal section */
+ gs_unref_object GMenu *section6 = g_menu_new ();
+ if (terminal_app_get_menu_unified (app)) {
+ gs_unref_object GMenuItem *item6 = g_menu_item_new (_("New _Terminal"), NULL);
+ g_menu_item_set_action_and_target (item6, "win.new-terminal",
+ "(ss)", "default", "current");
+ g_menu_append_item (section6, item6);
+ } else {
+ gs_unref_object GMenuItem *item61 = g_menu_item_new (_("New _Window"), NULL);
+ g_menu_item_set_action_and_target (item61, "win.new-terminal",
+ "(ss)", "window", "current");
+ g_menu_append_item (section6, item61);
+ gs_unref_object GMenuItem *item62 = g_menu_item_new (_("New _Tab"), NULL);
+ g_menu_item_set_action_and_target (item62, "win.new-terminal",
+ "(ss)", "tab", "current");
+ g_menu_append_item (section6, item62);
+ }
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section6));
+
+ /* Window section */
+ gs_unref_object GMenu *section7 = g_menu_new ();
+
+ /* Only show this if the WM doesn't show the menubar */
+ if (g_action_get_enabled (G_ACTION (lookup_action (window, "menubar-visible"))))
+ g_menu_append (section7, _("Show _Menubar"), "win.menubar-visible");
+ if (g_action_get_enabled (G_ACTION (lookup_action (window, "leave-fullscreen"))))
+ g_menu_append (section7, _("L_eave Full Screen"), "win.leave-fullscreen");
+
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section7));
+
+ /* Now create the popup menu and show it */
+ GtkWidget *popup_menu = context_menu_new (G_MENU_MODEL (menu), GTK_WIDGET (window));
+
+ /* Remove the popup info after the menu is done */
+ g_signal_connect (popup_menu, "selection-done",
+ G_CALLBACK (screen_popup_menu_selection_done_cb), window);
+
+ gtk_menu_popup (GTK_MENU (popup_menu), NULL, NULL,
+ NULL, NULL,
+ info->button,
+ info->timestamp);
+
+ if (info->button == 0)
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (popup_menu), FALSE);
+}
+
+static gboolean
+screen_match_clicked_cb (TerminalScreen *screen,
+ const char *url,
+ int url_flavor,
+ guint state,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (screen != priv->active_screen)
+ return FALSE;
+
+ gtk_widget_grab_focus (GTK_WIDGET (screen));
+ terminal_util_open_url (GTK_WIDGET (window), url, url_flavor,
+ gtk_get_current_event_time ());
+
+ return TRUE;
+}
+
+static void
+screen_close_cb (TerminalScreen *screen,
+ TerminalWindow *window)
+{
+ terminal_window_remove_screen (window, screen);
+}
+
+static void
+notebook_update_tabs_menu_cb (GtkMenuButton *button,
+ TerminalWindow *window)
+{
+ gs_unref_object GMenu *menu;
+ gs_free_list GList *tabs;
+ GList *t;
+ int i;
+
+ menu = g_menu_new ();
+ tabs = terminal_window_list_screen_containers (window);
+
+ for (t = tabs, i = 0; t != NULL; t = t->next, i++) {
+ TerminalScreenContainer *container = t->data;
+ TerminalScreen *screen = terminal_screen_container_get_screen (container);
+ gs_unref_object GMenuItem *item;
+ const char *title;
+
+ if (t->next == NULL) {
+ /* Last entry. If it has no dedicated shortcut "Switch to Tab N",
+ * display the accel of "Switch to Last Tab". */
+ GtkApplication *app = GTK_APPLICATION (g_application_get_default ());
+ gs_free gchar *detailed_action = g_strdup_printf("win.active-tab(%d)", i);
+ gs_strfreev gchar **accels = gtk_application_get_accels_for_action (app, detailed_action);
+ if (accels[0] == NULL)
+ i = -1;
+ }
+
+ title = terminal_screen_get_title (screen);
+
+ item = g_menu_item_new (title && title[0] ? title : _("Terminal"), NULL);
+ g_menu_item_set_action_and_target (item, "win.active-tab", "i", i);
+ g_menu_append_item (menu, item);
+ }
+
+ gtk_menu_button_set_menu_model (button, G_MENU_MODEL (menu));
+
+ /* Need this so the menu is positioned correctly */
+ gtk_widget_set_halign (GTK_WIDGET (gtk_menu_button_get_popup (button)), GTK_ALIGN_END);
+}
+
+static void
+terminal_window_fill_notebook_action_box (TerminalWindow *window,
+ gboolean add_new_tab_button)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GtkWidget *box, *new_tab_button, *tabs_menu_button;
+
+ box = terminal_notebook_get_action_box (TERMINAL_NOTEBOOK (priv->mdi_container), GTK_PACK_END);
+
+ /* Create the NewTerminal button */
+ if (add_new_tab_button)
+ {
+ new_tab_button = terminal_icon_button_new ("tab-new-symbolic");
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (new_tab_button), "win.new-terminal");
+ gtk_actionable_set_action_target (GTK_ACTIONABLE (new_tab_button), "(ss)", "tab", "current");
+ gtk_box_pack_start (GTK_BOX (box), new_tab_button, FALSE, FALSE, 0);
+ gtk_widget_show (new_tab_button);
+ }
+
+ /* Create Tabs menu button */
+ tabs_menu_button = terminal_menu_button_new ();
+ g_signal_connect (tabs_menu_button, "update-menu",
+ G_CALLBACK (notebook_update_tabs_menu_cb), window);
+ gtk_box_pack_start (GTK_BOX (box), tabs_menu_button, FALSE, FALSE, 0);
+ gtk_menu_button_set_align_widget (GTK_MENU_BUTTON (tabs_menu_button), box);
+ gtk_widget_show (tabs_menu_button);
+}
+
+/*****************************************/
+
+#ifdef ENABLE_DEBUG
+static void
+terminal_window_size_request_cb (GtkWidget *widget,
+ GtkRequisition *req)
+{
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] size-request result %d : %d\n",
+ widget, req->width, req->height);
+}
+
+static void
+terminal_window_size_allocate_cb (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] size-alloc result %d : %d at (%d, %d)\n",
+ widget,
+ allocation->width, allocation->height,
+ allocation->x, allocation->y);
+}
+#endif /* ENABLE_DEBUG */
+
+static void
+terminal_window_realize (GtkWidget *widget)
+{
+ TerminalWindow *window = TERMINAL_WINDOW (widget);
+ TerminalWindowPrivate *priv = window->priv;
+ GtkAllocation widget_allocation;
+
+ gtk_widget_get_allocation (widget, &widget_allocation);
+
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] realize, size %d : %d at (%d, %d)\n",
+ widget,
+ widget_allocation.width, widget_allocation.height,
+ widget_allocation.x, widget_allocation.y);
+
+ GTK_WIDGET_CLASS (terminal_window_parent_class)->realize (widget);
+
+ /* Now that we've been realized, we should know precisely how large the
+ * client-side decorations are going to be. Recalculate the geometry hints,
+ * export them to the windowing system, and resize the window accordingly. */
+ priv->realized = TRUE;
+ terminal_window_update_size (window);
+}
+
+static gboolean
+terminal_window_state_event (GtkWidget *widget,
+ GdkEventWindowState *event)
+{
+ gboolean (* window_state_event) (GtkWidget *, GdkEventWindowState *event) =
+ GTK_WIDGET_CLASS (terminal_window_parent_class)->window_state_event;
+
+ if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
+ {
+ TerminalWindow *window = TERMINAL_WINDOW (widget);
+ gboolean is_fullscreen;
+
+ is_fullscreen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
+
+ g_simple_action_set_state (lookup_action (window, "fullscreen"),
+ g_variant_new_boolean (is_fullscreen));
+ g_simple_action_set_enabled (lookup_action (window, "leave-fullscreen"),
+ is_fullscreen);
+ g_simple_action_set_enabled (lookup_action (window, "size-to"),
+ !is_fullscreen);
+ }
+
+ if (window_state_event)
+ return window_state_event (widget, event);
+
+ return FALSE;
+}
+
+static void
+terminal_window_screen_update (TerminalWindow *window,
+ GdkScreen *screen)
+{
+ GSettings *settings;
+ GtkSettings *gtk_settings;
+
+ if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (screen), "GT::HasSettingsConnection")))
+ return;
+
+ settings = terminal_app_get_global_settings (terminal_app_get ());
+ gtk_settings = gtk_settings_get_for_screen (screen);
+
+ g_object_set_data_full (G_OBJECT (screen), "GT::HasSettingsConnection",
+ gtk_settings,
+ (GDestroyNotify) app_setting_notify_destroy_cb);
+
+ g_settings_bind (settings,
+ TERMINAL_SETTING_ENABLE_SHORTCUTS_KEY,
+ gtk_settings,
+ "gtk-enable-accels",
+ G_SETTINGS_BIND_GET);
+
+ enable_menubar_accel_changed_cb (settings,
+ TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY,
+ gtk_settings);
+ g_signal_connect (settings, "changed::" TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY,
+ G_CALLBACK (enable_menubar_accel_changed_cb),
+ gtk_settings);
+}
+
+static void
+terminal_window_screen_changed (GtkWidget *widget,
+ GdkScreen *previous_screen)
+{
+ TerminalWindow *window = TERMINAL_WINDOW (widget);
+ void (* screen_changed) (GtkWidget *, GdkScreen *) =
+ GTK_WIDGET_CLASS (terminal_window_parent_class)->screen_changed;
+ GdkScreen *screen;
+
+ if (screen_changed)
+ screen_changed (widget, previous_screen);
+
+ screen = gtk_widget_get_screen (widget);
+ if (previous_screen == screen)
+ return;
+
+ if (!screen)
+ return;
+
+ terminal_window_screen_update (window, screen);
+}
+
+static void
+terminal_window_init (TerminalWindow *window)
+{
+ const GActionEntry action_entries[] = {
+ /* Actions without state */
+ { "about", action_about_cb, NULL, NULL, NULL },
+ { "close", action_close_cb, "s", NULL, NULL },
+ { "copy", action_copy_cb, "s", NULL, NULL },
+ { "copy-hyperlink", action_copy_hyperlink_cb, NULL, NULL, NULL },
+ { "copy-match", action_copy_match_cb, NULL, NULL, NULL },
+ { "edit-preferences", action_edit_preferences_cb, NULL, NULL, NULL },
+ { "enter-fullscreen", action_enter_fullscreen_cb, NULL, NULL, NULL },
+ { "find", action_find_cb, NULL, NULL, NULL },
+ { "find-backward", action_find_backward_cb, NULL, NULL, NULL },
+ { "find-clear", action_find_clear_cb, NULL, NULL, NULL },
+ { "find-forward", action_find_forward_cb, NULL, NULL, NULL },
+ { "help", action_help_cb, NULL, NULL, NULL },
+ { "inspector", action_inspector_cb, NULL, NULL, NULL },
+ { "leave-fullscreen", action_leave_fullscreen_cb, NULL, NULL, NULL },
+ { "new-terminal", action_new_terminal_cb, "(ss)", NULL, NULL },
+ { "open-match", action_open_match_cb, NULL, NULL, NULL },
+ { "open-hyperlink", action_open_hyperlink_cb, NULL, NULL, NULL },
+ { "paste-text", action_paste_text_cb, NULL, NULL, NULL },
+ { "paste-uris", action_paste_uris_cb, NULL, NULL, NULL },
+ { "reset", action_reset_cb, "b", NULL, NULL },
+ { "select-all", action_select_all_cb, NULL, NULL, NULL },
+ { "size-to", action_size_to_cb, "(uu)", NULL, NULL },
+ { "tab-detach", action_tab_detach_cb, NULL, NULL, NULL },
+ { "tab-move-left", action_tab_move_left_cb, NULL, NULL, NULL },
+ { "tab-move-right", action_tab_move_right_cb, NULL, NULL, NULL },
+ { "tab-switch-left", action_tab_switch_left_cb, NULL, NULL, NULL },
+ { "tab-switch-right", action_tab_switch_right_cb, NULL, NULL, NULL },
+ { "tabs-menu", NULL, NULL, NULL, NULL },
+ { "zoom-in", action_zoom_in_cb, NULL, NULL, NULL },
+ { "zoom-normal", action_zoom_normal_cb, NULL, NULL, NULL },
+ { "zoom-out", action_zoom_out_cb, NULL, NULL, NULL },
+#ifdef ENABLE_EXPORT
+ { "export", action_export_cb, NULL, NULL, NULL },
+#endif
+#ifdef ENABLE_PRINT
+ { "print", action_print_cb, NULL, NULL, NULL },
+#endif
+#ifdef ENABLE_SAVE
+ { "save-contents", action_save_contents_cb, NULL, NULL, NULL },
+#endif
+
+ /* Shadow actions for keybinding comsumption, see comment in terminal-accels.c */
+ { "shadow", action_shadow_activate_cb, "s", NULL, NULL },
+ { "shadow-mdi", action_shadow_activate_cb, "s", NULL, NULL },
+
+ /* Actions with state */
+ { "active-tab", action_active_tab_set_cb, "i", "@i 0", action_active_tab_state_cb },
+ { "header-menu", NULL /* toggles state */, NULL, "false", NULL },
+ { "fullscreen", NULL /* toggles state */, NULL, "false", action_fullscreen_state_cb },
+ { "menubar-visible", NULL /* toggles state */, NULL, "true", action_menubar_visible_state_cb },
+ { "profile", NULL /* changes state */, "s", "''", action_profile_state_cb },
+ { "read-only", NULL /* toggles state */, NULL, "false", action_read_only_state_cb },
+ };
+ TerminalWindowPrivate *priv;
+ TerminalApp *app;
+ GSettings *gtk_debug_settings;
+ GtkWindowGroup *window_group;
+ // GtkAccelGroup *accel_group;
+ uuid_t u;
+ char uuidstr[37], role[64];
+ gboolean shell_shows_menubar;
+ gboolean use_headerbar;
+ GSimpleAction *action;
+
+ app = terminal_app_get ();
+
+ priv = window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, TERMINAL_TYPE_WINDOW, TerminalWindowPrivate);
+
+ gtk_widget_init_template (GTK_WIDGET (window));
+
+ uuid_generate (u);
+ uuid_unparse (u, uuidstr);
+ priv->uuid = g_strdup (uuidstr);
+
+ g_signal_connect (G_OBJECT (window), "delete_event",
+ G_CALLBACK(terminal_window_delete_event),
+ NULL);
+#ifdef ENABLE_DEBUG
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_GEOMETRY)
+ {
+ g_signal_connect_after (window, "size-request", G_CALLBACK (terminal_window_size_request_cb), NULL);
+ g_signal_connect_after (window, "size-allocate", G_CALLBACK (terminal_window_size_allocate_cb), NULL);
+ }
+#endif
+
+ use_headerbar = terminal_app_get_use_headerbar (app);
+ if (use_headerbar) {
+ GtkWidget *headerbar;
+
+ headerbar = terminal_headerbar_new ();
+ gtk_window_set_titlebar (GTK_WINDOW (window), headerbar);
+ }
+
+ gtk_window_set_title (GTK_WINDOW (window), _("Terminal"));
+
+ priv->active_screen = NULL;
+
+ priv->main_vbox = gtk_bin_get_child (GTK_BIN (window));
+
+ priv->mdi_container = TERMINAL_MDI_CONTAINER (terminal_notebook_new ());
+
+ g_signal_connect (priv->mdi_container, "screen-close-request",
+ G_CALLBACK (screen_close_request_cb), window);
+
+ g_signal_connect_after (priv->mdi_container, "screen-switched",
+ G_CALLBACK (mdi_screen_switched_cb), window);
+ g_signal_connect_after (priv->mdi_container, "screen-added",
+ G_CALLBACK (mdi_screen_added_cb), window);
+ g_signal_connect_after (priv->mdi_container, "screen-removed",
+ G_CALLBACK (mdi_screen_removed_cb), window);
+ g_signal_connect_after (priv->mdi_container, "screens-reordered",
+ G_CALLBACK (mdi_screens_reordered_cb), window);
+
+ g_signal_connect_swapped (priv->mdi_container, "notify::tab-pos",
+ G_CALLBACK (terminal_window_update_geometry), window);
+ g_signal_connect_swapped (priv->mdi_container, "notify::show-tabs",
+ G_CALLBACK (terminal_window_update_geometry), window);
+
+ /* FIXME hack hack! */
+ if (GTK_IS_NOTEBOOK (priv->mdi_container)) {
+ g_signal_connect (priv->mdi_container, "button-press-event",
+ G_CALLBACK (notebook_button_press_cb), window);
+ g_signal_connect (priv->mdi_container, "popup-menu",
+ G_CALLBACK (notebook_popup_menu_cb), window);
+ g_signal_connect (priv->mdi_container, "create-window",
+ G_CALLBACK (handle_tab_droped_on_desktop), window);
+ }
+
+ gtk_box_pack_end (GTK_BOX (priv->main_vbox), GTK_WIDGET (priv->mdi_container), TRUE, TRUE, 0);
+ gtk_widget_show (GTK_WIDGET (priv->mdi_container));
+
+ priv->old_char_width = -1;
+ priv->old_char_height = -1;
+
+ priv->old_chrome_width = -1;
+ priv->old_chrome_height = -1;
+ priv->old_csd_width = -1;
+ priv->old_csd_height = -1;
+ priv->old_padding_width = -1;
+ priv->old_padding_height = -1;
+
+ priv->old_geometry_widget = NULL;
+
+ /* GAction setup */
+ g_action_map_add_action_entries (G_ACTION_MAP (window),
+ action_entries, G_N_ELEMENTS (action_entries),
+ window);
+
+ g_simple_action_set_enabled (lookup_action (window, "leave-fullscreen"), FALSE);
+
+ GSettings *global_settings = terminal_app_get_global_settings (app);
+ enable_mnemonics_changed_cb (global_settings, TERMINAL_SETTING_ENABLE_MNEMONICS_KEY, window);
+ g_signal_connect (global_settings, "changed::" TERMINAL_SETTING_ENABLE_MNEMONICS_KEY,
+ G_CALLBACK (enable_mnemonics_changed_cb), window);
+
+ /* Hide "menubar-visible" when the menubar is shown by the shell */
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+ "gtk-shell-shows-menubar", &shell_shows_menubar,
+ NULL);
+ if (shell_shows_menubar) {
+ g_simple_action_set_enabled (lookup_action (window, "menubar-visible"), FALSE);
+ } else {
+ priv->menubar = gtk_menu_bar_new_from_model (terminal_app_get_menubar (app));
+ gtk_box_pack_start (GTK_BOX (priv->main_vbox),
+ priv->menubar,
+ FALSE, FALSE, 0);
+
+ terminal_window_set_menubar_visible (window, !use_headerbar);
+ priv->use_default_menubar_visibility = !use_headerbar;
+ }
+
+ /* Maybe make Inspector available */
+ action = lookup_action (window, "inspector");
+ gtk_debug_settings = terminal_app_get_gtk_debug_settings (app);
+ if (gtk_debug_settings != NULL)
+ g_settings_bind (gtk_debug_settings,
+ "enable-inspector-keybinding",
+ action,
+ "enabled",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
+ else
+ g_simple_action_set_enabled (action, FALSE);
+
+ priv->clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
+ clipboard_targets_changed_cb (app, priv->clipboard, window);
+ g_signal_connect (app, "clipboard-targets-changed",
+ G_CALLBACK (clipboard_targets_changed_cb), window);
+
+ terminal_window_fill_notebook_action_box (window, !use_headerbar);
+
+ /* We have to explicitly call this, since screen-changed is NOT
+ * emitted for the toplevel the first time!
+ */
+ terminal_window_screen_update (window, gtk_widget_get_screen (GTK_WIDGET (window)));
+
+ window_group = gtk_window_group_new ();
+ gtk_window_group_add_window (window_group, GTK_WINDOW (window));
+ g_object_unref (window_group);
+
+ g_snprintf (role, sizeof (role), "gnome-terminal-window-%s", uuidstr);
+ gtk_window_set_role (GTK_WINDOW (window), role);
+}
+
+static void
+terminal_window_style_updated (GtkWidget *widget)
+{
+ TerminalWindow *window = TERMINAL_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (terminal_window_parent_class)->style_updated (widget);
+
+ terminal_window_update_size (window);
+}
+
+static void
+terminal_window_class_init (TerminalWindowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = terminal_window_dispose;
+ object_class->finalize = terminal_window_finalize;
+
+ widget_class->show = terminal_window_show;
+ widget_class->realize = terminal_window_realize;
+ widget_class->window_state_event = terminal_window_state_event;
+ widget_class->screen_changed = terminal_window_screen_changed;
+ widget_class->style_updated = terminal_window_style_updated;
+
+ GtkWindowClass *window_klass;
+ GtkBindingSet *binding_set;
+
+ window_klass = g_type_class_ref (GTK_TYPE_WINDOW);
+ binding_set = gtk_binding_set_by_class (window_klass);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_I, GDK_CONTROL_MASK|GDK_SHIFT_MASK);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_D, GDK_CONTROL_MASK|GDK_SHIFT_MASK);
+ g_type_class_unref (window_klass);
+
+ g_type_class_add_private (object_class, sizeof (TerminalWindowPrivate));
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/terminal/ui/window.ui");
+
+ gtk_widget_class_set_css_name(widget_class, TERMINAL_WINDOW_CSS_NAME);
+}
+
+static void
+terminal_window_dispose (GObject *object)
+{
+ TerminalWindow *window = TERMINAL_WINDOW (object);
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalApp *app = terminal_app_get ();
+
+ if (!priv->disposed) {
+ GSettings *global_settings = terminal_app_get_global_settings (app);
+ g_signal_handlers_disconnect_by_func (global_settings,
+ G_CALLBACK (enable_mnemonics_changed_cb),
+ window);
+ }
+
+ priv->disposed = TRUE;
+
+ if (priv->clipboard != NULL) {
+ g_signal_handlers_disconnect_by_func (app,
+ G_CALLBACK (clipboard_targets_changed_cb),
+ window);
+ priv->clipboard = NULL;
+ }
+
+ remove_popup_info (window);
+
+ if (priv->search_popover != NULL)
+ {
+ g_signal_handlers_disconnect_matched (priv->search_popover, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, window);
+ gtk_widget_destroy (GTK_WIDGET (priv->search_popover));
+ priv->search_popover = NULL;
+ }
+
+ G_OBJECT_CLASS (terminal_window_parent_class)->dispose (object);
+}
+
+static void
+terminal_window_finalize (GObject *object)
+{
+ TerminalWindow *window = TERMINAL_WINDOW (object);
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->confirm_close_dialog)
+ gtk_dialog_response (GTK_DIALOG (priv->confirm_close_dialog),
+ GTK_RESPONSE_DELETE_EVENT);
+
+ g_free (priv->uuid);
+
+ G_OBJECT_CLASS (terminal_window_parent_class)->finalize (object);
+}
+
+static gboolean
+terminal_window_delete_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
+{
+ return confirm_close_window_or_tab (TERMINAL_WINDOW (widget), NULL);
+}
+
+static void
+terminal_window_show (GtkWidget *widget)
+{
+ TerminalWindow *window = TERMINAL_WINDOW (widget);
+ TerminalWindowPrivate *priv = window->priv;
+ GtkAllocation widget_allocation;
+
+ gtk_widget_get_allocation (widget, &widget_allocation);
+
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] show, size %d : %d at (%d, %d)\n",
+ widget,
+ widget_allocation.width, widget_allocation.height,
+ widget_allocation.x, widget_allocation.y);
+
+ /* Because of the unexpected reentrancy caused by adding the tab to the notebook
+ * showing the TerminalWindow, we can get here when the first page has been
+ * added but not yet set current. By setting the page current, we get the
+ * right size when we first show the window */
+ if (GTK_IS_NOTEBOOK (priv->mdi_container) &&
+ gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->mdi_container)) == -1)
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->mdi_container), 0);
+
+ if (priv->active_screen != NULL)
+ {
+ /* At this point, we have our GdkScreen, and hence the right
+ * font size, so we can go ahead and size the window. */
+ terminal_window_update_size (window);
+ }
+
+ GTK_WIDGET_CLASS (terminal_window_parent_class)->show (widget);
+}
+
+TerminalWindow*
+terminal_window_new (GApplication *app)
+{
+ return g_object_new (TERMINAL_TYPE_WINDOW,
+ "application", app,
+ "show-menubar", FALSE,
+ NULL);
+}
+
+static void
+profile_set_cb (TerminalScreen *screen,
+ GSettings *old_profile,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (window)))
+ return;
+
+ if (screen != priv->active_screen)
+ return;
+
+ terminal_window_update_set_profile_menu_active_profile (window);
+}
+
+static void
+sync_screen_title (TerminalScreen *screen,
+ GParamSpec *psepc,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ const char *title;
+
+ if (screen != priv->active_screen)
+ return;
+
+ title = terminal_screen_get_title (screen);
+ gtk_window_set_title (GTK_WINDOW (window),
+ title && title[0] ? title : _("Terminal"));
+}
+
+static void
+screen_font_any_changed_cb (TerminalScreen *screen,
+ GParamSpec *psepc,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (window)))
+ return;
+
+ if (screen != priv->active_screen)
+ return;
+
+ terminal_window_update_size (window);
+}
+
+static void
+screen_hyperlink_hover_uri_changed (TerminalScreen *screen,
+ const char *uri,
+ const GdkRectangle *bbox G_GNUC_UNUSED,
+ TerminalWindow *window G_GNUC_UNUSED)
+{
+ gs_free char *label = NULL;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (screen)))
+ return;
+
+ label = terminal_util_hyperlink_uri_label (uri);
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (screen), label);
+}
+
+/* MDI container callbacks */
+
+static void
+screen_close_request_cb (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ TerminalWindow *window)
+{
+ if (confirm_close_window_or_tab (window, screen))
+ return;
+
+ terminal_window_remove_screen (window, screen);
+}
+
+int
+terminal_window_get_active_screen_num (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ return terminal_mdi_container_get_active_screen_num (priv->mdi_container);
+}
+
+void
+terminal_window_add_screen (TerminalWindow *window,
+ TerminalScreen *screen,
+ int position)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GtkWidget *old_window;
+
+ old_window = gtk_widget_get_toplevel (GTK_WIDGET (screen));
+ if (gtk_widget_is_toplevel (old_window) &&
+ TERMINAL_IS_WINDOW (old_window) &&
+ TERMINAL_WINDOW (old_window)== window)
+ return;
+
+ if (TERMINAL_IS_WINDOW (old_window))
+ terminal_window_remove_screen (TERMINAL_WINDOW (old_window), screen);
+
+ if (position == -1) {
+ GSettings *global_settings = terminal_app_get_global_settings (terminal_app_get ());
+ TerminalNewTabPosition position_pref = g_settings_get_enum (global_settings,
+ TERMINAL_SETTING_NEW_TAB_POSITION_KEY);
+ switch (position_pref) {
+ case TERMINAL_NEW_TAB_POSITION_NEXT:
+ position = terminal_window_get_active_screen_num (window) + 1;
+ break;
+
+ default:
+ case TERMINAL_NEW_TAB_POSITION_LAST:
+ position = -1;
+ break;
+ }
+ }
+
+ terminal_mdi_container_add_screen (priv->mdi_container, screen, position);
+}
+
+void
+terminal_window_remove_screen (TerminalWindow *window,
+ TerminalScreen *screen)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ terminal_mdi_container_remove_screen (priv->mdi_container, screen);
+}
+
+void
+terminal_window_move_screen (TerminalWindow *source_window,
+ TerminalWindow *dest_window,
+ TerminalScreen *screen,
+ int dest_position)
+{
+ TerminalScreenContainer *screen_container;
+
+ g_return_if_fail (TERMINAL_IS_WINDOW (source_window));
+ g_return_if_fail (TERMINAL_IS_WINDOW (dest_window));
+ g_return_if_fail (TERMINAL_IS_SCREEN (screen));
+ g_return_if_fail (gtk_widget_get_toplevel (GTK_WIDGET (screen)) == GTK_WIDGET (source_window));
+ g_return_if_fail (dest_position >= -1);
+
+ screen_container = terminal_screen_container_get_from_screen (screen);
+ g_assert (TERMINAL_IS_SCREEN_CONTAINER (screen_container));
+
+ /* We have to ref the screen container as well as the screen,
+ * because otherwise removing the screen container from the source
+ * window's notebook will cause the container and its containing
+ * screen to be gtk_widget_destroy()ed!
+ */
+ g_object_ref_sink (screen_container);
+ g_object_ref_sink (screen);
+ terminal_window_remove_screen (source_window, screen);
+
+ /* Now we can safely remove the screen from the container and let the container die */
+ gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (GTK_WIDGET (screen))), GTK_WIDGET (screen));
+ g_object_unref (screen_container);
+
+ terminal_window_add_screen (dest_window, screen, dest_position);
+ terminal_mdi_container_set_active_screen (dest_window->priv->mdi_container, screen);
+ g_object_unref (screen);
+}
+
+GList*
+terminal_window_list_screen_containers (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ return terminal_mdi_container_list_screen_containers (priv->mdi_container);
+}
+
+void
+terminal_window_set_menubar_visible (TerminalWindow *window,
+ gboolean setting)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->menubar == NULL)
+ return;
+
+ /* it's been set now, so don't override when adding a screen.
+ * this side effect must happen before we short-circuit below.
+ */
+ priv->use_default_menubar_visibility = FALSE;
+
+ g_simple_action_set_state (lookup_action (window, "menubar-visible"),
+ g_variant_new_boolean (setting));
+
+ g_object_set (priv->menubar, "visible", setting, NULL);
+
+ /* FIXMEchpe: use gtk_widget_get_realized instead? */
+ if (priv->active_screen)
+ {
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] setting size after toggling menubar visibility\n",
+ window);
+
+ terminal_window_update_size (window);
+ }
+}
+
+GtkWidget *
+terminal_window_get_mdi_container (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ g_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
+
+ return GTK_WIDGET (priv->mdi_container);
+}
+
+void
+terminal_window_update_size (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ int grid_width, grid_height;
+ int pixel_width, pixel_height;
+ GdkWindow *gdk_window;
+
+ gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
+
+ if (gdk_window != NULL &&
+ (gdk_window_get_state (gdk_window) &
+ (GDK_WINDOW_STATE_MAXIMIZED | WINDOW_STATE_TILED | GDK_WINDOW_STATE_FULLSCREEN)))
+ {
+ /* Don't adjust the size of maximized or tiled (snapped, half-maximized)
+ * windows: if we do, there will be ugly gaps of up to 1 character cell
+ * around otherwise tiled windows. */
+ return;
+ }
+
+ /* be sure our geometry is up-to-date */
+ terminal_window_update_geometry (window);
+
+ terminal_screen_get_size (priv->active_screen, &grid_width, &grid_height);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] size is %dx%d cells of %dx%d px\n",
+ window, grid_width, grid_height,
+ priv->old_char_width, priv->old_char_height);
+
+ /* the "old" struct members were updated by update_geometry */
+ pixel_width = priv->old_chrome_width + grid_width * priv->old_char_width;
+ pixel_height = priv->old_chrome_height + grid_height * priv->old_char_height;
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] %dx%d + %dx%d = %dx%d\n",
+ window, grid_width * priv->old_char_width,
+ grid_height * priv->old_char_height,
+ priv->old_chrome_width, priv->old_chrome_height,
+ pixel_width, pixel_height);
+
+ gtk_window_resize (GTK_WINDOW (window), pixel_width, pixel_height);
+}
+
+void
+terminal_window_switch_screen (TerminalWindow *window,
+ TerminalScreen *screen)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ terminal_mdi_container_set_active_screen (priv->mdi_container, screen);
+}
+
+TerminalScreen*
+terminal_window_get_active (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ return terminal_mdi_container_get_active_screen (priv->mdi_container);
+}
+
+static void
+notebook_show_context_menu (TerminalWindow *window,
+ GdkEvent *event,
+ guint button,
+ guint32 timestamp)
+{
+ /* Load the UI */
+ gs_unref_object GMenu *menu;
+ terminal_util_load_objects_resource ("/org/gnome/terminal/ui/notebook-menu.ui",
+ "notebook-popup", &menu,
+ NULL);
+
+ GtkWidget *popup_menu = context_menu_new (G_MENU_MODEL (menu), GTK_WIDGET (window));
+
+ gtk_widget_set_halign (popup_menu, GTK_ALIGN_START);
+ gtk_menu_popup (GTK_MENU (popup_menu), NULL, NULL,
+ NULL, NULL,
+ button, timestamp);
+
+ if (button == 0)
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (popup_menu), FALSE);
+}
+
+static gboolean
+notebook_button_press_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ TerminalWindow *window)
+{
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+ int tab_clicked;
+
+ if (event->type != GDK_BUTTON_PRESS ||
+ event->button != GDK_BUTTON_SECONDARY ||
+ (event->state & gtk_accelerator_get_default_mod_mask ()) != 0)
+ return FALSE;
+
+ tab_clicked = find_tab_num_at_pos (notebook, event->x_root, event->y_root);
+ if (tab_clicked < 0)
+ return FALSE;
+
+ /* switch to the page the mouse is over */
+ gtk_notebook_set_current_page (notebook, tab_clicked);
+
+ notebook_show_context_menu (window, (GdkEvent*)event, event->button, event->time);
+ return TRUE;
+}
+
+static gboolean
+notebook_popup_menu_cb (GtkWidget *widget,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GtkWidget *focus_widget;
+
+ focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
+ /* Only respond if the notebook is the actual focus */
+ if (focus_widget != GTK_WIDGET (priv->mdi_container))
+ return FALSE;
+
+ notebook_show_context_menu (window, NULL, 0, gtk_get_current_event_time ());
+ return TRUE;
+}
+
+static void
+mdi_screen_switched_cb (TerminalMdiContainer *container,
+ TerminalScreen *old_active_screen,
+ TerminalScreen *screen,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ int old_grid_width, old_grid_height;
+
+ _terminal_debug_print (TERMINAL_DEBUG_MDI,
+ "[window %p] MDI: screen-switched old %p new %p\n",
+ window, old_active_screen, screen);
+
+ if (priv->disposed)
+ return;
+
+ if (screen == NULL || old_active_screen == screen)
+ return;
+
+ if (priv->search_popover != NULL)
+ gtk_widget_hide (GTK_WIDGET (priv->search_popover));
+
+ _terminal_debug_print (TERMINAL_DEBUG_MDI,
+ "[window %p] MDI: setting active tab to screen %p (old active screen %p)\n",
+ window, screen, priv->active_screen);
+
+ if (old_active_screen != NULL && screen != NULL) {
+ terminal_screen_get_size (old_active_screen, &old_grid_width, &old_grid_height);
+
+ /* This is so that we maintain the same grid */
+ vte_terminal_set_size (VTE_TERMINAL (screen), old_grid_width, old_grid_height);
+ }
+
+ priv->active_screen = screen;
+
+ /* Override menubar setting if it wasn't restored from session */
+ if (priv->use_default_menubar_visibility)
+ {
+ gboolean setting =
+ g_settings_get_boolean (terminal_app_get_global_settings (terminal_app_get ()),
+ TERMINAL_SETTING_DEFAULT_SHOW_MENUBAR_KEY);
+
+ terminal_window_set_menubar_visible (window, setting);
+ }
+
+ sync_screen_title (screen, NULL, window);
+
+ /* set size of window to current grid size */
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] setting size after flipping notebook pages\n",
+ window);
+ terminal_window_update_size (window);
+
+ terminal_window_update_tabs_actions_sensitivity (window);
+ terminal_window_update_terminal_menu (window);
+ terminal_window_update_set_profile_menu_active_profile (window);
+ terminal_window_update_copy_sensitivity (screen, window);
+ terminal_window_update_zoom_sensitivity (window);
+ terminal_window_update_search_sensitivity (screen, window);
+ terminal_window_update_paste_sensitivity (window);
+}
+
+static void
+mdi_screen_added_cb (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ int pages;
+
+ _terminal_debug_print (TERMINAL_DEBUG_MDI,
+ "[window %p] MDI: screen %p inserted\n",
+ window, screen);
+
+ g_signal_connect (G_OBJECT (screen),
+ "profile-set",
+ G_CALLBACK (profile_set_cb),
+ window);
+
+ /* FIXME: only connect on the active screen, not all screens! */
+ g_signal_connect (screen, "notify::title",
+ G_CALLBACK (sync_screen_title), window);
+ g_signal_connect (screen, "notify::font-desc",
+ G_CALLBACK (screen_font_any_changed_cb), window);
+ g_signal_connect (screen, "notify::font-scale",
+ G_CALLBACK (screen_font_any_changed_cb), window);
+ g_signal_connect (screen, "notify::cell-height-scale",
+ G_CALLBACK (screen_font_any_changed_cb), window);
+ g_signal_connect (screen, "notify::cell-width-scale",
+ G_CALLBACK (screen_font_any_changed_cb), window);
+ g_signal_connect (screen, "selection-changed",
+ G_CALLBACK (terminal_window_update_copy_sensitivity), window);
+ g_signal_connect (screen, "hyperlink-hover-uri-changed",
+ G_CALLBACK (screen_hyperlink_hover_uri_changed), window);
+
+ g_signal_connect (screen, "show-popup-menu",
+ G_CALLBACK (screen_show_popup_menu_cb), window);
+ g_signal_connect (screen, "match-clicked",
+ G_CALLBACK (screen_match_clicked_cb), window);
+ g_signal_connect (screen, "resize-window",
+ G_CALLBACK (screen_resize_window_cb), window);
+
+ g_signal_connect (screen, "close-screen",
+ G_CALLBACK (screen_close_cb), window);
+
+ terminal_window_update_tabs_actions_sensitivity (window);
+ terminal_window_update_search_sensitivity (screen, window);
+ terminal_window_update_paste_sensitivity (window);
+
+#if 0
+ /* FIXMEchpe: wtf is this doing? */
+
+ /* If we have an active screen, match its size and zoom */
+ if (priv->active_screen)
+ {
+ int current_width, current_height;
+ double scale;
+
+ terminal_screen_get_size (priv->active_screen, &current_width, &current_height);
+ vte_terminal_set_size (VTE_TERMINAL (screen), current_width, current_height);
+
+ scale = terminal_screen_get_font_scale (priv->active_screen);
+ terminal_screen_set_font_scale (screen, scale);
+ }
+#endif
+
+ if (priv->present_on_insert)
+ {
+ gtk_window_present_with_time (GTK_WINDOW (window), gtk_get_current_event_time ());
+ priv->present_on_insert = FALSE;
+ }
+
+ pages = terminal_mdi_container_get_n_screens (container);
+ if (pages == 2)
+ {
+ terminal_window_update_size (window);
+ }
+}
+
+static void
+mdi_screen_removed_cb (TerminalMdiContainer *container,
+ TerminalScreen *screen,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ int pages;
+
+ if (priv->disposed)
+ return;
+
+ _terminal_debug_print (TERMINAL_DEBUG_MDI,
+ "[window %p] MDI: screen %p removed\n",
+ window, screen);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ G_CALLBACK (profile_set_cb),
+ window);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ G_CALLBACK (sync_screen_title),
+ window);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ G_CALLBACK (screen_font_any_changed_cb),
+ window);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ G_CALLBACK (terminal_window_update_copy_sensitivity),
+ window);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ G_CALLBACK (screen_hyperlink_hover_uri_changed),
+ window);
+
+ g_signal_handlers_disconnect_by_func (screen,
+ G_CALLBACK (screen_show_popup_menu_cb),
+ window);
+
+ g_signal_handlers_disconnect_by_func (screen,
+ G_CALLBACK (screen_match_clicked_cb),
+ window);
+ g_signal_handlers_disconnect_by_func (screen,
+ G_CALLBACK (screen_resize_window_cb),
+ window);
+
+ g_signal_handlers_disconnect_by_func (screen,
+ G_CALLBACK (screen_close_cb),
+ window);
+
+ /* We already got a switch-page signal whose handler sets the active tab to the
+ * new active tab, unless this screen was the only one in the notebook, so
+ * priv->active_tab is valid here.
+ */
+
+ pages = terminal_mdi_container_get_n_screens (container);
+ if (pages == 0)
+ {
+ priv->active_screen = NULL;
+
+ /* That was the last tab in the window; close it. */
+ gtk_widget_destroy (GTK_WIDGET (window));
+ return;
+ }
+
+ terminal_window_update_tabs_actions_sensitivity (window);
+ terminal_window_update_search_sensitivity (screen, window);
+
+ if (pages == 1)
+ {
+ TerminalScreen *active_screen = terminal_mdi_container_get_active_screen (container);
+ gtk_widget_grab_focus (GTK_WIDGET(active_screen)); /* bug 742422 */
+
+ terminal_window_update_size (window);
+ }
+}
+
+static void
+mdi_screens_reordered_cb (TerminalMdiContainer *container,
+ TerminalWindow *window)
+{
+ terminal_window_update_tabs_actions_sensitivity (window);
+}
+
+gboolean
+terminal_window_parse_geometry (TerminalWindow *window,
+ const char *geometry)
+{
+ TerminalWindowPrivate *priv = window->priv;
+
+ /* gtk_window_parse_geometry() needs to have the right base size
+ * and width/height increment to compute the window size from
+ * the geometry.
+ */
+ terminal_window_update_geometry (window);
+
+ if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry))
+ return FALSE;
+
+ /* We won't actually get allocated at the size parsed out of the
+ * geometry until the window is shown. If terminal_window_update_size()
+ * is called between now and then, that could result in us getting
+ * snapped back to the old grid size. So we need to immediately
+ * update the size of the active terminal to grid size from the
+ * geometry.
+ */
+ if (priv->active_screen)
+ {
+ int grid_width, grid_height;
+
+ /* After parse_geometry(), the default size is in units of the
+ * width/height increment, not a pixel size */
+ gtk_window_get_default_size (GTK_WINDOW (window), &grid_width, &grid_height);
+
+ vte_terminal_set_size (VTE_TERMINAL (priv->active_screen),
+ grid_width, grid_height);
+ }
+
+ return TRUE;
+}
+
+void
+terminal_window_update_geometry (TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GtkWidget *widget;
+ GdkGeometry hints;
+ GtkBorder padding;
+ GtkRequisition vbox_request, widget_request;
+ int grid_width, grid_height;
+ int char_width, char_height;
+ int chrome_width, chrome_height;
+ int csd_width = 0, csd_height = 0;
+
+ if (gtk_widget_in_destruction (GTK_WIDGET (window)))
+ return;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ widget = GTK_WIDGET (priv->active_screen);
+
+ /* We set geometry hints from the active term; best thing
+ * I can think of to do. Other option would be to try to
+ * get some kind of union of all hints from all terms in the
+ * window, but that doesn't make too much sense.
+ */
+ terminal_screen_get_cell_size (priv->active_screen, &char_width, &char_height);
+
+ terminal_screen_get_size (priv->active_screen, &grid_width, &grid_height);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "%dx%d cells of %dx%d px = %dx%d px\n",
+ grid_width, grid_height, char_width, char_height,
+ char_width * grid_width, char_height * grid_height);
+
+ gtk_style_context_get_padding(gtk_widget_get_style_context(widget),
+ gtk_widget_get_state_flags(widget),
+ &padding);
+
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "padding = %dx%d px\n",
+ padding.left + padding.right,
+ padding.top + padding.bottom);
+
+ gtk_widget_get_preferred_size (priv->main_vbox, NULL, &vbox_request);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "content area requests %dx%d px\n",
+ vbox_request.width, vbox_request.height);
+
+
+ chrome_width = vbox_request.width - (char_width * grid_width);
+ chrome_height = vbox_request.height - (char_height * grid_height);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "chrome: %dx%d px\n",
+ chrome_width, chrome_height);
+
+ if (priv->realized)
+ {
+ /* Only when having been realize the CSD can be calculated. Do this by
+ * using the actual allocation rather then the preferred size as the
+ * the preferred size takes the natural size of e.g. the title bar into
+ * account which can be far wider then the contents size when using a
+ * very long title */
+ GtkAllocation toplevel_allocation, vbox_allocation;
+
+ gtk_widget_get_allocation (GTK_WIDGET (priv->main_vbox), &vbox_allocation);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "terminal widget allocation %dx%d px\n",
+ vbox_allocation.width, vbox_allocation.height);
+
+ gtk_widget_get_allocation (GTK_WIDGET (window), &toplevel_allocation);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "window allocation %dx%d px\n",
+ toplevel_allocation.width, toplevel_allocation.height);
+
+ csd_width = toplevel_allocation.width - vbox_allocation.width;
+ csd_height = toplevel_allocation.height - vbox_allocation.height;
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "CSDs: %dx%d px\n",
+ csd_width, csd_height);
+ }
+
+ gtk_widget_get_preferred_size (widget, NULL, &widget_request);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "terminal widget requests %dx%d px\n",
+ widget_request.width, widget_request.height);
+
+ if (!priv->realized)
+ {
+ /* Don't actually set the geometry hints until we have been realized,
+ * because we don't know how large the client-side decorations are going
+ * to be. We also avoid setting priv->old_csd_width or
+ * priv->old_csd_height, so that next time through this function we'll
+ * definitely recalculate the hints.
+ *
+ * Similarly, the size request doesn't seem to include the padding
+ * until we've been redrawn at least once. Don't resize the window
+ * until we've done that. */
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "not realized yet\n");
+ }
+ else if (char_width != priv->old_char_width ||
+ char_height != priv->old_char_height ||
+ padding.left + padding.right != priv->old_padding_width ||
+ padding.top + padding.bottom != priv->old_padding_height ||
+ chrome_width != priv->old_chrome_width ||
+ chrome_height != priv->old_chrome_height ||
+ csd_width != priv->old_csd_width ||
+ csd_height != priv->old_csd_height ||
+ widget != (GtkWidget*) priv->old_geometry_widget)
+ {
+ hints.base_width = chrome_width + csd_width;
+ hints.base_height = chrome_height + csd_height;
+
+ hints.width_inc = char_width;
+ hints.height_inc = char_height;
+
+ /* min size is min size of the whole window, remember. */
+ hints.min_width = hints.base_width + hints.width_inc * MIN_WIDTH_CHARS;
+ hints.min_height = hints.base_height + hints.height_inc * MIN_HEIGHT_CHARS;
+
+ gtk_window_set_geometry_hints (GTK_WINDOW (window),
+ NULL,
+ &hints,
+ GDK_HINT_RESIZE_INC |
+ GDK_HINT_MIN_SIZE |
+ GDK_HINT_BASE_SIZE);
+
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] hints: base %dx%d min %dx%d inc %d %d\n",
+ window,
+ hints.base_width,
+ hints.base_height,
+ hints.min_width,
+ hints.min_height,
+ hints.width_inc,
+ hints.height_inc);
+
+ priv->old_csd_width = csd_width;
+ priv->old_csd_height = csd_height;
+ priv->old_geometry_widget = widget;
+ }
+ else
+ {
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "[window %p] hints: increment unchanged, not setting\n",
+ window);
+ }
+
+ /* We need these for the size calculation in terminal_window_update_size()
+ * (at least under GTK >= 3.19), so we set them unconditionally. */
+ priv->old_char_width = char_width;
+ priv->old_char_height = char_height;
+ priv->old_chrome_width = chrome_width;
+ priv->old_chrome_height = chrome_height;
+ priv->old_padding_width = padding.left + padding.right;
+ priv->old_padding_height = padding.top + padding.bottom;
+}
+
+static void
+confirm_close_response_cb (GtkWidget *dialog,
+ int response,
+ TerminalWindow *window)
+{
+ TerminalScreen *screen;
+
+ screen = g_object_get_data (G_OBJECT (dialog), "close-screen");
+
+ gtk_widget_destroy (dialog);
+
+ if (response != GTK_RESPONSE_ACCEPT)
+ return;
+
+ if (screen)
+ terminal_window_remove_screen (window, screen);
+ else
+ gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+/* Returns: TRUE if closing needs to wait until user confirmation;
+ * FALSE if the terminal or window can close immediately.
+ */
+static gboolean
+confirm_close_window_or_tab (TerminalWindow *window,
+ TerminalScreen *screen)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GtkWidget *dialog;
+ gboolean do_confirm;
+ int n_tabs;
+
+ if (priv->confirm_close_dialog)
+ {
+ /* WTF, already have one? It's modal, so how did that happen? */
+ gtk_dialog_response (GTK_DIALOG (priv->confirm_close_dialog),
+ GTK_RESPONSE_DELETE_EVENT);
+ }
+
+ do_confirm = g_settings_get_boolean (terminal_app_get_global_settings (terminal_app_get ()),
+ TERMINAL_SETTING_CONFIRM_CLOSE_KEY);
+ if (!do_confirm)
+ return FALSE;
+
+ if (screen)
+ {
+ do_confirm = terminal_screen_has_foreground_process (screen, NULL, NULL);
+ n_tabs = 1;
+ }
+ else
+ {
+ GList *tabs, *t;
+
+ do_confirm = FALSE;
+
+ tabs = terminal_window_list_screen_containers (window);
+ n_tabs = g_list_length (tabs);
+
+ for (t = tabs; t != NULL; t = t->next)
+ {
+ TerminalScreen *terminal_screen;
+
+ terminal_screen = terminal_screen_container_get_screen (TERMINAL_SCREEN_CONTAINER (t->data));
+ if (terminal_screen_has_foreground_process (terminal_screen, NULL, NULL))
+ {
+ do_confirm = TRUE;
+ break;
+ }
+ }
+ g_list_free (tabs);
+ }
+
+ if (!do_confirm)
+ return FALSE;
+
+ dialog = priv->confirm_close_dialog =
+ gtk_message_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_CANCEL,
+ "%s", n_tabs > 1 ? _("Close this window?") : _("Close this terminal?"));
+
+ if (n_tabs > 1)
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", _("There are still processes running in some terminals in this window. "
+ "Closing the window will kill all of them."));
+ else
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", _("There is still a process running in this terminal. "
+ "Closing the terminal will kill it."));
+
+ gtk_window_set_title (GTK_WINDOW (dialog), "");
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), n_tabs > 1 ? _("C_lose Window") : _("C_lose Terminal"), GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+ g_object_set_data (G_OBJECT (dialog), "close-screen", screen);
+
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (gtk_widget_destroyed), &priv->confirm_close_dialog);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (confirm_close_response_cb), window);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ return TRUE;
+}
+
+void
+terminal_window_request_close (TerminalWindow *window)
+{
+ g_return_if_fail (TERMINAL_IS_WINDOW (window));
+
+ if (confirm_close_window_or_tab (window, NULL))
+ return;
+
+ gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+const char *
+terminal_window_get_uuid (TerminalWindow *window)
+{
+ g_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
+
+ return window->priv->uuid;
+}
diff --git a/src/terminal-window.h b/src/terminal-window.h
new file mode 100644
index 0000000..7691c5a
--- /dev/null
+++ b/src/terminal-window.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2001 Havoc Pennington
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_WINDOW_H
+#define TERMINAL_WINDOW_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_WINDOW (terminal_window_get_type ())
+#define TERMINAL_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_WINDOW, TerminalWindow))
+#define TERMINAL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_WINDOW, TerminalWindowClass))
+#define TERMINAL_IS_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_WINDOW))
+#define TERMINAL_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_WINDOW))
+#define TERMINAL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_WINDOW, TerminalWindowClass))
+
+typedef struct _TerminalWindowClass TerminalWindowClass;
+typedef struct _TerminalWindowPrivate TerminalWindowPrivate;
+
+struct _TerminalWindow
+{
+ GtkApplicationWindow parent_instance;
+
+ TerminalWindowPrivate *priv;
+};
+
+struct _TerminalWindowClass
+{
+ GtkApplicationWindowClass parent_class;
+};
+
+GType terminal_window_get_type (void) G_GNUC_CONST;
+
+TerminalWindow* terminal_window_new (GApplication *app);
+
+GtkUIManager *terminal_window_get_ui_manager (TerminalWindow *window);
+
+int terminal_window_get_active_screen_num (TerminalWindow *window);
+
+void terminal_window_add_screen (TerminalWindow *window,
+ TerminalScreen *screen,
+ int position);
+
+void terminal_window_remove_screen (TerminalWindow *window,
+ TerminalScreen *screen);
+
+void terminal_window_move_screen (TerminalWindow *source_window,
+ TerminalWindow *dest_window,
+ TerminalScreen *screen,
+ int dest_position);
+
+/* Menubar visibility is part of session state, except that
+ * if it isn't restored from session, the window gets the setting
+ * from the profile of the first screen added to the window
+ */
+void terminal_window_set_menubar_visible (TerminalWindow *window,
+ gboolean setting);
+
+void terminal_window_update_size (TerminalWindow *window);
+
+void terminal_window_switch_screen (TerminalWindow *window,
+ TerminalScreen *screen);
+TerminalScreen* terminal_window_get_active (TerminalWindow *window);
+
+GList* terminal_window_list_screen_containers (TerminalWindow *window);
+
+gboolean terminal_window_parse_geometry (TerminalWindow *window,
+ const char *geometry);
+
+void terminal_window_update_geometry (TerminalWindow *window);
+
+GtkWidget* terminal_window_get_mdi_container (TerminalWindow *window);
+
+void terminal_window_request_close (TerminalWindow *window);
+
+const char *terminal_window_get_uuid (TerminalWindow *window);
+
+G_END_DECLS
+
+#endif /* TERMINAL_WINDOW_H */
diff --git a/src/terminal-window.ui b/src/terminal-window.ui
new file mode 100644
index 0000000..b0f63fd
--- /dev/null
+++ b/src/terminal-window.ui
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.10 -->
+ <template class="TerminalWindow" parent="GtkApplicationWindow">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="main_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/terminal.about b/src/terminal.about
new file mode 100644
index 0000000..3b097d5
--- /dev/null
+++ b/src/terminal.about
@@ -0,0 +1,5 @@
+[About]
+Authors=Behdad Esfahbod;Egmont Koblinger;Guilherme de S. Pastore;Havoc Pennington;Christian Persch;Mariano Suárez-Alvarez;
+Contributors=
+;Artists=
+Documenters=GNOME Documentation Team <gnome-doc-list%gnome.org>;
diff --git a/src/terminal.c b/src/terminal.c
new file mode 100644
index 0000000..ad97539
--- /dev/null
+++ b/src/terminal.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright © 2001, 2002 Havoc Pennington
+ * Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2002 Sun Microsystems
+ * Copyright © 2003 Mariano Suarez-Alvarez
+ * Copyright © 2008, 2010, 2011 Christian Persch
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+
+#include "terminal-debug.h"
+#include "terminal-defines.h"
+#include "terminal-i18n.h"
+#include "terminal-options.h"
+#include "terminal-gdbus-generated.h"
+#include "terminal-defines.h"
+#include "terminal-client-utils.h"
+#include "terminal-libgsystem.h"
+
+GS_DEFINE_CLEANUP_FUNCTION0(TerminalOptions*, gs_local_options_free, terminal_options_free)
+#define gs_free_options __attribute__ ((cleanup(gs_local_options_free)))
+
+/* Wait-for-exit helper */
+
+typedef struct {
+ GMainLoop *loop;
+ int status;
+} RunData;
+
+static void
+receiver_child_exited_cb (TerminalReceiver *receiver,
+ int status,
+ RunData *data)
+{
+ data->status = status;
+
+ if (g_main_loop_is_running (data->loop))
+ g_main_loop_quit (data->loop);
+}
+
+static void
+factory_name_owner_notify_cb (TerminalFactory *factory,
+ GParamSpec *pspec,
+ RunData *data)
+{
+ /* Name owner change to NULL can only mean that the server
+ * went away before it could send out our child-exited signal.
+ * Assume the server was killed and thus our child process
+ * too, and return with the corresponding exit code.
+ */
+ if (g_dbus_proxy_get_name_owner(G_DBUS_PROXY (factory)) != NULL)
+ return;
+
+ data->status = W_EXITCODE(0, SIGKILL);
+
+ if (g_main_loop_is_running (data->loop))
+ g_main_loop_quit (data->loop);
+}
+
+static int
+run_receiver (TerminalFactory *factory,
+ TerminalReceiver *receiver)
+{
+ RunData data = { g_main_loop_new (NULL, FALSE), 0 };
+ gulong receiver_exited_id = g_signal_connect (receiver, "child-exited",
+ G_CALLBACK (receiver_child_exited_cb), &data);
+ gulong factory_notify_id = g_signal_connect (factory, "notify::g-name-owner",
+ G_CALLBACK (factory_name_owner_notify_cb), &data);
+ g_main_loop_run (data.loop);
+ g_signal_handler_disconnect (receiver, receiver_exited_id);
+ g_signal_handler_disconnect (factory, factory_notify_id);
+ g_main_loop_unref (data.loop);
+
+ /* Mangle the exit status */
+ int exit_code;
+ if (WIFEXITED (data.status))
+ exit_code = WEXITSTATUS (data.status);
+ else if (WIFSIGNALED (data.status))
+ exit_code = 128 + (int) WTERMSIG (data.status);
+ else if (WCOREDUMP (data.status))
+ exit_code = 127;
+ else
+ exit_code = 127;
+
+ return exit_code;
+}
+
+/* Factory helpers */
+
+static gboolean
+get_factory_exit_status (const char *service_name,
+ const char *message,
+ int *exit_status)
+{
+ gs_free char *pattern = NULL, *number = NULL;
+ gs_unref_regex GRegex *regex = NULL;
+ gs_free_match_info GMatchInfo *match_info = NULL;
+ gint64 v;
+ char *end;
+ GError *err = NULL;
+
+ pattern = g_strdup_printf ("org.freedesktop.DBus.Error.Spawn.ChildExited: Process %s exited with status (\\d+)$",
+ service_name);
+ regex = g_regex_new (pattern, 0, 0, &err);
+ g_assert_no_error (err);
+
+ if (!g_regex_match (regex, message, 0, &match_info))
+ return FALSE;
+
+ number = g_match_info_fetch (match_info, 1);
+ g_assert_nonnull (number);
+
+ errno = 0;
+ v = g_ascii_strtoll (number, &end, 10);
+ if (errno || end == number || *end != '\0' || v < 0 || v > G_MAXINT)
+ return FALSE;
+
+ *exit_status = (int)v;
+ return TRUE;
+}
+
+static gboolean
+handle_factory_error (const char *service_name,
+ GError *error)
+{
+ int exit_status;
+
+ if (!g_dbus_error_is_remote_error (error) ||
+ !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_CHILD_EXITED) ||
+ !get_factory_exit_status (service_name, error->message, &exit_status))
+ return FALSE;
+
+ g_dbus_error_strip_remote_error (error);
+ terminal_printerr ("%s\n\n", error->message);
+
+ switch (exit_status) {
+ case _EXIT_FAILURE_WRONG_ID:
+ terminal_printerr ("You tried to run gnome-terminal-server with elevated privileged. This is not supported.\n");
+ break;
+ case _EXIT_FAILURE_NO_UTF8:
+ terminal_printerr ("The environment that gnome-terminal-server was launched with specified a non-UTF-8 locale. This is not supported.\n");
+ break;
+ case _EXIT_FAILURE_UNSUPPORTED_LOCALE:
+ terminal_printerr ("The environment that gnome-terminal-server was launched with specified an unsupported locale.\n");
+ break;
+ case _EXIT_FAILURE_GTK_INIT:
+ terminal_printerr ("The environment that gnome-terminal-server was launched with most likely contained an incorrect or unset \"DISPLAY\" variable.\n");
+ break;
+ default:
+ break;
+ }
+ terminal_printerr ("See https://wiki.gnome.org/Apps/Terminal/FAQ#Exit_status_%d for more information.\n", exit_status);
+
+ return TRUE;
+}
+
+static gboolean
+handle_create_instance_error (const char *service_name,
+ GError *error)
+{
+ if (handle_factory_error (service_name, error))
+ return TRUE;
+
+ g_dbus_error_strip_remote_error (error);
+ terminal_printerr ("Error creating terminal: %s\n", error->message);
+ return FALSE; /* don't abort */
+}
+
+static gboolean
+handle_create_receiver_proxy_error (const char *service_name,
+ GError *error)
+{
+ if (handle_factory_error (service_name, error))
+ return TRUE;
+
+ g_dbus_error_strip_remote_error (error);
+ terminal_printerr ("Failed to create proxy for terminal: %s\n", error->message);
+ return FALSE; /* don't abort */
+}
+
+static gboolean
+handle_exec_error (const char *service_name,
+ GError *error)
+{
+ if (handle_factory_error (service_name, error))
+ return TRUE;
+
+ g_dbus_error_strip_remote_error (error);
+ terminal_printerr ("Error: %s\n", error->message);
+ return FALSE; /* don't abort */
+}
+
+static gboolean
+factory_proxy_new_for_service_name (const char *service_name,
+ gboolean ping_server,
+ gboolean connect_signals,
+ TerminalFactory **factory_ptr,
+ char **service_name_ptr,
+ GError **error)
+{
+ if (service_name == NULL)
+ service_name = TERMINAL_APPLICATION_ID;
+
+ gs_free_error GError *err = NULL;
+ gs_unref_object TerminalFactory *factory =
+ terminal_factory_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ connect_signals ? 0 : G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ service_name,
+ TERMINAL_FACTORY_OBJECT_PATH,
+ NULL /* cancellable */,
+ &err);
+ if (factory == NULL) {
+ if (!handle_factory_error (service_name, err))
+ terminal_printerr ("Error constructing proxy for %s:%s: %s\n",
+ service_name, TERMINAL_FACTORY_OBJECT_PATH, err->message);
+ g_propagate_error (error, err);
+ err = NULL;
+ return FALSE;
+ }
+
+ if (ping_server) {
+ /* If we try to use the environment specified server, we need to make
+ * sure it actually exists so we can later fall back to the default name.
+ * There doesn't appear to a way to fail proxy creation above if the
+ * unique name doesn't exist; so we do it this way.
+ */
+ gs_unref_variant GVariant *v = g_dbus_proxy_call_sync (G_DBUS_PROXY (factory),
+ "org.freedesktop.DBus.Peer.Ping",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ 1000 /* 1s */,
+ NULL /* cancelleable */,
+ &err);
+ if (v == NULL) {
+ g_propagate_error (error, err);
+ err = NULL;
+ return FALSE;
+ }
+ }
+
+ gs_transfer_out_value (factory_ptr, &factory);
+ *service_name_ptr = g_strdup (service_name);
+ return TRUE;
+}
+
+static gboolean
+factory_proxy_new (TerminalOptions *options,
+ TerminalFactory **factory_ptr,
+ char **service_name_ptr,
+ char **parent_screen_object_path_ptr,
+ GError **error)
+{
+ const char *service_name = options->server_app_id;
+
+ /* If --app-id was specified, or the environment does not specify
+ * the server to use, create the factory proxy from the given (or default)
+ * name, with no fallback.
+ *
+ * If the server specified by the environment doesn't exist, fall back to the
+ * default server, and ignore the environment-specified parent screen.
+ */
+ if (options->server_app_id == NULL &&
+ options->server_unique_name != NULL) {
+ gs_free_error GError *err = NULL;
+ if (factory_proxy_new_for_service_name (options->server_unique_name,
+ TRUE,
+ options->wait,
+ factory_ptr,
+ service_name_ptr,
+ &err)) {
+ *parent_screen_object_path_ptr = g_strdup (options->parent_screen_object_path);
+ return TRUE;
+ }
+
+ terminal_printerr ("Failed to use specified server: %s\n",
+ err->message);
+ terminal_printerr ("Falling back to default server.\n");
+
+ /* Fall back to the default */
+ service_name = NULL;
+ }
+
+ *parent_screen_object_path_ptr = NULL;
+
+ return factory_proxy_new_for_service_name (service_name,
+ FALSE,
+ options->wait,
+ factory_ptr,
+ service_name_ptr,
+ error);
+}
+
+static void
+handle_show_preferences (TerminalOptions *options,
+ const char *service_name)
+{
+ gs_free_error GError *error = NULL;
+ gs_unref_object GDBusConnection *bus = NULL;
+ gs_free char *object_path = NULL;
+ GVariantBuilder builder;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (bus == NULL) {
+ terminal_printerr ("Failed to get session bus: %s\n", error->message);
+ return;
+ }
+
+ /* For reasons (!?), the org.gtk.Actions interface's object path
+ * is derived from the service name, i.e. for service name
+ * "foo.bar.baz" the object path is "/foo/bar/baz".
+ * This means that without the name (like when given only the unique name),
+ * we cannot activate the action.
+ */
+ if (g_dbus_is_unique_name(service_name)) {
+ terminal_printerr ("Cannot call this function from within gnome-terminal.\n");
+ return;
+ }
+
+ object_path = g_strdelimit (g_strdup_printf (".%s", service_name), ".", '/');
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sava{sv})"));
+ g_variant_builder_add (&builder, "s", "preferences");
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("av"));
+ g_variant_builder_close (&builder);
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (options->startup_id)
+ g_variant_builder_add (&builder, "{sv}",
+ "desktop-startup-id", g_variant_new_string (options->startup_id));
+ g_variant_builder_close (&builder);
+
+ if (!g_dbus_connection_call_sync (bus,
+ service_name,
+ object_path,
+ "org.gtk.Actions",
+ "Activate",
+ g_variant_builder_end (&builder),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ 30 * 1000 /* ms timeout */,
+ NULL /* cancelleable */,
+ &error)) {
+ terminal_printerr ("Activate call failed: %s\n", error->message);
+ return;
+ }
+}
+
+/**
+ * handle_options:
+ * @app:
+ * @options: a #TerminalOptions
+ * @allow_resume: whether to merge the terminal configuration from the
+ * saved session on resume
+ * @wait_for_receiver: location to store the #TerminalReceiver to wait for
+ *
+ * Processes @options. It loads or saves the terminal configuration, or
+ * opens the specified windows and tabs.
+ *
+ * Returns: %TRUE if @options could be successfully handled, or %FALSE on
+ * error
+ */
+static gboolean
+handle_options (TerminalOptions *options,
+ TerminalFactory *factory,
+ const char *service_name,
+ const char *parent_screen_object_path,
+ TerminalReceiver **wait_for_receiver)
+{
+ /* We need to forward the locale encoding to the server, see bug #732128 */
+ const char *encoding;
+ g_get_charset (&encoding);
+
+ if (options->show_preferences) {
+ handle_show_preferences (options, service_name);
+ } else {
+ /* Make sure we open at least one window */
+ terminal_options_ensure_window (options);
+ }
+
+ const char *factory_unique_name = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (factory));
+
+ for (GList *lw = options->initial_windows; lw != NULL; lw = lw->next)
+ {
+ InitialWindow *iw = lw->data;
+
+ g_assert_nonnull (iw);
+
+ guint window_id = 0;
+
+ gs_free char *previous_screen_object_path = NULL;
+ if (iw->implicit_first_window)
+ previous_screen_object_path = g_strdup (parent_screen_object_path);
+
+ /* Now add the tabs */
+ for (GList *lt = iw->tabs; lt != NULL; lt = lt->next)
+ {
+ InitialTab *it = lt->data;
+ g_assert_nonnull (it);
+
+ GVariantBuilder builder;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ terminal_client_append_create_instance_options (&builder,
+ options->display_name,
+ options->startup_id,
+ iw->geometry,
+ iw->role,
+ it->profile ? it->profile : options->default_profile,
+ encoding,
+ it->title ? it->title : options->default_title,
+ it->active,
+ iw->start_maximized,
+ iw->start_fullscreen);
+
+ /* This will be used to apply missing defaults */
+ if (parent_screen_object_path != NULL)
+ g_variant_builder_add (&builder, "{sv}",
+ "parent-screen", g_variant_new_object_path (parent_screen_object_path));
+
+ /* This will be used to get the parent window */
+ if (previous_screen_object_path)
+ g_variant_builder_add (&builder, "{sv}",
+ "window-from-screen", g_variant_new_object_path (previous_screen_object_path));
+ if (window_id)
+ g_variant_builder_add (&builder, "{sv}",
+ "window-id", g_variant_new_uint32 (window_id));
+ /* Restored windows shouldn't demand attention; see bug #586308. */
+ if (iw->source_tag == SOURCE_SESSION)
+ g_variant_builder_add (&builder, "{sv}",
+ "present-window", g_variant_new_boolean (FALSE));
+ if (options->zoom_set || it->zoom_set)
+ g_variant_builder_add (&builder, "{sv}",
+ "zoom", g_variant_new_double (it->zoom_set ? it->zoom : options->zoom));
+ if (iw->force_menubar_state)
+ g_variant_builder_add (&builder, "{sv}",
+ "show-menubar", g_variant_new_boolean (iw->menubar_state));
+
+ gs_free_error GError *err = NULL;
+ gs_free char *object_path = NULL;
+ if (!terminal_factory_call_create_instance_sync
+ (factory,
+ g_variant_builder_end (&builder),
+ &object_path,
+ NULL /* cancellable */,
+ &err)) {
+ if (handle_create_instance_error (service_name, err))
+ return FALSE;
+ else
+ continue; /* Continue processing the remaining options! */
+ }
+
+ /* Deprecated and not working on new server anymore */
+ char *p = strstr (object_path, "/window/");
+ if (p) {
+ char *end = NULL;
+ guint64 value;
+
+ errno = 0;
+ p += strlen ("/window/");
+ value = g_ascii_strtoull (p, &end, 10);
+ if (errno == 0 && end != p && *end == '/')
+ window_id = (guint) value;
+ }
+
+ g_free (previous_screen_object_path);
+ previous_screen_object_path = g_strdup (object_path);
+
+ gs_unref_object TerminalReceiver *receiver =
+ terminal_receiver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ (it->wait ? 0 : G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS),
+ factory_unique_name,
+ object_path,
+ NULL /* cancellable */,
+ &err);
+ if (receiver == NULL) {
+ if (handle_create_receiver_proxy_error (service_name, err))
+ return FALSE;
+ else
+ continue; /* Continue processing the remaining options! */
+ }
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ char **argv = it->exec_argv ? it->exec_argv : options->exec_argv;
+ int argc = argv ? g_strv_length (argv) : 0;
+
+ PassFdElement *fd_array = it->fd_array ? (PassFdElement*)it->fd_array->data : NULL;
+ gsize fd_array_len = it->fd_array ? it->fd_array->len : 0;
+
+ terminal_client_append_exec_options (&builder,
+ !options->no_environment,
+ it->working_dir ? it->working_dir
+ : options->default_working_dir,
+ fd_array, fd_array_len,
+ argc == 0);
+
+ if (!terminal_receiver_call_exec_sync (receiver,
+ g_variant_builder_end (&builder),
+ g_variant_new_bytestring_array ((const char * const *) argv, argc),
+ it->fd_list, NULL /* outfdlist */,
+ NULL /* cancellable */,
+ &err)) {
+ if (handle_exec_error (service_name, err))
+ return FALSE;
+ else
+ continue; /* Continue processing the remaining options! */
+ }
+
+ if (it->wait)
+ gs_transfer_out_value (wait_for_receiver, &receiver);
+
+ if (options->print_environment)
+ g_print ("%s=%s\n", TERMINAL_ENV_SCREEN, object_path);
+ }
+ }
+
+ return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+ int exit_code = EXIT_FAILURE;
+
+ g_log_set_writer_func (terminal_log_writer, NULL, NULL);
+
+ g_set_prgname ("gnome-terminal");
+
+ setlocale (LC_ALL, "");
+
+ terminal_i18n_init (TRUE);
+
+ _terminal_debug_init ();
+
+ gs_free_error GError *error = NULL;
+ gs_free_options TerminalOptions *options = terminal_options_parse (&argc, &argv, &error);
+ if (options == NULL) {
+ terminal_printerr (_("Failed to parse arguments: %s\n"), error->message);
+ return exit_code;
+ }
+
+ g_set_application_name (_("Terminal"));
+
+ gs_unref_object TerminalFactory *factory = NULL;
+ gs_free char *service_name = NULL;
+ gs_free char *parent_screen_object_path = NULL;
+ if (!factory_proxy_new (options,
+ &factory,
+ &service_name,
+ &parent_screen_object_path,
+ &error))
+ return exit_code;
+
+ if (options->print_environment) {
+ const char *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (factory));
+ if (name_owner != NULL)
+ g_print ("%s=%s\n", TERMINAL_ENV_SERVICE_NAME, name_owner);
+ else
+ return exit_code;
+ }
+
+ TerminalReceiver *receiver = NULL;
+ if (!handle_options (options, factory, service_name, parent_screen_object_path, &receiver))
+ return exit_code;
+
+ if (receiver != NULL) {
+ exit_code = run_receiver (factory, receiver);
+ g_object_unref (receiver);
+ } else
+ exit_code = EXIT_SUCCESS;
+
+ return exit_code;
+}
diff --git a/src/terminal.common.css b/src/terminal.common.css
new file mode 100644
index 0000000..4c57726
--- /dev/null
+++ b/src/terminal.common.css
@@ -0,0 +1,22 @@
+/* Generic theme-independent CSS file */
+
+terminal-window scrolledwindow undershoot.top,
+terminal-window scrolledwindow undershoot.bottom,
+terminal-window scrolledwindow overshoot.top,
+terminal-window scrolledwindow overshoot.bottom
+{
+ background: none;
+}
+
+popover button.model
+{
+ padding-left: 16px;
+ padding-right: 16px;
+}
+
+.disclosure-button
+{
+ padding-left: 4px;
+ padding-right: 4px;
+ min-width: 0;
+}
diff --git a/src/terminal.gresource.xml b/src/terminal.gresource.xml
new file mode 100644
index 0000000..8fd5040
--- /dev/null
+++ b/src/terminal.gresource.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2012 Christian Persch
+
+ 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 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope conf it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<gresources>
+ <gresource prefix="/org/gnome/terminal">
+ <file alias="css/terminal.css" compressed="true">terminal.common.css</file>
+ <file alias="ui/headerbar.ui" compressed="true" preprocess="xml-stripblanks">terminal-headerbar.ui</file>
+ <file alias="ui/headerbar-menu.ui" compressed="true" preprocess="xml-stripblanks">terminal-headermenu.ui</file>
+ <file alias="ui/menubar-with-mnemonics.ui" compressed="true" preprocess="xml-stripblanks">terminal-menubar-with-mnemonics.ui</file>
+ <file alias="ui/menubar-without-mnemonics.ui" compressed="true" preprocess="xml-stripblanks">terminal-menubar-without-mnemonics.ui</file>
+ <file alias="ui/notebook-menu.ui" compressed="true" preprocess="xml-stripblanks">terminal-notebook-menu.ui</file>
+ <file alias="ui/preferences.ui" compressed="true" preprocess="xml-stripblanks">preferences.ui</file>
+ <file alias="ui/search-popover.ui" compressed="true" preprocess="xml-stripblanks">search-popover.ui</file>
+ <file alias="ui/terminal.about" compressed="true">terminal.about</file>
+ <file alias="ui/window.ui" compressed="true" preprocess="xml-stripblanks">terminal-window.ui</file>
+ </gresource>
+</gresources>