Bug Summary

File:terminal-screen.c
Warning:line 607, column 45
Access of 'skey_regex_patterns' at index 2, while it holds only 2 'TerminalRegexPattern' elements

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name terminal-screen.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -D TERMINAL_COMPILATION -D TERMINAL_RESOURCES_PATH_PREFIX="/org/cafe/terminal" -D TERM_DATADIR="/usr/share" -D TERM_LOCALEDIR="/usr/share/locale" -D TERM_PKGDATADIR="/usr/share/cafe-terminal" -D TERM_HELPDIR="/usr/share/help" -D SN_API_NOT_YET_FROZEN -D CDK_MULTIHEAD_SAFE -D G_DISABLE_SINGLE_INCLUDES -D PANGO_DISABLE_SINGLE_INCLUDES -D ATK_DISABLE_SINGLE_INCLUDES -D CDK_DISABLE_SINGLE_INCLUDES -D CDK_PIXBUF_DISABLE_SINGLE_INCLUDES -D CTK_DISABLE_SINGLE_INCLUDES -D EGG_SM_CLIENT_BACKEND_XSMP -I /usr/local/include/bte-2.91 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/ctk-3.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/dconf -I /usr/include/uuid -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-08-13-130258-18860-1 -x c terminal-screen.c
1/*
2 * Copyright © 2001 Havoc Pennington
3 * Copyright © 2007, 2008, 2010 Christian Persch
4 *
5 * Cafe-terminal is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Cafe-terminal is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <config.h>
20
21#include <string.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <sys/wait.h>
25
26#include <gio/gio.h>
27#include <ctk/ctk.h>
28#include <cdk/cdkkeysyms.h>
29
30#include <cdk/cdk.h>
31#include <cdk/cdkx.h>
32#include <gdk-pixbuf/gdk-pixbuf.h>
33#include <cairo.h>
34
35#include <libnotify/notify.h>
36
37#include "terminal-accels.h"
38#include "terminal-app.h"
39#include "terminal-debug.h"
40#include "terminal-intl.h"
41#include "terminal-marshal.h"
42#include "terminal-profile.h"
43#include "terminal-screen-container.h"
44#include "terminal-util.h"
45#include "terminal-window.h"
46#include "terminal-info-bar.h"
47
48#include "eggshell.h"
49
50#define PCRE2_CODE_UNIT_WIDTH0 0
51#include <pcre2.h>
52
53
54typedef struct
55{
56 int tag;
57 TerminalURLFlavour flavor;
58} TagData;
59
60struct _TerminalScreenPrivate
61{
62 TerminalProfile *profile; /* may be NULL at times */
63 guint profile_changed_id;
64 guint profile_forgotten_id;
65 char *raw_title, *raw_icon_title;
66 char *cooked_title, *cooked_icon_title;
67 char *override_title;
68 gboolean icon_title_set;
69 char *initial_working_directory;
70 char **initial_env;
71 char **override_command;
72 int child_pid;
73 double font_scale;
74 gboolean user_title; /* title was manually set */
75 GSList *match_tags;
76 guint launch_child_source_id;
77 gulong bg_image_callback_id;
78 GdkPixbuf *bg_image;
79};
80
81enum
82{
83 PROFILE_SET,
84 SHOW_POPUP_MENU,
85 MATCH_CLICKED,
86 CLOSE_SCREEN,
87 LAST_SIGNAL
88};
89
90enum
91{
92 PROP_0,
93 PROP_PROFILE,
94 PROP_ICON_TITLE,
95 PROP_ICON_TITLE_SET,
96 PROP_OVERRIDE_COMMAND,
97 PROP_TITLE,
98 PROP_INITIAL_ENVIRONMENT
99};
100
101enum
102{
103 TARGET_COLOR,
104 TARGET_BGIMAGE,
105 TARGET_RESET_BG,
106 TARGET_MOZ_URL,
107 TARGET_NETSCAPE_URL,
108 TARGET_TAB
109};
110
111static void terminal_screen_dispose (GObject *object);
112static void terminal_screen_finalize (GObject *object);
113static void terminal_screen_drag_data_received (CtkWidget *widget,
114 CdkDragContext *context,
115 gint x,
116 gint y,
117 CtkSelectionData *selection_data,
118 guint info,
119 guint time);
120static void terminal_screen_system_font_notify_cb (TerminalApp *app,
121 GParamSpec *pspec,
122 TerminalScreen *screen);
123static void terminal_screen_change_font (TerminalScreen *screen);
124static gboolean terminal_screen_popup_menu (CtkWidget *widget);
125static gboolean terminal_screen_button_press (CtkWidget *widget,
126 CdkEventButton *event);
127static void terminal_screen_launch_child_on_idle (TerminalScreen *screen);
128static void terminal_screen_child_exited (BteTerminal *terminal, int status);
129
130static void terminal_screen_window_title_changed (BteTerminal *bte_terminal,
131 TerminalScreen *screen);
132static void terminal_screen_icon_title_changed (BteTerminal *bte_terminal,
133 TerminalScreen *screen);
134static void terminal_screen_text_inserted (BteTerminal *bte_terminal,
135 TerminalScreen *screen);
136
137static void update_color_scheme (TerminalScreen *screen);
138
139static gboolean terminal_screen_format_title (TerminalScreen *screen, const char *raw_title, char **old_cooked_title);
140
141static void terminal_screen_cook_title (TerminalScreen *screen);
142static void terminal_screen_cook_icon_title (TerminalScreen *screen);
143
144static char* terminal_screen_check_match (TerminalScreen *screen,
145 CdkEvent *event,
146 int *flavor);
147
148static guint signals[LAST_SIGNAL] = { 0 };
149
150#define USERCHARS"-[:alnum:]" "-[:alnum:]"
151#define USERCHARS_CLASS"[" "-[:alnum:]" "]" "[" USERCHARS"-[:alnum:]" "]"
152#define PASSCHARS_CLASS"[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]" "[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]"
153#define HOSTCHARS_CLASS"[-[:alnum:]]" "[-[:alnum:]]"
154#define HOST"[-[:alnum:]]" "+(\\." "[-[:alnum:]]" "+)*" HOSTCHARS_CLASS"[-[:alnum:]]" "+(\\." HOSTCHARS_CLASS"[-[:alnum:]]" "+)*"
155#define PORT"(?:\\:[[:digit:]]{1,5})?" "(?:\\:[[:digit:]]{1,5})?"
156#define PATHCHARS_CLASS"[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]" "[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]"
157#define PATHTERM_CLASS"[^\\Q]'.:}>) \t\r\n,\"\\E]" "[^\\Q]'.:}>) \t\r\n,\"\\E]"
158#define SCHEME"(?:news:|telnet:|nntp:|file:\\/|https?:|ftps?:|sftp:|webcal:)" "(?:news:|telnet:|nntp:|file:\\/|https?:|ftps?:|sftp:|webcal:)"
159#define USERPASS"[" "-[:alnum:]" "]" "+(?:" "[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]"
"+)?"
USERCHARS_CLASS"[" "-[:alnum:]" "]" "+(?:" PASSCHARS_CLASS"[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]" "+)?"
160#define URLPATH"(?:(/""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""+(?:[(]""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]"
"*[)])*""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""*)*""[^\\Q]'.:}>) \t\r\n,\"\\E]"
")?"
"(?:(/"PATHCHARS_CLASS"[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""+(?:[(]"PATHCHARS_CLASS"[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""*[)])*"PATHCHARS_CLASS"[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""*)*"PATHTERM_CLASS"[^\\Q]'.:}>) \t\r\n,\"\\E]"")?"
161
162typedef struct
163{
164 const char *pattern;
165 TerminalURLFlavour flavor;
166 guint32 flags;
167} TerminalRegexPattern;
168
169static const TerminalRegexPattern url_regex_patterns[] =
170{
171 { SCHEME"(?:news:|telnet:|nntp:|file:\\/|https?:|ftps?:|sftp:|webcal:)" "//(?:" USERPASS"[" "-[:alnum:]" "]" "+(?:" "[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]"
"+)?"
"\\@)?" HOST"[-[:alnum:]]" "+(\\." "[-[:alnum:]]" "+)*" PORT"(?:\\:[[:digit:]]{1,5})?" URLPATH"(?:(/""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""+(?:[(]""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]"
"*[)])*""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""*)*""[^\\Q]'.:}>) \t\r\n,\"\\E]"
")?"
, FLAVOR_AS_IS, PCRE2_CASELESS0x00000008u },
172 { "(?:www|ftp)" HOSTCHARS_CLASS"[-[:alnum:]]" "*\\." HOST"[-[:alnum:]]" "+(\\." "[-[:alnum:]]" "+)*" PORT"(?:\\:[[:digit:]]{1,5})?" URLPATH"(?:(/""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""+(?:[(]""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]"
"*[)])*""[-[:alnum:]\\Q_$.+!*,:;@&=?/~#%\\E]""*)*""[^\\Q]'.:}>) \t\r\n,\"\\E]"
")?"
, FLAVOR_DEFAULT_TO_HTTP, PCRE2_CASELESS0x00000008u },
173 { "(?:callto:|h323:|sip:)" USERCHARS_CLASS"[" "-[:alnum:]" "]" "[" USERCHARS"-[:alnum:]" ".]*(?:" PORT"(?:\\:[[:digit:]]{1,5})?" "/[a-z0-9]+)?\\@" HOST"[-[:alnum:]]" "+(\\." "[-[:alnum:]]" "+)*", FLAVOR_VOIP_CALL, PCRE2_CASELESS0x00000008u },
174 { "(?:mailto:)?" USERCHARS_CLASS"[" "-[:alnum:]" "]" "[" USERCHARS"-[:alnum:]" ".]*\\@" HOSTCHARS_CLASS"[-[:alnum:]]" "+\\." HOST"[-[:alnum:]]" "+(\\." "[-[:alnum:]]" "+)*", FLAVOR_EMAIL, PCRE2_CASELESS0x00000008u },
175 { "news:[[:alnum:]\\Q^_{|}~!\"#$%&'()*+,./;:=?`\\E]+", FLAVOR_AS_IS, PCRE2_CASELESS0x00000008u },
176};
177
178static BteRegex **url_regexes;
179static TerminalURLFlavour *url_regex_flavors;
180static guint n_url_regexes;
181
182static void terminal_screen_url_match_remove (TerminalScreen *screen);
183
184
185#ifdef ENABLE_SKEY1
186static const TerminalRegexPattern skey_regex_patterns[] =
187{
188 { "s/key [[:digit:]]* [-[:alnum:]]*", FLAVOR_AS_IS, 0 },
189 { "otp-[a-z0-9]* [[:digit:]]* [-[:alnum:]]*", FLAVOR_AS_IS, 0 },
190};
191
192static BteRegex **skey_regexes;
193static guint n_skey_regexes;
194
195static void terminal_screen_skey_match_remove (TerminalScreen *screen);
196#endif /* ENABLE_SKEY */
197
198G_DEFINE_TYPE_WITH_PRIVATE (TerminalScreen, terminal_screen, BTE_TYPE_TERMINAL)static void terminal_screen_init (TerminalScreen *self); static
void terminal_screen_class_init (TerminalScreenClass *klass)
; static GType terminal_screen_get_type_once (void); static gpointer
terminal_screen_parent_class = ((void*)0); static gint TerminalScreen_private_offset
; static void terminal_screen_class_intern_init (gpointer klass
) { terminal_screen_parent_class = g_type_class_peek_parent (
klass); if (TerminalScreen_private_offset != 0) g_type_class_adjust_private_offset
(klass, &TerminalScreen_private_offset); terminal_screen_class_init
((TerminalScreenClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer terminal_screen_get_instance_private
(TerminalScreen *self) { return (((gpointer) ((guint8*) (self
) + (glong) (TerminalScreen_private_offset)))); } GType terminal_screen_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= terminal_screen_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType terminal_screen_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
bte_terminal_get_type()), g_intern_static_string ("TerminalScreen"
), sizeof (TerminalScreenClass), (GClassInitFunc)(void (*)(void
)) terminal_screen_class_intern_init, sizeof (TerminalScreen)
, (GInstanceInitFunc)(void (*)(void)) terminal_screen_init, (
GTypeFlags) 0); { {{ TerminalScreen_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (TerminalScreenPrivate)); };} } return
g_define_type_id; }
1
Assuming 'TerminalScreen_private_offset' is equal to 0
2
Taking false branch
3
Calling 'terminal_screen_class_init'
199
200static char *
201cwd_of_pid (int pid)
202{
203 static const char patterns[][18] =
204 {
205 "/proc/%d/cwd", /* Linux */
206 "/proc/%d/path/cwd", /* Solaris >= 10 */
207 };
208 guint i;
209
210 if (pid == -1)
211 return NULL((void*)0);
212
213 /* Try to get the working directory using various OS-specific mechanisms */
214 for (i = 0; i < G_N_ELEMENTS (patterns)(sizeof (patterns) / sizeof ((patterns)[0])); ++i)
215 {
216 char cwd_file[64];
217 char buf[PATH_MAX4096 + 1];
218 int len;
219
220 g_snprintf (cwd_file, sizeof (cwd_file), patterns[i], pid);
221 len = readlink (cwd_file, buf, sizeof (buf) - 1);
222
223 if (len > 0 && buf[0] == '/')
224 return g_strndup (buf, len);
225
226 /* If that didn't do it, try this hack */
227 if (len <= 0)
228 {
229 char *cwd, *working_dir = NULL((void*)0);
230
231 cwd = g_get_current_dir ();
232 if (cwd != NULL((void*)0))
233 {
234 /* On Solaris, readlink returns an empty string, but the
235 * link can be used as a directory, including as a target
236 * of chdir().
237 */
238 if (chdir (cwd_file) == 0)
239 {
240 working_dir = g_get_current_dir ();
241 if (chdir (cwd) < 0)
242 g_warning ("Could not change working directory.");
243 }
244 g_free (cwd);
245 }
246
247 if (working_dir)
248 return working_dir;
249 }
250 }
251
252 return NULL((void*)0);
253}
254
255static void
256free_tag_data (TagData *tagdata)
257{
258 g_slice_free (TagData, tagdata)do { if (1) g_slice_free1 (sizeof (TagData), (tagdata)); else
(void) ((TagData*) 0 == (tagdata)); } while (0)
;
259}
260
261static void
262terminal_screen_class_enable_menu_bar_accel_notify_cb (TerminalApp *app,
263 GParamSpec *pspec,
264 TerminalScreenClass *klass)
265{
266 static gboolean is_enabled = TRUE(!(0)); /* the binding is enabled by default since CtkWidgetClass installs it */
267 gboolean enable;
268 CtkBindingSet *binding_set;
269
270 g_object_get (app, TERMINAL_APP_ENABLE_MENU_BAR_ACCEL"enable-menu-accels", &enable, NULL((void*)0));
271
272 /* Only remove the 'skip' entry when we have added it previously! */
273 if (enable == is_enabled)
274 return;
275
276 is_enabled = enable;
277
278 binding_set = ctk_binding_set_by_class (klass);
279 if (enable)
280 ctk_binding_entry_remove (binding_set, CDK_KEY_F100xffc7, CDK_SHIFT_MASK);
281 else
282 ctk_binding_entry_skip (binding_set, CDK_KEY_F100xffc7, CDK_SHIFT_MASK);
283}
284
285static TerminalWindow *
286terminal_screen_get_window (TerminalScreen *screen)
287{
288 CtkWidget *widget = CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
;
289 CtkWidget *toplevel;
290
291 toplevel = ctk_widget_get_toplevel (widget);
292 if (!ctk_widget_is_toplevel (toplevel))
293 return NULL((void*)0);
294
295 return TERMINAL_WINDOW (toplevel)((((TerminalWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((terminal_window_get_type ()))))))
;
296}
297
298static void
299terminal_screen_realize (CtkWidget *widget)
300{
301 TerminalScreen *screen = TERMINAL_SCREEN (widget)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((terminal_screen_get_type ()))))))
;
302
303 CTK_WIDGET_CLASS (terminal_screen_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((terminal_screen_parent_class)), ((ctk_widget_get_type ()
))))))
->realize (widget);
304
305 terminal_screen_set_font (screen);
306}
307
308static void
309terminal_screen_style_updated (CtkWidget *widget)
310{
311 TerminalScreen *screen = TERMINAL_SCREEN (widget)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((terminal_screen_get_type ()))))))
;
312
313 CTK_WIDGET_CLASS (terminal_screen_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((terminal_screen_parent_class)), ((ctk_widget_get_type ()
))))))
->style_updated (widget);
314
315 update_color_scheme (screen);
316
317 if (ctk_widget_get_realized (widget))
318 terminal_screen_change_font (screen);
319}
320
321#ifdef CAFE_ENABLE_DEBUG
322static void
323size_allocate (CtkWidget *widget,
324 CtkAllocation *allocation)
325{
326 _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,do { if (0) g_printerr("[screen %p] size-alloc %d : %d at (%d, %d)\n"
, widget, allocation->width, allocation->height, allocation
->x, allocation->y); } while (0)
327 "[screen %p] size-alloc %d : %d at (%d, %d)\n",do { if (0) g_printerr("[screen %p] size-alloc %d : %d at (%d, %d)\n"
, widget, allocation->width, allocation->height, allocation
->x, allocation->y); } while (0)
328 widget, allocation->width, allocation->height, allocation->x, allocation->y)do { if (0) g_printerr("[screen %p] size-alloc %d : %d at (%d, %d)\n"
, widget, allocation->width, allocation->height, allocation
->x, allocation->y); } while (0)
;
329}
330#endif
331
332static void
333terminal_screen_init (TerminalScreen *screen)
334{
335 const CtkTargetEntry target_table[] =
336 {
337 { "CTK_NOTEBOOK_TAB", CTK_TARGET_SAME_APP, TARGET_TAB },
338 { "application/x-color", 0, TARGET_COLOR },
339 { "property/bgimage", 0, TARGET_BGIMAGE },
340 { "x-special/cafe-reset-background", 0, TARGET_RESET_BG },
341 { "text/x-moz-url", 0, TARGET_MOZ_URL },
342 { "_NETSCAPE_URL", 0, TARGET_NETSCAPE_URL }
343 };
344 TerminalScreenPrivate *priv;
345 CtkTargetList *target_list;
346 CtkTargetEntry *targets;
347 int n_targets;
348
349 priv = screen->priv = terminal_screen_get_instance_private (screen);
350
351 bte_terminal_set_mouse_autohide (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, TRUE(!(0)));
352#if BTE_CHECK_VERSION (0, 52, 0)((0) > (0) || ((0) == (0) && (65) > (52)) || ((
0) == (0) && (65) == (52) && (0) >= (0)))
353 bte_terminal_set_bold_is_bright (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, TRUE(!(0)));
354#endif
355
356 priv->child_pid = -1;
357
358 priv->font_scale = PANGO_SCALE_MEDIUM((double)1.0);
359
360 /* Setup DND */
361 target_list = ctk_target_list_new (NULL((void*)0), 0);
362 ctk_target_list_add_uri_targets (target_list, 0);
363 ctk_target_list_add_text_targets (target_list, 0);
364 ctk_target_list_add_table (target_list, target_table, G_N_ELEMENTS (target_table)(sizeof (target_table) / sizeof ((target_table)[0])));
365
366 targets = ctk_target_table_new_from_list (target_list, &n_targets);
367
368 ctk_drag_dest_set (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
,
369 CTK_DEST_DEFAULT_MOTION |
370 CTK_DEST_DEFAULT_HIGHLIGHT |
371 CTK_DEST_DEFAULT_DROP,
372 targets, n_targets,
373 CDK_ACTION_COPY | CDK_ACTION_MOVE);
374
375 ctk_target_table_free (targets, n_targets);
376 ctk_target_list_unref (target_list);
377
378 priv->override_title = NULL((void*)0);
379 priv->user_title = FALSE(0);
380
381 g_signal_connect (screen, "window-title-changed",g_signal_connect_data ((screen), ("window-title-changed"), ((
(GCallback) (terminal_screen_window_title_changed))), (screen
), ((void*)0), (GConnectFlags) 0)
382 G_CALLBACK (terminal_screen_window_title_changed),g_signal_connect_data ((screen), ("window-title-changed"), ((
(GCallback) (terminal_screen_window_title_changed))), (screen
), ((void*)0), (GConnectFlags) 0)
383 screen)g_signal_connect_data ((screen), ("window-title-changed"), ((
(GCallback) (terminal_screen_window_title_changed))), (screen
), ((void*)0), (GConnectFlags) 0)
;
384 g_signal_connect (screen, "icon-title-changed",g_signal_connect_data ((screen), ("icon-title-changed"), (((GCallback
) (terminal_screen_icon_title_changed))), (screen), ((void*)0
), (GConnectFlags) 0)
385 G_CALLBACK (terminal_screen_icon_title_changed),g_signal_connect_data ((screen), ("icon-title-changed"), (((GCallback
) (terminal_screen_icon_title_changed))), (screen), ((void*)0
), (GConnectFlags) 0)
386 screen)g_signal_connect_data ((screen), ("icon-title-changed"), (((GCallback
) (terminal_screen_icon_title_changed))), (screen), ((void*)0
), (GConnectFlags) 0)
;
387 g_signal_connect (screen, "text-inserted",g_signal_connect_data ((screen), ("text-inserted"), (((GCallback
) (terminal_screen_text_inserted))), (screen), ((void*)0), (GConnectFlags
) 0)
388 G_CALLBACK (terminal_screen_text_inserted),g_signal_connect_data ((screen), ("text-inserted"), (((GCallback
) (terminal_screen_text_inserted))), (screen), ((void*)0), (GConnectFlags
) 0)
389 screen)g_signal_connect_data ((screen), ("text-inserted"), (((GCallback
) (terminal_screen_text_inserted))), (screen), ((void*)0), (GConnectFlags
) 0)
;
390
391 g_signal_connect (terminal_app_get (), "notify::system-font",g_signal_connect_data ((terminal_app_get ()), ("notify::system-font"
), (((GCallback) (terminal_screen_system_font_notify_cb))), (
screen), ((void*)0), (GConnectFlags) 0)
392 G_CALLBACK (terminal_screen_system_font_notify_cb), screen)g_signal_connect_data ((terminal_app_get ()), ("notify::system-font"
), (((GCallback) (terminal_screen_system_font_notify_cb))), (
screen), ((void*)0), (GConnectFlags) 0)
;
393
394 priv->bg_image_callback_id = 0;
395 priv->bg_image = NULL((void*)0);
396
397#ifdef CAFE_ENABLE_DEBUG
398 _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_GEOMETRY)if (0)
399 {
400 g_signal_connect_after (screen, "size-allocate", G_CALLBACK (size_allocate), NULL)g_signal_connect_data ((screen), ("size-allocate"), (((GCallback
) (size_allocate))), (((void*)0)), ((void*)0), G_CONNECT_AFTER
)
;
401 }
402#endif
403}
404
405static void
406terminal_screen_get_property (GObject *object,
407 guint prop_id,
408 GValue *value,
409 GParamSpec *pspec)
410{
411 TerminalScreen *screen = TERMINAL_SCREEN (object)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((terminal_screen_get_type ()))))))
;
412
413 switch (prop_id)
414 {
415 case PROP_PROFILE:
416 g_value_set_object (value, terminal_screen_get_profile (screen));
417 break;
418 case PROP_ICON_TITLE:
419 g_value_set_string (value, terminal_screen_get_icon_title (screen));
420 break;
421 case PROP_ICON_TITLE_SET:
422 g_value_set_boolean (value, terminal_screen_get_icon_title_set (screen));
423 break;
424 case PROP_OVERRIDE_COMMAND:
425 g_value_set_boxed (value, terminal_screen_get_override_command (screen));
426 break;
427 case PROP_INITIAL_ENVIRONMENT:
428 g_value_set_boxed (value, terminal_screen_get_initial_environment (screen));
429 break;
430 case PROP_TITLE:
431 g_value_set_string (value, terminal_screen_get_title (screen));
432 break;
433 default:
434 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "terminal-screen.c", 434, ("property"), _glib__property_id,
_glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
435 break;
436 }
437}
438
439static void
440terminal_screen_set_property (GObject *object,
441 guint prop_id,
442 const GValue *value,
443 GParamSpec *pspec)
444{
445 TerminalScreen *screen = TERMINAL_SCREEN (object)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((terminal_screen_get_type ()))))))
;
446
447 switch (prop_id)
448 {
449 case PROP_PROFILE:
450 {
451 TerminalProfile *profile;
452
453 profile = g_value_get_object (value);
454 g_assert (profile != NULL)do { if (profile != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "terminal-screen.c", 454, ((const char*) (__func__
)), "profile != NULL"); } while (0)
;
455 terminal_screen_set_profile (screen, profile);
456 break;
457 }
458 case PROP_OVERRIDE_COMMAND:
459 terminal_screen_set_override_command (screen, g_value_get_boxed (value));
460 break;
461 case PROP_INITIAL_ENVIRONMENT:
462 terminal_screen_set_initial_environment (screen, g_value_get_boxed (value));
463 break;
464 case PROP_ICON_TITLE:
465 case PROP_ICON_TITLE_SET:
466 case PROP_TITLE:
467 /* not writable */
468 default:
469 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "terminal-screen.c", 469, ("property"), _glib__property_id,
_glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
470 break;
471 }
472}
473
474static void
475terminal_screen_class_init (TerminalScreenClass *klass)
476{
477 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
478 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS(klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_widget_get_type ()))))))
;
479 BteTerminalClass *terminal_class = BTE_TERMINAL_CLASS (klass)((((BteTerminalClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((bte_terminal_get_type()))))))
;
480 TerminalApp *app;
481 guint i;
482
483 object_class->dispose = terminal_screen_dispose;
484 object_class->finalize = terminal_screen_finalize;
485 object_class->get_property = terminal_screen_get_property;
486 object_class->set_property = terminal_screen_set_property;
487
488 widget_class->realize = terminal_screen_realize;
489 widget_class->style_updated = terminal_screen_style_updated;
490 widget_class->drag_data_received = terminal_screen_drag_data_received;
491 widget_class->button_press_event = terminal_screen_button_press;
492 widget_class->popup_menu = terminal_screen_popup_menu;
493
494 terminal_class->child_exited = terminal_screen_child_exited;
495
496 signals[PROFILE_SET] =
497 g_signal_new (I_("profile-set")g_intern_static_string ("profile-set"),
498 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
499 G_SIGNAL_RUN_LAST,
500 G_STRUCT_OFFSET (TerminalScreenClass, profile_set)((glong) __builtin_offsetof(TerminalScreenClass, profile_set)
)
,
501 NULL((void*)0), NULL((void*)0),
502 g_cclosure_marshal_VOID__OBJECT,
503 G_TYPE_NONE((GType) ((1) << (2))),
504 1, TERMINAL_TYPE_PROFILE(terminal_profile_get_type ()));
505
506 signals[SHOW_POPUP_MENU] =
507 g_signal_new (I_("show-popup-menu")g_intern_static_string ("show-popup-menu"),
508 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
509 G_SIGNAL_RUN_LAST,
510 G_STRUCT_OFFSET (TerminalScreenClass, show_popup_menu)((glong) __builtin_offsetof(TerminalScreenClass, show_popup_menu
))
,
511 NULL((void*)0), NULL((void*)0),
512 g_cclosure_marshal_VOID__POINTER,
513 G_TYPE_NONE((GType) ((1) << (2))),
514 1,
515 G_TYPE_POINTER((GType) ((17) << (2))));
516
517 signals[MATCH_CLICKED] =
518 g_signal_new (I_("match-clicked")g_intern_static_string ("match-clicked"),
519 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
520 G_SIGNAL_RUN_LAST,
521 G_STRUCT_OFFSET (TerminalScreenClass, match_clicked)((glong) __builtin_offsetof(TerminalScreenClass, match_clicked
))
,
522 g_signal_accumulator_true_handled, NULL((void*)0),
523 _terminal_marshal_BOOLEAN__STRING_INT_UINT,
524 G_TYPE_BOOLEAN((GType) ((5) << (2))),
525 3, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_INT((GType) ((6) << (2))), G_TYPE_UINT((GType) ((7) << (2))));
526
527 signals[CLOSE_SCREEN] =
528 g_signal_new (I_("close-screen")g_intern_static_string ("close-screen"),
529 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
530 G_SIGNAL_RUN_LAST,
531 G_STRUCT_OFFSET (TerminalScreenClass, close_screen)((glong) __builtin_offsetof(TerminalScreenClass, close_screen
))
,
532 NULL((void*)0), NULL((void*)0),
533 g_cclosure_marshal_VOID__VOID,
534 G_TYPE_NONE((GType) ((1) << (2))),
535 0);
536
537 g_object_class_install_property
538 (object_class,
539 PROP_PROFILE,
540 g_param_spec_string ("profile", NULL((void*)0), NULL((void*)0),
541 NULL((void*)0),
542 G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
543
544 g_object_class_install_property
545 (object_class,
546 PROP_ICON_TITLE,
547 g_param_spec_string ("icon-title", NULL((void*)0), NULL((void*)0),
548 NULL((void*)0),
549 G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
550
551 g_object_class_install_property
552 (object_class,
553 PROP_ICON_TITLE_SET,
554 g_param_spec_boolean ("icon-title-set", NULL((void*)0), NULL((void*)0),
555 FALSE(0),
556 G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
557
558 g_object_class_install_property
559 (object_class,
560 PROP_OVERRIDE_COMMAND,
561 g_param_spec_boxed ("override-command", NULL((void*)0), NULL((void*)0),
562 G_TYPE_STRV(g_strv_get_type ()),
563 G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
564
565 g_object_class_install_property
566 (object_class,
567 PROP_TITLE,
568 g_param_spec_string ("title", NULL((void*)0), NULL((void*)0),
569 NULL((void*)0),
570 G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
571
572 g_object_class_install_property
573 (object_class,
574 PROP_INITIAL_ENVIRONMENT,
575 g_param_spec_boxed ("initial-environment", NULL((void*)0), NULL((void*)0),
576 G_TYPE_STRV(g_strv_get_type ()),
577 G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
578
579 /* Precompile the regexes */
580 n_url_regexes = G_N_ELEMENTS (url_regex_patterns)(sizeof (url_regex_patterns) / sizeof ((url_regex_patterns)[0
]))
;
581 url_regexes = g_new0 (BteRegex*, n_url_regexes)((BteRegex* *) g_malloc0_n ((n_url_regexes), sizeof (BteRegex
*)))
;
582 url_regex_flavors = g_new0 (TerminalURLFlavour, n_url_regexes)((TerminalURLFlavour *) g_malloc0_n ((n_url_regexes), sizeof (
TerminalURLFlavour)))
;
583
584 for (i = 0; i < n_url_regexes; ++i)
4
Assuming 'i' is >= 'n_url_regexes'
5
Loop condition is false. Execution continues on line 600
585 {
586 GError *error = NULL((void*)0);
587
588 url_regexes[i] = bte_regex_new_for_match(url_regex_patterns[i].pattern, -1,
589 url_regex_patterns[i].flags | PCRE2_MULTILINE0x00000400u, &error);
590 if (error)
591 {
592 g_message ("%s", error->message);
593 g_error_free (error);
594 }
595
596 url_regex_flavors[i] = url_regex_patterns[i].flavor;
597 }
598
599#ifdef ENABLE_SKEY1
600 n_skey_regexes = G_N_ELEMENTS (skey_regex_patterns)(sizeof (skey_regex_patterns) / sizeof ((skey_regex_patterns)
[0]))
;
601 skey_regexes = g_new0 (BteRegex*, n_skey_regexes)((BteRegex* *) g_malloc0_n ((n_skey_regexes), sizeof (BteRegex
*)))
;
602
603 for (i = 0; i < n_skey_regexes; ++i)
6
Assuming 'i' is < 'n_skey_regexes'
7
Loop condition is true. Entering loop body
10
Assuming 'i' is < 'n_skey_regexes'
11
Loop condition is true. Entering loop body
14
Assuming 'i' is < 'n_skey_regexes'
15
Loop condition is true. Entering loop body
604 {
605 GError *error = NULL((void*)0);
606
607 skey_regexes[i] = bte_regex_new_for_match(skey_regex_patterns[i].pattern, -1,
16
Access of 'skey_regex_patterns' at index 2, while it holds only 2 'TerminalRegexPattern' elements
608 PCRE2_MULTILINE0x00000400u | PCRE2_UTF0x00080000u | PCRE2_NO_UTF_CHECK0x40000000u, &error);
609 if (error)
8
Assuming 'error' is null
9
Taking false branch
12
Assuming 'error' is null
13
Taking false branch
610 {
611 g_message ("%s", error->message);
612 g_error_free (error);
613 }
614 }
615#endif /* ENABLE_SKEY */
616
617 /* This fixes bug #329827 */
618 app = terminal_app_get ();
619 terminal_screen_class_enable_menu_bar_accel_notify_cb (app, NULL((void*)0), klass);
620 g_signal_connect (app, "notify::" TERMINAL_APP_ENABLE_MENU_BAR_ACCEL,g_signal_connect_data ((app), ("notify::" "enable-menu-accels"
), (((GCallback) (terminal_screen_class_enable_menu_bar_accel_notify_cb
))), (klass), ((void*)0), (GConnectFlags) 0)
621 G_CALLBACK (terminal_screen_class_enable_menu_bar_accel_notify_cb), klass)g_signal_connect_data ((app), ("notify::" "enable-menu-accels"
), (((GCallback) (terminal_screen_class_enable_menu_bar_accel_notify_cb
))), (klass), ((void*)0), (GConnectFlags) 0)
;
622}
623
624static void
625terminal_screen_dispose (GObject *object)
626{
627 TerminalScreen *screen = TERMINAL_SCREEN (object)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((terminal_screen_get_type ()))))))
;
628 TerminalScreenPrivate *priv = screen->priv;
629 CtkSettings *settings;
630
631 settings = ctk_widget_get_settings (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
);
632 g_signal_handlers_disconnect_matched (settings, G_SIGNAL_MATCH_DATA,
633 0, 0, NULL((void*)0), NULL((void*)0),
634 screen);
635
636 if (priv->launch_child_source_id != 0)
637 {
638 g_source_remove (priv->launch_child_source_id);
639 priv->launch_child_source_id = 0;
640 }
641
642 G_OBJECT_CLASS (terminal_screen_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((terminal_screen_parent_class)), (((GType) ((20) <<
(2))))))))
->dispose (object);
643}
644
645static void
646terminal_screen_finalize (GObject *object)
647{
648 TerminalScreen *screen = TERMINAL_SCREEN (object)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((terminal_screen_get_type ()))))))
;
649 TerminalScreenPrivate *priv = screen->priv;
650
651 g_signal_handlers_disconnect_by_func (terminal_app_get (),g_signal_handlers_disconnect_matched ((terminal_app_get ()), (
GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)
, 0, 0, ((void*)0), (((GCallback) (terminal_screen_system_font_notify_cb
))), (screen))
652 G_CALLBACK (terminal_screen_system_font_notify_cb),g_signal_handlers_disconnect_matched ((terminal_app_get ()), (
GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)
, 0, 0, ((void*)0), (((GCallback) (terminal_screen_system_font_notify_cb
))), (screen))
653 screen)g_signal_handlers_disconnect_matched ((terminal_app_get ()), (
GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)
, 0, 0, ((void*)0), (((GCallback) (terminal_screen_system_font_notify_cb
))), (screen))
;
654
655 terminal_screen_set_profile (screen, NULL((void*)0));
656
657 g_free (priv->raw_title);
658 g_free (priv->cooked_title);
659 g_free (priv->override_title);
660 g_free (priv->raw_icon_title);
661 g_free (priv->cooked_icon_title);
662 g_free (priv->initial_working_directory);
663 g_strfreev (priv->override_command);
664 g_strfreev (priv->initial_env);
665
666 g_slist_foreach (priv->match_tags, (GFunc) free_tag_data, NULL((void*)0));
667 g_slist_free (priv->match_tags);
668
669 if (priv->bg_image)
670 g_object_unref (priv->bg_image);
671
672 G_OBJECT_CLASS (terminal_screen_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((terminal_screen_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
673}
674
675static gboolean
676terminal_screen_image_draw_cb (CtkWidget *widget, cairo_t *cr, void *userdata)
677{
678 TerminalScreen *screen = TERMINAL_SCREEN (widget)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((terminal_screen_get_type ()))))))
;
679 TerminalScreenPrivate *priv = screen->priv;
680 GdkPixbuf *bg_image = priv->bg_image;
681 CdkRectangle target_rect;
682 CtkAllocation alloc;
683 cairo_surface_t *child_surface;
684 cairo_t *child_cr;
685
686 if (!bg_image)
687 return FALSE(0);
688
689 ctk_widget_get_allocation (widget, &alloc);
690
691 target_rect.x = 0;
692 target_rect.y = 0;
693 target_rect.width = alloc.width;
694 target_rect.height = alloc.height;
695
696 child_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
697 child_cr = cairo_create (child_surface);
698
699 g_signal_handler_block (screen, priv->bg_image_callback_id);
700 ctk_widget_draw (widget, child_cr);
701 g_signal_handler_unblock (screen, priv->bg_image_callback_id);
702
703 cdk_cairo_set_source_pixbuf (cr, bg_image, 0, 0);
704 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
705
706 cdk_cairo_rectangle (cr, &target_rect);
707 cairo_fill (cr);
708
709 cairo_set_source_surface (cr, child_surface, 0, 0);
710 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
711 cairo_paint (cr);
712
713 cairo_destroy (child_cr);
714 cairo_surface_destroy (child_surface);
715
716 return TRUE(!(0));
717}
718
719TerminalScreen *
720terminal_screen_new (TerminalProfile *profile,
721 char **override_command,
722 const char *title,
723 const char *working_dir,
724 char **child_env,
725 double zoom)
726{
727 TerminalScreen *screen;
728 TerminalScreenPrivate *priv;
729
730 g_return_val_if_fail (TERMINAL_IS_PROFILE (profile), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((profile)); GType __t = ((terminal_profile_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "TERMINAL_IS_PROFILE (profile)"); return
(((void*)0)); } } while (0)
;
731
732 screen = g_object_new (TERMINAL_TYPE_SCREEN(terminal_screen_get_type ()), NULL((void*)0));
733 priv = screen->priv;
734
735 terminal_screen_set_profile (screen, profile);
736
737 if (terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_USE_CUSTOM_DEFAULT_SIZE"use-custom-default-size"))
738 {
739 bte_terminal_set_size (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
,
740 terminal_profile_get_property_int (profile, TERMINAL_PROFILE_DEFAULT_SIZE_COLUMNS"default-size-columns"),
741 terminal_profile_get_property_int (profile, TERMINAL_PROFILE_DEFAULT_SIZE_ROWS"default-size-rows"));
742 }
743
744 if (title)
745 terminal_screen_set_override_title (screen, title);
746
747 priv->initial_working_directory = g_strdup (working_dir)g_strdup_inline (working_dir);
748
749 if (override_command)
750 terminal_screen_set_override_command (screen, override_command);
751
752 if (child_env)
753 terminal_screen_set_initial_environment (screen, child_env);
754
755 terminal_screen_set_font_scale (screen, zoom);
756 terminal_screen_set_font (screen);
757
758 /* Launch the child on idle */
759 terminal_screen_launch_child_on_idle (screen);
760
761 return screen;
762}
763
764const char*
765terminal_screen_get_raw_title (TerminalScreen *screen)
766{
767 TerminalScreenPrivate *priv = screen->priv;
768
769 if (priv->raw_title)
770 return priv->raw_title;
771
772 return "";
773}
774
775const char*
776terminal_screen_get_title (TerminalScreen *screen)
777{
778 TerminalScreenPrivate *priv = screen->priv;
779
780 if (priv->cooked_title == NULL((void*)0))
781 terminal_screen_cook_title (screen);
782
783 /* cooked_title may still be NULL */
784 if (priv->cooked_title != NULL((void*)0))
785 return priv->cooked_title;
786 else
787 return "";
788}
789
790const char*
791terminal_screen_get_icon_title (TerminalScreen *screen)
792{
793 TerminalScreenPrivate *priv = screen->priv;
794
795 if (priv->cooked_icon_title == NULL((void*)0))
796 terminal_screen_cook_icon_title (screen);
797
798 /* cooked_icon_title may still be NULL */
799 if (priv->cooked_icon_title != NULL((void*)0))
800 return priv->cooked_icon_title;
801 else
802 return "";
803}
804
805gboolean
806terminal_screen_get_icon_title_set (TerminalScreen *screen)
807{
808 return screen->priv->icon_title_set;
809}
810
811/* Supported format specifiers:
812 * %S = static title
813 * %D = dynamic title
814 * %A = dynamic title, falling back to static title if empty
815 * %- = separator, if not at start or end of string (excluding whitespace)
816 */
817static const char *
818terminal_screen_get_title_format (TerminalScreen *screen)
819{
820 TerminalScreenPrivate *priv = screen->priv;
821 static const char *formats[] =
822 {
823 "%A" /* TERMINAL_TITLE_REPLACE */,
824 "%D%-%S" /* TERMINAL_TITLE_BEFORE */,
825 "%S%-%D" /* TERMINAL_TITLE_AFTER */,
826 "%S" /* TERMINAL_TITLE_IGNORE */
827 };
828
829 return formats[terminal_profile_get_property_enum (priv->profile, TERMINAL_PROFILE_TITLE_MODE"title-mode")];
830}
831
832/**
833 * terminal_screen_format_title::
834 * @screen:
835 * @raw_title: main ingredient
836 * @titleptr <inout>: pointer of the current title string
837 *
838 * Format title according @format, and stores it in <literal>*titleptr</literal>.
839 * Always ensures that *titleptr will be non-NULL.
840 *
841 * Returns: %TRUE iff the title changed
842 */
843static gboolean
844terminal_screen_format_title (TerminalScreen *screen,
845 const char *raw_title,
846 char **titleptr)
847{
848 TerminalScreenPrivate *priv = screen->priv;
849 const char *format, *arg;
850 const char *static_title = NULL((void*)0);
851 GString *title;
852 gboolean add_sep = FALSE(0);
853
854 g_assert (titleptr)do { if (titleptr) ; else g_assertion_message_expr (((gchar*)
0), "terminal-screen.c", 854, ((const char*) (__func__)), "titleptr"
); } while (0)
;
855
856 /* use --title argument if one was supplied, otherwise ask the profile */
857 if (priv->override_title)
858 static_title = priv->override_title;
859 else
860 static_title = terminal_profile_get_property_string (priv->profile, TERMINAL_PROFILE_TITLE"title");
861
862 //title = g_string_sized_new (strlen (static_title) + strlen (raw_title) + 3 + 1);
863 title = g_string_sized_new (128);
864
865 format = terminal_screen_get_title_format (screen);
866 for (arg = format; *arg; arg += 2)
867 {
868 const char *text_to_append = NULL((void*)0);
869
870 g_assert (arg[0] == '%')do { if (arg[0] == '%') ; else g_assertion_message_expr (((gchar
*) 0), "terminal-screen.c", 870, ((const char*) (__func__)), "arg[0] == '%'"
); } while (0)
;
871
872 switch (arg[1])
873 {
874 case 'A':
875 text_to_append = raw_title ? raw_title : static_title;
876 break;
877 case 'D':
878 text_to_append = raw_title;
879 break;
880 case 'S':
881 text_to_append = static_title;
882 break;
883 case '-':
884 text_to_append = NULL((void*)0);
885 add_sep = TRUE(!(0));
886 break;
887 default:
888 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "terminal-screen.c"
, 888, ((const char*) (__func__)), ((void*)0)); } while (0)
;
889 }
890
891 if (!text_to_append || !text_to_append[0])
892 continue;
893
894 if (add_sep && title->len > 0)
895 g_string_append (title, " - ")(__builtin_constant_p (" - ") ? __extension__ ({ const char *
const __val = (" - "); g_string_append_len_inline (title, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (title, " - "
, (gssize) -1))
;
896
897 g_string_append (title, text_to_append)(__builtin_constant_p (text_to_append) ? __extension__ ({ const
char * const __val = (text_to_append); g_string_append_len_inline
(title, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(title, text_to_append, (gssize) -1))
;
898 add_sep = FALSE(0);
899 }
900
901 if (*titleptr == NULL((void*)0) || strcmp (title->str, *titleptr) != 0)
902 {
903 g_free (*titleptr);
904 *titleptr = g_string_free (title, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((title
), ((0))) : g_string_free_and_steal (title)) : (g_string_free
) ((title), ((0))))
;
905 return TRUE(!(0));
906 }
907
908 g_string_free (title, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(title), ((!(0)))) : g_string_free_and_steal (title)) : (g_string_free
) ((title), ((!(0)))))
;
909 return FALSE(0);
910}
911
912static void
913terminal_screen_cook_title (TerminalScreen *screen)
914{
915 TerminalScreenPrivate *priv = screen->priv;
916
917 if (terminal_screen_format_title (screen, priv->raw_title, &priv->cooked_title))
918 g_object_notify (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "title");
919}
920
921static void
922terminal_screen_cook_icon_title (TerminalScreen *screen)
923{
924 TerminalScreenPrivate *priv = screen->priv;
925
926 if (terminal_screen_format_title (screen, priv->raw_icon_title, &priv->cooked_icon_title))
927 g_object_notify (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "icon-title");
928}
929
930static void
931terminal_screen_profile_notify_cb (TerminalProfile *profile,
932 GParamSpec *pspec,
933 TerminalScreen *screen)
934{
935 TerminalScreenPrivate *priv = screen->priv;
936 GObject *object = G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
;
937 BteTerminal *bte_terminal = BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
;
938 const char *prop_name;
939 TerminalWindow *window;
940
941 if (pspec)
942 prop_name = pspec->name;
943 else
944 prop_name = NULL((void*)0);
945
946 g_object_freeze_notify (object);
947
948 if ((window = terminal_screen_get_window (screen)))
949 {
950 /* We need these in line for the set_size in
951 * update_on_realize
952 */
953 terminal_window_update_geometry (window);
954
955 /* madars.vitolins@gmail.com 24/07/2014 -
956 * update terminal window config
957 * with the flag of copy selection to clipboard or not. */
958 terminal_window_update_copy_selection(screen, window);
959 }
960
961 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_SCROLLBAR_POSITION)g_intern_static_string ("scrollbar-position"))
962 _terminal_screen_update_scrollbar (screen);
963
964 if (!prop_name ||
965 prop_name == I_(TERMINAL_PROFILE_TITLE_MODE)g_intern_static_string ("title-mode") ||
966 prop_name == I_(TERMINAL_PROFILE_TITLE)g_intern_static_string ("title"))
967 {
968 terminal_screen_cook_title (screen);
969 terminal_screen_cook_icon_title (screen);
970 }
971
972 if (ctk_widget_get_realized (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
) &&
973 (!prop_name ||
974 prop_name == I_(TERMINAL_PROFILE_USE_SYSTEM_FONT)g_intern_static_string ("use-system-font") ||
975 prop_name == I_(TERMINAL_PROFILE_FONT)g_intern_static_string ("font")))
976 terminal_screen_change_font (screen);
977
978 if (!prop_name ||
979 prop_name == I_(TERMINAL_PROFILE_USE_THEME_COLORS)g_intern_static_string ("use-theme-colors") ||
980 prop_name == I_(TERMINAL_PROFILE_FOREGROUND_COLOR)g_intern_static_string ("foreground-color") ||
981 prop_name == I_(TERMINAL_PROFILE_BACKGROUND_COLOR)g_intern_static_string ("background-color") ||
982 prop_name == I_(TERMINAL_PROFILE_BACKGROUND_TYPE)g_intern_static_string ("background-type") ||
983 prop_name == I_(TERMINAL_PROFILE_BACKGROUND_DARKNESS)g_intern_static_string ("background-darkness") ||
984 prop_name == I_(TERMINAL_PROFILE_BACKGROUND_IMAGE)g_intern_static_string ("background-image") ||
985 prop_name == I_(TERMINAL_PROFILE_BOLD_COLOR_SAME_AS_FG)g_intern_static_string ("bold-color-same-as-fg") ||
986 prop_name == I_(TERMINAL_PROFILE_BOLD_COLOR)g_intern_static_string ("bold-color") ||
987 prop_name == I_(TERMINAL_PROFILE_PALETTE)g_intern_static_string ("palette"))
988 update_color_scheme (screen);
989
990 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_SILENT_BELL)g_intern_static_string ("silent-bell"))
991 bte_terminal_set_audible_bell (bte_terminal, !terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_SILENT_BELL"silent-bell"));
992 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_WORD_CHARS)g_intern_static_string ("word-chars"))
993 bte_terminal_set_word_char_exceptions (bte_terminal,
994 terminal_profile_get_property_string (profile, TERMINAL_PROFILE_WORD_CHARS"word-chars"));
995 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE)g_intern_static_string ("scroll-on-keystroke"))
996 bte_terminal_set_scroll_on_keystroke (bte_terminal,
997 terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE"scroll-on-keystroke"));
998 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_SCROLL_ON_OUTPUT)g_intern_static_string ("scroll-on-output"))
999 bte_terminal_set_scroll_on_output (bte_terminal,
1000 terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_SCROLL_ON_OUTPUT"scroll-on-output"));
1001 if (!prop_name ||
1002 prop_name == I_(TERMINAL_PROFILE_SCROLLBACK_LINES)g_intern_static_string ("scrollback-lines") ||
1003 prop_name == I_(TERMINAL_PROFILE_SCROLLBACK_UNLIMITED)g_intern_static_string ("scrollback-unlimited"))
1004 {
1005 glong lines = terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_SCROLLBACK_UNLIMITED"scrollback-unlimited") ?
1006 -1 : terminal_profile_get_property_int (profile, TERMINAL_PROFILE_SCROLLBACK_LINES"scrollback-lines");
1007 bte_terminal_set_scrollback_lines (bte_terminal, lines);
1008 }
1009
1010#ifdef ENABLE_SKEY1
1011 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_USE_SKEY)g_intern_static_string ("use-skey"))
1012 {
1013 if (terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_USE_SKEY"use-skey"))
1014 {
1015 guint i;
1016
1017 for (i = 0; i < n_skey_regexes; ++i)
1018 {
1019 TagData *tag_data;
1020
1021 tag_data = g_slice_new (TagData)((TagData*) g_slice_alloc (sizeof (TagData)));
1022 tag_data->flavor = FLAVOR_SKEY;
1023 tag_data->tag = bte_terminal_match_add_regex (bte_terminal, skey_regexes[i], 0);
1024 bte_terminal_match_set_cursor_name (bte_terminal, tag_data->tag, "hand2");
1025
1026 priv->match_tags = g_slist_prepend (priv->match_tags, tag_data);
1027 }
1028 }
1029 else
1030 {
1031 terminal_screen_skey_match_remove (screen);
1032 }
1033 }
1034#endif /* ENABLE_SKEY */
1035
1036 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_BACKSPACE_BINDING)g_intern_static_string ("backspace-binding"))
1037 bte_terminal_set_backspace_binding (bte_terminal,
1038 terminal_profile_get_property_enum (profile, TERMINAL_PROFILE_BACKSPACE_BINDING"backspace-binding"));
1039
1040 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_DELETE_BINDING)g_intern_static_string ("delete-binding"))
1041 bte_terminal_set_delete_binding (bte_terminal,
1042 terminal_profile_get_property_enum (profile, TERMINAL_PROFILE_DELETE_BINDING"delete-binding"));
1043
1044 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_ALLOW_BOLD)g_intern_static_string ("allow-bold"))
1045 bte_terminal_set_allow_bold (bte_terminal,
1046 terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_ALLOW_BOLD"allow-bold"));
1047
1048 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_CURSOR_BLINK_MODE)g_intern_static_string ("cursor-blink-mode"))
1049 bte_terminal_set_cursor_blink_mode (bte_terminal,
1050 terminal_profile_get_property_enum (priv->profile, TERMINAL_PROFILE_CURSOR_BLINK_MODE"cursor-blink-mode"));
1051
1052 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_CURSOR_SHAPE)g_intern_static_string ("cursor-shape"))
1053 bte_terminal_set_cursor_shape (bte_terminal,
1054 terminal_profile_get_property_enum (priv->profile, TERMINAL_PROFILE_CURSOR_SHAPE"cursor-shape"));
1055
1056 if (!prop_name || prop_name == I_(TERMINAL_PROFILE_USE_URLS)g_intern_static_string ("use-urls"))
1057 {
1058 if (terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_USE_URLS"use-urls"))
1059 {
1060 guint i;
1061
1062 for (i = 0; i < n_url_regexes; ++i)
1063 {
1064 TagData *tag_data;
1065
1066 tag_data = g_slice_new (TagData)((TagData*) g_slice_alloc (sizeof (TagData)));
1067 tag_data->flavor = url_regex_flavors[i];
1068 tag_data->tag = bte_terminal_match_add_regex (bte_terminal, url_regexes[i], 0);
1069 bte_terminal_match_set_cursor_name (bte_terminal, tag_data->tag, "hand2");
1070
1071 priv->match_tags = g_slist_prepend (priv->match_tags, tag_data);
1072 }
1073 }
1074 else
1075 {
1076 terminal_screen_url_match_remove (screen);
1077 }
1078 }
1079 g_object_thaw_notify (object);
1080}
1081
1082static void
1083update_color_scheme (TerminalScreen *screen)
1084{
1085 TerminalScreenPrivate *priv = screen->priv;
1086 TerminalProfile *profile = priv->profile;
1087 CdkRGBA colors[TERMINAL_PALETTE_SIZE16];
1088 const CdkRGBA *bold_rgba;
1089 TerminalBackgroundType bg_type;
1090 const gchar *bg_image_file;
1091 double bg_alpha = 1.0;
1092 CdkRGBA fg, bg;
1093 CdkRGBA *c;
1094 guint n_colors;
1095 CtkStyleContext *context;
1096 GError *error = NULL((void*)0);
1097
1098 context = ctk_widget_get_style_context (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
);
1099 ctk_style_context_save (context);
1100 ctk_style_context_set_state (context, CTK_STATE_FLAG_NORMAL);
1101 ctk_style_context_get_color (context, CTK_STATE_FLAG_NORMAL, &fg);
1102
1103 ctk_style_context_get (context, CTK_STATE_FLAG_NORMAL,
1104 CTK_STYLE_PROPERTY_BACKGROUND_COLOR"background-color",
1105 &c, NULL((void*)0));
1106 bg = *c;
1107 cdk_rgba_free (c);
1108
1109 ctk_style_context_restore (context);
1110
1111 bold_rgba = NULL((void*)0);
1112
1113 if (!terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_USE_THEME_COLORS"use-theme-colors"))
1114 {
1115 const CdkRGBA *fg_rgba, *bg_rgba;
1116
1117 fg_rgba = terminal_profile_get_property_boxed (profile, TERMINAL_PROFILE_FOREGROUND_COLOR"foreground-color");
1118 bg_rgba = terminal_profile_get_property_boxed (profile, TERMINAL_PROFILE_BACKGROUND_COLOR"background-color");
1119
1120 if (!terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_BOLD_COLOR_SAME_AS_FG"bold-color-same-as-fg"))
1121 bold_rgba = terminal_profile_get_property_boxed (profile, TERMINAL_PROFILE_BOLD_COLOR"bold-color");
1122
1123 if (fg_rgba)
1124 fg = *fg_rgba;
1125 if (bg_rgba)
1126 bg = *bg_rgba;
1127 }
1128
1129 n_colors = G_N_ELEMENTS (colors)(sizeof (colors) / sizeof ((colors)[0]));
1130 terminal_profile_get_palette (priv->profile, colors, &n_colors);
1131
1132 bg_type = terminal_profile_get_property_enum (profile, TERMINAL_PROFILE_BACKGROUND_TYPE"background-type");
1133 bg_image_file = terminal_profile_get_property_string (profile, TERMINAL_PROFILE_BACKGROUND_IMAGE_FILE"background-image-file");
1134
1135 if (bg_type == TERMINAL_BACKGROUND_TRANSPARENT)
1136 bg_alpha = terminal_profile_get_property_double (profile, TERMINAL_PROFILE_BACKGROUND_DARKNESS"background-darkness");
1137 else if (bg_type == TERMINAL_BACKGROUND_IMAGE)
1138 bg_alpha = 0.0;
1139 bg.alpha = bg_alpha;
1140
1141 if (bg_type == TERMINAL_BACKGROUND_IMAGE)
1142 {
1143 if (!priv->bg_image_callback_id)
1144 priv->bg_image_callback_id = g_signal_connect (screen, "draw", G_CALLBACK (terminal_screen_image_draw_cb), NULL)g_signal_connect_data ((screen), ("draw"), (((GCallback) (terminal_screen_image_draw_cb
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
1145
1146 g_clear_object (&priv->bg_image)do { _Static_assert (sizeof *((&priv->bg_image)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->bg_image))) _pp = ((&priv->bg_image)); __typeof__
(*((&priv->bg_image))) _ptr = *_pp; *_pp = ((void*)0)
; if (_ptr) (g_object_unref) (_ptr); } while (0)
;
1147 priv->bg_image = gdk_pixbuf_new_from_file (bg_image_file, &error);
1148
1149 if (error) {
1150 g_printerr ("Failed to load background image: %s\n", error->message);
1151 g_clear_error (&error);
1152 }
1153
1154 ctk_widget_queue_draw (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
);
1155 } else {
1156 if (priv->bg_image_callback_id)
1157 {
1158 g_signal_handler_disconnect (screen, priv->bg_image_callback_id);
1159 priv->bg_image_callback_id = 0;
1160 }
1161 }
1162
1163 bte_terminal_set_colors (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
,
1164 &fg, &bg,
1165 colors, n_colors);
1166 if (bold_rgba)
1167 bte_terminal_set_color_bold (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
,
1168 bold_rgba);
1169}
1170
1171void
1172terminal_screen_set_font (TerminalScreen *screen)
1173{
1174 TerminalScreenPrivate *priv = screen->priv;
1175 TerminalProfile *profile;
1176 PangoFontDescription *desc;
1177
1178 profile = priv->profile;
1179
1180 if (terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_USE_SYSTEM_FONT"use-system-font"))
1181 g_object_get (terminal_app_get (), "system-font", &desc, NULL((void*)0));
1182 else
1183 g_object_get (profile, TERMINAL_PROFILE_FONT"font", &desc, NULL((void*)0));
1184 g_assert (desc)do { if (desc) ; else g_assertion_message_expr (((gchar*) 0),
"terminal-screen.c", 1184, ((const char*) (__func__)), "desc"
); } while (0)
;
1185
1186 if (pango_font_description_get_size_is_absolute (desc))
1187 pango_font_description_set_absolute_size (desc,
1188 priv->font_scale *
1189 pango_font_description_get_size (desc));
1190 else
1191 pango_font_description_set_size (desc,
1192 priv->font_scale *
1193 pango_font_description_get_size (desc));
1194
1195 bte_terminal_set_font (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, desc);
1196
1197 pango_font_description_free (desc);
1198}
1199
1200static void
1201terminal_screen_system_font_notify_cb (TerminalApp *app,
1202 GParamSpec *pspec,
1203 TerminalScreen *screen)
1204{
1205 TerminalScreenPrivate *priv = screen->priv;
1206
1207 if (!ctk_widget_get_realized (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
))
1208 return;
1209
1210 if (!terminal_profile_get_property_boolean (priv->profile, TERMINAL_PROFILE_USE_SYSTEM_FONT"use-system-font"))
1211 return;
1212
1213 terminal_screen_change_font (screen);
1214}
1215
1216static void
1217terminal_screen_change_font (TerminalScreen *screen)
1218{
1219 TerminalWindow *window;
1220
1221 terminal_screen_set_font (screen);
1222
1223 window = terminal_screen_get_window (screen);
1224 terminal_window_update_size (window, screen, TRUE(!(0)));
1225}
1226
1227static void
1228profile_forgotten_callback (TerminalProfile *profile,
1229 TerminalScreen *screen)
1230{
1231 TerminalProfile *new_profile;
1232
1233 new_profile = terminal_app_get_profile_for_new_term (terminal_app_get ());
1234 g_assert (new_profile != NULL)do { if (new_profile != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "terminal-screen.c", 1234, ((const char*) (__func__
)), "new_profile != NULL"); } while (0)
;
1235 terminal_screen_set_profile (screen, new_profile);
1236}
1237
1238void
1239terminal_screen_set_profile (TerminalScreen *screen,
1240 TerminalProfile *profile)
1241{
1242 TerminalScreenPrivate *priv = screen->priv;
1243 TerminalProfile *old_profile;
1244
1245 old_profile = priv->profile;
1246 if (profile == old_profile)
1247 return;
1248
1249 if (priv->profile_changed_id)
1250 {
1251 g_signal_handler_disconnect (G_OBJECT (priv->profile)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->profile)), (((GType) ((20) << (2))))))))
,
1252 priv->profile_changed_id);
1253 priv->profile_changed_id = 0;
1254 }
1255
1256 if (priv->profile_forgotten_id)
1257 {
1258 g_signal_handler_disconnect (G_OBJECT (priv->profile)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->profile)), (((GType) ((20) << (2))))))))
,
1259 priv->profile_forgotten_id);
1260 priv->profile_forgotten_id = 0;
1261 }
1262
1263 priv->profile = profile;
1264 if (profile)
1265 {
1266 g_object_ref (profile)((__typeof__ (profile)) (g_object_ref) (profile));
1267 priv->profile_changed_id =
1268 g_signal_connect (profile, "notify",g_signal_connect_data ((profile), ("notify"), (((GCallback) (
terminal_screen_profile_notify_cb))), (screen), ((void*)0), (
GConnectFlags) 0)
1269 G_CALLBACK (terminal_screen_profile_notify_cb),g_signal_connect_data ((profile), ("notify"), (((GCallback) (
terminal_screen_profile_notify_cb))), (screen), ((void*)0), (
GConnectFlags) 0)
1270 screen)g_signal_connect_data ((profile), ("notify"), (((GCallback) (
terminal_screen_profile_notify_cb))), (screen), ((void*)0), (
GConnectFlags) 0)
;
1271 priv->profile_forgotten_id =
1272 g_signal_connect (G_OBJECT (profile),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((profile)), (((GType) ((20) << (2))
))))))), ("forgotten"), (((GCallback) (profile_forgotten_callback
))), (screen), ((void*)0), (GConnectFlags) 0)
1273 "forgotten",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((profile)), (((GType) ((20) << (2))
))))))), ("forgotten"), (((GCallback) (profile_forgotten_callback
))), (screen), ((void*)0), (GConnectFlags) 0)
1274 G_CALLBACK (profile_forgotten_callback),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((profile)), (((GType) ((20) << (2))
))))))), ("forgotten"), (((GCallback) (profile_forgotten_callback
))), (screen), ((void*)0), (GConnectFlags) 0)
1275 screen)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((profile)), (((GType) ((20) << (2))
))))))), ("forgotten"), (((GCallback) (profile_forgotten_callback
))), (screen), ((void*)0), (GConnectFlags) 0)
;
1276
1277 terminal_screen_profile_notify_cb (profile, NULL((void*)0), screen);
1278
1279 g_signal_emit (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, signals[PROFILE_SET], 0, old_profile);
1280 }
1281
1282 if (old_profile)
1283 g_object_unref (old_profile);
1284
1285 g_object_notify (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "profile");
1286}
1287
1288TerminalProfile*
1289terminal_screen_get_profile (TerminalScreen *screen)
1290{
1291 TerminalScreenPrivate *priv = screen->priv;
1292
1293 g_assert (priv->profile != NULL)do { if (priv->profile != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "terminal-screen.c", 1293, ((const char*) (__func__
)), "priv->profile != NULL"); } while (0)
;
1294 return priv->profile;
1295}
1296
1297void
1298terminal_screen_set_override_command (TerminalScreen *screen,
1299 char **argv)
1300{
1301 TerminalScreenPrivate *priv;
1302
1303 g_return_if_fail (TERMINAL_IS_SCREEN (screen))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return; } } while
(0)
;
1304
1305 priv = screen->priv;
1306 g_strfreev (priv->override_command);
1307 priv->override_command = g_strdupv (argv);
1308}
1309
1310const char**
1311terminal_screen_get_override_command (TerminalScreen *screen)
1312{
1313 g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return (((void
*)0)); } } while (0)
;
1314
1315 return (const char**) screen->priv->override_command;
1316}
1317
1318void
1319terminal_screen_set_initial_environment (TerminalScreen *screen,
1320 char **argv)
1321{
1322 TerminalScreenPrivate *priv;
1323
1324 g_return_if_fail (TERMINAL_IS_SCREEN (screen))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return; } } while
(0)
;
1325
1326 priv = screen->priv;
1327 g_assert (priv->initial_env == NULL)do { if (priv->initial_env == ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "terminal-screen.c", 1327, ((const char*) (__func__
)), "priv->initial_env == NULL"); } while (0)
;
1328 priv->initial_env = g_strdupv (argv);
1329}
1330
1331char**
1332terminal_screen_get_initial_environment (TerminalScreen *screen)
1333{
1334 g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return (((void
*)0)); } } while (0)
;
1335
1336 return screen->priv->initial_env;
1337}
1338
1339static gboolean
1340get_child_command (TerminalScreen *screen,
1341 const char *shell_env,
1342 GSpawnFlags *spawn_flags_p,
1343 char ***argv_p,
1344 GError **err)
1345{
1346 TerminalScreenPrivate *priv = screen->priv;
1347 TerminalProfile *profile;
1348 char **argv;
1349
1350 g_assert (spawn_flags_p != NULL && argv_p != NULL)do { if (spawn_flags_p != ((void*)0) && argv_p != ((void
*)0)) ; else g_assertion_message_expr (((gchar*) 0), "terminal-screen.c"
, 1350, ((const char*) (__func__)), "spawn_flags_p != NULL && argv_p != NULL"
); } while (0)
;
1351
1352 profile = priv->profile;
1353
1354 *argv_p = argv = NULL((void*)0);
1355
1356 if (priv->override_command)
1357 {
1358 argv = g_strdupv (priv->override_command);
1359
1360 *spawn_flags_p |= G_SPAWN_SEARCH_PATH;
1361 }
1362 else if (terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_USE_CUSTOM_COMMAND"use-custom-command"))
1363 {
1364 if (!g_shell_parse_argv (terminal_profile_get_property_string (profile, TERMINAL_PROFILE_CUSTOM_COMMAND"custom-command"),
1365 NULL((void*)0), &argv,
1366 err))
1367 return FALSE(0);
1368
1369 *spawn_flags_p |= G_SPAWN_SEARCH_PATH;
1370 }
1371 else
1372 {
1373 const char *only_name;
1374 char *shell;
1375 int argc = 0;
1376
1377 shell = egg_shell (shell_env);
1378
1379 only_name = strrchr (shell, '/');
1380 if (only_name != NULL((void*)0))
1381 only_name++;
1382 else
1383 only_name = shell;
1384
1385 argv = g_new (char*, 3)((char* *) g_malloc_n ((3), sizeof (char*)));
1386
1387 argv[argc++] = shell;
1388
1389 if (terminal_profile_get_property_boolean (profile, TERMINAL_PROFILE_LOGIN_SHELL"login-shell"))
1390 argv[argc++] = g_strconcat ("-", only_name, NULL((void*)0));
1391 else
1392 argv[argc++] = g_strdup (only_name)g_strdup_inline (only_name);
1393
1394 argv[argc++] = NULL((void*)0);
1395
1396 *spawn_flags_p |= G_SPAWN_FILE_AND_ARGV_ZERO;
1397 }
1398
1399 *argv_p = argv;
1400
1401 return TRUE(!(0));
1402}
1403
1404static char**
1405get_child_environment (TerminalScreen *screen,
1406 char **shell)
1407{
1408 TerminalScreenPrivate *priv = screen->priv;
1409 CtkWidget *term = CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
;
1410 CtkWidget *window;
1411 CdkDisplay *display;
1412 char **env;
1413 char *e, *v;
1414 GHashTable *env_table;
1415 GHashTableIter iter;
1416 GPtrArray *retval;
1417 guint i;
1418 gchar **list_schemas = NULL((void*)0);
1419 gboolean schema_exists;
1420
1421 window = ctk_widget_get_toplevel (term);
1422 g_assert (window != NULL)do { if (window != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "terminal-screen.c", 1422, ((const char*) (__func__
)), "window != NULL"); } while (0)
;
1423 g_assert (ctk_widget_is_toplevel (window))do { if (ctk_widget_is_toplevel (window)) ; else g_assertion_message_expr
(((gchar*) 0), "terminal-screen.c", 1423, ((const char*) (__func__
)), "ctk_widget_is_toplevel (window)"); } while (0)
;
1424 display = cdk_window_get_display (ctk_widget_get_window (window));
1425
1426 env_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1427
1428 /* First take the factory's environment */
1429 env = g_listenv ();
1430 for (i = 0; env[i]; ++i)
1431 g_hash_table_insert (env_table, env[i], g_strdup (g_getenv (env[i]))g_strdup_inline (g_getenv (env[i])));
1432 g_free (env); /* the strings themselves are now owned by the hash table */
1433
1434 /* and then merge the child environment, if any */
1435 env = priv->initial_env;
1436 if (env)
1437 {
1438 for (i = 0; env[i]; ++i)
1439 {
1440 v = strchr (env[i], '=');
1441 if (v)
1442 g_hash_table_replace (env_table, g_strndup (env[i], v - env[i]), g_strdup (v + 1)g_strdup_inline (v + 1));
1443 else
1444 g_hash_table_replace (env_table, g_strdup (env[i])g_strdup_inline (env[i]), NULL((void*)0));
1445 }
1446 }
1447
1448 g_hash_table_remove (env_table, "COLUMNS");
1449 g_hash_table_remove (env_table, "LINES");
1450 g_hash_table_remove (env_table, "CAFE_DESKTOP_ICON");
1451
1452 g_hash_table_replace (env_table, g_strdup ("TERM")g_strdup_inline ("TERM"), g_strdup ("xterm-256color")g_strdup_inline ("xterm-256color")); /* FIXME configurable later? */
1453
1454 /* FIXME: moving the tab between windows, or the window between displays will make the next two invalid... */
1455 g_hash_table_replace (env_table, g_strdup ("WINDOWID")g_strdup_inline ("WINDOWID"), g_strdup_printf ("%ld", CDK_WINDOW_XID (ctk_widget_get_window (window))(cdk_x11_window_get_xid (ctk_widget_get_window (window)))));
1456 g_hash_table_replace (env_table, g_strdup ("DISPLAY")g_strdup_inline ("DISPLAY"), g_strdup (cdk_display_get_name (display))g_strdup_inline (cdk_display_get_name (display)));
1457
1458 g_settings_schema_source_list_schemas (g_settings_schema_source_get_default (), TRUE(!(0)), &list_schemas, NULL((void*)0));
1459
1460 schema_exists = FALSE(0);
1461 for (i = 0; list_schemas[i] != NULL((void*)0); i++) {
1462 if (g_strcmp0 (list_schemas[i], CONF_PROXY_SCHEMA"org.gnome.system.proxy") == 0)
1463 {
1464 schema_exists = TRUE(!(0));
1465 break;
1466 }
1467 }
1468
1469 g_strfreev (list_schemas);
1470
1471 if (schema_exists == TRUE(!(0))) {
1472 terminal_util_add_proxy_env (env_table);
1473 }
1474
1475 retval = g_ptr_array_sized_new (g_hash_table_size (env_table));
1476 g_hash_table_iter_init (&iter, env_table);
1477 while (g_hash_table_iter_next (&iter, (gpointer *) &e, (gpointer *) &v))
1478 g_ptr_array_add (retval, g_strdup_printf ("%s=%s", e, v ? v : ""));
1479 g_ptr_array_add (retval, NULL((void*)0));
1480
1481 *shell = g_strdup (g_hash_table_lookup (env_table, "SHELL"))g_strdup_inline (g_hash_table_lookup (env_table, "SHELL"));
1482
1483 g_hash_table_destroy (env_table);
1484 return (char **) g_ptr_array_free (retval, FALSE(0));
1485}
1486
1487enum
1488{
1489 RESPONSE_RELAUNCH,
1490 RESPONSE_EDIT_PROFILE
1491};
1492
1493static void
1494info_bar_response_cb (CtkWidget *info_bar,
1495 int response,
1496 TerminalScreen *screen)
1497{
1498 ctk_widget_grab_focus (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
);
1499
1500 switch (response)
1501 {
1502 case CTK_RESPONSE_CANCEL:
1503 ctk_widget_destroy (info_bar);
1504 g_signal_emit (screen, signals[CLOSE_SCREEN], 0);
1505 break;
1506 case RESPONSE_RELAUNCH:
1507 ctk_widget_destroy (info_bar);
1508 terminal_screen_launch_child_on_idle (screen);
1509 break;
1510 case RESPONSE_EDIT_PROFILE:
1511 terminal_app_edit_profile (terminal_app_get (),
1512 terminal_screen_get_profile (screen),
1513 CTK_WINDOW (terminal_screen_get_window (screen))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((terminal_screen_get_window (screen))), ((ctk_window_get_type
()))))))
,
1514 "custom-command-entry");
1515 break;
1516 default:
1517 ctk_widget_destroy (info_bar);
1518 break;
1519 }
1520}
1521
1522static void handle_error_child (TerminalScreen *screen,
1523 GError *err)
1524{
1525 CtkWidget *info_bar;
1526
1527 info_bar = terminal_info_bar_new (CTK_MESSAGE_ERROR,
1528 _("_Profile Preferences")gettext ("_Profile Preferences"), RESPONSE_EDIT_PROFILE,
1529 _("_Relaunch")gettext ("_Relaunch"), RESPONSE_RELAUNCH,
1530 NULL((void*)0));
1531 terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar)((((TerminalInfoBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info_bar)), ((terminal_info_bar_get_type ()))))))
,
1532 _("There was an error creating the child process for this terminal")gettext ("There was an error creating the child process for this terminal"
)
);
1533 terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar)((((TerminalInfoBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info_bar)), ((terminal_info_bar_get_type ()))))))
,
1534 "%s", err->message);
1535 g_signal_connect (info_bar, "response",g_signal_connect_data ((info_bar), ("response"), (((GCallback
) (info_bar_response_cb))), (screen), ((void*)0), (GConnectFlags
) 0)
1536 G_CALLBACK (info_bar_response_cb), screen)g_signal_connect_data ((info_bar), ("response"), (((GCallback
) (info_bar_response_cb))), (screen), ((void*)0), (GConnectFlags
) 0)
;
1537
1538 ctk_box_pack_start (CTK_BOX (terminal_screen_container_get_from_screen (screen))((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((terminal_screen_container_get_from_screen (screen))), ((
ctk_box_get_type ()))))))
,
1539 info_bar, FALSE(0), FALSE(0), 0);
1540 ctk_info_bar_set_default_response (CTK_INFO_BAR (info_bar)((((CtkInfoBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info_bar)), ((ctk_info_bar_get_type()))))))
, CTK_RESPONSE_CANCEL);
1541 ctk_widget_show (info_bar);
1542}
1543
1544static void term_spawn_callback (CtkWidget *terminal,
1545 GPid pid,
1546 GError *error,
1547 gpointer user_data)
1548{
1549 TerminalScreen *screen = TERMINAL_SCREEN (terminal)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((terminal)), ((terminal_screen_get_type ()))))))
;
1550
1551 if (error)
1552 {
1553 handle_error_child (screen, error);
1554 }
1555 else
1556 {
1557 TerminalScreenPrivate *priv = screen->priv;
1558 priv->child_pid = pid;
1559 }
1560}
1561
1562static gboolean
1563terminal_screen_launch_child_cb (TerminalScreen *screen)
1564{
1565 TerminalScreenPrivate *priv = screen->priv;
1566 BteTerminal *terminal = BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
;
1567 char **env, **argv;
1568 char *shell = NULL((void*)0);
1569 GError *err = NULL((void*)0);
1570 const char *working_dir;
1571 BtePtyFlags pty_flags = BTE_PTY_DEFAULT;
1572 GSpawnFlags spawn_flags = 0;
1573
1574 priv->launch_child_source_id = 0;
1575
1576 _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,do { if (0) g_printerr("[screen %p] now launching the child process\n"
, screen); } while (0)
1577 "[screen %p] now launching the child process\n",do { if (0) g_printerr("[screen %p] now launching the child process\n"
, screen); } while (0)
1578 screen)do { if (0) g_printerr("[screen %p] now launching the child process\n"
, screen); } while (0)
;
1579
1580 env = get_child_environment (screen, &shell);
1581
1582 if (priv->initial_working_directory)
1583 working_dir = priv->initial_working_directory;
1584 else
1585 working_dir = g_get_home_dir ();
1586
1587 if (!get_child_command (screen, shell, &spawn_flags, &argv, &err))
1588 {
1589 handle_error_child (screen, err);
1590
1591 g_error_free (err);
1592 g_strfreev (env);
1593 g_free (shell);
1594
1595 return FALSE(0);
1596 }
1597
1598 bte_terminal_spawn_async (terminal,
1599 pty_flags,
1600 working_dir,
1601 argv,
1602 env,
1603 spawn_flags,
1604 NULL((void*)0),
1605 NULL((void*)0),
1606 NULL((void*)0),
1607 -1,
1608 NULL((void*)0),
1609 (BteTerminalSpawnAsyncCallback) term_spawn_callback,
1610 NULL((void*)0));
1611
1612 g_free (shell);
1613 g_strfreev (argv);
1614 g_strfreev (env);
1615
1616 return FALSE(0); /* don't run again */
1617}
1618
1619static void
1620terminal_screen_launch_child_on_idle (TerminalScreen *screen)
1621{
1622 TerminalScreenPrivate *priv = screen->priv;
1623
1624 if (priv->launch_child_source_id != 0)
1625 return;
1626
1627 _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,do { if (0) g_printerr("[screen %p] scheduling launching the child process on idle\n"
, screen); } while (0)
1628 "[screen %p] scheduling launching the child process on idle\n",do { if (0) g_printerr("[screen %p] scheduling launching the child process on idle\n"
, screen); } while (0)
1629 screen)do { if (0) g_printerr("[screen %p] scheduling launching the child process on idle\n"
, screen); } while (0)
;
1630
1631 priv->launch_child_source_id = g_idle_add ((GSourceFunc) terminal_screen_launch_child_cb, screen);
1632}
1633
1634static TerminalScreenPopupInfo *
1635terminal_screen_popup_info_new (TerminalScreen *screen)
1636{
1637 TerminalScreenPopupInfo *info;
1638
1639 info = g_slice_new0 (TerminalScreenPopupInfo)((TerminalScreenPopupInfo*) g_slice_alloc0 (sizeof (TerminalScreenPopupInfo
)))
;
1640 info->ref_count = 1;
1641 info->screen = g_object_ref (screen)((__typeof__ (screen)) (g_object_ref) (screen));
1642 info->window = terminal_screen_get_window (screen);
1643
1644 return info;
1645}
1646
1647TerminalScreenPopupInfo *
1648terminal_screen_popup_info_ref (TerminalScreenPopupInfo *info)
1649{
1650 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "info != NULL"); return
(((void*)0)); } } while (0)
;
1651
1652 info->ref_count++;
1653 return info;
1654}
1655
1656void
1657terminal_screen_popup_info_unref (TerminalScreenPopupInfo *info)
1658{
1659 g_return_if_fail (info != NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "info != NULL"); return
; } } while (0)
;
1660
1661 if (--info->ref_count > 0)
1662 return;
1663
1664 g_object_unref (info->screen);
1665 g_free (info->string);
1666 g_slice_free (TerminalScreenPopupInfo, info)do { if (1) g_slice_free1 (sizeof (TerminalScreenPopupInfo), (
info)); else (void) ((TerminalScreenPopupInfo*) 0 == (info));
} while (0)
;
1667}
1668
1669static gboolean
1670terminal_screen_popup_menu (CtkWidget *widget)
1671{
1672 TerminalScreen *screen = TERMINAL_SCREEN (widget)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((terminal_screen_get_type ()))))))
;
1673 TerminalScreenPopupInfo *info;
1674
1675 info = terminal_screen_popup_info_new (screen);
1676 info->button = 0;
1677 info->timestamp = ctk_get_current_event_time ();
1678
1679 g_signal_emit (screen, signals[SHOW_POPUP_MENU], 0, info);
1680 terminal_screen_popup_info_unref (info);
1681
1682 return TRUE(!(0));
1683}
1684
1685static gboolean
1686terminal_screen_button_press (CtkWidget *widget,
1687 CdkEventButton *event)
1688{
1689 TerminalScreen *screen = TERMINAL_SCREEN (widget)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((terminal_screen_get_type ()))))))
;
1690 gboolean (* button_press_event) (CtkWidget*, CdkEventButton*) =
1691 CTK_WIDGET_CLASS (terminal_screen_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((terminal_screen_parent_class)), ((ctk_widget_get_type ()
))))))
->button_press_event;
1692 char *matched_string;
1693 int matched_flavor = 0;
1694 guint state;
1695
1696 state = event->state & ctk_accelerator_get_default_mod_mask ();
1697
1698 matched_string = terminal_screen_check_match (screen, (CdkEvent*)event, &matched_flavor);
1699
1700 if (matched_string != NULL((void*)0) &&
1701 (event->button == 1 || event->button == 2) &&
1702 (state & CDK_CONTROL_MASK))
1703 {
1704 gboolean handled = FALSE(0);
1705
1706#ifdef ENABLE_SKEY1
1707 if (matched_flavor != FLAVOR_SKEY ||
1708 terminal_profile_get_property_boolean (screen->priv->profile, TERMINAL_PROFILE_USE_SKEY"use-skey"))
1709#endif
1710 {
1711 g_signal_emit (screen, signals[MATCH_CLICKED], 0,
1712 matched_string,
1713 matched_flavor,
1714 state,
1715 &handled);
1716 }
1717
1718 g_free (matched_string);
1719
1720 if (handled)
1721 return TRUE(!(0)); /* don't do anything else such as select with the click */
1722 }
1723
1724 if (event->button == 3 &&
1725 (state & (CDK_SHIFT_MASK | CDK_CONTROL_MASK | CDK_MOD1_MASK)) == 0)
1726 {
1727 TerminalScreenPopupInfo *info;
1728
1729 info = terminal_screen_popup_info_new (screen);
1730 info->button = event->button;
1731 info->state = state;
1732 info->timestamp = event->time;
1733 info->string = matched_string; /* adopted */
1734 info->flavour = matched_flavor;
1735
1736 g_signal_emit (screen, signals[SHOW_POPUP_MENU], 0, info);
1737 terminal_screen_popup_info_unref (info);
1738
1739 return TRUE(!(0));
1740 }
1741
1742 /* default behavior is to let the terminal widget deal with it */
1743 if (button_press_event)
1744 return button_press_event (widget, event);
1745
1746 return FALSE(0);
1747}
1748
1749static void
1750terminal_screen_set_dynamic_title (TerminalScreen *screen,
1751 const char *title,
1752 gboolean userset)
1753{
1754 TerminalScreenPrivate *priv = screen->priv;
1755
1756 g_assert (TERMINAL_IS_SCREEN (screen))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "terminal-screen.c",
1756, ((const char*) (__func__)), "TERMINAL_IS_SCREEN (screen)"
); } while (0)
;
1757
1758 if ((priv->user_title && !userset) ||
1759 (priv->raw_title && title &&
1760 strcmp (priv->raw_title, title) == 0))
1761 return;
1762
1763 g_free (priv->raw_title);
1764 priv->raw_title = g_strdup (title)g_strdup_inline (title);
1765 terminal_screen_cook_title (screen);
1766}
1767
1768static void
1769terminal_screen_set_dynamic_icon_title (TerminalScreen *screen,
1770 const char *icon_title,
1771 gboolean userset)
1772{
1773 TerminalScreenPrivate *priv = screen->priv;
1774 GObject *object = G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
;
1775
1776 g_assert (TERMINAL_IS_SCREEN (screen))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "terminal-screen.c",
1776, ((const char*) (__func__)), "TERMINAL_IS_SCREEN (screen)"
); } while (0)
;
1777
1778 if ((priv->user_title && !userset) ||
1779 (priv->icon_title_set &&
1780 priv->raw_icon_title &&
1781 icon_title &&
1782 strcmp (priv->raw_icon_title, icon_title) == 0))
1783 return;
1784
1785 g_object_freeze_notify (object);
1786
1787 g_free (priv->raw_icon_title);
1788 priv->raw_icon_title = g_strdup (icon_title)g_strdup_inline (icon_title);
1789 priv->icon_title_set = TRUE(!(0));
1790
1791 g_object_notify (object, "icon-title-set");
1792 terminal_screen_cook_icon_title (screen);
1793
1794 g_object_thaw_notify (object);
1795}
1796
1797void
1798terminal_screen_set_override_title (TerminalScreen *screen,
1799 const char *title)
1800{
1801 TerminalScreenPrivate *priv = screen->priv;
1802 char *old_title;
1803
1804 old_title = priv->override_title;
1805 priv->override_title = g_strdup (title)g_strdup_inline (title);
1806 g_free (old_title);
1807
1808 terminal_screen_set_dynamic_title (screen, title, FALSE(0));
1809 terminal_screen_set_dynamic_icon_title (screen, title, FALSE(0));
1810}
1811
1812const char*
1813terminal_screen_get_dynamic_title (TerminalScreen *screen)
1814{
1815 g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return (((void
*)0)); } } while (0)
;
1816
1817 return screen->priv->raw_title;
1818}
1819
1820const char*
1821terminal_screen_get_dynamic_icon_title (TerminalScreen *screen)
1822{
1823 g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return (((void
*)0)); } } while (0)
;
1824
1825 return screen->priv->raw_icon_title;
1826}
1827
1828/**
1829 * terminal_screen_get_current_dir:
1830 * @screen:
1831 *
1832 * Tries to determine the current working directory of the foreground process
1833 * in @screen's PTY, falling back to the current working directory of the
1834 * primary child.
1835 *
1836 * Returns: a newly allocated string containing the current working directory,
1837 * or %NULL on failure
1838 */
1839char*
1840terminal_screen_get_current_dir (TerminalScreen *screen)
1841{
1842 TerminalScreenPrivate *priv = screen->priv;
1843 BtePty *pty;
1844
1845 pty = bte_terminal_get_pty (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
);
1846 if (pty != NULL((void*)0))
1847 {
1848 char *cwd;
1849
1850#if 0
1851 /* Get the foreground process ID */
1852 cwd = cwd_of_pid (tcgetpgrp (priv->pty_fd));
1853 if (cwd != NULL((void*)0))
1854 return cwd;
1855#endif
1856
1857 /* If that didn't work, try falling back to the primary child. See bug #575184. */
1858 cwd = cwd_of_pid (priv->child_pid);
1859 if (cwd != NULL((void*)0))
1860 return cwd;
1861 }
1862
1863 return NULL((void*)0);
1864}
1865
1866/**
1867 * terminal_screen_get_current_dir_with_fallback:
1868 * @screen:
1869 *
1870 * Like terminal_screen_get_current_dir(), but falls back to returning
1871 * @screen's initial working directory, with a further fallback to the
1872 * user's home directory.
1873 *
1874 * Returns: a newly allocated string containing the current working directory,
1875 * or %NULL on failure
1876 */
1877char*
1878terminal_screen_get_current_dir_with_fallback (TerminalScreen *screen)
1879{
1880 BtePty *pty;
1881 TerminalScreenPrivate *priv = screen->priv;
1882
1883 pty = bte_terminal_get_pty (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
);
1884 if (pty == NULL((void*)0))
1885 return g_strdup (priv->initial_working_directory)g_strdup_inline (priv->initial_working_directory);
1886
1887 return terminal_screen_get_current_dir (screen);
1888}
1889
1890void
1891terminal_screen_set_font_scale (TerminalScreen *screen,
1892 double factor)
1893{
1894 TerminalScreenPrivate *priv = screen->priv;
1895
1896 g_return_if_fail (TERMINAL_IS_SCREEN (screen))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return; } } while
(0)
;
1897
1898 if (factor < TERMINAL_SCALE_MINIMUM((((((double)0.5787037037037)/1.2)/1.2)/1.2)/1.2))
1899 factor = TERMINAL_SCALE_MINIMUM((((((double)0.5787037037037)/1.2)/1.2)/1.2)/1.2);
1900 if (factor > TERMINAL_SCALE_MAXIMUM((((((double)1.728)*1.2)*1.2)*1.2)*1.2))
1901 factor = TERMINAL_SCALE_MAXIMUM((((((double)1.728)*1.2)*1.2)*1.2)*1.2);
1902
1903 priv->font_scale = factor;
1904
1905 if (ctk_widget_get_realized (CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
))
1906 {
1907 /* Update the font */
1908 terminal_screen_change_font (screen);
1909 }
1910}
1911
1912double
1913terminal_screen_get_font_scale (TerminalScreen *screen)
1914{
1915 g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), 1.0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((terminal_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "TERMINAL_IS_SCREEN (screen)"); return (1.0); }
} while (0)
;
1916
1917 return screen->priv->font_scale;
1918}
1919
1920static void
1921terminal_screen_window_title_changed (BteTerminal *bte_terminal,
1922 TerminalScreen *screen)
1923{
1924 terminal_screen_set_dynamic_title (screen,
1925 bte_terminal_get_window_title (bte_terminal),
1926 FALSE(0));
1927}
1928
1929static void
1930terminal_screen_icon_title_changed (BteTerminal *bte_terminal,
1931 TerminalScreen *screen)
1932{
1933 terminal_screen_set_dynamic_icon_title (screen,
1934 bte_terminal_get_icon_title (bte_terminal),
1935 FALSE(0));
1936}
1937
1938static void
1939terminal_screen_text_inserted (BteTerminal *bte_terminal,
1940 TerminalScreen *screen)
1941{
1942 if ((ctk_window_is_active (CTK_WINDOW (terminal_screen_get_window (screen))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((terminal_screen_get_window (screen))), ((ctk_window_get_type
()))))))
) == FALSE(0)) &&
1943 (terminal_screen_has_foreground_process (screen) == FALSE(0)))
1944 {
1945 notify_init ("cafe-terminal");
1946 NotifyNotification *notification;
1947
1948 notification = notify_notification_new ("CAFE Terminal",
1949 _("Process completed")gettext ("Process completed"),
1950 "utilities-terminal");
1951
1952 notify_notification_show (notification, NULL((void*)0));
1953 g_object_unref (G_OBJECT (notification)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((notification)), (((GType) ((20) << (2))))))))
);
1954 notify_uninit();
1955 }
1956}
1957
1958static void
1959terminal_screen_child_exited (BteTerminal *terminal, int status)
1960{
1961 TerminalScreen *screen = TERMINAL_SCREEN (terminal)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((terminal)), ((terminal_screen_get_type ()))))))
;
1962 TerminalScreenPrivate *priv = screen->priv;
1963 TerminalExitAction action;
1964
1965 /* No need to chain up to BteTerminalClass::child_exited since it's NULL */
1966
1967 _terminal_debug_print (TERMINAL_DEBUG_PROCESSES,do { if (0) g_printerr("[screen %p] child process exited\n", screen
); } while (0)
1968 "[screen %p] child process exited\n",do { if (0) g_printerr("[screen %p] child process exited\n", screen
); } while (0)
1969 screen)do { if (0) g_printerr("[screen %p] child process exited\n", screen
); } while (0)
;
1970
1971 priv->child_pid = -1;
1972
1973 action = terminal_profile_get_property_enum (priv->profile, TERMINAL_PROFILE_EXIT_ACTION"exit-action");
1974
1975 switch (action)
1976 {
1977 case TERMINAL_EXIT_CLOSE:
1978 if ((status != 9) || (priv->override_command != NULL((void*)0)))
1979 g_signal_emit (screen, signals[CLOSE_SCREEN], 0);
1980 break;
1981 case TERMINAL_EXIT_RESTART:
1982 terminal_screen_launch_child_on_idle (screen);
1983 break;
1984 case TERMINAL_EXIT_HOLD:
1985 {
1986 if ((status == 9) && (priv->override_command == NULL((void*)0)))
1987 break;
1988
1989 CtkWidget *info_bar;
1990
1991 info_bar = terminal_info_bar_new (CTK_MESSAGE_INFO,
1992 _("_Relaunch")gettext ("_Relaunch"), RESPONSE_RELAUNCH,
1993 NULL((void*)0));
1994 if (WIFEXITED (status)(((status) & 0x7f) == 0))
1995 {
1996 terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar)((((TerminalInfoBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info_bar)), ((terminal_info_bar_get_type ()))))))
,
1997 _("The child process exited normally with status %d.")gettext ("The child process exited normally with status %d."), WEXITSTATUS (status)(((status) & 0xff00) >> 8));
1998 }
1999 else if (WIFSIGNALED (status)(((signed char) (((status) & 0x7f) + 1) >> 1) > 0
)
)
2000 {
2001 terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar)((((TerminalInfoBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info_bar)), ((terminal_info_bar_get_type ()))))))
,
2002 _("The child process was terminated by signal %d.")gettext ("The child process was terminated by signal %d."), WTERMSIG (status)((status) & 0x7f));
2003 }
2004 else
2005 {
2006 terminal_info_bar_format_text (TERMINAL_INFO_BAR (info_bar)((((TerminalInfoBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info_bar)), ((terminal_info_bar_get_type ()))))))
,
2007 _("The child process was terminated.")gettext ("The child process was terminated."));
2008 }
2009 g_signal_connect (info_bar, "response",g_signal_connect_data ((info_bar), ("response"), (((GCallback
) (info_bar_response_cb))), (screen), ((void*)0), (GConnectFlags
) 0)
2010 G_CALLBACK (info_bar_response_cb), screen)g_signal_connect_data ((info_bar), ("response"), (((GCallback
) (info_bar_response_cb))), (screen), ((void*)0), (GConnectFlags
) 0)
;
2011
2012 ctk_box_pack_start (CTK_BOX (terminal_screen_container_get_from_screen (screen))((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((terminal_screen_container_get_from_screen (screen))), ((
ctk_box_get_type ()))))))
,
2013 info_bar, FALSE(0), FALSE(0), 0);
2014 ctk_info_bar_set_default_response (CTK_INFO_BAR (info_bar)((((CtkInfoBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((info_bar)), ((ctk_info_bar_get_type()))))))
, RESPONSE_RELAUNCH);
2015 ctk_widget_show (info_bar);
2016 break;
2017 }
2018
2019 default:
2020 break;
2021 }
2022}
2023
2024void
2025terminal_screen_set_user_title (TerminalScreen *screen,
2026 const char *text)
2027{
2028 TerminalScreenPrivate *priv = screen->priv;
2029
2030 /* The user set the title to nothing, let's understand that as a
2031 request to revert to dynamically setting the title again. */
2032 if (!text || !text[0])
2033 priv->user_title = FALSE(0);
2034 else
2035 {
2036 priv->user_title = TRUE(!(0));
2037 terminal_screen_set_dynamic_title (screen, text, TRUE(!(0)));
2038 terminal_screen_set_dynamic_icon_title (screen, text, TRUE(!(0)));
2039 }
2040}
2041
2042static void
2043terminal_screen_drag_data_received (CtkWidget *widget,
2044 CdkDragContext *context,
2045 gint x,
2046 gint y,
2047 CtkSelectionData *selection_data,
2048 guint info,
2049 guint timestamp)
2050{
2051 TerminalScreen *screen = TERMINAL_SCREEN (widget)((((TerminalScreen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((terminal_screen_get_type ()))))))
;
2052 TerminalScreenPrivate *priv = screen->priv;
2053 const guchar *selection_data_data;
2054 CdkAtom selection_data_target;
2055 gint selection_data_length, selection_data_format;
2056
2057 selection_data_data = ctk_selection_data_get_data (selection_data);
2058 selection_data_target = ctk_selection_data_get_target (selection_data);
2059 selection_data_length = ctk_selection_data_get_length (selection_data);
2060 selection_data_format = ctk_selection_data_get_format (selection_data);
2061
2062#if 0
2063 {
2064 GList *tmp;
2065
2066 g_print ("info: %d\n", info);
2067 tmp = context->targets;
2068 while (tmp != NULL((void*)0))
2069 {
2070 CdkAtom atom = CDK_POINTER_TO_ATOM (tmp->data)((CdkAtom)(tmp->data));
2071
2072 g_print ("Target: %s\n", cdk_atom_name (atom));
2073
2074 tmp = tmp->next;
2075 }
2076
2077 g_print ("Chosen target: %s\n", cdk_atom_name (selection_data->target));
2078 }
2079#endif
2080
2081 if (ctk_targets_include_uri (&selection_data_target, 1))
2082 {
2083 char **uris;
2084 char *text;
2085 gsize len;
2086
2087 uris = ctk_selection_data_get_uris (selection_data);
2088 if (!uris)
2089 return;
2090
2091 terminal_util_transform_uris_to_quoted_fuse_paths (uris);
2092
2093 text = terminal_util_concat_uris (uris, &len);
2094 bte_terminal_feed_child (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, text, len);
2095 g_free (text);
2096
2097 g_strfreev (uris);
2098 }
2099 else if (ctk_targets_include_text (&selection_data_target, 1))
2100 {
2101 char *text;
2102
2103 text = (char *) ctk_selection_data_get_text (selection_data);
2104 if (text && text[0])
2105 bte_terminal_feed_child (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, text, strlen (text));
2106 g_free (text);
2107 }
2108 else switch (info)
2109 {
2110 case TARGET_COLOR:
2111 {
2112 guint16 *data = (guint16 *)selection_data_data;
2113 CdkRGBA color;
2114
2115 /* We accept drops with the wrong format, since the KDE color
2116 * chooser incorrectly drops application/x-color with format 8.
2117 * So just check for the data length.
2118 */
2119 if (selection_data_length != 8)
2120 return;
2121
2122 color.red = (double) data[0] / 65535.;
2123 color.green = (double) data[1] / 65535.;
2124 color.blue = (double) data[2] / 65535.;
2125 color.alpha = 1.;
2126 /* FIXME: use opacity from data[3] */
2127
2128 g_object_set (priv->profile,
2129 TERMINAL_PROFILE_BACKGROUND_TYPE"background-type", TERMINAL_BACKGROUND_SOLID,
2130 TERMINAL_PROFILE_USE_THEME_COLORS"use-theme-colors", FALSE(0),
2131 TERMINAL_PROFILE_BACKGROUND_COLOR"background-color", &color,
2132 NULL((void*)0));
2133 }
2134 break;
2135
2136 case TARGET_MOZ_URL:
2137 {
2138 char *utf8_data, *newline, *text;
2139 char *uris[2];
2140 gsize len;
2141
2142 /* MOZ_URL is in UCS-2 but in format 8. BROKEN!
2143 *
2144 * The data contains the URL, a \n, then the
2145 * title of the web page.
2146 */
2147 if (selection_data_format != 8 ||
2148 selection_data_length == 0 ||
2149 (selection_data_length % 2) != 0)
2150 return;
2151
2152 utf8_data = g_utf16_to_utf8 ((const gunichar2*) selection_data_data,
2153 selection_data_length / 2,
2154 NULL((void*)0), NULL((void*)0), NULL((void*)0));
2155 if (!utf8_data)
2156 return;
2157
2158 newline = strchr (utf8_data, '\n');
2159 if (newline)
2160 *newline = '\0';
2161
2162 uris[0] = utf8_data;
2163 uris[1] = NULL((void*)0);
2164 terminal_util_transform_uris_to_quoted_fuse_paths (uris); /* This may replace uris[0] */
2165
2166 text = terminal_util_concat_uris (uris, &len);
2167 bte_terminal_feed_child (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, text, len);
2168 g_free (text);
2169 g_free (uris[0]);
2170 }
2171 break;
2172
2173 case TARGET_NETSCAPE_URL:
2174 {
2175 char *utf8_data, *newline, *text;
2176 char *uris[2];
2177 gsize len;
2178
2179 /* The data contains the URL, a \n, then the
2180 * title of the web page.
2181 */
2182 if (selection_data_length < 0 || selection_data_format != 8)
2183 return;
2184
2185 utf8_data = g_strndup ((char *) selection_data_data, selection_data_length);
2186 newline = strchr (utf8_data, '\n');
2187 if (newline)
2188 *newline = '\0';
2189
2190 uris[0] = utf8_data;
2191 uris[1] = NULL((void*)0);
2192 terminal_util_transform_uris_to_quoted_fuse_paths (uris); /* This may replace uris[0] */
2193
2194 text = terminal_util_concat_uris (uris, &len);
2195 bte_terminal_feed_child (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, text, len);
2196 g_free (text);
2197 g_free (uris[0]);
2198 }
2199 break;
2200
2201 case TARGET_BGIMAGE:
2202 {
2203 char *utf8_data;
2204 char **uris;
2205
2206 if (selection_data_length < 0 || selection_data_format != 8)
2207 return;
2208
2209 utf8_data = g_strndup ((char *) selection_data_data, selection_data_length);
2210 uris = g_uri_list_extract_uris (utf8_data);
2211 g_free (utf8_data);
2212
2213 /* FIXME: use terminal_util_transform_uris_to_quoted_fuse_paths? */
2214
2215 if (uris && uris[0])
2216 {
2217 char *filename;
2218
2219 filename = g_filename_from_uri (uris[0], NULL((void*)0), NULL((void*)0));
2220 if (filename)
2221 {
2222 g_object_set (priv->profile,
2223 TERMINAL_PROFILE_BACKGROUND_TYPE"background-type", TERMINAL_BACKGROUND_IMAGE,
2224 TERMINAL_PROFILE_BACKGROUND_IMAGE_FILE"background-image-file", filename,
2225 NULL((void*)0));
2226 }
2227
2228 g_free (filename);
2229 }
2230
2231 g_strfreev (uris);
2232 }
2233 break;
2234
2235 case TARGET_RESET_BG:
2236 g_object_set (priv->profile,
2237 TERMINAL_PROFILE_BACKGROUND_TYPE"background-type", TERMINAL_BACKGROUND_SOLID,
2238 NULL((void*)0));
2239 break;
2240
2241 case TARGET_TAB:
2242 {
2243 CtkWidget *container;
2244 TerminalScreen *moving_screen;
2245 TerminalWindow *source_window;
2246 TerminalWindow *dest_window;
2247 CtkWidget *dest_notebook;
2248 int page_num;
2249
2250 container = *(CtkWidget**) selection_data_data;
2251 if (!CTK_IS_WIDGET (container)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(container)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
2252 return;
2253
2254 moving_screen = terminal_screen_container_get_screen (TERMINAL_SCREEN_CONTAINER (container)((((TerminalScreenContainer*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((container)), ((terminal_screen_container_get_type
()))))))
);
2255 g_return_if_fail (TERMINAL_IS_SCREEN (moving_screen))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((moving_screen)); GType __t = ((terminal_screen_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning (((gchar*) 0
), ((const char*) (__func__)), "TERMINAL_IS_SCREEN (moving_screen)"
); return; } } while (0)
;
2256 if (!TERMINAL_IS_SCREEN (moving_screen)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(moving_screen)); GType __t = ((terminal_screen_get_type ()))
; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))
)
2257 return;
2258
2259 source_window = terminal_screen_get_window (moving_screen);
2260 dest_window = terminal_screen_get_window (screen);
2261 dest_notebook = terminal_window_get_notebook (dest_window);
2262 page_num = ctk_notebook_page_num (CTK_NOTEBOOK (dest_notebook)((((CtkNotebook*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dest_notebook)), ((ctk_notebook_get_type ()))))))
,
2263 CTK_WIDGET (screen)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((ctk_widget_get_type ()))))))
);
2264 terminal_window_move_screen (source_window, dest_window, moving_screen, page_num + 1);
2265
2266 ctk_drag_finish (context, TRUE(!(0)), TRUE(!(0)), timestamp);
2267 }
2268 break;
2269
2270 default:
2271 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "terminal-screen.c"
, 2271, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2272 }
2273}
2274
2275void
2276_terminal_screen_update_scrollbar (TerminalScreen *screen)
2277{
2278 TerminalScreenPrivate *priv = screen->priv;
2279 TerminalScreenContainer *container;
2280 CtkPolicyType policy = CTK_POLICY_ALWAYS;
2281 CtkCornerType corner = CTK_CORNER_TOP_LEFT;
2282
2283 container = terminal_screen_container_get_from_screen (screen);
2284 if (container == NULL((void*)0))
2285 return;
2286
2287 switch (terminal_profile_get_property_enum (priv->profile, TERMINAL_PROFILE_SCROLLBAR_POSITION"scrollbar-position"))
2288 {
2289 case TERMINAL_SCROLLBAR_HIDDEN:
2290 policy = CTK_POLICY_NEVER;
2291 break;
2292 case TERMINAL_SCROLLBAR_RIGHT:
2293 policy = CTK_POLICY_ALWAYS;
2294 corner = CTK_CORNER_TOP_LEFT;
2295 break;
2296 case TERMINAL_SCROLLBAR_LEFT:
2297 policy = CTK_POLICY_ALWAYS;
2298 corner = CTK_CORNER_TOP_RIGHT;
2299 break;
2300 default:
2301 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "terminal-screen.c"
, 2301, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2302 break;
2303 }
2304
2305 terminal_screen_container_set_placement (container, corner);
2306 terminal_screen_container_set_policy (container, CTK_POLICY_NEVER, policy);
2307}
2308
2309void
2310terminal_screen_get_size (TerminalScreen *screen,
2311 int *width_chars,
2312 int *height_chars)
2313{
2314 BteTerminal *terminal = BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
;
2315
2316 *width_chars = bte_terminal_get_column_count (terminal);
2317 *height_chars = bte_terminal_get_row_count (terminal);
2318}
2319
2320void
2321terminal_screen_get_cell_size (TerminalScreen *screen,
2322 int *cell_width_pixels,
2323 int *cell_height_pixels)
2324{
2325 BteTerminal *terminal = BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
;
2326
2327 *cell_width_pixels = bte_terminal_get_char_width (terminal);
2328 *cell_height_pixels = bte_terminal_get_char_height (terminal);
2329}
2330
2331#ifdef ENABLE_SKEY1
2332static void
2333terminal_screen_skey_match_remove (TerminalScreen *screen)
2334{
2335 TerminalScreenPrivate *priv = screen->priv;
2336 GSList *l, *next;
2337
2338 l = priv->match_tags;
2339 while (l != NULL((void*)0))
2340 {
2341 TagData *tag_data = (TagData *) l->data;
2342
2343 next = l->next;
2344 if (tag_data->flavor == FLAVOR_SKEY)
2345 {
2346 bte_terminal_match_remove (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, tag_data->tag);
2347 priv->match_tags = g_slist_delete_link (priv->match_tags, l);
2348 }
2349
2350 l = next;
2351 }
2352}
2353#endif /* ENABLE_SKEY */
2354
2355static void
2356terminal_screen_url_match_remove (TerminalScreen *screen)
2357{
2358 TerminalScreenPrivate *priv = screen->priv;
2359 GSList *l, *next;
2360
2361 l = priv->match_tags;
2362 while (l != NULL((void*)0))
2363 {
2364 TagData *tag_data = (TagData *) l->data;
2365
2366 next = l->next;
2367#ifdef ENABLE_SKEY1
2368 if (tag_data->flavor != FLAVOR_SKEY)
2369#endif
2370 {
2371 bte_terminal_match_remove (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, tag_data->tag);
2372 priv->match_tags = g_slist_delete_link (priv->match_tags, l);
2373 }
2374
2375 l = next;
2376 }
2377}
2378
2379static char*
2380terminal_screen_check_match (TerminalScreen *screen,
2381 CdkEvent *event,
2382 int *flavor)
2383{
2384 TerminalScreenPrivate *priv = screen->priv;
2385 GSList *tags;
2386 int tag;
2387 char *match;
2388
2389 match = bte_terminal_match_check_event (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
, event, &tag);
2390 for (tags = priv->match_tags; tags != NULL((void*)0); tags = tags->next)
2391 {
2392 TagData *tag_data = (TagData*) tags->data;
2393 if (tag_data->tag == tag)
2394 {
2395 if (flavor)
2396 *flavor = tag_data->flavor;
2397 return match;
2398 }
2399 }
2400
2401 g_free (match);
2402 return NULL((void*)0);
2403}
2404
2405void
2406terminal_screen_save_config (TerminalScreen *screen,
2407 GKeyFile *key_file,
2408 const char *group)
2409{
2410 TerminalScreenPrivate *priv = screen->priv;
2411 BteTerminal *terminal = BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
;
2412 TerminalProfile *profile = priv->profile;
2413 const char *profile_id;
2414 char *working_directory;
2415
2416 profile_id = terminal_profile_get_property_string (profile, TERMINAL_PROFILE_NAME"name");
2417 g_key_file_set_string (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_PROFILE_ID"ProfileID", profile_id);
2418
2419 if (priv->override_command)
2420 terminal_util_key_file_set_argv (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_COMMAND"Command",
2421 -1, priv->override_command);
2422
2423 if (priv->override_title)
2424 g_key_file_set_string (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_TITLE"Title", priv->override_title);
2425
2426 /* FIXMEchpe: use the initial_working_directory instead?? */
2427 working_directory = terminal_screen_get_current_dir (screen);
2428 if (working_directory)
2429 terminal_util_key_file_set_string_escape (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_WORKING_DIRECTORY"WorkingDirectory", working_directory);
2430 g_free (working_directory);
2431
2432 g_key_file_set_double (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_ZOOM"Zoom", priv->font_scale);
2433
2434 g_key_file_set_integer (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_WIDTH"Width",
2435 bte_terminal_get_column_count (terminal));
2436 g_key_file_set_integer (key_file, group, TERMINAL_CONFIG_TERMINAL_PROP_HEIGHT"Height",
2437 bte_terminal_get_row_count (terminal));
2438}
2439
2440/**
2441 * terminal_screen_has_foreground_process:
2442 * @screen:
2443 *
2444 * Checks whether there's a foreground process running in
2445 * this terminal.
2446 *
2447 * Returns: %TRUE iff there's a foreground process running in @screen
2448 */
2449gboolean
2450terminal_screen_has_foreground_process (TerminalScreen *screen)
2451{
2452 TerminalScreenPrivate *priv = screen->priv;
2453 BtePty *pty;
2454 int fd;
2455 int fgpid;
2456
2457 pty = bte_terminal_get_pty (BTE_TERMINAL (screen)((((BteTerminal*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((bte_terminal_get_type()))))))
);
2458 if (pty == NULL((void*)0))
2459 return FALSE(0);
2460
2461 fd = bte_pty_get_fd (pty);
2462 if (fd == -1)
2463 return FALSE(0);
2464
2465 fgpid = tcgetpgrp (fd);
2466 if (fgpid == -1 || fgpid == priv->child_pid)
2467 return FALSE(0);
2468
2469 return TRUE(!(0));
2470
2471#if 0
2472 char *cmdline, *basename, *name;
2473 gsize len;
2474 char filename[64];
2475
2476 g_snprintf (filename, sizeof (filename), "/proc/%d/cmdline", fgpid);
2477 if (!g_file_get_contents (filename, &cmdline, &len, NULL((void*)0)))
2478 return TRUE(!(0));
2479
2480 basename = g_path_get_basename (cmdline);
2481 g_free (cmdline);
2482 if (!basename)
2483 return TRUE(!(0));
2484
2485 name = g_filename_to_utf8 (basename, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2486 g_free (basename);
2487 if (!name)
2488 return TRUE(!(0));
2489
2490 if (process_name)
2491 *process_name = name;
2492
2493 return TRUE(!(0));
2494#endif
2495}