[vte] vteapp: Reimplement vteapp in vala



commit fd128d70048c566442aa90cca58a9bf1e0960103
Author: Christian Persch <chpe gnome org>
Date:   Mon Apr 14 18:58:02 2014 +0200

    vteapp: Reimplement vteapp in vala

 configure.ac          |   46 ++-
 src/Makefile.am       |   91 +++--
 src/app.gresource.xml |   22 +
 src/app.ui            |   91 ++++
 src/app.vala          |  823 ++++++++++++++++++++++++++++++++++
 src/config.vapi       |    5 +
 src/pty.c             |    4 +-
 src/vte.c             |    2 +-
 src/vteapp.c          | 1181 -------------------------------------------------
 9 files changed, 1043 insertions(+), 1222 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 87b0c97..a28abe2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -188,8 +188,8 @@ case $host in
        ;;
 esac
 
-GLIB_REQUIRED=2.31.13
-GIO_REQUIRED=2.31.13
+GLIB_REQUIRED=2.40.0
+GIO_REQUIRED=2.40.0
 PANGO_REQUIRED=1.22.0
 AC_DEFINE(GDK_MULTIHEAD_SAFE,1,[Force use of GDK multihead-safe APIs.])
 PKG_CHECK_MODULES(GLIB,[glib-2.0 >= $GLIB_REQUIRED gobject-2.0 gio-2.0 >= $GIO_REQUIRED])
@@ -198,12 +198,6 @@ PKG_CHECK_MODULES(GTK,[glib-2.0 >= $GLIB_REQUIRED gobject-2.0 gio-2.0 >= $GIO_RE
 AC_PATH_PROG([GLIB_GENMARSHAL],[glib-genmarshal])
 AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums])
 
-AC_ARG_VAR([GLIB_COMPILE_RESOURCES],[the glib-compile-resources programme])
-AC_PATH_PROG([GLIB_COMPILE_RESOURCES],[glib-compile-resources],[])
-if test -z "$GLIB_COMPILE_RESOURCES"; then
-  AC_MSG_ERROR([glib-compile-resources not found])
-fi
-
 VTE_DEFAULT_EMULATION=xterm
 AC_DEFINE_UNQUOTED(VTE_DEFAULT_EMULATION,"$VTE_DEFAULT_EMULATION",[The default terminal type to be 
emulated.])
 
@@ -355,7 +349,40 @@ if test -z "$enable_vala"; then
   enable_vala=no
 fi
 
-VAPIGEN_CHECK([0.16])
+VAPIGEN_CHECK([0.18])
+
+# ****************
+# Test Application
+# ****************
+
+AC_MSG_CHECKING([whether to build the test application])
+AC_ARG_ENABLE([test-application],
+        [AS_HELP_STRING([--disable-test-application],[Disable test application])],
+        [],[enable_test_application=$enable_vala])
+AC_MSG_RESULT([$enable_test_application])
+
+AM_PROG_VALAC([0.18.0],[],[
+  if test "$enable_test_application" != "no"; then
+    AC_MSG_ERROR([vala support enabled by vala compiler not found])
+  fi])
+
+AM_CONDITIONAL([ENABLE_TEST_APPLICATION],[test "$enable_test_application" = "yes"])
+
+# ***************
+# Auxiliary tools
+# ***************
+
+AC_ARG_VAR([GLIB_COMPILE_RESOURCES],[the glib-compile-resources programme])
+AC_PATH_PROG([GLIB_COMPILE_RESOURCES],[glib-compile-resources],[])
+if test -z "$GLIB_COMPILE_RESOURCES"; then
+  AC_MSG_ERROR([glib-compile-resources not found])
+fi
+
+AC_ARG_VAR([XMLLINT],[the xmllint programme])
+AC_PATH_PROG([XMLLINT],[xmllint],[])
+if test -z "$XMLLINT"; then
+  AC_MSG_ERROR([xmllint not found])
+fi
 
 ################################################################################
 
@@ -410,4 +437,5 @@ Configuration for libvte $VERSION for gtk+-$GTK_API_VERSION
        Debugging: $enable_debug
        Introspection: $enable_introspection
         Vala bindings: $enable_vala
+        Test application: $enable_test_application
 EOF
diff --git a/src/Makefile.am b/src/Makefile.am
index 05c54b2..9484374 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,7 @@
 
 EXTRA_DIST = iso2022.txt
 
+noinst_PROGRAMS =
 
 # The library
 
@@ -150,29 +151,6 @@ vteseq-list.h: vteseq-2.gperf vteseq-n.gperf
 vteresources.c: vte.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies 
vte.gresource.xml)
        $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target $@ --sourcedir . --generate --c-name vte $<
 
-# vte the application
-
-bin_PROGRAMS = vte- VTE_API_MAJOR_VERSION@  VTE_API_MINOR_VERSION@
-
-vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_SOURCES = \
-       vteapp.c \
-       debug.c \
-       debug.h \
-       $(NULL)
-
-vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_CPPFLAGS = \
-        -DGLIB_DISABLE_DEPRECATION_WARNINGS \
-        -DGDK_DISABLE_DEPRECATION_WARNINGS \
-       $(AM_CPPFLAGS)
-
-vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_CFLAGS = \
-       $(VTE_CFLAGS) \
-       $(AM_CFLAGS)
-
-vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_LDADD = \
-       libvte-$(VTE_API_VERSION).la \
-       $(VTE_LIBS)
-
 # introspection
 
 INTROSPECTION_GIRS =
