Drop the GTK+2 support, switch to VTE 0.34 and Vala 0.17.7
[valaterm:valaterm.git] / src / terminal.vala
1 /****************************
2 ** Copyright © 2011 Jacques-Pascal Deplaix
3 **
4 ** ValaTerm is free software: you can redistribute it and/or modify
5 ** it under the terms of the GNU General Public License as published by
6 ** the Free Software Foundation, either version 3 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU General Public License for more details.
13 **
14 ** You should have received a copy of the GNU General Public License
15 ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 ****************************/
17
18 public class Terminal : Vte.Terminal
19 {
20     private GLib.Pid? child_pid = null;
21     private string shell = Terminal.get_shell();
22
23     public signal void title_changed(string title);
24
25     public Terminal()
26     {
27         this.scroll_on_keystroke = true;
28
29         this.background_transparent = Settings.transparency;
30         this.scrollback_lines = Settings.scrollback_lines;
31         this.set_font_from_string(Settings.font);
32         this.set_colors(Settings.foreground_color,
33                         Settings.background_color,
34                         Colors.colors_palette);
35
36         this.active_mouse("""(https?|ftps?)://\S+""");
37
38         this.active_signals();
39     }
40
41     private void active_mouse(string str)
42     {
43         try
44         {
45             var regex = new GLib.Regex(str);
46             int id = this.match_add_gregex(regex, 0);
47
48             this.match_set_cursor_type(id, Gdk.CursorType.HAND2);
49         }
50         catch(GLib.RegexError error)
51         {
52             Errors.print(error);
53         }
54     }
55
56     public string? get_link(long x, long y)
57     {
58         long col = x / this.get_char_width();
59         long row = y / this.get_char_height();
60
61         return this.match_check(col, row, null);
62     }
63
64     private void active_signals()
65     {
66         this.window_title_changed.connect(() => {
67                 this.title_changed(this.window_title);
68             });
69     }
70
71     public async void active_shell(string dir)
72     {
73         Idle.add(this.active_shell.callback, GLib.Priority.LOW);
74         yield;
75
76         try
77         {
78             var args = new string[0];
79
80             GLib.Shell.parse_argv(this.shell, out args);
81
82             if(Settings.command != null)
83             {
84                 args += "-c";
85                 args += (!)(Settings.command);
86             }
87
88             this.fork_command_full(Vte.PtyFlags.DEFAULT, dir, args, null,
89                                    GLib.SpawnFlags.SEARCH_PATH, null,
90                                    out this.child_pid);
91         }
92         catch(GLib.Error error)
93         {
94             Errors.print(error);
95         }
96     }
97
98     public int calcul_width(int column_count)
99     {
100         return (int)(this.get_char_width()) * column_count;
101     }
102
103     public int calcul_height(int row_count)
104     {
105         return (int)(this.get_char_height()) * row_count;
106     }
107
108     public bool has_foreground_process()
109     {
110         int pty = this.pty_object.fd;
111         int fgpid = Posix.tcgetpgrp(pty);
112
113         return fgpid != this.child_pid && fgpid != -1;
114     }
115
116     private static string get_shell()
117     {
118         string? shell = Vte.get_user_shell();
119
120         if(shell == null)
121         {
122             shell = "/bin/sh";
123         }
124
125         return (!)(shell);
126     }
127
128     //FIXME: Is it portable ?
129     //Will be replaced by Vte.Terminal.get_current_directory_uri (vte 0.35)
130     public string? get_shell_cwd()
131     {
132         int pid = (!)(this.child_pid);
133
134         try
135         {
136             return GLib.FileUtils.read_link("/proc/%d/cwd".printf(pid));
137         }
138         catch(GLib.FileError error)
139         {
140             Errors.print(error);
141         }
142
143         return null;
144     }
145 }