@@ -210,18 +188,18 @@ CLEANFILES += $(nodist_gir_DATA) $(nodist_typelib_DATA)
 if ENABLE_VAPIGEN
 include $(VAPIGEN_MAKEFILE)
 
-VAPIGEN_VAPIS = Vte-$(VTE_API_VERSION).vapi
+VAPIGEN_VAPIS = vte-$(VTE_API_VERSION).vapi
 
-Vte- VTE_API_VERSION@.vapi: Vte-$(VTE_API_VERSION).gir
-Vte_ VTE_API_VERSION_U@_vapi_DEPS = \
+vte- VTE_API_VERSION@.vapi: Vte-$(VTE_API_VERSION).gir
+vte_ VTE_API_VERSION_U@_vapi_DEPS = \
        glib-2.0 \
        gio-2.0 \
        pango \
        gdk-$(GTK_API_VERSION) \
        gtk+-$(GTK_API_VERSION) \
        $(NULL)
-Vte_ VTE_API_VERSION_U@_vapi_METADATADIRS = $(srcdir)
-Vte_ VTE_API_VERSION_U@_vapi_FILES = Vte-$(VTE_API_VERSION).gir
+vte_ VTE_API_VERSION_U@_vapi_METADATADIRS = $(srcdir)
+vte_ VTE_API_VERSION_U@_vapi_FILES = Vte-$(VTE_API_VERSION).gir
 
 vapidir = $(datadir)/vala/vapi
 nodist_vapi_DATA = $(VAPIGEN_VAPIS)
@@ -232,9 +210,64 @@ endif # ENABLE_VAPIGEN
 
 endif # HAVE_INTROSPECTION
 
+# Test application
+
+if ENABLE_TEST_APPLICATION
+
+bin_PROGRAMS = vte- VTE_API_MAJOR_VERSION@  VTE_API_MINOR_VERSION@
+
+vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_SOURCES = \
+       app.vala \
+       config.vapi \
+       $(NULL)
+
+nodist_vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_SOURCES = \
+       appresources.c \
+       $(NULL)
+
+vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_VALAFLAGS = \
+       --vapidir=. \
+       --girdir=. \
+       --pkg=posix \
+       --pkg=linux \
+       --pkg=gio-2.0 \
+       --pkg=gtk+-$(GTK_API_VERSION) \
+       --pkg=vte-$(VTE_API_VERSION) \
+       $(NULL)
+
+vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_CPPFLAGS = \
+       $(AM_CPPFLAGS) \
+       $(NULL)
+
+vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_CFLAGS = \
+       -Wno-unused-variable \
+       -Wno-unused-but-set-variable \
+       $(VTE_CFLAGS) \
+       $(AM_CFLAGS) \
+       $(NULL)
+
+vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       $(NULL)
+
+vte_ VTE_API_MAJOR_VERSION@_ VTE_API_MINOR_VERSION@_LDADD = \
+       libvte-$(VTE_API_VERSION).la \
+       $(VTE_LIBS) \
+       $(NULL)
+
+EXTRA_DIST += \
+        app.gresource.xml \
+       app.ui \
+       $(NULL)
+
+appresources.c: app.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies 
--sourcedir $(srcdir) $(srcdir)/app.gresource.xml)
+       $(AM_V_GEN) XMLLINT=$(XMLLINT) $(GLIB_COMPILE_RESOURCES) --target $@ --sourcedir $(srcdir) --generate 
--c-name app $<
+
+endif # ENABLE_TEST_APPLICATION
+
 # Misc unit tests and utilities
 
-noinst_PROGRAMS = interpret slowcat
+noinst_PROGRAMS += interpret slowcat
 noinst_SCRIPTS = decset osc window
 EXTRA_DIST += $(noinst_SCRIPTS)
 
diff --git a/src/app.gresource.xml b/src/app.gresource.xml
new file mode 100644
index 0000000..5c1d086
--- /dev/null
+++ b/src/app.gresource.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright © 2014 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 2, 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/vte/test/app">
+    <file alias="ui/window.ui" compressed="true" preprocess="xml-stripblanks">app.ui</file>
+  </gresource>
+</gresources>
diff --git a/src/app.ui b/src/app.ui
new file mode 100644
index 0000000..ac7752e
--- /dev/null
+++ b/src/app.ui
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.16.0 on Sun Apr 13 22:39:56 2014 -->
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <object class="GtkBox" id="main-box">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkToolbar" id="toolbar">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkToolButton" id="copy-toolbutton">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="tooltip_text" translatable="yes">Copy</property>
+            <property name="action_name">win.copy</property>
+            <property name="label" translatable="yes">Copy</property>
+            <property name="icon_name">edit-copy</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="homogeneous">False</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkToolButton" id="paste-toolbutton">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="tooltip_text" translatable="yes">Paste</property>
+            <property name="action_name">win.paste</property>
+            <property name="label" translatable="yes">Paste</property>
+            <property name="icon_name">edit-paste</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="homogeneous">False</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkToolButton" id="reset-toolbutton">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="tooltip_text" translatable="yes">Reset (use Ctrl to reset and clear)</property>
+            <property name="action_name">win.reset</property>
+            <property name="label" translatable="yes">Reset</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="homogeneous">False</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="GtkBox" id="terminal-box">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkScrollbar" id="scrollbar">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="restrict_to_fill_level">False</property>
+            <property name="fill_level">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>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/src/app.vala b/src/app.vala
new file mode 100644
index 0000000..d6764f5
--- /dev/null
+++ b/src/app.vala
@@ -0,0 +1,823 @@
+/*
+ * Copyright © 2001,2002 Red Hat, Inc.
+ * Copyright © 2014 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Test
+{
+
+class Window : Gtk.ApplicationWindow
+{
+       private Vte.Terminal terminal;
+       private Gtk.Scrollbar scrollbar;
+       private Gtk.Clipboard clipboard;
+       private GLib.Pid child_pid;
+
+       private string[] builtin_dingus = {
+               
"(((gopher|news|telnet|nntp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?",
+               
"(((gopher|news|telnet|nntp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\)
 ,\\\"]"
+       };
+
+    private const GLib.ActionEntry[] action_entries = {
+        { "copy",        action_copy_cb            },
+        { "copy-match",  action_copy_match_cb, "s" },
+        { "paste",       action_paste_cb           },
+        { "reset",       action_reset_cb           }
+    };
+
+       public Window(App app)
+       {
+               Object(application: app);
+
+        add_action_entries (action_entries, this);
+
+               /* set_resize_mode(Gtk.ResizeMode.IMMEDIATE); */
+
+               clipboard = get_clipboard(Gdk.SELECTION_CLIPBOARD);
+               clipboard.owner_change.connect(clipboard_owner_change_cb);
+
+               title = "Terminal";
+
+               /* Set ARGB visual */
+               if (!App.Options.no_argb_visual) {
+                       var screen = get_screen();
+                       Gdk.Visual? visual = screen.get_rgba_visual();
+                       if (visual != null)
+                               set_visual(visual);
+               }
+
+               var ui = new Gtk.Builder.from_resource("/org/gnome/vte/test/app/ui/window.ui");
+               add(ui.get_object("main-box") as Gtk.Widget);
+
+               var box = ui.get_object("terminal-box") as Gtk.Box;
+
+               if (App.Options.no_toolbar) {
+                       var toolbar = ui.get_object("toolbar") as Gtk.Widget;
+                       toolbar.hide();
+               }
+                       
+               terminal = new Vte.Terminal();
+
+               /* Connect scrollbar */
+               scrollbar = ui.get_object("scrollbar") as Gtk.Scrollbar;
+               scrollbar.set_adjustment(terminal.get_vadjustment());
+
+               /* Signals */
+               terminal.button_press_event.connect(button_press_event_cb);
+               terminal.char_size_changed.connect(char_size_changed_cb);
+               terminal.child_exited.connect(child_exited_cb);
+               terminal.decrease_font_size.connect(decrease_font_size_cb);
+               terminal.deiconify_window.connect(deiconify_window_cb);
+               terminal.icon_title_changed.connect(icon_title_changed_cb);
+               terminal.iconify_window.connect(iconify_window_cb);
+               terminal.increase_font_size.connect(increase_font_size_cb);
+               terminal.lower_window.connect(lower_window_cb);
+               terminal.maximize_window.connect(maximize_window_cb);
+               terminal.move_window.connect(move_window_cb);
+               terminal.raise_window.connect(raise_window_cb);
+               terminal.realize.connect(realize_cb);
+               terminal.refresh_window.connect(refresh_window_cb);
+               terminal.resize_window.connect(resize_window_cb);
+               terminal.restore_window.connect(restore_window_cb);
+               terminal.selection_changed.connect(selection_changed_cb);
+               terminal.status_line_changed.connect(status_line_changed_cb);
+               terminal.window_title_changed.connect(window_title_changed_cb);
+               if (App.Options.object_notifications)
+                       terminal.notify.connect(notify_cb);
+
+               /* Settings */
+               if (App.Options.no_double_buffer)
+                       terminal.set_double_buffered(true);
+
+               if (App.Options.termcap != null)
+                       terminal.set_emulation(App.Options.termcap);
+               if (App.Options.encoding != null)
+                       terminal.set_encoding(App.Options.encoding);
+
+               terminal.set_audible_bell(App.Options.audible);
+               terminal.set_cjk_ambiguous_width(App.Options.get_cjk_ambiguous_width());
+               terminal.set_cursor_blink_mode(App.Options.get_cursor_blink_mode());
+               terminal.set_cursor_shape(App.Options.get_cursor_shape());
+               terminal.set_mouse_autohide(true);
+               terminal.set_rewrap_on_resize(!App.Options.no_rewrap);
+               terminal.set_scroll_on_output(false);
+               terminal.set_scroll_on_keystroke(true);
+               terminal.set_scrollback_lines(App.Options.scrollback_lines);
+               terminal.set_visible_bell(!App.Options.audible);
+
+               /* Style */
+               if (App.Options.font_string != null) {
+                       var desc = Pango.FontDescription.from_string(App.Options.font_string);
+                       terminal.set_font(desc);
+               }
+
+               terminal.set_colors_rgba(App.Options.get_color_fg(),
+                                                                App.Options.get_color_bg(),
+                                                                null);
+               terminal.set_color_cursor_rgba(App.Options.get_color_cursor());
+               terminal.set_color_highlight_rgba(App.Options.get_color_hl_bg());
+               terminal.set_color_highlight_foreground_rgba(App.Options.get_color_hl_fg());
+
+               /* Dingus */
+               if (!App.Options.no_builtin_dingus)
+                       add_dingus(builtin_dingus);
+               if (App.Options.dingus != null)
+                       add_dingus(App.Options.dingus);
+
+               /* Done! */
+               box.pack_start(terminal);
+               terminal.show();
+
+               update_paste_sensitivity();
+               update_copy_sensitivity();
+
+               terminal.grab_focus();
+
+               assert(!get_realized());
+       }
+
+       private void add_dingus(string[] dingus)
+       {
+               const Gdk.CursorType cursors[] = { Gdk.CursorType.GUMBY, Gdk.CursorType.HAND1 };
+
+               for (int i = 0; i < dingus.length; ++i) {
+                       try {
+                               GLib.Regex regex;
+                               int tag;
+
+                               regex = new GLib.Regex(dingus[i], GLib.RegexCompileFlags.OPTIMIZE, 0);
+                               tag = terminal.match_add_gregex(regex, 0);
+                               terminal.match_set_cursor_type(tag, cursors[i % cursors.length]);
+                       } catch (Error e) {
+                               printerr("Failed to compile regex \"%s\": %s\n", dingus[i], e.message);
+                       }
+               }
+       }
+
+       private void adjust_font_size(double factor)
+       {
+               var columns = terminal.get_column_count();
+               var rows = terminal.get_row_count();
+
+               terminal.set_font_scale(terminal.get_font_scale() * factor);
+
+               update_geometry();
+               resize_to_geometry((int)columns, (int)rows);
+       }
+
+       public void apply_geometry()
+       {
+               /* The terminal needs to be realized first, so that when parsing the
+                * geometry, the right geometry hints are already in place.
+                */
+               terminal.realize();
+
+               if (App.Options.geometry != null) {
+                       if (parse_geometry(App.Options.geometry)) {
+                               /* After parse_geometry(), we can get the default size in
+                                * width/height increments, i.e. in grid size.
+                                */
+                               int columns, rows;
+                               get_default_size(out columns, out rows);
+                               terminal.set_size(columns, rows);
+                               resize_to_geometry(columns, rows);
+                       } else
+                               printerr("Failed to parse geometry spec \"%s\"\n", App.Options.geometry);
+               } else {
+                       /* In GTK+ 3.0, the default size of a window comes from its minimum
+                        * size not its natural size, so we need to set the right default size
+                        * explicitly */
+                       set_default_geometry((int)terminal.get_column_count(),
+                                                                (int)terminal.get_row_count());
+               }
+       }
+
+       private void launch_command(string command) throws Error
+       {
+               string[] argv;
+
+               Shell.parse_argv(command, out argv);
+               terminal.spawn_sync(App.Options.get_pty_flags(),
+                                                       App.Options.working_directory,
+                                                       argv,
+                                                       App.Options.environment,
+                                                       GLib.SpawnFlags.SEARCH_PATH,
+                                                       null, /* child setup */
+                                                       out child_pid,
+                                                       null /* cancellable */);
+               print("Fork succeeded, PID %d\n", child_pid);
+       }
+
+       private void launch_shell() throws Error
+       {
+               string? shell;
+
+               shell = Vte.get_user_shell();
+               if (shell == null || shell[0] == '\0')
+                       shell = Environment.get_variable("SHELL");
+               if (shell == null || shell[0] == '\0')
+                       shell = "/bin/sh";
+
+               launch_command(shell);
+       }
+
+       private void fork() throws Error
+       {
+               Vte.Pty pty;
+               Posix.pid_t pid;
+
+               pty = new Vte.Pty.sync(App.Options.get_pty_flags(), null);
+
+               pid = Posix.fork();
+
+               switch (pid) {
+               case -1: /* error */
+                       printerr("Error forking: %m");
+                       break;
+               case 0: /* child */ {
+                       pty.child_setup();
+
+                       for (int i = 0; ; i++) {
+                               switch (i % 3) {
+                               case 0:
+                               case 1:
+                                       print("%d\n", i);
+                                       break;
+                               case 2:
+                                       printerr("%d\n", i);
+                                       break;
+                               }
+                               Posix.sleep(1);
+                       }
+                       Posix._exit(0);
+                       break;
+               }
+               default: /* parent */
+                       terminal.set_pty(pty);
+                       terminal.watch_child(pid);
+                       print("Child PID is %d (mine is %d).\n", (int)pid, (int)Posix.getpid());
+                       break;
+               }
+       }
+
+       public void launch()
+       {
+               try {
+                       if (App.Options.command != null)
+                               launch_command(App.Options.command);
+                       else if (!App.Options.no_shell)
+                               launch_shell();
+                       else
+                               fork();
+               } catch (Error e) {
+                       printerr("Error: %s\n", e.message);
+               }
+       }
+
+       private void update_copy_sensitivity()
+       {
+               var action = lookup_action("copy") as GLib.SimpleAction;
+               action.set_enabled(terminal.get_has_selection());
+       }
+
+       private void update_paste_sensitivity()
+       {
+               Gdk.Atom[] targets;
+               bool can_paste;
+
+               if (clipboard.wait_for_targets(out targets))
+                       can_paste = Gtk.targets_include_text(targets);
+               else
+                       can_paste = false;
+
+               var action = lookup_action("paste") as GLib.SimpleAction;
+               action.set_enabled(can_paste);
+       }
+
+       private void update_geometry()
+       {
+               if (App.Options.no_geometry_hints)
+                       return;
+               if (!terminal.get_realized())
+                       return;
+
+               terminal.set_geometry_hints_for_window(this);
+       }
+
+       /* Callbacks */
+
+       private void action_copy_cb()
+       {
+               terminal.copy_clipboard();
+       }
+
+       private void action_copy_match_cb(GLib.SimpleAction action, GLib.Variant? parameter)
+       {
+               size_t len;
+               unowned string str = parameter.get_string(out len);
+               clipboard.set_text(str, (int)len);
+       }
+
+       private void action_paste_cb()
+       {
+               terminal.paste_clipboard();
+       }
+
+       private void action_reset_cb()
+       {
+               bool clear;
+               Gdk.ModifierType modifiers;
+
+               if (Gtk.get_current_event_state(out modifiers))
+                       clear = (modifiers & Gdk.ModifierType.CONTROL_MASK) != 0;
+               else
+                       clear = false;
+
+               terminal.reset(true, clear);
+       }
+
+       private bool button_press_event_cb(Gtk.Widget widget, Gdk.EventButton event)
+       {
+               if (event.button != 3)
+                       return false;
+               if (App.Options.no_context_menu)
+                       return false;
+
+               var padding = get_style_context().get_padding(get_state_flags());
+        var char_width = terminal.get_char_width();
+        var char_height = terminal.get_char_height();
+               var match = terminal.match_check(((int)event.x - padding.left) / (int)char_width,
+                                                                                ((int)event.y - padding.top) 
/ (int)char_height,
+                                                                                null);
+
+               var menu = new GLib.Menu();
+               menu.append("_Copy", "win.copy");
+               if (match != null)
+                       menu.append("Copy _Match", "win.copy-match::" + match);
+
+               menu.append("_Paste", "win.paste");
+
+               var popup = new Gtk.Menu.from_model(menu);
+               popup.attach_to_widget(this, null);
+               popup.popup(null, null, null, event.button, event.time);
+
+               return false;
+       }
+
+       private void char_size_changed_cb(Vte.Terminal terminal, uint width, uint height)
+       {
+               update_geometry();
+       }
+
+       private void child_exited_cb(Vte.Terminal terminal, int status)
+       {
+               printerr("Child exited with status %x\n", status);
+
+               if (App.Options.output_filename != null) {
+                       try {
+                               var file = GLib.File.new_for_commandline_arg(App.Options.output_filename);
+                               var stream = file.replace(null, false, GLib.FileCreateFlags.NONE, null);
+                               terminal.write_contents(stream, Vte.WriteFlags.DEFAULT, null);
+                       } catch (Error e) {
+                               printerr("Failed to write output to \"%s\": %s\n",
+                                                App.Options.output_filename, e.message);
+                       }
+               }
+
+               if (App.Options.keep)
+                       return;
+
+               destroy();
+       }
+
+       private void clipboard_owner_change_cb(Gtk.Clipboard clipboard, Gdk.Event event)
+       {
+               update_paste_sensitivity();
+       }
+
+       private void decrease_font_size_cb(Vte.Terminal terminal)
+       {
+               adjust_font_size(1.0 / 1.2);
+       }
+
+       public void deiconify_window_cb(Vte.Terminal terminal)
+       {
+               deiconify();
+       }
+
+       private void icon_title_changed_cb(Vte.Terminal terminal)
+       {
+               get_window().set_icon_name(terminal.get_icon_title());
+       }
+
+       private void iconify_window_cb(Vte.Terminal terminal)
+       {
+               iconify();
+       }
+
+       private void increase_font_size_cb(Vte.Terminal terminal)
+       {
+               adjust_font_size(1.2);
+       }
+
+       private void lower_window_cb(Vte.Terminal terminal)
+       {
+               if (!get_realized())
+                       return;
+
+               get_window().lower();
+       }
+
+       private void maximize_window_cb(Vte.Terminal terminal)
+       {
+               maximize();
+       }
+
+       private void move_window_cb(Vte.Terminal terminal, uint x, uint y)
+       {
+               move((int)x, (int)y);
+       }
+
+       private void notify_cb(Object object, ParamSpec pspec)
+       {
+               if (pspec.owner_type != typeof(Vte.Terminal))
+                       return;
+
+               var value = GLib.Value(pspec.value_type);
+               object.get_property(pspec.name, ref value);
+               var str = value.strdup_contents();
+               print("NOTIFY property \"%s\" value %s\n", pspec.name, str);
+       }
+
+       private void raise_window_cb(Vte.Terminal terminal)
+       {
+               if (!get_realized())
+                       return;
+
+               get_window().raise();
+       }
+
+       private void realize_cb(Gtk.Widget widget)
+       {
+               update_geometry();
+       }
+
+       private void refresh_window_cb(Vte.Terminal terminal)
+       {
+               queue_draw();
+       }
+
+       private void resize_window_cb(Vte.Terminal terminal, uint width, uint height)
+       {
+        long char_width, char_height, columns, rows;
+               int owidth, oheight;
+               Gtk.Border padding;
+
+               /* Read the screen dimensions in cells. */
+               columns = terminal.get_column_count();
+               rows = terminal.get_column_count();
+
+               /* Take into account padding and border overhead. */
+               get_size(out owidth, out oheight);
+        char_width = terminal.get_char_width();
+        char_height = terminal.get_char_height();
+
+               if (width < 2 || height < 2)
+                       return;
+
+               /* Take into account border overhead. */
+               padding = get_style_context().get_padding(get_state_flags());
+
+               owidth -= (int)(char_width * columns) + padding.left + padding.right;
+               oheight -= (int)(char_height * rows) + padding.top + padding.bottom;
+               // FIXMEchpe use resize_to_geometry
+               resize((int)(width + owidth),
+                          (int)(height + oheight));
+       }
+
+       private void restore_window_cb(Vte.Terminal terminal)
+       {
+               unmaximize();
+       }
+
+       private void selection_changed_cb(Vte.Terminal terminal)
+       {
+               update_copy_sensitivity();
+       }
+
+       private void status_line_changed_cb(Vte.Terminal terminal)
+       {
+               print("Status: `%s'\n", terminal.get_status_line());
+       }
+
+       private void window_title_changed_cb(Vte.Terminal terminal)
+       {
+               set_title(terminal.get_window_title());
+       }
+
+} /* class Window */
+
+class App : Gtk.Application
+{
+       private Window window;
+
+       public App()
+       {
+               Object(application_id: "org.gnome.Vte.TestApp",
+                          flags: ApplicationFlags.NON_UNIQUE);
+       }
+
+       protected override void startup()
+       {
+               base.startup();
+
+               window = new Window(this);
+               window.launch();
+       }
+
+       protected override void activate()
+       {
+               window.apply_geometry();
+               window.present();
+       }
+
+       public struct Options
+       {
+               public static bool audible = false;
+               public static string? command = null;
+               private static string? cjk_ambiguous_width_string = null;
+               private static string? cursor_blink_mode_string = null;
+               private static string? cursor_color_string = null;
+               private static string? cursor_shape_string = null;
+               public static string[]? dingus = null;
+               public static bool debug = false;
+               public static string? encoding = null;
+               public static string[]? environment = null;
+               public static string? font_string = null;
+               public static string? geometry = null;
+               private static string? hl_bg_color_string = null;
+               private static string? hl_fg_color_string = null;
+               public static string? icon_title = null;
+               public static bool keep = false;
+               public static bool no_argb_visual = false;
+               public static bool no_builtin_dingus = false;
+               public static bool no_context_menu = false;
+               public static bool no_double_buffer = false;
+               public static bool no_geometry_hints = false;
+               public static bool no_rewrap = false;
+               public static bool no_shell = false;
+               public static bool no_toolbar = false;
+               public static bool object_notifications = false;
+               public static string? output_filename = null;
+               private static string? pty_flags_string = null;
+               public static bool reverse = false;
+               public static int scrollback_lines = 512;
+               public static string? termcap = null;
+               public static int transparency_percent = 0;
+               public static bool version = false;
+               public static string? working_directory = null;
+
+               private static int parse_enum(Type type, string str)
+               {
+                       int value = 0;
+                       EnumClass enum_klass = (EnumClass)type.class_ref();
+                       unowned EnumValue? enum_value = enum_klass.get_value_by_nick(str);
+                       if (enum_value != null)
+                               value = enum_value.value;
+                       else
+                               printerr("Failed to parse enum value \"%s\" as type \"%s\"\n",
+                                                str, type.qname().to_string());
+                       return value;
+               }
+
+               private static uint parse_flags(Type type, string str)
+               {
+                       uint value = 0;
+                       var flags_klass = (FlagsClass)type.class_ref();
+                       string[]? flags = str.split(",|", -1);
+                 
+                       if (flags == null)
+                               return value;
+
+                       for (int i = 0; flags[i] != null; i++) {
+                               unowned FlagsValue? flags_value = flags_klass.get_value_by_nick(flags[i]);
+                               if (flags_value != null)
+                                       value |= flags_value.value;
+                               else
+                                       printerr("Failed to parse flags value \"%s\" as type \"%s\"\n",
+                                                        str, type.qname().to_string());
+                       }
+                       return value;
+               }
+
+               public static int get_cjk_ambiguous_width()
+               {
+                       if (cjk_ambiguous_width_string == null)
+                               return 1;
+                       if (cjk_ambiguous_width_string == "narrow")
+                               return 1;
+                       if (cjk_ambiguous_width_string == "wide")
+                               return 2;
+                       printerr("Failed to parse \"%s\" argument to --cjk-width. Allowed values are 
\"narrow\" or \"wide\".\n", cjk_ambiguous_width_string);
+                       return 1;
+               }
+
+               public static Gdk.RGBA get_color_bg()
+               {
+                       var color = Gdk.RGBA();
+                       color.alpha = (double)(100 - transparency_percent.clamp(0, 100)) / 100.0;
+                       if (Options.reverse) {
+                               color.red = color.green = color.blue = 1.0;
+                       } else {
+                               color.red = color.green = color.blue = 0.0;
+                       }
+                       return color;
+               }
+
+               public static Gdk.RGBA get_color_fg()
+               {
+                       var color = Gdk.RGBA();
+                       color.alpha = 1.0;
+                       if (Options.reverse) {
+                               color.red = color.green = color.blue = 0.0;
+                       } else {
+                               color.red = color.green = color.blue = 1.0;
+                       }
+                       return color;
+               }
+
+               private static Gdk.RGBA? get_color(string? str)
+               {
+                       if (str == null)
+                               return null;
+                       var color = Gdk.RGBA();
+                       if (!color.parse(str))
+                               return null;
+                       return color;
+               }
+
+               public static Gdk.RGBA? get_color_cursor()
+               {
+                       return get_color(cursor_color_string);
+               }
+
+               public static Gdk.RGBA? get_color_hl_bg()
+               {
+                       return get_color(hl_bg_color_string);
+               }
+
+               public static Gdk.RGBA? get_color_hl_fg()
+               {
+                       return get_color(hl_fg_color_string);
+               }
+
+               public static Vte.CursorBlinkMode get_cursor_blink_mode()
+               {
+                       Vte.CursorBlinkMode value;
+                       if (cursor_blink_mode_string != null)
+                               value = (Vte.CursorBlinkMode)parse_enum(typeof(Vte.CursorBlinkMode),
+                                                                                                             
  cursor_blink_mode_string);
+                       else
+                               value = Vte.CursorBlinkMode.SYSTEM;
+                       return value;
+               }
+
+               public static Vte.CursorShape get_cursor_shape()
+               {
+                       Vte.CursorShape value;
+                       if (cursor_shape_string != null)
+                               value = (Vte.CursorShape)parse_enum(typeof(Vte.CursorShape),
+                                                                                                       
cursor_shape_string);
+                       else
+                               value = Vte.CursorShape.BLOCK;
+                       return value;
+               }
+
+               public static Vte.PtyFlags get_pty_flags()
+               {
+                       Vte.PtyFlags flags;
+                       if (cursor_shape_string != null)
+                               flags = (Vte.PtyFlags)parse_flags(typeof(Vte.CursorShape),
+                                                                                                 
pty_flags_string);
+                       else
+                               flags = Vte.PtyFlags.DEFAULT;
+                       return flags;
+               }
+               
+               public static const OptionEntry[] entries = {
+                       { "audible-bell", 'a', 0, OptionArg.NONE, ref audible,
+                         "Use audible terminal bell", null },
+                       { "command", 'c', 0, OptionArg.STRING, ref command,
+                         "Execute a command in the terminal", null },
+                       { "cjk-width", 0, 0, OptionArg.STRING, ref cjk_ambiguous_width_string,
+                         "Specify the cjk ambiguous width to use for UTF-8 encoding", "NARROW|WIDE" },
+                       { "cursor-blink", 0, 0, OptionArg.STRING, ref cursor_blink_mode_string,
+                         "Cursor blink mode (system|on|off)", "MODE" },
+                       { "cursor-color", 0, 0, OptionArg.STRING, ref cursor_color_string,
+                         "Enable a colored cursor", null },
+                       { "cursor-shape", 0, 0, OptionArg.STRING, ref cursor_shape_string,
+                         "Set cursor shape (block|underline|ibeam)", null },
+                       { "dingu", 'D', 0, OptionArg.STRING_ARRAY, ref dingus,
+                         "Add regex highlight", null },
+                       { "debug", 'd', 0,OptionArg.NONE, ref debug,
+                         "Enable various debugging checks", null },
+                       { "encoding", 0, 0, OptionArg.STRING, ref encoding,
+                         "Specify the terminal encoding to use", null },
+                       { "env", 0, 0, OptionArg.STRING_ARRAY, ref environment,
+                         "Add environment variable to the child\'s environment", "VAR=VALUE" },
+                       { "font", 'f', 0, OptionArg.STRING, ref font_string,
+                         "Specify a font to use", null },
+                       { "geometry", 'g', 0, OptionArg.STRING, ref geometry,
+                         "Set the size (in characters) and position", "GEOMETRY" },
+                       { "highlight-background-color", 0, 0, OptionArg.STRING, ref hl_bg_color_string,
+                         "Enable distinct highlight background color for selection", null },
+                       { "highlight-foreground-color", 0, 0, OptionArg.STRING, ref hl_fg_color_string,
+                         "Enable distinct highlight foreground color for selection", null },
+                       { "icon-title", 'i', 0, OptionArg.NONE, ref icon_title,
+                         "Enable the setting of the icon title", null },
+                       { "keep", 'k', 0, OptionArg.NONE, ref keep,
+                         "Live on after the command exits", null },
+                       { "no-argb-visual", 0, 0, OptionArg.NONE, ref no_argb_visual,
+                         "Don't use an ARGB visual", null },
+                       { "no-builtin-dingus", 0, 0, OptionArg.NONE, ref no_builtin_dingus,
+                         "Highlight URLs inside the terminal", null },
+                       { "no-context-menu", 0, 0, OptionArg.NONE, ref no_context_menu,
+                         "Disable context menu", null },
+                       { "no-double-buffer", '2', 0, OptionArg.NONE, ref no_double_buffer,
+                         "Disable double-buffering", null },
+                       { "no-geometry-hints", 'G', 0, OptionArg.NONE, ref no_geometry_hints,
+                         "Allow the terminal to be resized to any dimension, not constrained to fit to an 
integer multiple of characters", null },
+                       { "no-rewrap", 'R', 0, OptionArg.NONE, ref no_rewrap,
+                         "Disable rewrapping on resize", null },
+                       { "no-shell", 'S', 0, OptionArg.NONE, ref no_shell,
+                         "Disable spawning a shell inside the terminal", null },
+                       { "no-toolbar", 0, 0, OptionArg.NONE, ref no_toolbar,
+                         "Disable toolbar", null },
+                       { "object-notifications", 'N', 0, OptionArg.NONE, ref object_notifications,
+                         "Print VteTerminal object notifications", null },
+                       { "output-file", 0, 0, OptionArg.FILENAME, ref output_filename,
+                         "Save terminal contents to file at exit", null },
+                       { "pty-flags", 0, 0, OptionArg.STRING, ref pty_flags_string,
+                         "PTY flags set from default|no-utmp|no-wtmp|no-lastlog|no-helper|no-fallback", null 
},
+                       { "reverse", 0, 0, OptionArg.NONE, ref reverse,
+                         "Reverse foreground/background colors", null },
+                       { "scrollback-lines", 'n', 0, OptionArg.INT, ref scrollback_lines,
+                         "Specify the number of scrollback-lines", null },
+                       { "termcap", 't', 0, OptionArg.STRING, ref termcap,
+                         "Specify the terminal emulation to use", null },
+                       { "transparent", 'T', 0, OptionArg.INT, ref transparency_percent,
+                         "Enable the use of a transparent background", "0..100" },
+                       { "version", 0, 0, OptionArg.NONE, ref version,
+                         "Show version", null },
+                       { "working-directory", 'w', 0,OptionArg.FILENAME, ref working_directory,
+                         "Specify the initial working directory of the terminal", null },
+                       { null }
+               };
+       }
+
+       public static int main(string[] argv)
+       {
+               if (Environment.get_variable("VTE_CJK_WIDTH") != null) {
+                       printerr("VTE_CJK_WIDTH is not supported anymore, use --cjk-width instead\n");
+               }
+               Environment.set_prgname("vte-app");
+               Environment.set_application_name("Terminal");
+
+               try {
+                       var context = new OptionContext("— simple VTE test application");
+                       context.set_help_enabled(true);
+                       context.add_main_entries(Options.entries, null);
+                       context.add_group(Gtk.get_option_group(true));
+                       context.parse(ref argv);
+               } catch (OptionError e) {
+                       printerr("Error parsing arguments: %s\n", e.message);
+                       return 1;
+               }
+
+               if (Options.version) {
+                       print("Simple VTE Test Application %s\n", Config.VERSION);
+                       return 0;
+               }
+
+               if (Options.debug)
+                       Gdk.Window.set_debug_updates(Options.debug);
+
+               var app = new App();
+               return app.run(null);
+       }
+} /* class App */
+
+} /* namespace */
diff --git a/src/config.vapi b/src/config.vapi
new file mode 100644
index 0000000..9acec71
--- /dev/null
+++ b/src/config.vapi
@@ -0,0 +1,5 @@
+[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
+namespace Config
+{
+       public const string VERSION;
+}
diff --git a/src/pty.c b/src/pty.c
index 8c84a57..a5e6996 100644
--- a/src/pty.c
+++ b/src/pty.c
@@ -1694,7 +1694,7 @@ vte_pty_error_quark(void)
 }
 
 /**
- * vte_pty_new_sync:
+ * vte_pty_new_sync: (constructor)
  * @flags: flags from #VtePtyFlags
  * @cancellable: (allow-none): a #GCancellable, or %NULL
  * @error: (allow-none): return location for a #GError, or %NULL
@@ -1744,7 +1744,7 @@ vte_pty_new_sync (VtePtyFlags flags,
 }
 
 /**
- * vte_pty_new_foreign_sync:
+ * vte_pty_new_foreign_sync: (constructor)
  * @fd: (transfer full): a file descriptor to the PTY
  * @cancellable: (allow-none): a #GCancellable, or %NULL
  * @error: (allow-none): return location for a #GError, or %NULL
diff --git a/src/vte.c b/src/vte.c
index 70262d9..a0fd639 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -2843,7 +2843,7 @@ vte_terminal_set_color_highlight_foreground_rgba(VteTerminal *terminal,
  * @terminal: a #VteTerminal
  * @foreground: (allow-none): the new foreground color, or %NULL
  * @background: (allow-none): the new background color, or %NULL
- * @palette: (array length=palette_size zero-terminated=0) (element-type Gdk.RGBA): the color palette
+ * @palette: (array length=palette_size zero-terminated=0) (element-type Gdk.RGBA) (allow-none): the color 
palette
  * @palette_size: the number of entries in @palette
  *
  * The terminal widget uses a 28-color model comprised of the default foreground



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