1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #undef VTE_SEAL_ENABLE
4 #define VTE_COMPILATION /* Don't define _VTE_GNUC_NONNULL as __attribute__(__nonnull__) */
5 #include <vte/vte.h>
6 #ifndef VTE_CHECK_VERSION
7 #define VTE_CHECK_VERSION(a, b, c) (0)
8 #endif
9
10 /* for wayland/ui.h */
11 #define COMPAT_LIBVTE
12
13 #include <sys/wait.h> /* waitpid */
14 #include <pwd.h> /* getpwuid */
15 #include <pobl/bl_sig_child.h>
16 #include <pobl/bl_str.h> /* strdup */
17 #include <pobl/bl_mem.h>
18 #include <pobl/bl_path.h>
19 #include <pobl/bl_debug.h>
20 #include <pobl/bl_util.h> /* DIGIT_STR_LEN */
21 #include <pobl/bl_privilege.h>
22 #include <pobl/bl_unistd.h>
23 #include <pobl/bl_locale.h>
24 #include <pobl/bl_conf_io.h>
25 #include <pobl/bl_pty.h> /* bl_pty_helper_set_flag */
26 #include <pobl/bl_conf.h>
27 #include <vt_str_parser.h>
28 #include <vt_term_manager.h>
29 #include <vt_pty_intern.h> /* XXX for config_menu.pid */
30 #include <ui_screen.h>
31 #include <ui_xic.h>
32 #include <ui_main_config.h>
33 #include <ui_imagelib.h>
34 #include <ui_selection_encoding.h>
35 #ifdef USE_BRLAPI
36 #include <ui_brltty.h>
37 #endif
38
39 #include "../main/version.h"
40
41 #include "marshal.h"
42
43 #if !VTE_CHECK_VERSION(0, 38, 0)
44 #include <vte/reaper.h>
45 #else
46 typedef struct _VteReaper VteReaper;
47 VteReaper *vte_reaper_get(void);
48 int vte_reaper_add_child(GPid pid);
49 #endif
50
51 #ifdef SYSCONFDIR
52 #define CONFIG_PATH SYSCONFDIR
53 #endif
54
55 #if 0
56 #define __DEBUG
57 #endif
58
59 #ifndef I_
60 #define I_(a) a
61 #endif
62
63 #if !GTK_CHECK_VERSION(2, 14, 0)
64 #define gtk_adjustment_get_upper(adj) ((adj)->upper)
65 #define gtk_adjustment_get_value(adj) ((adj)->value)
66 #define gtk_adjustment_get_page_size(adj) ((adj)->page_size)
67 #define gtk_widget_get_window(widget) ((widget)->window)
68 #endif
69
70 #if !GTK_CHECK_VERSION(2, 18, 0)
71 #define gtk_widget_set_window(widget, win) ((widget)->window = (win))
72 #define gtk_widget_set_allocation(widget, alloc) ((widget)->allocation = *(alloc))
73 #define gtk_widget_get_allocation(widget, alloc) (*(alloc) = (widget)->allocation)
74 #endif
75
76 #if GTK_CHECK_VERSION(2, 90, 0)
77 #define GTK_WIDGET_SET_REALIZED(widget) gtk_widget_set_realized(widget, TRUE)
78 #define GTK_WIDGET_UNSET_REALIZED(widget) gtk_widget_set_realized(widget, FALSE)
79 #define GTK_WIDGET_REALIZED(widget) gtk_widget_get_realized(widget)
80 #define GTK_WIDGET_SET_HAS_FOCUS(widget) (0)
81 #define GTK_WIDGET_UNSET_HAS_FOCUS(widget) (0)
82 #define GTK_WIDGET_UNSET_MAPPED(widget) gtk_widget_set_mapped(widget, FALSE)
83 #define GTK_WIDGET_MAPPED(widget) gtk_widget_get_mapped(widget)
84 #define GTK_WIDGET_SET_CAN_FOCUS(widget) gtk_widget_set_can_focus(widget, TRUE)
85 #else /* GTK_CHECK_VERSION(2,90,0) */
86 #define GTK_WIDGET_SET_REALIZED(widget) GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED)
87 #define GTK_WIDGET_UNSET_REALIZED(widget) GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED)
88 #define GTK_WIDGET_SET_HAS_FOCUS(widget) GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS)
89 #define GTK_WIDGET_UNSET_HAS_FOCUS(widget) GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS)
90 #define GTK_WIDGET_UNSET_MAPPED(widget) GTK_WIDGET_UNSET_FLAGS(widget, GTK_MAPPED)
91 #define GTK_WIDGET_SET_CAN_FOCUS(widget) GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS)
92 #endif /* GTK_CHECK_VERSION(2,90,0) */
93
94 #define VTE_WIDGET(screen) ((VteTerminal *)(screen)->system_listener->self)
95 /* XXX Hack to distinguish ui_screen_t from ui_{candidate|status}_screent_t */
96 #define IS_MLTERM_SCREEN(win) (!PARENT_WINDOWID_IS_TOP(win))
97
98 #if !VTE_CHECK_VERSION(0, 38, 0)
99 #define WINDOW_MARGIN 1
100 #define VteCursorBlinkMode VteTerminalCursorBlinkMode
101 #define VteCursorShape VteTerminalCursorShape
102 #define VteEraseBinding VteTerminalEraseBinding
103 #endif
104
105 #define STATIC_PARAMS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
106
107 #if VTE_CHECK_VERSION(0, 46, 0)
108 struct _VteRegex {
109 int ref_count;
110 GRegex *gregex;
111 };
112
113 G_DEFINE_BOXED_TYPE(VteRegex, vte_regex,
114 vte_regex_ref, (GBoxedFreeFunc)vte_regex_unref)
115 G_DEFINE_QUARK(vte-regex-error, vte_regex_error)
116 #endif
117
118 #define VTE_TERMINAL_CSS_NAME "vte-terminal"
119
120 #if VTE_CHECK_VERSION(0, 40, 0)
121 typedef struct _VteTerminalPrivate VteTerminalPrivate;
122 #endif
123
124 struct _VteTerminalPrivate {
125 /* Not NULL until finalized. screen->term is NULL until widget is realized. */
126 ui_screen_t *screen;
127
128 /*
129 * Not NULL until finalized. term->pty is NULL until pty is forked or
130 * inherited from parent.
131 */
132 vt_term_t *term;
133
134 #if VTE_CHECK_VERSION(0, 26, 0)
135 VtePty *pty;
136 #endif
137
138 ui_system_event_listener_t system_listener;
139
140 void (*line_scrolled_out)(void *);
141 void (*xterm_resize)(void *, u_int, u_int, int);
142 ui_screen_scroll_event_listener_t screen_scroll_listener;
143 int8_t adj_value_changed_by_myself;
144
145 /* for roxterm-2.6.5 */
146 int8_t init_char_size;
147
148 GIOChannel *io;
149 guint src_id;
150
151 GdkPixbuf *image; /* Original image which vte_terminal_set_background_image passed */
152 Pixmap pixmap;
153 u_int pix_width;
154 u_int pix_height;
155 ui_picture_modifier_t *pic_mod; /* caching previous pic_mod in update_wall_picture.*/
156
157 #if GLIB_CHECK_VERSION(2, 14, 0)
158 GRegex *gregex;
159 GRegex **match_gregexes;
160 #if VTE_CHECK_VERSION(0, 46, 0)
161 VteRegex *vregex;
162 VteRegex **match_vregexes;
163 u_int16_t num_match_vregexes;
164 #endif
165 u_int16_t num_match_gregexes;
166 #endif
167
168 #if VTE_CHECK_VERSION(0, 38, 0)
169 GtkAdjustment *adjustment;
170 gchar *window_title;
171 gchar *icon_title;
172 glong char_width;
173 glong char_height;
174 glong row_count;
175 glong column_count;
176 #if VTE_CHECK_VERSION(0, 40, 0)
177 #define ADJUSTMENT(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])->adjustment
178 #define WINDOW_TITLE(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])->window_title
179 #define ICON_TITLE(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])->icon_title
180 #define CHAR_WIDTH(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])->char_width
181 #define CHAR_HEIGHT(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])->char_height
182 #define ROW_COUNT(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])->row_count
183 #define COLUMN_COUNT(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])->column_count
184 #else
185 #define ADJUSTMENT(terminal) (terminal)->pvt->adjustment
186 #define WINDOW_TITLE(terminal) (terminal)->pvt->window_title
187 #define ICON_TITLE(terminal) (terminal)->pvt->icon_title
188 #define CHAR_WIDTH(terminal) (terminal)->pvt->char_width
189 #define CHAR_HEIGHT(terminal) (terminal)->pvt->char_height
190 #define ROW_COUNT(terminal) (terminal)->pvt->row_count
191 #define COLUMN_COUNT(terminal) (terminal)->pvt->column_count
192 #endif
193 #else
194 #define ADJUSTMENT(terminal) (terminal)->adjustment
195 #define WINDOW_TITLE(terminal) (terminal)->window_title
196 #define ICON_TITLE(terminal) (terminal)->icon_title
197 #define CHAR_WIDTH(terminal) (terminal)->char_width
198 #define CHAR_HEIGHT(terminal) (terminal)->char_height
199 #define ROW_COUNT(terminal) (terminal)->row_count
200 #define COLUMN_COUNT(terminal) (terminal)->column_count
201 #endif
202 };
203
204 #if VTE_CHECK_VERSION(0, 40, 0)
205 #define PVT(terminal) ((VteTerminalPrivate*)(terminal)->_unused_padding[0])
206 #else
207 #define PVT(terminal) (terminal)->pvt
208 #endif
209
210 enum {
211 SIGNAL_BELL,
212 SIGNAL_CHAR_SIZE_CHANGED,
213 SIGNAL_CHILD_EXITED,
214 SIGNAL_COMMIT,
215 SIGNAL_CONTENTS_CHANGED,
216 SIGNAL_COPY_CLIPBOARD,
217 SIGNAL_CURRENT_DIRECTORY_URI_CHANGED,
218 SIGNAL_CURRENT_FILE_URI_CHANGED,
219 SIGNAL_CURSOR_MOVED,
220 SIGNAL_DECREASE_FONT_SIZE,
221 SIGNAL_DEICONIFY_WINDOW,
222 SIGNAL_ENCODING_CHANGED,
223 SIGNAL_EOF,
224 SIGNAL_ICON_TITLE_CHANGED,
225 SIGNAL_ICONIFY_WINDOW,
226 SIGNAL_INCREASE_FONT_SIZE,
227 SIGNAL_LOWER_WINDOW,
228 SIGNAL_MAXIMIZE_WINDOW,
229 SIGNAL_MOVE_WINDOW,
230 SIGNAL_PASTE_CLIPBOARD,
231 SIGNAL_RAISE_WINDOW,
232 SIGNAL_REFRESH_WINDOW,
233 SIGNAL_RESIZE_WINDOW,
234 SIGNAL_RESTORE_WINDOW,
235 SIGNAL_SELECTION_CHANGED,
236 SIGNAL_TEXT_DELETED,
237 SIGNAL_TEXT_INSERTED,
238 SIGNAL_TEXT_MODIFIED,
239 SIGNAL_TEXT_SCROLLED,
240 SIGNAL_WINDOW_TITLE_CHANGED,
241 LAST_SIGNAL
242 };
243
244 enum {
245 PROP_0,
246 #if GTK_CHECK_VERSION(2, 90, 0)
247 PROP_HADJUSTMENT,
248 PROP_VADJUSTMENT,
249 PROP_HSCROLL_POLICY,
250 PROP_VSCROLL_POLICY,
251 #endif
252 PROP_ALLOW_BOLD,
253 PROP_AUDIBLE_BELL,
254 PROP_BACKGROUND_IMAGE_FILE,
255 PROP_BACKGROUND_IMAGE_PIXBUF,
256 PROP_BACKGROUND_OPACITY,
257 PROP_BACKGROUND_SATURATION,
258 PROP_BACKGROUND_TINT_COLOR,
259 PROP_BACKGROUND_TRANSPARENT,
260 PROP_BACKSPACE_BINDING,
261 PROP_CURSOR_BLINK_MODE,
262 PROP_CURSOR_SHAPE,
263 PROP_DELETE_BINDING,
264 PROP_EMULATION,
265 PROP_ENCODING,
266 PROP_FONT_DESC,
267 PROP_ICON_TITLE,
268 PROP_MOUSE_POINTER_AUTOHIDE,
269 PROP_PTY,
270 PROP_SCROLL_BACKGROUND,
271 PROP_SCROLLBACK_LINES,
272 PROP_SCROLL_ON_KEYSTROKE,
273 PROP_SCROLL_ON_OUTPUT,
274 PROP_WINDOW_TITLE,
275 PROP_WORD_CHARS,
276 PROP_VISIBLE_BELL
277 };
278
279 #if GTK_CHECK_VERSION(2, 90, 0)
280 struct _VteTerminalClassPrivate {
281 GtkStyleProvider *style_provider;
282 };
283
284 G_DEFINE_TYPE_WITH_CODE(VteTerminal, vte_terminal, GTK_TYPE_WIDGET,
285 g_type_add_class_private(g_define_type_id, sizeof(VteTerminalClassPrivate));
286 G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL))
287 #else
288 G_DEFINE_TYPE(VteTerminal, vte_terminal, GTK_TYPE_WIDGET);
289 #endif
290
291 /* --- static variables --- */
292
293 static ui_main_config_t main_config;
294 static ui_shortcut_t shortcut;
295 static ui_display_t disp;
296
297 #if VTE_CHECK_VERSION(0, 19, 0)
298 static guint signals[LAST_SIGNAL];
299 #endif
300
301 static int (*orig_select_in_window)(void *, vt_char_t **, u_int *, int, int, int, int, int);
302
303 #if defined(USE_XLIB)
304 #include "vte_xlib.c"
305 #elif defined(USE_WAYLAND)
306 #include "vte_wayland.c"
307 #else
308 #error "Unsupported platform for libvte compatible library."
309 #endif
310
311 /* --- static functions --- */
312
313 #if defined(__DEBUG) && defined(USE_XLIB)
error_handler(Display * display,XErrorEvent * event)314 static int error_handler(Display *display, XErrorEvent *event) {
315 char buffer[1024];
316
317 XGetErrorText(display, event->error_code, buffer, 1024);
318
319 bl_msg_printf("%s\n", buffer);
320
321 abort();
322
323 return 1;
324 }
325 #endif
326
select_in_window(void * p,vt_char_t ** chars,u_int * len,int beg_char_index,int beg_row,int end_char_index,int end_row,int is_rect)327 static int select_in_window(void *p, vt_char_t **chars, u_int *len, int beg_char_index, int beg_row,
328 int end_char_index, int end_row, int is_rect) {
329 int ret = (*orig_select_in_window)(p, chars, len, beg_char_index, beg_row,
330 end_char_index, end_row, is_rect);
331 #if VTE_CHECK_VERSION(0, 19, 0)
332 g_signal_emit(VTE_WIDGET((ui_screen_t*)p), signals[SIGNAL_SELECTION_CHANGED], 0);
333 #endif
334
335 return ret;
336 }
337
selection(ui_selection_t * sel,int char_index_1,int row_1,int char_index_2,int row_2)338 static int selection(ui_selection_t *sel, int char_index_1, int row_1, int char_index_2,
339 int row_2) {
340 ui_sel_clear(sel);
341
342 ui_start_selection(sel, char_index_1 - 1, row_1, char_index_1, row_1, SEL_CHAR, 0);
343 ui_selecting(sel, char_index_2, row_2);
344 ui_stop_selecting(sel);
345
346 return 1;
347 }
348
349 #if GLIB_CHECK_VERSION(2, 14, 0)
match_gregex(size_t * beg,size_t * len,void * gregex,u_char * str,int backward)350 static int match_gregex(size_t *beg, size_t *len, void *gregex, u_char *str, int backward) {
351 GMatchInfo *info;
352
353 if (g_regex_match(gregex, str, 0, &info)) {
354 gchar *word;
355 u_char *p;
356
357 p = str;
358
359 do {
360 word = g_match_info_fetch(info, 0);
361
362 p = strstr(p, word);
363 *beg = p - str;
364 *len = strlen(word);
365
366 g_free(word);
367
368 p += (*len);
369 } while (g_match_info_next(info, NULL));
370
371 g_match_info_free(info);
372
373 return 1;
374 }
375
376 return 0;
377 }
378
379 #if VTE_CHECK_VERSION(0, 46, 0)
match_vteregex(size_t * beg,size_t * len,void * vregex,u_char * str,int backward)380 static int match_vteregex(size_t *beg, size_t *len, void *vregex, u_char *str, int backward) {
381 return match_gregex(beg, len, ((VteRegex*)vregex)->gregex, str, backward);
382 }
383 #endif
384
search_find(VteTerminal * terminal,int backward)385 static gboolean search_find(VteTerminal *terminal, int backward) {
386 int beg_char_index;
387 int beg_row;
388 int end_char_index;
389 int end_row;
390 void *regex;
391
392 if (!GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
393 return FALSE;
394 }
395
396 #if VTE_CHECK_VERSION(0, 46, 0)
397 regex = PVT(terminal)->gregex ? PVT(terminal)->gregex : PVT(terminal)->vregex;
398 #else
399 regex = PVT(terminal)->gregex;
400 #endif
401
402 if (!regex) {
403 return FALSE;
404 }
405
406 if (vt_term_search_find(PVT(terminal)->term, &beg_char_index, &beg_row, &end_char_index, &end_row,
407 regex, backward)) {
408 gdouble value;
409
410 selection(&PVT(terminal)->screen->sel, beg_char_index, beg_row, end_char_index, end_row);
411
412 value = vt_term_get_num_logged_lines(PVT(terminal)->term) + (beg_row >= 0 ? 0 : beg_row);
413
414 #if GTK_CHECK_VERSION(2, 14, 0)
415 gtk_adjustment_set_value(ADJUSTMENT(terminal), value);
416 #else
417 ADJUSTMENT(terminal)->value = value;
418 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
419 #endif
420
421 /*
422 * XXX
423 * Dirty hack, but without this, selection() above is not reflected to
424 * window
425 * if aother word is hit in the same line. (If row is not changed,
426 * gtk_adjustment_set_value() doesn't call ui_screen_scroll_to().)
427 */
428 ui_window_update(&PVT(terminal)->screen->window, 1 /* UPDATE_SCREEN */);
429
430 return TRUE;
431 } else {
432 return FALSE;
433 }
434 }
435 #endif
436
437 #if !GTK_CHECK_VERSION(2, 12, 0)
438 /* gdk_color_to_string() was not supported by gtk+ < 2.12. */
gdk_color_to_string(const GdkColor * color)439 static gchar *gdk_color_to_string(const GdkColor *color) {
440 gchar *str;
441
442 if ((str = g_malloc(14)) == NULL) {
443 return NULL;
444 }
445
446 sprintf(str, "#%04x%04x%04x", color->red, color->green, color->blue);
447
448 return str;
449 }
450 #endif
451
452 #if GTK_CHECK_VERSION(2, 99, 0)
gdk_rgba_to_string2(const GdkRGBA * color)453 static gchar *gdk_rgba_to_string2(const GdkRGBA *color) {
454 gchar *str;
455
456 if ((str = g_malloc(10)) == NULL) {
457 return NULL;
458 }
459
460 sprintf(str, color->alpha > 0.999 ? "#%02x%02x%02x" : "#%02x%02x%02x%02x",
461 (int)((color->red > 0.999 ? 1 : color->red) * 255 + 0.5),
462 (int)((color->green > 0.999 ? 1 : color->green) * 255 + 0.5),
463 (int)((color->blue > 0.999 ? 1 : color->blue) * 255 + 0.5),
464 (int)((color->alpha > 0.999 ? 1 : color->alpha) * 255 + 0.5));
465
466 return str;
467 }
468 #endif
469
is_initial_allocation(GtkAllocation * allocation)470 static int is_initial_allocation(GtkAllocation *allocation) {
471 /* { -1 , -1 , 1 , 1 } is default value of GtkAllocation. */
472 return (allocation->x == -1 && allocation->y == -1 && allocation->width == 1 &&
473 allocation->height == 1);
474 }
475
close_dead_terms(gpointer data)476 static gboolean close_dead_terms(gpointer data) {
477 vt_close_dead_terms();
478
479 return FALSE; /* Never repeat to call this function. */
480 }
481
catch_child_exited(VteReaper * reaper,int pid,int status,VteTerminal * terminal)482 static void catch_child_exited(VteReaper *reaper, int pid, int status, VteTerminal *terminal) {
483 bl_trigger_sig_child(pid);
484
485 g_timeout_add_full(G_PRIORITY_HIGH, 0, close_dead_terms, NULL, NULL);
486 }
487
488 static int is_sending_data;
489
transfer_data(gpointer data)490 static gboolean transfer_data(gpointer data) {
491 vt_term_parse_vt100_sequence((vt_term_t*)data);
492
493 if (!vt_term_is_sending_data((vt_term_t*)data)) {
494 is_sending_data = 0;
495
496 return FALSE; /* disable this timeout function */
497 } else {
498 return TRUE;
499 }
500 }
501
502 /*
503 * This handler works even if VteTerminal widget is not realized and vt_term_t
504 * is not
505 * attached to ui_screen_t.
506 * That's why the time ui_screen_attach is called is delayed(in
507 * vte_terminal_fork* or
508 * vte_terminal_realized).
509 */
vte_terminal_io(GIOChannel * source,GIOCondition conditon,gpointer data)510 static gboolean vte_terminal_io(GIOChannel *source, GIOCondition conditon,
511 gpointer data /* vt_term_t */) {
512 vt_term_parse_vt100_sequence((vt_term_t *)data);
513
514 if (!is_sending_data && vt_term_is_sending_data((vt_term_t *)data)) {
515 #if GTK_CHECK_VERSION(2, 12, 0)
516 gdk_threads_add_timeout(1, transfer_data, data);
517 #else
518 g_timeout_add(1, transfer_data, data);
519 #endif
520 is_sending_data = 1;
521 }
522
523 vt_close_dead_terms();
524
525 return TRUE;
526 }
527
create_io(VteTerminal * terminal)528 static void create_io(VteTerminal *terminal) {
529 #ifdef DEBUG
530 bl_debug_printf(BL_DEBUG_TAG " Create GIO of pty master %d\n",
531 vt_term_get_master_fd(PVT(terminal)->term));
532 #endif
533
534 PVT(terminal)->io = g_io_channel_unix_new(vt_term_get_master_fd(PVT(terminal)->term));
535 PVT(terminal)->src_id =
536 g_io_add_watch(PVT(terminal)->io, G_IO_IN, vte_terminal_io, PVT(terminal)->term);
537 }
538
destroy_io(VteTerminal * terminal)539 static void destroy_io(VteTerminal *terminal) {
540 if (PVT(terminal)->io) {
541 #ifdef DEBUG
542 bl_debug_printf(BL_DEBUG_TAG " Destroy GIO of pty master %d\n",
543 vt_term_get_master_fd(PVT(terminal)->term));
544 #endif
545
546 g_source_destroy(g_main_context_find_source_by_id(NULL, PVT(terminal)->src_id));
547 #if 0
548 g_io_channel_shutdown(PVT(terminal)->io, TRUE, NULL);
549 #endif
550 g_io_channel_unref(PVT(terminal)->io);
551 PVT(terminal)->src_id = 0;
552 PVT(terminal)->io = NULL;
553 }
554 }
555
556 /*
557 * vt_pty_event_listener_t overriding handler.
558 */
pty_closed(void * p)559 static void pty_closed(void *p /* screen->term->pty is NULL */
560 ) {
561 ui_screen_t *screen;
562 vt_term_t *term;
563 VteTerminal *terminal;
564
565 screen = p;
566 terminal = VTE_WIDGET(screen);
567 destroy_io(terminal);
568
569 if ((term = vt_get_detached_term(NULL))) {
570 PVT(terminal)->term = term;
571 create_io(terminal);
572
573 /*
574 * Not screen->term but screen->term->pty is being destroyed in
575 * vt_close_dead_terms()
576 * because of vt_term_manager_enable_zombie_pty(1) in
577 * vte_terminal_class_init().
578 */
579 term = screen->term;
580 ui_screen_detach(screen);
581 vt_term_destroy(term);
582
583 /* It is after widget is realized that ui_screen_attach can be called. */
584 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
585 ui_screen_attach(screen, PVT(terminal)->term);
586
587 #ifdef DEBUG
588 bl_debug_printf(BL_DEBUG_TAG " pty is closed and detached pty is re-attached.\n");
589 #endif
590 }
591 } else {
592 #if VTE_CHECK_VERSION(0, 38, 0)
593 g_signal_emit_by_name(terminal, "child-exited", 0);
594 #else
595 g_signal_emit_by_name(terminal, "child-exited");
596 #endif
597
598 #ifdef DEBUG
599 bl_debug_printf(BL_DEBUG_TAG " pty is closed\n");
600 #endif
601 }
602 }
603
604 /*
605 * ui_system_event_listener_t handlers
606 */
607
font_config_updated(void)608 static void font_config_updated(void) {
609 u_int count;
610
611 ui_font_cache_unload_all();
612
613 for (count = 0; count < disp.num_roots; count++) {
614 if (IS_MLTERM_SCREEN(disp.roots[count])) {
615 ui_screen_reset_view((ui_screen_t *)disp.roots[count]);
616 }
617 }
618 }
619
color_config_updated(void)620 static void color_config_updated(void) {
621 u_int count;
622
623 ui_color_cache_unload_all();
624
625 for (count = 0; count < disp.num_roots; count++) {
626 if (IS_MLTERM_SCREEN(disp.roots[count])) {
627 ui_screen_reset_view((ui_screen_t *)disp.roots[count]);
628 }
629 }
630 }
631
open_pty(void * p,ui_screen_t * screen,char * dev)632 static void open_pty(void *p, ui_screen_t *screen, char *dev) {
633 if (dev) {
634 vt_term_t *new;
635
636 if ((new = vt_get_detached_term(dev))) {
637 VteTerminal *terminal = VTE_WIDGET(screen);
638 destroy_io(terminal);
639 PVT(terminal)->term = new;
640 create_io(terminal);
641
642 ui_screen_detach(screen);
643
644 /* It is after widget is reailzed that ui_screen_attach can be called. */
645 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
646 ui_screen_attach(screen, new);
647 }
648 }
649 }
650 }
651
652 /*
653 * EXIT_PROGRAM shortcut calls this at last.
654 * this is for debugging.
655 */
656 #ifdef BL_DEBUG
657 #include <pobl/bl_locale.h> /* bl_locale_final */
658 #endif
__exit(void * p,int status)659 static void __exit(void *p, int status) {
660 #ifdef BL_DEBUG
661 u_int count;
662
663 #if 1
664 bl_mem_dump_all();
665 #endif
666
667 vt_free_word_separators();
668 ui_free_mod_meta_prefix();
669 bl_set_msg_log_file_name(NULL);
670
671 /*
672 * Don't loop from 0 to dis.num_roots owing to processing inside
673 * ui_display_remove_root.
674 */
675 for (count = disp.num_roots; count > 0; count--) {
676 if (IS_MLTERM_SCREEN(disp.roots[count - 1])) {
677 gtk_widget_destroy(GTK_WIDGET(VTE_WIDGET((ui_screen_t *)disp.roots[count - 1])));
678 } else {
679 ui_display_remove_root(&disp, disp.roots[count - 1]);
680 }
681 }
682 free(disp.roots);
683 ui_gc_destroy(disp.gc);
684 #ifdef USE_XLIB
685 ui_xim_display_closed(disp.display);
686 #endif
687 ui_picture_display_closed(disp.display);
688
689 #ifdef USE_BRLAPI
690 ui_brltty_final();
691 #endif
692
693 vt_term_manager_final();
694 bl_locale_final();
695 ui_main_config_final(&main_config);
696 vt_color_config_final();
697 ui_shortcut_final(&shortcut);
698 #ifdef USE_XLIB
699 ui_xim_final();
700 #endif
701 bl_sig_child_final();
702
703 bl_alloca_garbage_collect();
704
705 bl_msg_printf("reporting unfreed memories --->\n");
706 bl_mem_free_all();
707
708 bl_dl_close_all();
709 #endif
710
711 #if 1
712 exit(1);
713 #else
714 gtk_main_quit();
715 #endif
716 }
717
718 /*
719 * vt_xterm_event_listener_t (overriding) handlers
720 */
721
xterm_resize(void * p,u_int width,u_int height,int flag)722 static void xterm_resize(void *p, u_int width, u_int height, int flag) {
723 ui_screen_t *screen = p;
724 VteTerminal *terminal = VTE_WIDGET(screen);
725
726 if (flag) {
727 flag --; /* converting to ui_maximize_flag_t */
728 if (flag == MAXIMIZE_FULL) {
729 gtk_window_maximize(gtk_widget_get_toplevel(GTK_WIDGET(terminal)));
730 } else if (flag == MAXIMIZE_RESTORE) {
731 gtk_window_unmaximize(gtk_widget_get_toplevel(GTK_WIDGET(terminal)));
732 }
733 } else {
734 (*PVT(terminal)->xterm_resize)(p, width, height, 0);
735 }
736 }
737
set_window_name(void * p,u_char * name)738 static void set_window_name(void *p, u_char *name) {
739 ui_screen_t *screen;
740 VteTerminal *terminal;
741
742 screen = p;
743 terminal = VTE_WIDGET(screen);
744
745 WINDOW_TITLE(terminal) = vt_term_window_name(screen->term);
746
747 gdk_window_set_title(gtk_widget_get_window(GTK_WIDGET(terminal)),
748 WINDOW_TITLE(terminal));
749 g_signal_emit_by_name(terminal, "window-title-changed");
750
751 #if VTE_CHECK_VERSION(0, 20, 0)
752 g_object_notify(G_OBJECT(terminal), "window-title");
753 #endif
754 }
755
set_icon_name(void * p,u_char * name)756 static void set_icon_name(void *p, u_char *name) {
757 ui_screen_t *screen;
758 VteTerminal *terminal;
759
760 screen = p;
761 terminal = VTE_WIDGET(screen);
762
763 ICON_TITLE(terminal) = vt_term_icon_name(screen->term);
764
765 gdk_window_set_icon_name(gtk_widget_get_window(GTK_WIDGET(terminal)),
766 ICON_TITLE(terminal));
767 g_signal_emit_by_name(terminal, "icon-title-changed");
768
769 #if VTE_CHECK_VERSION(0, 20, 0)
770 g_object_notify(G_OBJECT(terminal), "icon-title");
771 #endif
772 }
773
774 /*
775 * vt_screen_event_listener_t (overriding) handler
776 */
777
line_scrolled_out(void * p)778 static void line_scrolled_out(void *p /* must be ui_screen_t */
779 ) {
780 ui_screen_t *screen;
781 VteTerminal *terminal;
782 gdouble upper;
783 gdouble value;
784
785 screen = p;
786 terminal = VTE_WIDGET(screen);
787
788 (*PVT(terminal)->line_scrolled_out)(p);
789
790 /*
791 * line_scrolled_out is called in vt100 mode
792 * (after vt_xterm_event_listener_t::start_vt100 event), so
793 * don't call ui_screen_scroll_to() in adjustment_value_changed()
794 * in this context.
795 */
796 PVT(terminal)->adj_value_changed_by_myself = 1;
797
798 value = gtk_adjustment_get_value(ADJUSTMENT(terminal));
799
800 if ((upper = gtk_adjustment_get_upper(ADJUSTMENT(terminal))) <
801 vt_term_get_log_size(PVT(terminal)->term) + ROW_COUNT(terminal)) {
802 #if GTK_CHECK_VERSION(2, 14, 0)
803 gtk_adjustment_set_upper(ADJUSTMENT(terminal), upper + 1);
804 #else
805 ADJUSTMENT(terminal)->upper++;
806 gtk_adjustment_changed(ADJUSTMENT(terminal));
807 #endif
808
809 if (vt_term_is_backscrolling(PVT(terminal)->term) != BSM_STATIC) {
810 #if GTK_CHECK_VERSION(2, 14, 0)
811 gtk_adjustment_set_value(ADJUSTMENT(terminal), value + 1);
812 #else
813 ADJUSTMENT(terminal)->value++;
814 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
815 #endif
816 }
817 } else if (vt_term_is_backscrolling(PVT(terminal)->term) == BSM_STATIC && value > 0) {
818 #if GTK_CHECK_VERSION(2, 14, 0)
819 gtk_adjustment_set_value(ADJUSTMENT(terminal), value - 1);
820 #else
821 ADJUSTMENT(terminal)->value--;
822 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
823 #endif
824 }
825
826 #ifdef __DEBUG
827 bl_debug_printf(BL_DEBUG_TAG " line_scrolled_out upper %f value %f\n",
828 gtk_adjustment_get_upper(ADJUSTMENT(terminal)),
829 gtk_adjustment_get_value(ADJUSTMENT(terminal)));
830 #endif
831 }
832
833 /*
834 * ui_screen_scroll_event_listener_t handlers
835 */
836
bs_mode_exited(void * p)837 static void bs_mode_exited(void *p) {
838 VteTerminal *terminal;
839 int upper;
840 int page_size;
841
842 terminal = p;
843
844 PVT(terminal)->adj_value_changed_by_myself = 1;
845
846 upper = gtk_adjustment_get_upper(ADJUSTMENT(terminal));
847 page_size = gtk_adjustment_get_page_size(ADJUSTMENT(terminal));
848
849 #if GTK_CHECK_VERSION(2, 14, 0)
850 gtk_adjustment_set_value(ADJUSTMENT(terminal), upper - page_size);
851 #else
852 ADJUSTMENT(terminal)->value = upper - page_size;
853 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
854 #endif
855
856 #ifdef __DEBUG
857 bl_debug_printf(BL_DEBUG_TAG " bs_mode_exited upper %d page_size %d\n", upper, page_size);
858 #endif
859 }
860
scrolled_upward(void * p,u_int size)861 static void scrolled_upward(void *p, u_int size) {
862 VteTerminal *terminal;
863 int value;
864 int upper;
865 int page_size;
866
867 terminal = p;
868
869 value = gtk_adjustment_get_value(ADJUSTMENT(terminal));
870 upper = gtk_adjustment_get_upper(ADJUSTMENT(terminal));
871 page_size = gtk_adjustment_get_page_size(ADJUSTMENT(terminal));
872
873 if (value + page_size >= upper) {
874 return;
875 }
876
877 if (value + page_size + size > upper) {
878 size = upper - value - page_size;
879 }
880
881 PVT(terminal)->adj_value_changed_by_myself = 1;
882
883 #if GTK_CHECK_VERSION(2, 14, 0)
884 gtk_adjustment_set_value(ADJUSTMENT(terminal), value + size);
885 #else
886 ADJUSTMENT(terminal)->value += size;
887 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
888 #endif
889 }
890
scrolled_downward(void * p,u_int size)891 static void scrolled_downward(void *p, u_int size) {
892 VteTerminal *terminal;
893 int value;
894
895 terminal = p;
896
897 if ((value = gtk_adjustment_get_value(ADJUSTMENT(terminal))) == 0) {
898 return;
899 }
900
901 if (value < size) {
902 value = size;
903 }
904
905 PVT(terminal)->adj_value_changed_by_myself = 1;
906
907 #if GTK_CHECK_VERSION(2, 14, 0)
908 gtk_adjustment_set_value(ADJUSTMENT(terminal), value - size);
909 #else
910 ADJUSTMENT(terminal)->value -= size;
911 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
912 #endif
913 }
914
scrolled_to(void * p,int row)915 static void scrolled_to(void *p, int row) {
916 VteTerminal *terminal;
917
918 terminal = p;
919
920 PVT(terminal)->adj_value_changed_by_myself = 1;
921
922 #if GTK_CHECK_VERSION(2, 14, 0)
923 gtk_adjustment_set_value(ADJUSTMENT(terminal),
924 vt_term_get_num_logged_lines(PVT(terminal)->term) + row);
925 #else
926 ADJUSTMENT(terminal)->value = row;
927 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
928 #endif
929 }
930
log_size_changed(void * p,u_int log_size)931 static void log_size_changed(void *p, u_int log_size) {
932 VteTerminal *terminal;
933 int upper;
934 int page_size;
935
936 terminal = p;
937
938 PVT(terminal)->adj_value_changed_by_myself = 1;
939
940 upper = gtk_adjustment_get_upper(ADJUSTMENT(terminal));
941 page_size = gtk_adjustment_get_page_size(ADJUSTMENT(terminal));
942 if (upper > log_size + page_size) {
943 #if GTK_CHECK_VERSION(2, 14, 0)
944 gtk_adjustment_set_upper(ADJUSTMENT(terminal), log_size + page_size);
945 gtk_adjustment_set_value(ADJUSTMENT(terminal), log_size);
946 #else
947 ADJUSTMENT(terminal)->upper = log_size + page_size;
948 ADJUSTMENT(terminal)->value = log_size;
949 gtk_adjustment_changed(ADJUSTMENT(terminal));
950 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
951 #endif
952 }
953 }
954
term_changed(void * p,u_int log_size,u_int logged_lines)955 static void term_changed(void *p, u_int log_size, u_int logged_lines) {
956 VteTerminal *terminal;
957 int page_size;
958
959 terminal = p;
960
961 PVT(terminal)->adj_value_changed_by_myself = 1;
962
963 page_size = gtk_adjustment_get_page_size(ADJUSTMENT(terminal));
964 #if GTK_CHECK_VERSION(2, 14, 0)
965 gtk_adjustment_set_upper(ADJUSTMENT(terminal), logged_lines + page_size);
966 gtk_adjustment_set_value(ADJUSTMENT(terminal), logged_lines);
967 #else
968 ADJUSTMENT(terminal)->upper = logged_lines + page_size;
969 ADJUSTMENT(terminal)->value = logged_lines;
970 gtk_adjustment_changed(ADJUSTMENT(terminal));
971 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
972 #endif
973 }
974
adjustment_value_changed(VteTerminal * terminal)975 static void adjustment_value_changed(VteTerminal *terminal) {
976 int value;
977 int upper;
978 int page_size;
979
980 if (PVT(terminal)->adj_value_changed_by_myself) {
981 PVT(terminal)->adj_value_changed_by_myself = 0;
982
983 return;
984 }
985
986 value = gtk_adjustment_get_value(ADJUSTMENT(terminal));
987 upper = gtk_adjustment_get_upper(ADJUSTMENT(terminal));
988 page_size = gtk_adjustment_get_page_size(ADJUSTMENT(terminal));
989
990 #ifdef __DEBUG
991 bl_debug_printf(BL_DEBUG_TAG " scroll to %d\n", value - (upper - page_size));
992 #endif
993
994 ui_screen_scroll_to(PVT(terminal)->screen, value - (upper - page_size));
995 }
996
set_adjustment(VteTerminal * terminal,GtkAdjustment * adjustment)997 static void set_adjustment(VteTerminal *terminal, GtkAdjustment *adjustment) {
998 if (adjustment == ADJUSTMENT(terminal) || adjustment == NULL) {
999 return;
1000 }
1001
1002 if (ADJUSTMENT(terminal)) {
1003 g_signal_handlers_disconnect_by_func(ADJUSTMENT(terminal),
1004 G_CALLBACK(adjustment_value_changed), terminal);
1005 g_object_unref(ADJUSTMENT(terminal));
1006 }
1007
1008 g_object_ref_sink(adjustment);
1009 ADJUSTMENT(terminal) = adjustment;
1010 g_signal_connect_swapped(ADJUSTMENT(terminal), "value-changed",
1011 G_CALLBACK(adjustment_value_changed), terminal);
1012 PVT(terminal)->adj_value_changed_by_myself = 0;
1013 }
1014
reset_vte_size_member(VteTerminal * terminal)1015 static void reset_vte_size_member(VteTerminal *terminal) {
1016 int emit;
1017
1018 emit = 0;
1019
1020 if (/* If char_width == 0, reset_vte_size_member is called from
1021 vte_terminal_init */
1022 CHAR_WIDTH(terminal) != 0 &&
1023 CHAR_WIDTH(terminal) != ui_col_width(PVT(terminal)->screen)) {
1024 emit = 1;
1025 }
1026 CHAR_WIDTH(terminal) = ui_col_width(PVT(terminal)->screen);
1027
1028 if (/* If char_height == 0, reset_vte_size_member is called from
1029 vte_terminal_init */
1030 CHAR_HEIGHT(terminal) != 0 &&
1031 CHAR_HEIGHT(terminal) != ui_line_height(PVT(terminal)->screen)) {
1032 emit = 1;
1033 }
1034 CHAR_HEIGHT(terminal) = ui_line_height(PVT(terminal)->screen);
1035
1036 if (emit) {
1037 g_signal_emit_by_name(terminal, "char-size-changed", CHAR_WIDTH(terminal),
1038 CHAR_HEIGHT(terminal));
1039 }
1040
1041 #if !VTE_CHECK_VERSION(0, 38, 0)
1042 terminal->char_ascent = ui_line_ascent(PVT(terminal)->screen);
1043 terminal->char_descent = CHAR_HEIGHT(terminal) - terminal->char_ascent;
1044 #endif
1045
1046 emit = 0;
1047
1048 if (/* If row_count == 0, reset_vte_size_member is called from
1049 vte_terminal_init */
1050 ROW_COUNT(terminal) != 0 &&
1051 ROW_COUNT(terminal) != vt_term_get_rows(PVT(terminal)->term)) {
1052 emit = 1;
1053 }
1054
1055 ROW_COUNT(terminal) = vt_term_get_rows(PVT(terminal)->term);
1056
1057 if (/* If column_count == 0, reset_vte_size_member is called from
1058 vte_terminal_init */
1059 COLUMN_COUNT(terminal) != 0 &&
1060 COLUMN_COUNT(terminal) != vt_term_get_cols(PVT(terminal)->term)) {
1061 emit = 1;
1062 }
1063
1064 COLUMN_COUNT(terminal) = vt_term_get_cols(PVT(terminal)->term);
1065
1066 if (emit) {
1067 #if GTK_CHECK_VERSION(2, 14, 0)
1068 int value;
1069
1070 value = vt_term_get_num_logged_lines(PVT(terminal)->term);
1071 gtk_adjustment_configure(ADJUSTMENT(terminal), value /* value */, 0 /* lower */,
1072 value + ROW_COUNT(terminal) /* upper */, 1 /* step increment */,
1073 ROW_COUNT(terminal) /* page increment */,
1074 ROW_COUNT(terminal) /* page size */);
1075 #else
1076 ADJUSTMENT(terminal)->value = vt_term_get_num_logged_lines(PVT(terminal)->term);
1077 ADJUSTMENT(terminal)->upper = ADJUSTMENT(terminal)->value + ROW_COUNT(terminal);
1078 ADJUSTMENT(terminal)->page_increment = ROW_COUNT(terminal);
1079 ADJUSTMENT(terminal)->page_size = ROW_COUNT(terminal);
1080
1081 gtk_adjustment_changed(ADJUSTMENT(terminal));
1082 gtk_adjustment_value_changed(ADJUSTMENT(terminal));
1083 #endif
1084 }
1085
1086 #if !GTK_CHECK_VERSION(2, 90, 0)
1087 /*
1088 * XXX
1089 * Vertical writing mode and screen_(width|height)_ratio option are not
1090 *supported.
1091 *
1092 * Processing similar to vte_terminal_get_preferred_{width|height}().
1093 */
1094 GTK_WIDGET(terminal)->requisition.width =
1095 COLUMN_COUNT(terminal) * CHAR_WIDTH(terminal) + PVT(terminal)->screen->window.hmargin * 2;
1096 GTK_WIDGET(terminal)->requisition.height =
1097 ROW_COUNT(terminal) * CHAR_HEIGHT(terminal) + PVT(terminal)->screen->window.vmargin * 2;
1098
1099 #ifdef __DEBUG
1100 bl_debug_printf(BL_DEBUG_TAG
1101 " char_width %d char_height %d row_count %d column_count %d "
1102 "width %d height %d\n",
1103 CHAR_WIDTH(terminal), CHAR_HEIGHT(terminal), ROW_COUNT(terminal),
1104 COLUMN_COUNT(terminal), GTK_WIDGET(terminal)->requisition.width,
1105 GTK_WIDGET(terminal)->requisition.height);
1106 #endif
1107 #endif /* ! GTK_CHECK_VERSION(2,90,0) */
1108 }
1109
vte_terminal_timeout(gpointer data)1110 static gboolean vte_terminal_timeout(gpointer data) {
1111 /*
1112 * If gdk_threads_add_timeout (2.12 or later) doesn't exist,
1113 * call gdk_threads_{enter|leave} manually for MT-safe.
1114 */
1115 #if !GTK_CHECK_VERSION(2, 12, 0)
1116 gdk_threads_enter();
1117 #endif
1118
1119 vt_close_dead_terms();
1120
1121 ui_display_idling(&disp);
1122
1123 #if !GTK_CHECK_VERSION(2, 12, 0)
1124 gdk_threads_leave();
1125 #endif
1126
1127 return TRUE;
1128 }
1129
vte_terminal_finalize(GObject * obj)1130 static void vte_terminal_finalize(GObject *obj) {
1131 VteTerminal *terminal;
1132 GtkSettings *settings;
1133
1134 #ifdef DEBUG
1135 bl_debug_printf(BL_DEBUG_TAG " vte terminal finalized.\n");
1136 #endif
1137
1138 terminal = VTE_TERMINAL(obj);
1139
1140 #if GLIB_CHECK_VERSION(2, 14, 0)
1141 if (PVT(terminal)->gregex) {
1142 g_regex_unref(PVT(terminal)->gregex);
1143 PVT(terminal)->gregex = NULL;
1144 }
1145
1146 #if VTE_CHECK_VERSION(0, 46, 0)
1147 if (PVT(terminal)->vregex) {
1148 vte_regex_unref(PVT(terminal)->vregex);
1149 PVT(terminal)->vregex = NULL;
1150 }
1151 #endif
1152 #endif
1153
1154 #if VTE_CHECK_VERSION(0, 38, 0)
1155 vte_terminal_match_remove_all(terminal);
1156 #else
1157 vte_terminal_match_clear_all(terminal);
1158 #endif
1159
1160 #if VTE_CHECK_VERSION(0, 26, 0)
1161 if (PVT(terminal)->pty) {
1162 g_object_unref(PVT(terminal)->pty);
1163 PVT(terminal)->pty = NULL;
1164 }
1165 #endif
1166
1167 ui_font_manager_destroy(PVT(terminal)->screen->font_man);
1168 ui_color_manager_destroy(PVT(terminal)->screen->color_man);
1169
1170 if (PVT(terminal)->image) {
1171 g_object_unref(PVT(terminal)->image);
1172 PVT(terminal)->image = NULL;
1173 }
1174
1175 if (PVT(terminal)->pixmap) {
1176 #ifdef USE_XLIB
1177 XFreePixmap(disp.display, PVT(terminal)->pixmap);
1178 #else
1179 /* XXX */
1180 #endif
1181 PVT(terminal)->pixmap = None;
1182 }
1183
1184 free(PVT(terminal)->pic_mod);
1185
1186 ui_window_final(&PVT(terminal)->screen->window);
1187 PVT(terminal)->screen = NULL;
1188
1189 if (ADJUSTMENT(terminal)) {
1190 g_object_unref(ADJUSTMENT(terminal));
1191 }
1192
1193 settings = gtk_widget_get_settings(GTK_WIDGET(obj));
1194 g_signal_handlers_disconnect_matched(settings, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, terminal);
1195
1196 G_OBJECT_CLASS(vte_terminal_parent_class)->finalize(obj);
1197
1198 #ifdef __DEBUG
1199 bl_debug_printf("End of vte_terminal_finalize() \n");
1200 #endif
1201 }
1202
vte_terminal_get_property(GObject * obj,guint prop_id,GValue * value,GParamSpec * pspec)1203 static void vte_terminal_get_property(GObject *obj, guint prop_id, GValue *value,
1204 GParamSpec *pspec) {
1205 VteTerminal *terminal;
1206
1207 terminal = VTE_TERMINAL(obj);
1208
1209 switch (prop_id) {
1210 #if GTK_CHECK_VERSION(2, 90, 0)
1211 case PROP_VADJUSTMENT:
1212 g_value_set_object(value, ADJUSTMENT(terminal));
1213 break;
1214 #endif
1215
1216 case PROP_ICON_TITLE:
1217 g_value_set_string(value, vte_terminal_get_icon_title(terminal));
1218 break;
1219
1220 case PROP_WINDOW_TITLE:
1221 g_value_set_string(value, vte_terminal_get_window_title(terminal));
1222 break;
1223
1224 #if 0
1225 default:
1226 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
1227 #endif
1228 }
1229 }
1230
vte_terminal_set_property(GObject * obj,guint prop_id,const GValue * value,GParamSpec * pspec)1231 static void vte_terminal_set_property(GObject *obj, guint prop_id, const GValue *value,
1232 GParamSpec *pspec) {
1233 VteTerminal *terminal;
1234
1235 terminal = VTE_TERMINAL(obj);
1236
1237 switch (prop_id) {
1238 #if GTK_CHECK_VERSION(2, 90, 0)
1239 case PROP_VADJUSTMENT:
1240 set_adjustment(terminal, g_value_get_object(value));
1241 break;
1242 #endif
1243
1244 #if 0
1245 case PROP_ICON_TITLE:
1246 set_icon_name(PVT(terminal)->screen, g_value_get_string(value));
1247 break;
1248
1249 case PROP_WINDOW_TITLE:
1250 set_window_name(PVT(terminal)->screen, g_value_get_string(value));
1251 break;
1252 #endif
1253
1254 #if 0
1255 default:
1256 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
1257 #endif
1258 }
1259 }
1260
init_screen(VteTerminal * terminal,ui_font_manager_t * font_man,ui_color_manager_t * color_man)1261 static void init_screen(VteTerminal *terminal, ui_font_manager_t *font_man,
1262 ui_color_manager_t *color_man) {
1263 u_int hmargin;
1264 u_int vmargin;
1265
1266 #if VTE_CHECK_VERSION(0, 38, 0)
1267 GtkBorder padding;
1268
1269 gtk_style_context_get_padding(gtk_widget_get_style_context(GTK_WIDGET(terminal)),
1270 gtk_widget_get_state_flags(GTK_WIDGET(terminal)), &padding);
1271 hmargin = BL_MIN(padding.left, padding.right);
1272 vmargin = BL_MIN(padding.top, padding.bottom);
1273 #else
1274 hmargin = WINDOW_MARGIN;
1275 vmargin = WINDOW_MARGIN;
1276 #endif
1277
1278 /*
1279 * XXX
1280 * PVT(terminal)->term is specified to ui_screen_new in order to set
1281 * ui_window_t::width and height property, but screen->term is NULL
1282 * until widget is realized.
1283 */
1284 PVT(terminal)->screen = ui_screen_new(PVT(terminal)->term, font_man, color_man,
1285 main_config.brightness, main_config.contrast,
1286 main_config.gamma, main_config.alpha,
1287 main_config.fade_ratio, &shortcut,
1288 /* main_config.screen_width_ratio */ 100,
1289 main_config.mod_meta_key, main_config.mod_meta_mode,
1290 main_config.bel_mode, main_config.receive_string_via_ucs,
1291 main_config.pic_file_path, main_config.use_transbg,
1292 main_config.use_vertical_cursor, main_config.borderless,
1293 main_config.line_space, main_config.input_method,
1294 main_config.allow_osc52, hmargin, vmargin,
1295 main_config.hide_underline, main_config.underline_offset,
1296 main_config.baseline_offset);
1297 if (PVT(terminal)->term) {
1298 vt_term_detach(PVT(terminal)->term);
1299 PVT(terminal)->screen->term = NULL;
1300 } else {
1301 /*
1302 * PVT(terminal)->term can be NULL if this function is called from
1303 * vte_terminal_unrealize.
1304 */
1305 }
1306
1307 memset(&PVT(terminal)->system_listener, 0, sizeof(ui_system_event_listener_t));
1308 PVT(terminal)->system_listener.self = terminal;
1309 PVT(terminal)->system_listener.font_config_updated = font_config_updated;
1310 PVT(terminal)->system_listener.color_config_updated = color_config_updated;
1311 PVT(terminal)->system_listener.open_pty = open_pty;
1312 PVT(terminal)->system_listener.exit = __exit;
1313 ui_set_system_listener(PVT(terminal)->screen, &PVT(terminal)->system_listener);
1314
1315 memset(&PVT(terminal)->screen_scroll_listener, 0, sizeof(ui_screen_scroll_event_listener_t));
1316 PVT(terminal)->screen_scroll_listener.self = terminal;
1317 PVT(terminal)->screen_scroll_listener.bs_mode_exited = bs_mode_exited;
1318 PVT(terminal)->screen_scroll_listener.scrolled_upward = scrolled_upward;
1319 PVT(terminal)->screen_scroll_listener.scrolled_downward = scrolled_downward;
1320 PVT(terminal)->screen_scroll_listener.scrolled_to = scrolled_to;
1321 PVT(terminal)->screen_scroll_listener.log_size_changed = log_size_changed;
1322 PVT(terminal)->screen_scroll_listener.term_changed = term_changed;
1323 ui_set_screen_scroll_listener(PVT(terminal)->screen, &PVT(terminal)->screen_scroll_listener);
1324
1325 PVT(terminal)->line_scrolled_out = PVT(terminal)->screen->screen_listener.line_scrolled_out;
1326 PVT(terminal)->screen->screen_listener.line_scrolled_out = line_scrolled_out;
1327
1328 PVT(terminal)->screen->xterm_listener.set_window_name = set_window_name;
1329 PVT(terminal)->screen->xterm_listener.set_icon_name = set_icon_name;
1330 PVT(terminal)->xterm_resize = PVT(terminal)->screen->xterm_listener.resize;
1331 PVT(terminal)->screen->xterm_listener.resize = xterm_resize;
1332
1333 orig_select_in_window = PVT(terminal)->screen->sel_listener.select_in_window;
1334 PVT(terminal)->screen->sel_listener.select_in_window = select_in_window;
1335
1336 /* overriding */
1337 PVT(terminal)->screen->pty_listener.closed = pty_closed;
1338 }
1339
1340 #if VTE_CHECK_VERSION(0, 38, 0)
1341 void vte_terminal_set_background_image(VteTerminal *terminal, GdkPixbuf *image);
1342 void vte_terminal_set_background_image_file(VteTerminal *terminal, const char *path);
1343 #endif
1344
update_wall_picture(VteTerminal * terminal)1345 static void update_wall_picture(VteTerminal *terminal) {
1346 ui_window_t *win;
1347 ui_picture_modifier_t *pic_mod;
1348 GdkPixbuf *image;
1349 char file[7 + DIGIT_STR_LEN(PVT(terminal)->pixmap) + 1];
1350
1351 if (!PVT(terminal)->image) {
1352 return;
1353 }
1354
1355 win = &PVT(terminal)->screen->window;
1356 pic_mod = ui_screen_get_picture_modifier(PVT(terminal)->screen);
1357
1358 if (PVT(terminal)->pix_width == ACTUAL_WIDTH(win) &&
1359 PVT(terminal)->pix_height == ACTUAL_WIDTH(win) &&
1360 ui_picture_modifiers_equal(pic_mod, PVT(terminal)->pic_mod) && PVT(terminal)->pixmap) {
1361 goto set_bg_image;
1362 } else if (gdk_pixbuf_get_width(PVT(terminal)->image) != ACTUAL_WIDTH(win) ||
1363 gdk_pixbuf_get_height(PVT(terminal)->image) != ACTUAL_HEIGHT(win)) {
1364 #ifdef DEBUG
1365 bl_debug_printf(
1366 BL_DEBUG_TAG " Scaling bg img %d %d => %d %d\n", gdk_pixbuf_get_width(PVT(terminal)->image),
1367 gdk_pixbuf_get_height(PVT(terminal)->image), ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win));
1368 #endif
1369
1370 image = gdk_pixbuf_scale_simple(PVT(terminal)->image, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win),
1371 GDK_INTERP_BILINEAR);
1372 } else {
1373 image = PVT(terminal)->image;
1374 }
1375
1376 if (PVT(terminal)->pixmap) {
1377 #ifdef USE_XLIB
1378 XFreePixmap(disp.display, PVT(terminal)->pixmap);
1379 #else
1380 /* XXX */
1381 #endif
1382 }
1383
1384 PVT(terminal)->pixmap = ui_imagelib_pixbuf_to_pixmap(win, pic_mod, image);
1385
1386 if (image != PVT(terminal)->image) {
1387 g_object_unref(image);
1388 }
1389
1390 if (PVT(terminal)->pixmap == None) {
1391 bl_msg_printf(
1392 "Failed to convert pixbuf to pixmap. "
1393 "Rebuild mlterm with gdk-pixbuf.\n");
1394
1395 PVT(terminal)->pix_width = 0;
1396 PVT(terminal)->pix_height = 0;
1397 PVT(terminal)->pic_mod = NULL;
1398
1399 return;
1400 }
1401
1402 PVT(terminal)->pix_width = ACTUAL_WIDTH(win);
1403 PVT(terminal)->pix_height = ACTUAL_HEIGHT(win);
1404 if (pic_mod) {
1405 if (PVT(terminal)->pic_mod == NULL) {
1406 PVT(terminal)->pic_mod = malloc(sizeof(ui_picture_modifier_t));
1407 }
1408
1409 *PVT(terminal)->pic_mod = *pic_mod;
1410 } else {
1411 free(PVT(terminal)->pic_mod);
1412 PVT(terminal)->pic_mod = NULL;
1413 }
1414
1415 set_bg_image:
1416 ui_change_true_transbg_alpha(PVT(terminal)->screen->color_man, 255);
1417
1418 sprintf(file, "pixmap:%lu", PVT(terminal)->pixmap);
1419 vte_terminal_set_background_image_file(terminal, file);
1420 }
1421
vte_terminal_realize(GtkWidget * widget)1422 static void vte_terminal_realize(GtkWidget *widget) {
1423 VteTerminal *terminal = VTE_TERMINAL(widget);
1424 GdkWindowAttr attr;
1425 GtkAllocation allocation;
1426
1427 if (gtk_widget_get_window(widget)) {
1428 return;
1429 }
1430
1431 ui_screen_attach(PVT(terminal)->screen, PVT(terminal)->term);
1432
1433 gtk_widget_get_allocation(widget, &allocation);
1434
1435 #ifdef DEBUG
1436 bl_debug_printf(BL_DEBUG_TAG " vte terminal realized with size x %d y %d w %d h %d\n",
1437 allocation.x, allocation.y, allocation.width, allocation.height);
1438 #endif
1439
1440 GTK_WIDGET_SET_REALIZED(widget);
1441
1442 attr.window_type = GDK_WINDOW_CHILD;
1443 attr.x = allocation.x;
1444 attr.y = allocation.y;
1445 attr.width = allocation.width;
1446 attr.height = allocation.height;
1447 attr.wclass = GDK_INPUT_OUTPUT;
1448 attr.visual = gtk_widget_get_visual(widget);
1449 #if !GTK_CHECK_VERSION(2, 90, 0)
1450 attr.colormap = gtk_widget_get_colormap(widget);
1451 #endif
1452 attr.event_mask = gtk_widget_get_events(widget) | GDK_FOCUS_CHANGE_MASK | GDK_BUTTON_PRESS_MASK |
1453 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
1454 GDK_SUBSTRUCTURE_MASK; /* DestroyNotify from child */
1455
1456 gtk_widget_set_window(widget,
1457 gdk_window_new(gtk_widget_get_parent_window(widget), &attr,
1458 GDK_WA_X | GDK_WA_Y | (attr.visual ? GDK_WA_VISUAL : 0)
1459 #if !GTK_CHECK_VERSION(2, 90, 0)
1460 | (attr.colormap ? GDK_WA_COLORMAP : 0)
1461 #endif
1462 ));
1463
1464 /*
1465 * Note that hook key and button events in vte_terminal_filter doesn't work
1466 * without this.
1467 */
1468 #if GTK_CHECK_VERSION(3, 8, 0)
1469 gtk_widget_register_window(widget, gtk_widget_get_window(widget));
1470 #else
1471 gdk_window_set_user_data(gtk_widget_get_window(widget), widget);
1472 #endif
1473
1474 #if !GTK_CHECK_VERSION(2, 90, 0)
1475 if (widget->style->font_desc) {
1476 pango_font_description_free(widget->style->font_desc);
1477 widget->style->font_desc = NULL;
1478 }
1479
1480 /* private_font(_desc) should be NULL if widget->style->font_desc is set NULL
1481 * above. */
1482 if (widget->style->private_font) {
1483 gdk_font_unref(widget->style->private_font);
1484 widget->style->private_font = NULL;
1485 }
1486
1487 if (widget->style->private_font_desc) {
1488 pango_font_description_free(widget->style->private_font_desc);
1489 widget->style->private_font_desc = NULL;
1490 }
1491 #endif
1492
1493 #ifdef USE_XLIB
1494 g_signal_connect_swapped(gtk_widget_get_toplevel(widget), "configure-event",
1495 G_CALLBACK(toplevel_configure), terminal);
1496 #endif
1497
1498 show_root(&disp, widget);
1499
1500 /*
1501 * allocation passed by size_allocate is not necessarily to be reflected
1502 * to ui_window_t or vt_term_t, so ui_window_resize must be called here.
1503 */
1504 if (PVT(terminal)->term->pty && !is_initial_allocation(&allocation)) {
1505 if (ui_window_resize_with_margin(&PVT(terminal)->screen->window, allocation.width,
1506 allocation.height, NOTIFY_TO_MYSELF)) {
1507 reset_vte_size_member(terminal);
1508 }
1509 }
1510
1511 update_wall_picture(terminal);
1512 }
1513
vte_terminal_unrealize(GtkWidget * widget)1514 static void vte_terminal_unrealize(GtkWidget *widget) {
1515 VteTerminal *terminal = VTE_TERMINAL(widget);
1516 ui_screen_t *screen = PVT(terminal)->screen;
1517
1518 #ifdef DEBUG
1519 bl_debug_printf(BL_DEBUG_TAG " vte terminal unrealized.\n");
1520 #endif
1521
1522 ui_screen_detach(screen);
1523
1524 if (!PVT(terminal)->term->pty) {
1525 /* PVT(terminal)->term is not destroyed in pty_closed() */
1526 vt_term_destroy(PVT(terminal)->term);
1527 PVT(terminal)->term = NULL;
1528 }
1529
1530 /* Create dummy screen in case terminal will be realized again. */
1531 init_screen(terminal, screen->font_man, screen->color_man);
1532 ui_display_remove_root(&disp, &screen->window);
1533
1534 #ifdef USE_XLIB
1535 g_signal_handlers_disconnect_by_func(gtk_widget_get_toplevel(GTK_WIDGET(terminal)),
1536 G_CALLBACK(toplevel_configure), terminal);
1537 #endif
1538
1539 /* gtk_widget_unregister_window() and gdk_window_destroy() are called. */
1540 GTK_WIDGET_CLASS(vte_terminal_parent_class)->unrealize(widget);
1541
1542 #ifdef __DEBUG
1543 bl_debug_printf("End of vte_terminal_unrealize()\n");
1544 #endif
1545 }
1546
vte_terminal_focus_in(GtkWidget * widget,GdkEventFocus * event)1547 static gboolean vte_terminal_focus_in(GtkWidget *widget, GdkEventFocus *event) {
1548 GTK_WIDGET_SET_HAS_FOCUS(widget);
1549
1550 if (GTK_WIDGET_MAPPED(widget)) {
1551 ui_window_t *win = &PVT(VTE_TERMINAL(widget))->screen->window;
1552 #ifdef USE_WAYLAND
1553 win->disp->display->wlserv->current_kbd_surface = win->disp->display->surface;
1554 #endif
1555
1556 #ifdef __DEBUG
1557 bl_debug_printf(BL_DEBUG_TAG " focus in\n");
1558 #endif
1559
1560 ui_window_set_input_focus(win);
1561 }
1562
1563 return FALSE;
1564 }
1565
vte_terminal_focus_out(GtkWidget * widget,GdkEventFocus * event)1566 static gboolean vte_terminal_focus_out(GtkWidget *widget, GdkEventFocus *event) {
1567 #ifdef USE_WAYLAND
1568 ui_window_t *win = &PVT(VTE_TERMINAL(widget))->screen->window;
1569 if (win->window_unfocused) {
1570 win->is_focused = 0;
1571 (*win->window_unfocused)(win);
1572 }
1573 #endif
1574
1575 #ifdef __DEBUG
1576 bl_debug_printf(BL_DEBUG_TAG " focus out\n");
1577 #endif
1578
1579 GTK_WIDGET_UNSET_HAS_FOCUS(widget);
1580
1581 return FALSE;
1582 }
1583
1584 #if GTK_CHECK_VERSION(2, 90, 0)
1585
vte_terminal_get_preferred_width(GtkWidget * widget,gint * minimum_width,gint * natural_width)1586 static void vte_terminal_get_preferred_width(GtkWidget *widget, gint *minimum_width,
1587 gint *natural_width) {
1588 /* Processing similar to setting GtkWidget::requisition in
1589 * reset_vte_size_member(). */
1590 VteTerminal *terminal = VTE_TERMINAL(widget);
1591
1592 if (minimum_width) {
1593 *minimum_width =
1594 CHAR_WIDTH(terminal) + PVT(terminal)->screen->window.hmargin * 2;
1595
1596 #ifdef DEBUG
1597 bl_debug_printf(BL_DEBUG_TAG " preferred minimum width %d\n", *minimum_width);
1598 #endif
1599 }
1600
1601 if (natural_width) {
1602 *natural_width = COLUMN_COUNT(terminal) * CHAR_WIDTH(terminal) +
1603 PVT(terminal)->screen->window.hmargin * 2;
1604
1605 #ifdef DEBUG
1606 bl_debug_printf(BL_DEBUG_TAG " preferred natural width %d\n", *natural_width);
1607 #endif
1608 }
1609 }
1610
vte_terminal_get_preferred_width_for_height(GtkWidget * widget,gint height,gint * minimum_width,gint * natural_width)1611 static void vte_terminal_get_preferred_width_for_height(GtkWidget *widget, gint height,
1612 gint *minimum_width, gint *natural_width) {
1613 #ifdef __DEBUG
1614 bl_debug_printf(BL_DEBUG_TAG " preferred width for height %d\n", height);
1615 #endif
1616
1617 vte_terminal_get_preferred_width(widget, minimum_width, natural_width);
1618 }
1619
vte_terminal_get_preferred_height(GtkWidget * widget,gint * minimum_height,gint * natural_height)1620 static void vte_terminal_get_preferred_height(GtkWidget *widget, gint *minimum_height,
1621 gint *natural_height) {
1622 /* Processing similar to setting GtkWidget::requisition in
1623 * reset_vte_size_member(). */
1624 VteTerminal *terminal = VTE_TERMINAL(widget);
1625
1626 /* XXX */
1627 if (!PVT(terminal)->init_char_size &&
1628 (strstr(g_get_prgname(), "roxterm") ||
1629 /*
1630 * Hack for roxterm started by "x-terminal-emulator" or
1631 * "exo-open --launch TerminalEmulator" (which calls
1632 * "x-terminal-emulator" internally)
1633 */
1634 g_object_get_data(gtk_widget_get_parent(widget), "roxterm_tab"))) {
1635 /*
1636 * XXX
1637 * I don't know why, but the size of roxterm 2.6.5 (GTK+3) is
1638 * minimized unless "char-size-changed" signal is emit once in
1639 * vte_terminal_get_preferred_height() or
1640 * vte_terminal_get_preferred_height() in startup.
1641 */
1642 g_signal_emit_by_name(widget, "char-size-changed", CHAR_WIDTH(terminal),
1643 CHAR_HEIGHT(terminal));
1644 }
1645
1646 PVT(terminal)->init_char_size = 1;
1647
1648 if (minimum_height) {
1649 *minimum_height =
1650 CHAR_HEIGHT(terminal) + PVT(terminal)->screen->window.vmargin * 2;
1651
1652 #ifdef DEBUG
1653 bl_debug_printf(BL_DEBUG_TAG " preferred minimum height %d\n", *minimum_height);
1654 #endif
1655 }
1656
1657 if (natural_height) {
1658 *natural_height = ROW_COUNT(terminal) * CHAR_HEIGHT(terminal) +
1659 PVT(terminal)->screen->window.vmargin * 2;
1660
1661 #ifdef DEBUG
1662 bl_debug_printf(BL_DEBUG_TAG " preferred natural height %d\n", *natural_height);
1663 #endif
1664 }
1665 }
1666
vte_terminal_get_preferred_height_for_width(GtkWidget * widget,gint width,gint * minimum_height,gint * natural_height)1667 static void vte_terminal_get_preferred_height_for_width(GtkWidget *widget, gint width,
1668 gint *minimum_height,
1669 gint *natural_height) {
1670 #ifdef __DEBUG
1671 bl_debug_printf(BL_DEBUG_TAG " preferred height for width %d\n", width);
1672 #endif
1673
1674 vte_terminal_get_preferred_height(widget, minimum_height, natural_height);
1675 }
1676
1677 #else /* GTK_CHECK_VERSION(2,90,0) */
1678
vte_terminal_size_request(GtkWidget * widget,GtkRequisition * req)1679 static void vte_terminal_size_request(GtkWidget *widget, GtkRequisition *req) {
1680 *req = widget->requisition;
1681
1682 #ifdef DEBUG
1683 bl_debug_printf(BL_DEBUG_TAG " size_request %d %d cur alloc %d %d\n", req->width, req->height,
1684 widget->allocation.width, widget->allocation.height);
1685 #endif
1686 }
1687
1688 #endif /* GTK_CHECK_VERSION(2,90,0) */
1689
vte_terminal_size_allocate(GtkWidget * widget,GtkAllocation * allocation)1690 static void vte_terminal_size_allocate(GtkWidget *widget, GtkAllocation *allocation) {
1691 int is_resized;
1692 GtkAllocation cur_allocation;
1693
1694 gtk_widget_get_allocation(widget, &cur_allocation);
1695
1696 #ifdef DEBUG
1697 bl_debug_printf(BL_DEBUG_TAG " size_allocate %d %d %d %d => %d %d %d %d\n", cur_allocation.x,
1698 cur_allocation.y, cur_allocation.width, cur_allocation.height, allocation->x,
1699 allocation->y, allocation->width, allocation->height);
1700 #endif
1701
1702 if (!(is_resized = (cur_allocation.width != allocation->width ||
1703 cur_allocation.height != allocation->height)) &&
1704 cur_allocation.x == allocation->x && cur_allocation.y == allocation->y) {
1705 return;
1706 }
1707
1708 gtk_widget_set_allocation(widget, allocation);
1709
1710 if (GTK_WIDGET_REALIZED(widget)) {
1711 VteTerminal *terminal = VTE_TERMINAL(widget);
1712 if (is_resized && PVT(terminal)->term->pty) {
1713 /*
1714 * Even if ui_window_resize_with_margin returns 0,
1715 * reset_vte_size_member etc functions must be called,
1716 * because VTE_TERMNAL(widget)->pvt->screen can be already
1717 * resized and vte_terminal_size_allocate can be called
1718 * from vte_terminal_filter.
1719 */
1720 ui_window_resize_with_margin(&PVT(terminal)->screen->window, allocation->width,
1721 allocation->height, NOTIFY_TO_MYSELF);
1722 reset_vte_size_member(terminal);
1723 update_wall_picture(terminal);
1724 /*
1725 * gnome-terminal(2.29.6 or later ?) is not resized correctly
1726 * without this.
1727 */
1728 gtk_widget_queue_resize_no_redraw(widget);
1729 }
1730
1731 gdk_window_move_resize(gtk_widget_get_window(widget), allocation->x, allocation->y,
1732 allocation->width, allocation->height);
1733 #ifdef USE_WAYLAND
1734 /* Multiple displays can coexist on wayland, so '&disp' isn't used. */
1735 ui_display_move(PVT(terminal)->screen->window.disp, allocation->x, allocation->y);
1736 #endif
1737 } else {
1738 /*
1739 * ui_window_resize_with_margin(widget->allocation.width, height)
1740 * will be called in vte_terminal_realize() or vte_terminal_fork*().
1741 */
1742 }
1743 }
1744
1745 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_screen_changed(GtkWidget * widget,GdkScreen * previous_screen)1746 static void vte_terminal_screen_changed(GtkWidget *widget, GdkScreen *previous_screen) {
1747 GdkScreen *screen;
1748 GtkSettings *settings;
1749
1750 screen = gtk_widget_get_screen(widget);
1751 if (previous_screen != NULL && (screen != previous_screen || screen == NULL)) {
1752 settings = gtk_settings_get_for_screen(previous_screen);
1753 g_signal_handlers_disconnect_matched(settings, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, widget);
1754 }
1755
1756 if (GTK_WIDGET_CLASS(vte_terminal_parent_class)->screen_changed) {
1757 GTK_WIDGET_CLASS(vte_terminal_parent_class)->screen_changed(widget, previous_screen);
1758 }
1759 }
1760 #endif
1761
1762 #if GTK_CHECK_VERSION(2, 90, 0)
vte_terminal_draw(GtkWidget * widget,cairo_t * cr)1763 static gboolean vte_terminal_draw(GtkWidget *widget, cairo_t *cr) {
1764 int width = gtk_widget_get_allocated_width(widget);
1765 int height = gtk_widget_get_allocated_height(widget);
1766 cairo_rectangle(cr, 0, 0, width, height);
1767 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1768 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
1769 cairo_fill(cr);
1770
1771 return TRUE;
1772 }
1773 #endif
1774
vte_terminal_key_press(GtkWidget * widget,GdkEventKey * event)1775 static gboolean vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event) {
1776 /* Check if GtkWidget's behavior already does something with this key. */
1777 GTK_WIDGET_CLASS(vte_terminal_parent_class)->key_press_event(widget, event);
1778
1779 /* If FALSE is returned, tab operation is unexpectedly started in
1780 * gnome-terminal. */
1781 return TRUE;
1782 }
1783
vte_terminal_class_init(VteTerminalClass * vclass)1784 static void vte_terminal_class_init(VteTerminalClass *vclass) {
1785 char *value;
1786 bl_conf_t *conf;
1787 char *argv[] = {"mlterm", NULL};
1788 GObjectClass *oclass;
1789 GtkWidgetClass *wclass;
1790
1791 #if defined(__DEBUG) && defined(USE_XLIB)
1792 XSetErrorHandler(error_handler);
1793 XSynchronize(gdk_x11_display_get_xdisplay(gdk_display_get_default()), True);
1794 #endif
1795
1796 /* bl_sig_child_start() calls signal(3) internally. */
1797 #if 0
1798 bl_sig_child_start();
1799 #endif
1800
1801 bl_priv_change_euid(bl_getuid());
1802 bl_priv_change_egid(bl_getgid());
1803
1804 #if 0
1805 bindtextdomain("vte", LOCALEDIR);
1806 bind_textdomain_codeset("vte", "UTF-8");
1807 #endif
1808
1809 if (!bl_locale_init("")) {
1810 bl_msg_printf("locale settings failed.\n");
1811 }
1812
1813 bl_set_sys_conf_dir(CONFIG_PATH);
1814
1815 vt_term_manager_init(1);
1816 vt_term_manager_enable_zombie_pty();
1817 #ifdef USE_WAYLAND
1818 gdk_threads_add_timeout(25, vte_terminal_timeout, NULL); /* 25 miliseconds */
1819 #else
1820 #if GTK_CHECK_VERSION(2, 12, 0)
1821 gdk_threads_add_timeout(100, vte_terminal_timeout, NULL); /* 100 miliseconds */
1822 #else
1823 g_timeout_add(100, vte_terminal_timeout, NULL); /* 100 miliseconds */
1824 #endif
1825 #endif
1826
1827 vt_color_config_init();
1828
1829 ui_shortcut_init(&shortcut);
1830 ui_shortcut_parse(&shortcut, "Button3", "\"none\"");
1831 ui_shortcut_parse(&shortcut, "UNUSED", "OPEN_SCREEN");
1832 ui_shortcut_parse(&shortcut, "UNUSED", "OPEN_PTY");
1833 ui_shortcut_parse(&shortcut, "UNUSED", "NEXT_PTY");
1834 ui_shortcut_parse(&shortcut, "UNUSED", "PREV_PTY");
1835 ui_shortcut_parse(&shortcut, "UNUSED", "HSPLIT_SCREEN");
1836 ui_shortcut_parse(&shortcut, "UNUSED", "VSPLIT_SCREEN");
1837 ui_shortcut_parse(&shortcut, "UNUSED", "NEXT_SCREEN");
1838 ui_shortcut_parse(&shortcut, "UNUSED", "CLOSE_SCREEN");
1839 ui_shortcut_parse(&shortcut, "UNUSED", "HEXPAND_SCREEN");
1840 ui_shortcut_parse(&shortcut, "UNUSED", "VEXPAND_SCREEN");
1841
1842 #ifdef USE_XLIB
1843 ui_xim_init(1);
1844 #endif
1845 ui_font_use_point_size(1);
1846
1847 bl_init_prog(g_get_prgname(), VERSION);
1848
1849 if ((conf = bl_conf_new()) == NULL) {
1850 return;
1851 }
1852
1853 ui_prepare_for_main_config(conf);
1854
1855 /*
1856 * Same processing as main_loop_init().
1857 * Following options are not possible to specify as arguments of mlclient.
1858 * 1) Options which are used only when mlterm starts up and which aren't
1859 * changed dynamically. (e.g. "startup_screens")
1860 * 2) Options which change status of all ptys or windows. (Including ones
1861 * which are possible to change dynamically.)
1862 * (e.g. "font_size_range")
1863 */
1864
1865 #if 0
1866 bl_conf_add_opt(conf, 'R', "fsrange", 0, "font_size_range", NULL);
1867 #endif
1868 bl_conf_add_opt(conf, 'Y', "decsp", 1, "compose_dec_special_font", NULL);
1869 bl_conf_add_opt(conf, 'c', "cp932", 1, "use_cp932_ucs_for_xft", NULL);
1870 #if 0
1871 bl_conf_add_opt(conf, '\0', "maxptys", 0, "max_ptys", NULL);
1872 #endif
1873 #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG)
1874 /* USE_WAYLAND */
1875 bl_conf_add_opt(conf, '\0', "aafont", 1, "use_aafont",
1876 "use [tv]aafont files with the use of fontconfig [true]");
1877 #endif
1878
1879 ui_main_config_init(&main_config, conf, 1, argv);
1880
1881 #if 0
1882 if ((value = bl_conf_get_value(conf, "font_size_range"))) {
1883 u_int min_font_size;
1884 u_int max_font_size;
1885
1886 if (get_font_size_range(&min_font_size, &max_font_size, value)) {
1887 ui_set_font_size_range(min_font_size, max_font_size);
1888 }
1889 }
1890 #endif
1891
1892 /* BACKWARD COMPAT (3.1.7 or before) */
1893 #if 1
1894 {
1895 size_t count;
1896 /*
1897 * Compat with button3_behavior (shortcut_str[3]) is not applied
1898 * because button3 is disabled by
1899 * ui_shortcut_parse( &shortcut , "Button3" , "\"none\"") above.
1900 */
1901 char key0[] = "Control+Button1";
1902 char key1[] = "Control+Button2";
1903 char key2[] = "Control+Button3";
1904 char *keys[] = {
1905 key0, key1, key2,
1906 };
1907
1908 for (count = 0; count < sizeof(keys) / sizeof(keys[0]); count++) {
1909 if (main_config.shortcut_strs[count]) {
1910 ui_shortcut_parse(&shortcut, keys[count], main_config.shortcut_strs[count]);
1911 }
1912 }
1913 }
1914 #endif
1915
1916 if (main_config.type_engine == TYPE_XCORE) {
1917 /*
1918 * XXX Hack
1919 * Default value of type_engine is TYPE_XCORE in normal mlterm,
1920 * but default value in libvte compatible library of mlterm is TYPE_XFT.
1921 */
1922 char *value;
1923
1924 if ((value = bl_conf_get_value(conf, "type_engine")) == NULL || strcmp(value, "xcore") != 0) {
1925 /*
1926 * cairo is prefered if mlterm works as libvte because gtk+
1927 * usually depends on cairo.
1928 */
1929 #if !defined(USE_TYPE_CAIRO) && defined(USE_TYPE_XFT)
1930 main_config.type_engine = TYPE_XFT;
1931 #else
1932 main_config.type_engine = TYPE_CAIRO;
1933 #endif
1934 }
1935 }
1936
1937 /* Default value of vte "audible-bell" is TRUE, while "visible-bell" is FALSE.
1938 */
1939 main_config.bel_mode = BEL_SOUND;
1940
1941 if ((value = bl_conf_get_value(conf, "compose_dec_special_font"))) {
1942 if (strcmp(value, "true") == 0) {
1943 ui_compose_dec_special_font();
1944 }
1945 }
1946
1947 #ifdef USE_XLIB
1948 if ((value = bl_conf_get_value(conf, "use_cp932_ucs_for_xft")) == NULL ||
1949 strcmp(value, "true") == 0) {
1950 ui_use_cp932_ucs_for_xft();
1951 }
1952 #endif
1953
1954 #ifdef KEY_REPEAT_BY_MYSELF
1955 if ((value = bl_conf_get_value(conf, "kbd_repeat_1"))) {
1956 extern int kbd_repeat_1;
1957
1958 bl_str_to_int(&kbd_repeat_1, value);
1959 }
1960
1961 if ((value = bl_conf_get_value(conf, "kbd_repeat_N"))) {
1962 extern int kbd_repeat_N;
1963
1964 bl_str_to_int(&kbd_repeat_N, value);
1965 }
1966 #endif
1967 #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG)
1968 /* USE_WAYLAND */
1969 if (!(value = bl_conf_get_value(conf, "use_aafont")) || strcmp(value, "false") != 0) {
1970 ui_use_aafont();
1971 }
1972 #endif
1973
1974 bl_conf_destroy(conf);
1975
1976 #ifdef USE_BRLAPI
1977 ui_brltty_init();
1978 #endif
1979
1980 g_signal_connect(vte_reaper_get(), "child-exited", G_CALLBACK(catch_child_exited), NULL);
1981
1982 g_type_class_add_private(vclass, sizeof(VteTerminalPrivate));
1983
1984 memset(&disp, 0, sizeof(ui_display_t));
1985 init_display(&disp, vclass);
1986
1987 ui_picture_display_opened(disp.display);
1988
1989 oclass = G_OBJECT_CLASS(vclass);
1990 wclass = GTK_WIDGET_CLASS(vclass);
1991
1992 oclass->finalize = vte_terminal_finalize;
1993 oclass->get_property = vte_terminal_get_property;
1994 oclass->set_property = vte_terminal_set_property;
1995 wclass->realize = vte_terminal_realize;
1996 wclass->unrealize = vte_terminal_unrealize;
1997 wclass->focus_in_event = vte_terminal_focus_in;
1998 wclass->focus_out_event = vte_terminal_focus_out;
1999 wclass->size_allocate = vte_terminal_size_allocate;
2000 #if GTK_CHECK_VERSION(2, 90, 0)
2001 wclass->get_preferred_width = vte_terminal_get_preferred_width;
2002 wclass->get_preferred_height = vte_terminal_get_preferred_height;
2003 wclass->get_preferred_width_for_height = vte_terminal_get_preferred_width_for_height;
2004 wclass->get_preferred_height_for_width = vte_terminal_get_preferred_height_for_width;
2005 #if VTE_CHECK_VERSION(0, 38, 0)
2006 wclass->screen_changed = vte_terminal_screen_changed;
2007 #endif
2008 #else
2009 wclass->size_request = vte_terminal_size_request;
2010 #endif
2011 wclass->key_press_event = vte_terminal_key_press;
2012 #if GTK_CHECK_VERSION(3, 0, 0)
2013 wclass->draw = vte_terminal_draw;
2014 #endif
2015
2016 #if GTK_CHECK_VERSION(3, 19, 5)
2017 gtk_widget_class_set_css_name(wclass, VTE_TERMINAL_CSS_NAME);
2018 #endif
2019
2020 #if GTK_CHECK_VERSION(2, 90, 0)
2021 g_object_class_override_property(oclass, PROP_HADJUSTMENT, "hadjustment");
2022 g_object_class_override_property(oclass, PROP_VADJUSTMENT, "vadjustment");
2023 g_object_class_override_property(oclass, PROP_HSCROLL_POLICY, "hscroll-policy");
2024 g_object_class_override_property(oclass, PROP_VSCROLL_POLICY, "vscroll-policy");
2025 #endif
2026
2027 #if !GTK_CHECK_VERSION(2, 90, 0)
2028 vclass->eof_signal =
2029 #else
2030 signals[SIGNAL_EOF] =
2031 #endif
2032 g_signal_new(I_("eof"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2033 G_STRUCT_OFFSET(VteTerminalClass, eof), NULL, NULL,
2034 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2035
2036 #if !GTK_CHECK_VERSION(2, 90, 0)
2037 vclass->child_exited_signal =
2038 #else
2039 signals[SIGNAL_CHILD_EXITED] =
2040 #endif
2041 #if VTE_CHECK_VERSION(0, 38, 0)
2042 g_signal_new(I_("child-exited"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2043 G_STRUCT_OFFSET(VteTerminalClass, child_exited), NULL, NULL,
2044 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
2045 #else
2046 g_signal_new(I_("child-exited"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2047 G_STRUCT_OFFSET(VteTerminalClass, child_exited), NULL, NULL,
2048 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2049 #endif
2050
2051 #if !GTK_CHECK_VERSION(2, 90, 0)
2052 vclass->window_title_changed_signal =
2053 #else
2054 signals[SIGNAL_WINDOW_TITLE_CHANGED] =
2055 #endif
2056 g_signal_new(I_("window-title-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2057 G_STRUCT_OFFSET(VteTerminalClass, window_title_changed), NULL, NULL,
2058 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2059
2060 #if !GTK_CHECK_VERSION(2, 90, 0)
2061 vclass->icon_title_changed_signal =
2062 #else
2063 signals[SIGNAL_ICON_TITLE_CHANGED] =
2064 #endif
2065 g_signal_new(I_("icon-title-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2066 G_STRUCT_OFFSET(VteTerminalClass, icon_title_changed), NULL, NULL,
2067 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2068
2069 #if VTE_CHECK_VERSION(0, 34, 0)
2070 signals[SIGNAL_CURRENT_FILE_URI_CHANGED] =
2071 g_signal_new(I_("current-file-uri-changed"), G_OBJECT_CLASS_TYPE(vclass),
2072 G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2073
2074 signals[SIGNAL_CURRENT_DIRECTORY_URI_CHANGED] =
2075 g_signal_new(I_("current-directory-uri-changed"), G_OBJECT_CLASS_TYPE(vclass),
2076 G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2077 #endif
2078
2079 #if !GTK_CHECK_VERSION(2, 90, 0)
2080 vclass->encoding_changed_signal =
2081 #else
2082 signals[SIGNAL_ENCODING_CHANGED] =
2083 #endif
2084 g_signal_new(I_("encoding-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2085 G_STRUCT_OFFSET(VteTerminalClass, encoding_changed), NULL, NULL,
2086 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2087
2088 #if !GTK_CHECK_VERSION(2, 90, 0)
2089 vclass->commit_signal =
2090 #else
2091 signals[SIGNAL_COMMIT] =
2092 #endif
2093 g_signal_new(I_("commit"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2094 G_STRUCT_OFFSET(VteTerminalClass, commit), NULL, NULL,
2095 _vte_marshal_VOID__STRING_UINT, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT);
2096
2097 #if !VTE_CHECK_VERSION(0, 38, 0)
2098 #if !GTK_CHECK_VERSION(2, 90, 0)
2099 vclass->emulation_changed_signal =
2100 #endif
2101 g_signal_new(I_("emulation-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2102 G_STRUCT_OFFSET(VteTerminalClass, emulation_changed), NULL, NULL,
2103 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2104 #endif
2105
2106 #if !GTK_CHECK_VERSION(2, 90, 0)
2107 vclass->char_size_changed_signal =
2108 #else
2109 signals[SIGNAL_CHAR_SIZE_CHANGED] =
2110 #endif
2111 g_signal_new(I_("char-size-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2112 G_STRUCT_OFFSET(VteTerminalClass, char_size_changed), NULL, NULL,
2113 _vte_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2114
2115 #if !GTK_CHECK_VERSION(2, 90, 0)
2116 vclass->selection_changed_signal =
2117 #else
2118 signals[SIGNAL_SELECTION_CHANGED] =
2119 #endif
2120 g_signal_new(I_("selection-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2121 G_STRUCT_OFFSET(VteTerminalClass, selection_changed), NULL, NULL,
2122 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2123
2124 #if !GTK_CHECK_VERSION(2, 90, 0)
2125 vclass->contents_changed_signal =
2126 #else
2127 signals[SIGNAL_CONTENTS_CHANGED] =
2128 #endif
2129 g_signal_new(I_("contents-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2130 G_STRUCT_OFFSET(VteTerminalClass, contents_changed), NULL, NULL,
2131 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2132
2133 #if !GTK_CHECK_VERSION(2, 90, 0)
2134 vclass->cursor_moved_signal =
2135 #else
2136 signals[SIGNAL_CURSOR_MOVED] =
2137 #endif
2138 g_signal_new(I_("cursor-moved"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2139 G_STRUCT_OFFSET(VteTerminalClass, cursor_moved), NULL, NULL,
2140 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2141
2142 #if !GTK_CHECK_VERSION(2, 90, 0)
2143 vclass->deiconify_window_signal =
2144 #else
2145 signals[SIGNAL_DEICONIFY_WINDOW] =
2146 #endif
2147 g_signal_new(I_("deiconify-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2148 G_STRUCT_OFFSET(VteTerminalClass, deiconify_window), NULL, NULL,
2149 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2150
2151 #if !GTK_CHECK_VERSION(2, 90, 0)
2152 vclass->iconify_window_signal =
2153 #else
2154 signals[SIGNAL_ICONIFY_WINDOW] =
2155 #endif
2156 g_signal_new(I_("iconify-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2157 G_STRUCT_OFFSET(VteTerminalClass, iconify_window), NULL, NULL,
2158 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2159
2160 #if !GTK_CHECK_VERSION(2, 90, 0)
2161 vclass->raise_window_signal =
2162 #else
2163 signals[SIGNAL_RAISE_WINDOW] =
2164 #endif
2165 g_signal_new(I_("raise-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2166 G_STRUCT_OFFSET(VteTerminalClass, raise_window), NULL, NULL,
2167 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2168
2169 #if !GTK_CHECK_VERSION(2, 90, 0)
2170 vclass->lower_window_signal =
2171 #else
2172 signals[SIGNAL_LOWER_WINDOW] =
2173 #endif
2174 g_signal_new(I_("lower-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2175 G_STRUCT_OFFSET(VteTerminalClass, lower_window), NULL, NULL,
2176 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2177
2178 #if !GTK_CHECK_VERSION(2, 90, 0)
2179 vclass->refresh_window_signal =
2180 #else
2181 signals[SIGNAL_REFRESH_WINDOW] =
2182 #endif
2183 g_signal_new(I_("refresh-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2184 G_STRUCT_OFFSET(VteTerminalClass, refresh_window), NULL, NULL,
2185 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2186
2187 #if !GTK_CHECK_VERSION(2, 90, 0)
2188 vclass->restore_window_signal =
2189 #else
2190 signals[SIGNAL_RESTORE_WINDOW] =
2191 #endif
2192 g_signal_new(I_("restore-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2193 G_STRUCT_OFFSET(VteTerminalClass, restore_window), NULL, NULL,
2194 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2195
2196 #if !GTK_CHECK_VERSION(2, 90, 0)
2197 vclass->maximize_window_signal =
2198 #else
2199 signals[SIGNAL_MAXIMIZE_WINDOW] =
2200 #endif
2201 g_signal_new(I_("maximize-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2202 G_STRUCT_OFFSET(VteTerminalClass, maximize_window), NULL, NULL,
2203 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2204
2205 #if !GTK_CHECK_VERSION(2, 90, 0)
2206 vclass->resize_window_signal =
2207 #else
2208 signals[SIGNAL_RESIZE_WINDOW] =
2209 #endif
2210 g_signal_new(I_("resize-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2211 G_STRUCT_OFFSET(VteTerminalClass, resize_window), NULL, NULL,
2212 _vte_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2213
2214 #if !GTK_CHECK_VERSION(2, 90, 0)
2215 vclass->move_window_signal =
2216 #else
2217 signals[SIGNAL_MOVE_WINDOW] =
2218 #endif
2219 g_signal_new(I_("move-window"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2220 G_STRUCT_OFFSET(VteTerminalClass, move_window), NULL, NULL,
2221 _vte_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2222
2223 #if !VTE_CHECK_VERSION(0, 38, 0)
2224 #if !GTK_CHECK_VERSION(2, 90, 0)
2225 vclass->status_line_changed_signal =
2226 #endif
2227 g_signal_new(I_("status-line-changed"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2228 G_STRUCT_OFFSET(VteTerminalClass, status_line_changed), NULL, NULL,
2229 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2230 #endif
2231
2232 #if !GTK_CHECK_VERSION(2, 90, 0)
2233 vclass->increase_font_size_signal =
2234 #else
2235 signals[SIGNAL_INCREASE_FONT_SIZE] =
2236 #endif
2237 g_signal_new(I_("increase-font-size"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2238 G_STRUCT_OFFSET(VteTerminalClass, increase_font_size), NULL, NULL,
2239 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2240
2241 #if !GTK_CHECK_VERSION(2, 90, 0)
2242 vclass->decrease_font_size_signal =
2243 #else
2244 signals[SIGNAL_DECREASE_FONT_SIZE] =
2245 #endif
2246 g_signal_new(I_("decrease-font-size"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2247 G_STRUCT_OFFSET(VteTerminalClass, decrease_font_size), NULL, NULL,
2248 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2249
2250 #if !GTK_CHECK_VERSION(2, 90, 0)
2251 vclass->text_modified_signal =
2252 #else
2253 signals[SIGNAL_TEXT_MODIFIED] =
2254 #endif
2255 g_signal_new(I_("text-modified"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2256 G_STRUCT_OFFSET(VteTerminalClass, text_modified), NULL, NULL,
2257 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2258
2259 #if !GTK_CHECK_VERSION(2, 90, 0)
2260 vclass->text_inserted_signal =
2261 #else
2262 signals[SIGNAL_TEXT_INSERTED] =
2263 #endif
2264 g_signal_new(I_("text-inserted"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2265 G_STRUCT_OFFSET(VteTerminalClass, text_inserted), NULL, NULL,
2266 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2267
2268 #if !GTK_CHECK_VERSION(2, 90, 0)
2269 vclass->text_deleted_signal =
2270 #else
2271 signals[SIGNAL_TEXT_DELETED] =
2272 #endif
2273 g_signal_new(I_("text-deleted"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2274 G_STRUCT_OFFSET(VteTerminalClass, text_deleted), NULL, NULL,
2275 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2276
2277 #if !GTK_CHECK_VERSION(2, 90, 0)
2278 vclass->text_scrolled_signal =
2279 #else
2280 signals[SIGNAL_TEXT_SCROLLED] =
2281 #endif
2282 g_signal_new(I_("text-scrolled"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2283 G_STRUCT_OFFSET(VteTerminalClass, text_scrolled), NULL, NULL,
2284 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
2285
2286 #if VTE_CHECK_VERSION(0, 19, 0)
2287 signals[SIGNAL_COPY_CLIPBOARD] = g_signal_new(I_("copy-clipboard"), G_OBJECT_CLASS_TYPE(vclass),
2288 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2289 G_STRUCT_OFFSET(VteTerminalClass, copy_clipboard),
2290 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2291 G_TYPE_NONE, 0);
2292
2293 signals[SIGNAL_PASTE_CLIPBOARD] = g_signal_new(I_("paste-clipboard"), G_OBJECT_CLASS_TYPE(vclass),
2294 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2295 G_STRUCT_OFFSET(VteTerminalClass, paste_clipboard),
2296 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2297 G_TYPE_NONE, 0);
2298 #endif
2299 #if VTE_CHECK_VERSION(0, 44, 0)
2300 signals[SIGNAL_BELL] = g_signal_new(I_("bell"), G_OBJECT_CLASS_TYPE(vclass), G_SIGNAL_RUN_LAST,
2301 G_STRUCT_OFFSET(VteTerminalClass, bell), NULL, NULL,
2302 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2303 #endif
2304
2305 #if VTE_CHECK_VERSION(0, 20, 0)
2306 g_object_class_install_property(
2307 oclass, PROP_WINDOW_TITLE,
2308 g_param_spec_string("window-title", NULL, NULL, NULL, G_PARAM_READABLE | STATIC_PARAMS));
2309
2310 g_object_class_install_property(
2311 oclass, PROP_ICON_TITLE,
2312 g_param_spec_string("icon-title", NULL, NULL, NULL, G_PARAM_READABLE | STATIC_PARAMS));
2313 #endif
2314
2315 #if VTE_CHECK_VERSION(0, 23, 2)
2316 /*
2317 * doc/references/html/VteTerminal.html describes that inner-border property
2318 * is since 0.24.0, but actually it is added at Nov 30 2009 (between 0.23.1 and
2319 * 0.23.2)
2320 * in ChangeLog.
2321 */
2322
2323 #if !VTE_CHECK_VERSION(0, 38, 0)
2324 gtk_widget_class_install_style_property(
2325 wclass, g_param_spec_boxed("inner-border", NULL, NULL, GTK_TYPE_BORDER,
2326 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2327 #endif
2328
2329 #if GTK_CHECK_VERSION(2, 90, 0)
2330 vclass->priv = G_TYPE_CLASS_GET_PRIVATE(vclass, VTE_TYPE_TERMINAL, VteTerminalClassPrivate);
2331 vclass->priv->style_provider = GTK_STYLE_PROVIDER(gtk_css_provider_new());
2332 #if !VTE_CHECK_VERSION(0, 38, 0)
2333 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(vclass->priv->style_provider) ,
2334 "VteTerminal {\n"
2335 "-VteTerminal-inner-border: " BL_INT_TO_STR(WINDOW_MARGIN) ";\n"
2336 "}\n",
2337 -1, NULL) ;
2338 #else
2339 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(vclass->priv->style_provider) ,
2340 "VteTerminal, " VTE_TERMINAL_CSS_NAME " {\n"
2341 "padding: 1px 1px 1px 1px;\n"
2342 "background-color: @theme_base_color;\n"
2343 "color: @theme_fg_color;\n"
2344 "}\n",
2345 -1 , NULL) ;
2346 #endif
2347 #else /* VTE_CHECK_VERSION(0,23,2) */
2348 gtk_rc_parse_string("style \"vte-default-style\" {\n"
2349 "VteTerminal::inner-border = { "
2350 BL_INT_TO_STR(WINDOW_MARGIN) " , "
2351 BL_INT_TO_STR(WINDOW_MARGIN) " , "
2352 BL_INT_TO_STR(WINDOW_MARGIN) " , "
2353 BL_INT_TO_STR(WINDOW_MARGIN) " }\n"
2354 "}\n"
2355 "class \"VteTerminal\" style : gtk \"vte-default-style\"\n") ;
2356 #endif
2357 #endif /* VTE_CHECK_VERSION(0,23,2) */
2358 }
2359
vte_terminal_init(VteTerminal * terminal)2360 static void vte_terminal_init(VteTerminal *terminal) {
2361 static int init_inherit_ptys;
2362 ef_charset_t usascii_font_cs;
2363 gdouble dpi;
2364
2365 GTK_WIDGET_SET_CAN_FOCUS(GTK_WIDGET(terminal));
2366 #if VTE_CHECK_VERSION(0, 38, 0)
2367 gtk_widget_set_app_paintable(GTK_WIDGET(terminal), TRUE);
2368 gtk_widget_set_redraw_on_allocate(GTK_WIDGET(terminal), FALSE);
2369 #endif
2370
2371 #if VTE_CHECK_VERSION(0, 40, 0)
2372 terminal->_unused_padding[0] = G_TYPE_INSTANCE_GET_PRIVATE(terminal, VTE_TYPE_TERMINAL, VteTerminalPrivate);
2373 #else
2374 terminal->pvt = G_TYPE_INSTANCE_GET_PRIVATE(terminal, VTE_TYPE_TERMINAL, VteTerminalPrivate);
2375 #endif
2376
2377 #if GTK_CHECK_VERSION(2, 18, 0)
2378 gtk_widget_set_has_window(GTK_WIDGET(terminal), TRUE);
2379 #endif
2380
2381 /* We do our own redrawing. */
2382 gtk_widget_set_redraw_on_allocate(GTK_WIDGET(terminal), FALSE);
2383
2384 ADJUSTMENT(terminal) = NULL;
2385 set_adjustment(terminal, GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, main_config.rows, 1,
2386 main_config.rows, main_config.rows)));
2387
2388 #ifdef USE_XLIB
2389 g_signal_connect(terminal, "hierarchy-changed", G_CALLBACK(vte_terminal_hierarchy_changed), NULL);
2390 #endif
2391
2392 #if GTK_CHECK_VERSION(2, 90, 0)
2393 gtk_style_context_add_provider(gtk_widget_get_style_context(GTK_WIDGET(terminal)),
2394 VTE_TERMINAL_GET_CLASS(terminal)->priv->style_provider,
2395 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
2396 #endif
2397
2398 PVT(terminal)->term = vt_create_term(main_config.term_type, main_config.cols, main_config.rows,
2399 main_config.tab_size, main_config.num_log_lines,
2400 main_config.encoding, main_config.is_auto_encoding,
2401 main_config.use_auto_detect, main_config.logging_vt_seq,
2402 main_config.unicode_policy, main_config.col_size_of_width_a,
2403 main_config.use_char_combining,
2404 main_config.use_multi_col_char, main_config.use_ctl,
2405 main_config.bidi_mode, main_config.bidi_separators,
2406 main_config.use_dynamic_comb, main_config.bs_mode,
2407 /* main_config.vertical_mode */ 0,
2408 main_config.use_local_echo, main_config.title,
2409 main_config.icon_name, main_config.use_ansi_colors,
2410 main_config.alt_color_mode, main_config.use_ot_layout,
2411 main_config.blink_cursor ? CS_BLINK|CS_BLOCK : CS_BLOCK,
2412 main_config.ignore_broadcasted_chars);
2413 if (!init_inherit_ptys) {
2414 u_int num;
2415 vt_term_t **terms;
2416 u_int count;
2417
2418 num = vt_get_all_terms(&terms);
2419 for (count = 0; count < num; count++) {
2420 if (terms[count] != PVT(terminal)->term) {
2421 vte_reaper_add_child(vt_term_get_child_pid(terms[count]));
2422 }
2423 }
2424
2425 init_inherit_ptys = 1;
2426 }
2427
2428 if (main_config.unlimit_log_size) {
2429 vt_term_unlimit_log_size(PVT(terminal)->term);
2430 }
2431
2432 #if VTE_CHECK_VERSION(0, 26, 0)
2433 PVT(terminal)->pty = NULL;
2434 #endif
2435
2436 if (main_config.unicode_policy & NOT_USE_UNICODE_FONT || main_config.iso88591_font_for_usascii) {
2437 usascii_font_cs = ui_get_usascii_font_cs(VT_ISO8859_1);
2438 } else if (main_config.unicode_policy & ONLY_USE_UNICODE_FONT) {
2439 usascii_font_cs = ui_get_usascii_font_cs(VT_UTF8);
2440 } else {
2441 usascii_font_cs = ui_get_usascii_font_cs(vt_term_get_encoding(PVT(terminal)->term));
2442 }
2443
2444 /* related to ui_font_use_point_size(1) in vte_terminal_class_init. */
2445 if ((dpi = gdk_screen_get_resolution(gtk_widget_get_screen(GTK_WIDGET(terminal)))) != -1) {
2446 #ifdef DEBUG
2447 bl_debug_printf(BL_DEBUG_TAG " Setting dpi %f\n", dpi);
2448 #endif
2449
2450 ui_font_set_dpi_for_fc(dpi);
2451 }
2452
2453 init_screen(terminal, ui_font_manager_new(
2454 disp.display, main_config.type_engine, main_config.font_present,
2455 main_config.font_size, usascii_font_cs,
2456 main_config.step_in_changing_font_size, main_config.letter_space,
2457 main_config.use_bold_font, main_config.use_italic_font),
2458 ui_color_manager_new(&disp, main_config.fg_color, main_config.bg_color,
2459 main_config.cursor_fg_color, main_config.cursor_bg_color,
2460 main_config.bd_color, main_config.ul_color,
2461 main_config.bl_color, main_config.rv_color,
2462 main_config.it_color, main_config.co_color));
2463
2464 PVT(terminal)->io = NULL;
2465 PVT(terminal)->src_id = 0;
2466
2467 PVT(terminal)->image = NULL;
2468 PVT(terminal)->pixmap = None;
2469 PVT(terminal)->pix_width = 0;
2470 PVT(terminal)->pix_height = 0;
2471 PVT(terminal)->pic_mod = NULL;
2472
2473 #if GLIB_CHECK_VERSION(2, 14, 0)
2474 PVT(terminal)->gregex = NULL;
2475 PVT(terminal)->match_gregexes = NULL;
2476 PVT(terminal)->num_match_gregexes = 0;
2477 #if VTE_CHECK_VERSION(0, 46, 0)
2478 PVT(terminal)->vregex = NULL;
2479 PVT(terminal)->match_vregexes = NULL;
2480 PVT(terminal)->num_match_vregexes = 0;
2481 #endif
2482 #endif
2483
2484 WINDOW_TITLE(terminal) = vt_term_window_name(PVT(terminal)->term);
2485 ICON_TITLE(terminal) = vt_term_icon_name(PVT(terminal)->term);
2486
2487 #if !GTK_CHECK_VERSION(2, 90, 0)
2488 /* XXX */
2489 if (strstr(g_get_prgname(), "roxterm") ||
2490 /*
2491 * Hack for roxterm started by "x-terminal-emulator" or
2492 * "exo-open --launch TerminalEmulator" (which calls
2493 * "x-terminal-emulator" internally)
2494 */
2495 g_object_get_data(gtk_widget_get_parent(GTK_WIDGET(terminal)), "roxterm_tab")) {
2496 /*
2497 * XXX
2498 * I don't know why, but gtk_widget_ensure_style() doesn't apply
2499 * "inner-border"
2500 * and min width/height of roxterm are not correctly set.
2501 */
2502 gtk_widget_set_rc_style(&terminal->widget);
2503 } else
2504 #endif
2505 {
2506 /*
2507 * gnome-terminal(2.32.1) fails to set "inner-border" and
2508 * min width/height without this.
2509 */
2510 gtk_widget_ensure_style(&terminal->widget);
2511 }
2512
2513 reset_vte_size_member(terminal);
2514 }
2515
vt_term_open_pty_wrap(VteTerminal * terminal,const char * cmd_path,char ** argv,char ** envv,const char * work_dir,const char * pass,const char * pubkey,const char * privkey)2516 static int vt_term_open_pty_wrap(VteTerminal *terminal, const char *cmd_path, char **argv,
2517 char **envv, const char *work_dir, const char *pass,
2518 const char *pubkey, const char *privkey) {
2519 const char *host;
2520 char **env_p;
2521 u_int num;
2522
2523 host = gdk_display_get_name(gtk_widget_get_display(GTK_WIDGET(terminal)));
2524
2525 if (argv) {
2526 char **argv_p;
2527
2528 num = 0;
2529 argv_p = argv;
2530 while (*(argv_p++)) {
2531 num++;
2532 }
2533
2534 if (num > 0 && !strstr(cmd_path, argv[0]) && (argv_p = alloca(sizeof(char *) * (num + 2)))) {
2535 memcpy(argv_p + 1, argv, sizeof(char *) * (num + 1));
2536 argv_p[0] = cmd_path;
2537 argv = argv_p;
2538
2539 #if 0
2540 for (argv_p = argv; *argv_p; argv_p++) {
2541 bl_debug_printf("%s\n", *argv_p);
2542 }
2543 #endif
2544 }
2545 }
2546
2547 num = 0;
2548 if (envv) {
2549 env_p = envv;
2550 while (*(env_p++)) {
2551 num++;
2552 }
2553 }
2554
2555 /* 7 => MLTERM,TERM,WINDOWID,WAYLAND_DISPLAY,DISPLAY,COLORFGBG,NULL */
2556 if ((env_p = alloca(sizeof(char *) * (num + 7)))) {
2557 if (num > 0) {
2558 envv = memcpy(env_p, envv, sizeof(char *) * num);
2559 env_p += num;
2560 } else {
2561 envv = env_p;
2562 }
2563
2564 *(env_p++) = "MLTERM=" VERSION;
2565
2566 #ifdef USE_XLIB
2567 /* "WINDOWID="(9) + [32bit digit] + NULL(1) */
2568 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal)) &&
2569 (*env_p = alloca(9 + DIGIT_STR_LEN(Window) + 1))) {
2570 sprintf(*(env_p++), "WINDOWID=%ld",
2571 #if 1
2572 gdk_x11_drawable_get_xid(gtk_widget_get_window(GTK_WIDGET(terminal)))
2573 #else
2574 PVT(terminal)->screen->window.my_window
2575 #endif
2576 );
2577 }
2578 #endif
2579
2580 #ifdef USE_WAYLAND
2581 /* "WAYLAND_DISPLAY="(16) + NULL(1) */
2582 if (host && (*env_p = alloca(16 + strlen(host) + 1))) {
2583 sprintf(*(env_p++), "WAYLAND_DISPLAY=%s", host);
2584 }
2585 *(env_p++) = "DISPLAY=:0.0";
2586 #else
2587 /* "DISPLAY="(8) + NULL(1) */
2588 if ((*env_p = alloca(8 + strlen(host) + 1))) {
2589 sprintf(*(env_p++), "DISPLAY=%s", host);
2590 }
2591 #endif
2592
2593 /* "TERM="(5) + NULL(1) */
2594 if ((*env_p = alloca(5 + strlen(main_config.term_type) + 1))) {
2595 sprintf(*(env_p++), "TERM=%s", main_config.term_type);
2596 }
2597
2598 *(env_p++) = "COLORFGBG=default;default";
2599
2600 /* NULL terminator */
2601 *env_p = NULL;
2602 }
2603
2604 #if 0
2605 env_p = envv;
2606 while (*env_p) {
2607 bl_debug_printf("%s\n", *(env_p++));
2608 }
2609 #endif
2610
2611 if (vt_term_open_pty(PVT(terminal)->term, cmd_path, argv, envv, host, work_dir, pass, pubkey,
2612 privkey, PVT(terminal)->screen->window.width,
2613 PVT(terminal)->screen->window.height)) {
2614 return 1;
2615 } else {
2616 return 0;
2617 }
2618 }
2619
set_alpha(VteTerminal * terminal,u_int8_t alpha)2620 static void set_alpha(VteTerminal *terminal, u_int8_t alpha) {
2621 #ifdef DEBUG
2622 bl_debug_printf(BL_DEBUG_TAG " ALPHA => %d\n", alpha);
2623 #endif
2624
2625 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2626 char value[DIGIT_STR_LEN(u_int8_t) + 1];
2627
2628 sprintf(value, "%d", (int)alpha);
2629
2630 ui_screen_set_config(PVT(terminal)->screen, NULL, "alpha", value);
2631 ui_window_update(&PVT(terminal)->screen->window, 3 /* UPDATE_SCREEN|UPDATE_CURSOR */);
2632 update_wall_picture(terminal);
2633 } else {
2634 PVT(terminal)->screen->pic_mod.alpha = alpha;
2635 ui_change_true_transbg_alpha(PVT(terminal)->screen->color_man, alpha);
2636 }
2637 }
2638
set_color_bold(VteTerminal * terminal,const void * bold,gchar * (* to_string)(const void *))2639 static void set_color_bold(VteTerminal *terminal, const void *bold,
2640 gchar *(*to_string)(const void *)) {
2641 gchar *str;
2642
2643 if (!bold) {
2644 str = strdup("");
2645 } else {
2646 /* #rrrrggggbbbb */
2647 str = (*to_string)(bold);
2648 }
2649
2650 #ifdef DEBUG
2651 bl_debug_printf(BL_DEBUG_TAG " set_color_bold %s\n", str);
2652 #endif
2653
2654 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2655 ui_screen_set_config(PVT(terminal)->screen, NULL, "bd_color", str);
2656 ui_window_update(&PVT(terminal)->screen->window, 3 /* UPDATE_SCREEN|UPDATE_CURSOR */);
2657 } else {
2658 if (ui_color_manager_set_alt_color(PVT(terminal)->screen->color_man, VT_BOLD_COLOR,
2659 *str ? str : NULL)) {
2660 vt_term_set_alt_color_mode(PVT(terminal)->term,
2661 *str ? (vt_term_get_alt_color_mode(PVT(terminal)->term) | 1)
2662 : (vt_term_get_alt_color_mode(PVT(terminal)->term) & ~1));
2663 }
2664 }
2665
2666 g_free(str);
2667 }
2668
set_color_foreground(VteTerminal * terminal,const void * foreground,gchar * (* to_string)(const void *))2669 static void set_color_foreground(VteTerminal *terminal, const void *foreground,
2670 gchar *(*to_string)(const void *)) {
2671 gchar *str;
2672
2673 if (!foreground) {
2674 return;
2675 }
2676
2677 /* #rrrrggggbbbb */
2678 str = (*to_string)(foreground);
2679
2680 #ifdef DEBUG
2681 bl_debug_printf(BL_DEBUG_TAG " set_color_foreground %s\n", str);
2682 #endif
2683
2684 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2685 ui_screen_set_config(PVT(terminal)->screen, NULL, "fg_color", str);
2686 ui_window_update(&PVT(terminal)->screen->window, 3 /* UPDATE_SCREEN|UPDATE_CURSOR */);
2687 } else {
2688 ui_color_manager_set_fg_color(PVT(terminal)->screen->color_man, str);
2689 }
2690
2691 g_free(str);
2692 }
2693
set_color_background(VteTerminal * terminal,const void * background,gchar * (* to_string)(const void *))2694 static void set_color_background(VteTerminal *terminal, const void *background,
2695 gchar *(*to_string)(const void *)) {
2696 gchar *str;
2697
2698 if (!background) {
2699 return;
2700 }
2701
2702 /* #rrrrggggbbbb */
2703 str = (*to_string)(background);
2704
2705 #ifdef DEBUG
2706 bl_debug_printf(BL_DEBUG_TAG " set_color_background %s\n", str);
2707 #endif
2708
2709 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2710 ui_screen_set_config(PVT(terminal)->screen, NULL, "bg_color", str);
2711 ui_window_update(&PVT(terminal)->screen->window, 3 /* UPDATE_SCREEN|UPDATE_CURSOR */);
2712
2713 if (PVT(terminal)->image && PVT(terminal)->screen->pic_mod.alpha < 255) {
2714 update_wall_picture(terminal);
2715 }
2716 } else {
2717 ui_color_manager_set_bg_color(PVT(terminal)->screen->color_man, str);
2718 }
2719
2720 g_free(str);
2721 }
2722
set_color_cursor(VteTerminal * terminal,const void * cursor_background,gchar * (* to_string)(const void *))2723 static void set_color_cursor(VteTerminal *terminal, const void *cursor_background,
2724 gchar *(*to_string)(const void *)) {
2725 gchar *str;
2726
2727 if (!cursor_background) {
2728 return;
2729 }
2730
2731 /* #rrrrggggbbbb */
2732 str = (*to_string)(cursor_background);
2733
2734 #ifdef DEBUG
2735 bl_debug_printf(BL_DEBUG_TAG " set_color_cursor %s\n", str);
2736 #endif
2737
2738 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2739 ui_screen_set_config(PVT(terminal)->screen, NULL, "cursor_bg_color", str);
2740 ui_window_update(&PVT(terminal)->screen->window, 3 /* UPDATE_SCREEN|UPDATE_CURSOR */);
2741 } else {
2742 ui_color_manager_set_cursor_bg_color(PVT(terminal)->screen->color_man, str);
2743 }
2744
2745 g_free(str);
2746 }
2747
set_colors(VteTerminal * terminal,const char * palette,glong palette_size,size_t color_size,gchar * (* to_string)(const char *))2748 static int set_colors(VteTerminal *terminal, const char *palette, glong palette_size,
2749 size_t color_size, gchar *(*to_string)(const char *)) {
2750 int need_redraw = 0;
2751 vt_color_t color;
2752
2753 if (palette_size != 0 && palette_size != 8 && palette_size != 16 &&
2754 (palette_size < 24 || 256 < palette_size)) {
2755 #ifdef DEBUG
2756 bl_debug_printf(BL_DEBUG_TAG " palette_size %d is illegal\n", palette_size);
2757 #endif
2758
2759 return 0;
2760 }
2761
2762 if (palette_size >= 8) {
2763 for (color = 0; color < palette_size; color++) {
2764 gchar *rgb;
2765 char *name;
2766
2767 rgb = (*to_string)(palette);
2768 name = vt_get_color_name(color);
2769
2770 #ifdef DEBUG
2771 bl_debug_printf(BL_DEBUG_TAG " Setting rgb %s=%s\n", name, rgb);
2772 #endif
2773
2774 need_redraw |= vt_customize_color_file(name, rgb, 0);
2775
2776 g_free(rgb);
2777 palette += color_size;
2778 }
2779 } else {
2780 for (color = 0; color < 256; color++) {
2781 char *name = vt_get_color_name(color);
2782
2783 #ifdef DEBUG
2784 bl_debug_printf(BL_DEBUG_TAG " Erase rgb of %s\n", name);
2785 #endif
2786
2787 need_redraw |= vt_customize_color_file(name, "", 0);
2788 }
2789 }
2790
2791 if (need_redraw && GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2792 ui_color_cache_unload_all();
2793 ui_screen_reset_view(PVT(terminal)->screen);
2794 }
2795
2796 return 1;
2797 }
2798
2799 /* --- global functions --- */
2800
vte_terminal_new()2801 GtkWidget *vte_terminal_new() { return g_object_new(VTE_TYPE_TERMINAL, NULL); }
2802
2803 /*
2804 * vte_terminal_spawn_sync, vte_terminal_fork_command or vte_terminal_forkpty
2805 * functions
2806 * are possible to call before VteTerminal widget is realized.
2807 */
2808
vte_terminal_fork_command(VteTerminal * terminal,const char * command,char ** argv,char ** envv,const char * directory,gboolean lastlog,gboolean utmp,gboolean wtmp)2809 pid_t vte_terminal_fork_command(VteTerminal *terminal,
2810 const char *command, /* If NULL, open default shell. */
2811 char **argv, /* If NULL, open default shell. */
2812 char **envv, const char *directory, gboolean lastlog, gboolean utmp,
2813 gboolean wtmp) {
2814 /*
2815 * If pty is inherited from dead parent, PVT(terminal)->term->pty is non-NULL
2816 * but create_io() and vte_reaper_add_child() aren't executed.
2817 * So PVT(terminal)->io is used to check if pty is completely set up.
2818 */
2819 if (!PVT(terminal)->io) {
2820 #ifdef DEBUG
2821 bl_debug_printf(BL_DEBUG_TAG " forking with %s\n", command);
2822 #endif
2823
2824 if (!command) {
2825 if (!(command = getenv("SHELL")) || *command == '\0') {
2826 struct passwd *pw;
2827
2828 if ((pw = getpwuid(getuid())) == NULL || *(command = pw->pw_shell) == '\0') {
2829 command = "/bin/sh";
2830 }
2831 }
2832 }
2833
2834 if (!argv || !argv[0]) {
2835 argv = alloca(sizeof(char *) * 2);
2836 argv[0] = command;
2837 argv[1] = NULL;
2838 }
2839
2840 bl_pty_helper_set_flag(lastlog, utmp, wtmp);
2841
2842 if (!vt_term_open_pty_wrap(terminal, command, argv, envv, directory, NULL, NULL, NULL)) {
2843 #ifdef DEBUG
2844 bl_debug_printf(BL_DEBUG_TAG " fork failed\n");
2845 #endif
2846
2847 return -1;
2848 }
2849
2850 create_io(terminal);
2851
2852 vte_reaper_add_child(vt_term_get_child_pid(PVT(terminal)->term));
2853
2854 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2855 GtkAllocation allocation;
2856
2857 gtk_widget_get_allocation(GTK_WIDGET(terminal), &allocation);
2858
2859 if (!is_initial_allocation(&allocation) &&
2860 ui_window_resize_with_margin(&PVT(terminal)->screen->window, allocation.width,
2861 allocation.height, NOTIFY_TO_MYSELF)) {
2862 reset_vte_size_member(terminal);
2863 update_wall_picture(terminal);
2864 }
2865 }
2866
2867 /*
2868 * In order to receive pty_closed() event even if vte_terminal_realize()
2869 * isn't called.
2870 */
2871 vt_pty_set_listener(PVT(terminal)->term->pty, &PVT(terminal)->screen->pty_listener);
2872 }
2873
2874 return vt_term_get_child_pid(PVT(terminal)->term);
2875 }
2876
2877 #if VTE_CHECK_VERSION(0, 26, 0)
2878 gboolean
2879 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_spawn_sync(VteTerminal * terminal,VtePtyFlags pty_flags,const char * working_directory,char ** argv,char ** envv,GSpawnFlags spawn_flags,GSpawnChildSetupFunc child_setup,gpointer child_setup_data,GPid * child_pid,GCancellable * cancellable,GError ** error)2880 vte_terminal_spawn_sync(VteTerminal *terminal, VtePtyFlags pty_flags, const char *working_directory,
2881 char **argv, char **envv, GSpawnFlags spawn_flags,
2882 GSpawnChildSetupFunc child_setup, gpointer child_setup_data,
2883 GPid *child_pid /* out */, GCancellable *cancellable, GError **error)
2884 #else
2885 vte_terminal_fork_command_full(VteTerminal *terminal, VtePtyFlags pty_flags,
2886 const char *working_directory, char **argv, char **envv,
2887 GSpawnFlags spawn_flags, GSpawnChildSetupFunc child_setup,
2888 gpointer child_setup_data, GPid *child_pid /* out */, GError **error)
2889 #endif
2890 {
2891 GPid pid;
2892
2893 pid = vte_terminal_fork_command(terminal, argv[0], argv + 1, envv, working_directory,
2894 (pty_flags & VTE_PTY_NO_LASTLOG) ? FALSE : TRUE,
2895 (pty_flags & VTE_PTY_NO_UTMP) ? FALSE : TRUE,
2896 (pty_flags & VTE_PTY_NO_WTMP) ? FALSE : TRUE);
2897 if (child_pid) {
2898 *child_pid = pid;
2899 }
2900
2901 if (error) {
2902 *error = NULL;
2903 }
2904
2905 if (pid > 0) {
2906 return TRUE;
2907 } else {
2908 return FALSE;
2909 }
2910 }
2911 #endif
2912
2913 #if VTE_CHECK_VERSION(0, 48, 0)
vte_terminal_spawn_async(VteTerminal * terminal,VtePtyFlags pty_flags,const char * working_directory,char ** argv,char ** envv,GSpawnFlags spawn_flags,GSpawnChildSetupFunc child_setup,gpointer child_setup_data,GDestroyNotify child_setup_data_destroy,int timeout,GCancellable * cancellable,VteTerminalSpawnAsyncCallback callback,gpointer user_data)2914 void vte_terminal_spawn_async(VteTerminal *terminal, VtePtyFlags pty_flags,
2915 const char *working_directory,
2916 char **argv, char **envv, GSpawnFlags spawn_flags,
2917 GSpawnChildSetupFunc child_setup, gpointer child_setup_data,
2918 GDestroyNotify child_setup_data_destroy,
2919 int timeout, GCancellable *cancellable,
2920 VteTerminalSpawnAsyncCallback callback, gpointer user_data) {
2921 GPid child_pid;
2922 GError *error;
2923
2924 vte_terminal_spawn_sync(terminal, pty_flags, working_directory, argv, envv, spawn_flags,
2925 child_setup, child_setup_data, &child_pid, cancellable, &error);
2926 if (callback) {
2927 (*callback)(terminal, child_pid, NULL, user_data);
2928 }
2929 }
2930 #endif
2931
2932 #if VTE_CHECK_VERSION(0, 62, 0)
vte_terminal_spawn_with_fds_async(VteTerminal * terminal,VtePtyFlags pty_flags,const char * working_directory,char const * const * argv,char const * const * envv,int const * fds,int n_fds,int const * fd_map_to,int n_fd_map_to,GSpawnFlags spawn_flags,GSpawnChildSetupFunc child_setup,gpointer child_setup_data,GDestroyNotify child_setup_data_destroy,int timeout,GCancellable * cancellable,VteTerminalSpawnAsyncCallback callback,gpointer user_data)2933 void vte_terminal_spawn_with_fds_async(VteTerminal *terminal, VtePtyFlags pty_flags,
2934 const char *working_directory,
2935 char const* const* argv, char const* const* envv,
2936 int const *fds, int n_fds,
2937 int const *fd_map_to, int n_fd_map_to,
2938 GSpawnFlags spawn_flags,
2939 GSpawnChildSetupFunc child_setup, gpointer child_setup_data,
2940 GDestroyNotify child_setup_data_destroy,
2941 int timeout, GCancellable *cancellable,
2942 VteTerminalSpawnAsyncCallback callback, gpointer user_data) {
2943 GPid child_pid;
2944 GError *error;
2945
2946 /* XXX fds and fd_map_to */
2947
2948 if (n_fds > 0 || n_fd_map_to > 0) {
2949 bl_msg_printf("vte_terminal_spawn_with_fds_async() ignores fds and fd_map_to.\n");
2950 }
2951
2952 vte_terminal_spawn_sync(terminal, pty_flags, working_directory, argv, envv, spawn_flags,
2953 child_setup, child_setup_data, &child_pid, cancellable, &error);
2954 if (callback) {
2955 (*callback)(terminal, child_pid, NULL, user_data);
2956 }
2957 }
2958 #endif
2959
vte_terminal_forkpty(VteTerminal * terminal,char ** envv,const char * directory,gboolean lastlog,gboolean utmp,gboolean wtmp)2960 pid_t vte_terminal_forkpty(VteTerminal *terminal, char **envv, const char *directory,
2961 gboolean lastlog, gboolean utmp, gboolean wtmp) {
2962 /*
2963 * If pty is inherited from dead parent, PVT(terminal)->term->pty is non-NULL
2964 * but create_io() and vte_reaper_add_child() aren't executed.
2965 * So PVT(terminal)->io is used to check if pty is completely set up.
2966 */
2967 if (!PVT(terminal)->io) {
2968 #ifdef DEBUG
2969 bl_debug_printf(BL_DEBUG_TAG " forking pty\n");
2970 #endif
2971
2972 bl_pty_helper_set_flag(lastlog, utmp, wtmp);
2973
2974 if (!vt_term_open_pty_wrap(terminal, NULL, NULL, envv, directory, NULL, NULL, NULL)) {
2975 #ifdef DEBUG
2976 bl_debug_printf(BL_DEBUG_TAG " fork failed\n");
2977 #endif
2978
2979 return -1;
2980 }
2981
2982 if (vt_term_get_child_pid(PVT(terminal)->term) == 0) {
2983 /* Child process */
2984
2985 return 0;
2986 }
2987
2988 create_io(terminal);
2989
2990 vte_reaper_add_child(vt_term_get_child_pid(PVT(terminal)->term));
2991
2992 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
2993 GtkAllocation allocation;
2994
2995 gtk_widget_get_allocation(GTK_WIDGET(terminal), &allocation);
2996
2997 if (!is_initial_allocation(&allocation) &&
2998 ui_window_resize_with_margin(&PVT(terminal)->screen->window, allocation.width,
2999 allocation.height, NOTIFY_TO_MYSELF)) {
3000 reset_vte_size_member(terminal);
3001 update_wall_picture(terminal);
3002 }
3003 }
3004
3005 /*
3006 * In order to receive pty_closed() event even if vte_terminal_realize()
3007 * isn't called.
3008 */
3009 vt_pty_set_listener(PVT(terminal)->term->pty, &PVT(terminal)->screen->pty_listener);
3010 }
3011
3012 return vt_term_get_child_pid(PVT(terminal)->term);
3013 }
3014
3015 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_feed(VteTerminal * terminal,const char * data,gssize length)3016 void vte_terminal_feed(VteTerminal *terminal, const char *data, gssize length)
3017 #else
3018 void vte_terminal_feed(VteTerminal *terminal, const char *data, glong length)
3019 #endif
3020 {
3021 vt_term_write_loopback(PVT(terminal)->term, data, length == -1 ? strlen(data) : length);
3022 }
3023
3024 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_feed_child(VteTerminal * terminal,const char * text,gssize length)3025 void vte_terminal_feed_child(VteTerminal *terminal, const char *text, gssize length)
3026 #else
3027 void vte_terminal_feed_child(VteTerminal *terminal, const char *text, glong length)
3028 #endif
3029 {
3030 vt_term_write(PVT(terminal)->term, text, length == -1 ? strlen(text) : length);
3031 }
3032
3033 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_feed_child_binary(VteTerminal * terminal,const guint8 * data,gsize length)3034 void vte_terminal_feed_child_binary(VteTerminal *terminal, const guint8 *data, gsize length)
3035 #else
3036 void vte_terminal_feed_child_binary(VteTerminal *terminal, const char *data, glong length)
3037 #endif
3038 {
3039 vt_term_write(PVT(terminal)->term, data, length);
3040 }
3041
vte_terminal_copy_clipboard(VteTerminal * terminal)3042 void vte_terminal_copy_clipboard(VteTerminal *terminal) {
3043 GtkClipboard *clipboard;
3044 ef_conv_t *conv;
3045 ef_parser_t *parser;
3046 u_char *buf;
3047 size_t len;
3048
3049 if (!vte_terminal_get_has_selection(terminal) ||
3050 !(conv = ui_get_selection_conv(1)) /* utf8 */ ||
3051 !(parser = vt_str_parser_new())) {
3052 return;
3053 }
3054
3055 len = PVT(terminal)->screen->sel.sel_len * VTCHAR_UTF_MAX_SIZE;
3056
3057 /*
3058 * Don't use alloca() here because len can be too big value.
3059 * (VTCHAR_UTF_MAX_SIZE defined in vt_char.h is 48 byte.)
3060 */
3061 if ((buf = malloc(len))) {
3062 (*parser->init)(parser);
3063 vt_str_parser_set_str(parser, PVT(terminal)->screen->sel.sel_str,
3064 PVT(terminal)->screen->sel.sel_len);
3065 (*conv->init)(conv);
3066
3067 len = (*conv->convert)(conv, buf, len, parser);
3068
3069 if (len > 0 && (clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))) {
3070 #ifdef USE_WAYLAND
3071 extern gint64 deadline_ignoring_source_cancelled_event;
3072 deadline_ignoring_source_cancelled_event = g_get_monotonic_time() + 1000000; /* microsecond */
3073 #endif
3074
3075 gtk_clipboard_set_text(clipboard, buf, len);
3076 gtk_clipboard_store(clipboard);
3077 #if GTK_CHECK_VERSION(2, 6, 0)
3078 /*
3079 * XXX gnome-terminal 3.24.2 doesn't make "EditPaste" menuitem sensitive after
3080 * clicking "EditCopy" menu item without invoking "owner-change" event explicitly.
3081 */
3082 g_signal_emit_by_name(clipboard, "owner-change");
3083 #endif
3084 }
3085
3086 free(buf);
3087 }
3088
3089 (*parser->destroy)(parser);
3090 }
3091
3092 #if VTE_CHECK_VERSION(0, 50, 0)
vte_terminal_copy_clipboard_format(VteTerminal * terminal,VteFormat format)3093 void vte_terminal_copy_clipboard_format(VteTerminal *terminal, VteFormat format) {
3094 if (format == VTE_FORMAT_TEXT) {
3095 vte_terminal_copy_clipboard(terminal);
3096 } else if (format == VTE_FORMAT_HTML) {
3097 /* XXX do nothing */
3098 }
3099 }
3100 #endif
3101
vte_terminal_paste_clipboard(VteTerminal * terminal)3102 void vte_terminal_paste_clipboard(VteTerminal *terminal) {
3103 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3104 ui_screen_exec_cmd(PVT(terminal)->screen, "paste");
3105 }
3106 }
3107
vte_terminal_copy_primary(VteTerminal * terminal)3108 void vte_terminal_copy_primary(VteTerminal *terminal) {}
3109
vte_terminal_paste_primary(VteTerminal * terminal)3110 void vte_terminal_paste_primary(VteTerminal *terminal) { vte_terminal_paste_clipboard(terminal); }
3111
vte_terminal_select_all(VteTerminal * terminal)3112 void vte_terminal_select_all(VteTerminal *terminal) {
3113 int beg_row;
3114 int end_row;
3115 vt_line_t *line;
3116
3117 if (!GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3118 return;
3119 }
3120
3121 beg_row = -vt_term_get_num_logged_lines(PVT(terminal)->term);
3122
3123 for (end_row = vt_term_get_rows(PVT(terminal)->term) - 1; end_row >= 0; end_row--) {
3124 line = vt_term_get_line(PVT(terminal)->term, end_row); /* Always non-NULL */
3125 if (!vt_line_is_empty(line)) {
3126 break;
3127 }
3128 }
3129
3130 selection(&PVT(terminal)->screen->sel, 0, beg_row, line->num_filled_chars - 1, end_row);
3131
3132 ui_window_update(&PVT(terminal)->screen->window, 1 /* UPDATE_SCREEN */);
3133 }
3134
3135 #if VTE_CHECK_VERSION(0, 52, 0)
vte_terminal_unselect_all(VteTerminal * terminal)3136 void vte_terminal_unselect_all(VteTerminal *terminal) {
3137 /* see restore_selected_region_color_instantly() in ui_screen.c */
3138 if (ui_restore_selected_region_color(&PVT(terminal)->screen->sel)) {
3139 ui_window_update(&PVT(terminal)->screen->window, 0x3/*UPDATE_SCREEN|UPDATE_CURSOR*/);
3140 }
3141 }
3142 #endif
3143
3144 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_select_none(VteTerminal * terminal)3145 void vte_terminal_select_none(VteTerminal *terminal)
3146 #else
3147 void vte_terminal_unselect_all(VteTerminal *terminal)
3148 #endif
3149 {
3150 if (!GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3151 return;
3152 }
3153
3154 ui_sel_clear(&PVT(terminal)->screen->sel);
3155
3156 ui_window_update(&PVT(terminal)->screen->window, 3 /* UPDATE_SCREEN|UPDATE_CURSOR */);
3157 }
3158
vte_terminal_set_size(VteTerminal * terminal,glong columns,glong rows)3159 void vte_terminal_set_size(VteTerminal *terminal, glong columns, glong rows) {
3160 ui_screen_t *screen = PVT(terminal)->screen;
3161 vt_term_t *term = PVT(terminal)->term;
3162
3163 #ifdef DEBUG
3164 bl_debug_printf(BL_DEBUG_TAG " set cols %d rows %d\n", columns, rows);
3165 #endif
3166
3167 vt_term_resize(term, columns, rows,
3168 /*
3169 * Vertical writing mode and screen_(width|height)_ratio option
3170 * aren't supported.
3171 * See reset_vte_size_member().
3172 */
3173 CHAR_WIDTH(terminal) * columns, CHAR_HEIGHT(terminal) * rows);
3174 reset_vte_size_member(terminal);
3175
3176 /* gnome-terminal(2.29.6 or later ?) is not resized correctly without this. */
3177 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3178 #ifdef USE_WAYLAND
3179 /*
3180 * Screen may be redrawn before gtk_widget_queue_resize_no_redraw() results in resizing.
3181 * This causes illegal memory access without this ui_window_resize_with_margin()
3182 * on wayland.
3183 */
3184 gint width;
3185 gint height;
3186 vte_terminal_get_preferred_width(GTK_WIDGET(terminal), NULL, &width);
3187 vte_terminal_get_preferred_height(GTK_WIDGET(terminal), NULL, &height);
3188 ui_window_resize_with_margin(&screen->window, width, height, 0);
3189 #endif
3190 gtk_widget_queue_resize_no_redraw(GTK_WIDGET(terminal));
3191 } else {
3192 screen->window.width = CHAR_WIDTH(terminal) * columns;
3193 screen->window.height = CHAR_HEIGHT(terminal) * rows;
3194 }
3195 }
3196
3197 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_font_scale(VteTerminal * terminal,gdouble scale)3198 void vte_terminal_set_font_scale(VteTerminal *terminal, gdouble scale) {}
3199
vte_terminal_get_font_scale(VteTerminal * terminal)3200 gdouble vte_terminal_get_font_scale(VteTerminal *terminal) { return 14; }
3201 #endif
3202
vte_terminal_set_audible_bell(VteTerminal * terminal,gboolean is_audible)3203 void vte_terminal_set_audible_bell(VteTerminal *terminal, gboolean is_audible) {
3204 ui_screen_set_config(
3205 PVT(terminal)->screen, NULL, "bel_mode",
3206 ui_get_bel_mode_name(is_audible ? (BEL_SOUND | PVT(terminal)->screen->bel_mode)
3207 : (~BEL_SOUND & PVT(terminal)->screen->bel_mode)));
3208 }
3209
vte_terminal_get_audible_bell(VteTerminal * terminal)3210 gboolean vte_terminal_get_audible_bell(VteTerminal *terminal) {
3211 if (PVT(terminal)->screen->bel_mode & BEL_SOUND) {
3212 return TRUE;
3213 } else {
3214 return FALSE;
3215 }
3216 }
3217
3218 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_visible_bell(VteTerminal * terminal,gboolean is_visible)3219 void vte_terminal_set_visible_bell(VteTerminal *terminal, gboolean is_visible) {
3220 ui_screen_set_config(
3221 PVT(terminal)->screen, NULL, "bel_mode",
3222 ui_get_bel_mode_name(is_visible ? (BEL_VISUAL | PVT(terminal)->screen->bel_mode)
3223 : (~BEL_VISUAL & PVT(terminal)->screen->bel_mode)));
3224 }
3225
vte_terminal_get_visible_bell(VteTerminal * terminal)3226 gboolean vte_terminal_get_visible_bell(VteTerminal *terminal) {
3227 if (PVT(terminal)->screen->bel_mode & BEL_VISUAL) {
3228 return TRUE;
3229 } else {
3230 return FALSE;
3231 }
3232 }
3233 #endif
3234
vte_terminal_set_scroll_background(VteTerminal * terminal,gboolean scroll)3235 void vte_terminal_set_scroll_background(VteTerminal *terminal, gboolean scroll) {}
3236
vte_terminal_set_scroll_on_output(VteTerminal * terminal,gboolean scroll)3237 void vte_terminal_set_scroll_on_output(VteTerminal *terminal, gboolean scroll) {
3238 ui_exit_backscroll_by_pty(scroll);
3239 }
3240
vte_terminal_set_scroll_on_keystroke(VteTerminal * terminal,gboolean scroll)3241 void vte_terminal_set_scroll_on_keystroke(VteTerminal *terminal, gboolean scroll) {}
3242
3243 #if VTE_CHECK_VERSION(0, 36, 0)
vte_terminal_set_rewrap_on_resize(VteTerminal * terminal,gboolean rewrap)3244 void vte_terminal_set_rewrap_on_resize(VteTerminal *terminal, gboolean rewrap) {}
3245
vte_terminal_get_rewrap_on_resize(VteTerminal * terminal)3246 gboolean vte_terminal_get_rewrap_on_resize(VteTerminal *terminal) { return TRUE; }
3247 #endif
3248
3249 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_color_dim(VteTerminal * terminal,const GdkColor * dim)3250 void vte_terminal_set_color_dim(VteTerminal *terminal, const GdkColor *dim) {}
3251
vte_terminal_set_color_bold(VteTerminal * terminal,const GdkColor * bold)3252 void vte_terminal_set_color_bold(VteTerminal *terminal, const GdkColor *bold) {
3253 set_color_bold(terminal, bold, gdk_color_to_string);
3254 }
3255
vte_terminal_set_color_foreground(VteTerminal * terminal,const GdkColor * foreground)3256 void vte_terminal_set_color_foreground(VteTerminal *terminal, const GdkColor *foreground) {
3257 set_color_foreground(terminal, foreground, gdk_color_to_string);
3258 }
3259
vte_terminal_set_color_background(VteTerminal * terminal,const GdkColor * background)3260 void vte_terminal_set_color_background(VteTerminal *terminal, const GdkColor *background) {
3261 set_color_background(terminal, background, gdk_color_to_string);
3262 }
3263
vte_terminal_set_color_cursor(VteTerminal * terminal,const GdkColor * cursor_background)3264 void vte_terminal_set_color_cursor(VteTerminal *terminal, const GdkColor *cursor_background) {
3265 set_color_cursor(terminal, cursor_background, gdk_color_to_string);
3266 }
3267
vte_terminal_set_color_highlight(VteTerminal * terminal,const GdkColor * highlight_background)3268 void vte_terminal_set_color_highlight(VteTerminal *terminal, const GdkColor *highlight_background) {
3269 }
3270
3271 #if VTE_CHECK_VERSION(0, 36, 0)
vte_terminal_set_color_highlight_foreground(VteTerminal * terminal,const GdkColor * highlight_foreground)3272 void vte_terminal_set_color_highlight_foreground(VteTerminal *terminal,
3273 const GdkColor *highlight_foreground) {}
3274 #endif
3275
vte_terminal_set_colors(VteTerminal * terminal,const GdkColor * foreground,const GdkColor * background,const GdkColor * palette,glong palette_size)3276 void vte_terminal_set_colors(VteTerminal *terminal, const GdkColor *foreground,
3277 const GdkColor *background, const GdkColor *palette,
3278 glong palette_size) {
3279 if (set_colors(terminal, palette, palette_size, sizeof(GdkColor), gdk_color_to_string) &&
3280 palette_size > 0) {
3281 if (foreground == NULL) {
3282 foreground = &palette[7];
3283 }
3284 if (background == NULL) {
3285 background = &palette[0];
3286 }
3287 }
3288
3289 if (foreground) {
3290 vte_terminal_set_color_foreground(terminal, foreground);
3291 } else {
3292 GdkColor color = { 0xc000, 0xc000, 0xc000 };
3293
3294 vte_terminal_set_color_foreground(terminal, &color);
3295 }
3296
3297 if (background) {
3298 vte_terminal_set_color_background(terminal, background);
3299 } else {
3300 GdkColor color = { 0, 0, 0 };
3301
3302 vte_terminal_set_color_background(terminal, &color);
3303 }
3304
3305 /*
3306 * XXX
3307 * VTE_BOLD_FG, VTE_DIM_BG, VTE_DEF_HL and VTE_CUR_BG should be reset.
3308 * (See vte_terminal_set_colors() in vte-0.xx.xx/src/vte.c)
3309 */
3310 }
3311
3312 #if GTK_CHECK_VERSION(2, 99, 0)
vte_terminal_set_color_dim_rgba(VteTerminal * terminal,const GdkRGBA * dim)3313 void vte_terminal_set_color_dim_rgba(VteTerminal *terminal, const GdkRGBA *dim) {}
3314 #endif
3315 #else /* VTE_CHECK_VERSION(0,38,0) */
3316 #define vte_terminal_set_color_bold_rgba vte_terminal_set_color_bold
3317 #define vte_terminal_set_color_foreground_rgba vte_terminal_set_color_foreground
3318 #define vte_terminal_set_color_background_rgba vte_terminal_set_color_background
3319 #define vte_terminal_set_color_cursor_rgba vte_terminal_set_color_cursor
3320 #define vte_terminal_set_color_highlight_rgba vte_terminal_set_color_highlight
3321 #define vte_terminal_set_color_highlight_foreground_rgba vte_terminal_set_color_highlight_foreground
3322 #define vte_terminal_set_colors_rgba vte_terminal_set_colors
3323 #endif /* VTE_CHECK_VERSION(0,38,0) */
3324
3325 #if GTK_CHECK_VERSION(2, 99, 0)
vte_terminal_set_color_bold_rgba(VteTerminal * terminal,const GdkRGBA * bold)3326 void vte_terminal_set_color_bold_rgba(VteTerminal *terminal, const GdkRGBA *bold) {
3327 set_color_bold(terminal, bold, gdk_rgba_to_string2);
3328 }
3329
vte_terminal_set_color_foreground_rgba(VteTerminal * terminal,const GdkRGBA * foreground)3330 void vte_terminal_set_color_foreground_rgba(VteTerminal *terminal, const GdkRGBA *foreground) {
3331 set_color_foreground(terminal, foreground, gdk_rgba_to_string2);
3332 }
3333
vte_terminal_set_color_background_rgba(VteTerminal * terminal,const GdkRGBA * background)3334 void vte_terminal_set_color_background_rgba(VteTerminal *terminal, const GdkRGBA *background) {
3335 set_color_background(terminal, background, gdk_rgba_to_string2);
3336 }
3337
vte_terminal_set_color_cursor_rgba(VteTerminal * terminal,const GdkRGBA * cursor_background)3338 void vte_terminal_set_color_cursor_rgba(VteTerminal *terminal, const GdkRGBA *cursor_background) {
3339 set_color_cursor(terminal, cursor_background, gdk_rgba_to_string2);
3340 }
3341
3342 #if VTE_CHECK_VERSION(0, 44, 0)
vte_terminal_set_color_cursor_foreground(VteTerminal * terminal,const GdkRGBA * cursor_foreground)3343 void vte_terminal_set_color_cursor_foreground(VteTerminal *terminal,
3344 const GdkRGBA *cursor_foreground) {
3345 gchar *str;
3346
3347 if (!cursor_foreground) {
3348 return;
3349 }
3350
3351 /* #rrrrggggbbbb */
3352 str = gdk_rgba_to_string2(cursor_foreground);
3353
3354 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3355 ui_screen_set_config(PVT(terminal)->screen, NULL, "cursor_fg_color", str);
3356 ui_window_update(&PVT(terminal)->screen->window, 3 /* UPDATE_SCREEN|UPDATE_CURSOR */);
3357 } else {
3358 ui_color_manager_set_cursor_bg_color(PVT(terminal)->screen->color_man, str);
3359 }
3360
3361 g_free(str);
3362 }
3363 #endif
3364
vte_terminal_set_color_highlight_rgba(VteTerminal * terminal,const GdkRGBA * highlight_background)3365 void vte_terminal_set_color_highlight_rgba(VteTerminal *terminal,
3366 const GdkRGBA *highlight_background) {}
3367
3368 #if VTE_CHECK_VERSION(0, 36, 0)
vte_terminal_set_color_highlight_foreground_rgba(VteTerminal * terminal,const GdkRGBA * highlight_foreground)3369 void vte_terminal_set_color_highlight_foreground_rgba(VteTerminal *terminal,
3370 const GdkRGBA *highlight_foreground) {}
3371 #endif
3372
vte_terminal_set_colors_rgba(VteTerminal * terminal,const GdkRGBA * foreground,const GdkRGBA * background,const GdkRGBA * palette,gsize palette_size)3373 void vte_terminal_set_colors_rgba(VteTerminal *terminal, const GdkRGBA *foreground,
3374 const GdkRGBA *background, const GdkRGBA *palette,
3375 gsize palette_size) {
3376 if (set_colors(terminal, palette, palette_size, sizeof(GdkRGBA), gdk_rgba_to_string2) &&
3377 palette_size > 0) {
3378 if (foreground == NULL) {
3379 foreground = &palette[7];
3380 }
3381 if (background == NULL) {
3382 background = &palette[0];
3383 }
3384 }
3385
3386 if (foreground) {
3387 vte_terminal_set_color_foreground_rgba(terminal, foreground);
3388 } else {
3389 /* 192 = 0xc0 */
3390 GdkRGBA color = { 192.0 / 255.0, 192.0 / 255.0, 192.0 / 255.0, 1.0 };
3391
3392 vte_terminal_set_color_foreground_rgba(terminal, &color);
3393 }
3394
3395 if (background) {
3396 vte_terminal_set_color_background_rgba(terminal, background);
3397 } else {
3398 GdkRGBA color = { 0.0, 0.0, 0.0, 1.0 };
3399
3400 vte_terminal_set_color_background_rgba(terminal, &color);
3401 }
3402
3403 /*
3404 * XXX
3405 * VTE_BOLD_FG, VTE_HIGHLIGHT_BG, VTE_HIGHLIGHT_FG, VTE_CURSOR_BG and VTE_CURSOR_FG
3406 * should be reset.
3407 * (see Terminal::set_colors in vte-0.xx.xx/src/vte.cc)
3408 */
3409 }
3410 #endif /* GTK_CHECK_VERSION(2,99,0) */
3411
vte_terminal_set_default_colors(VteTerminal * terminal)3412 void vte_terminal_set_default_colors(VteTerminal *terminal) {
3413 set_colors(terminal, NULL, 0, 0, NULL);
3414 }
3415
vte_terminal_set_background_image(VteTerminal * terminal,GdkPixbuf * image)3416 void vte_terminal_set_background_image(
3417 VteTerminal *terminal,
3418 GdkPixbuf *image /* can be NULL and same as current PVT(terminal)->image */
3419 ) {
3420 #ifdef DEBUG
3421 bl_debug_printf(BL_DEBUG_TAG " Setting image %p\n", image);
3422 #endif
3423
3424 if (PVT(terminal)->image) {
3425 if (PVT(terminal)->image == image) {
3426 return;
3427 }
3428
3429 g_object_unref(PVT(terminal)->image);
3430 }
3431
3432 if ((PVT(terminal)->image = image) == NULL) {
3433 vte_terminal_set_background_image_file(terminal, "");
3434
3435 return;
3436 }
3437
3438 g_object_ref(image);
3439
3440 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3441 update_wall_picture(terminal);
3442 }
3443 }
3444
vte_terminal_set_background_image_file(VteTerminal * terminal,const char * path)3445 void vte_terminal_set_background_image_file(VteTerminal *terminal, const char *path) {
3446 #ifdef DEBUG
3447 bl_debug_printf(BL_DEBUG_TAG " Setting image file %s\n", path);
3448 #endif
3449
3450 /*
3451 * Don't unref PVT(terminal)->image if path is
3452 * "pixmap:<pixmap id>" (Ex. the case of
3453 * vte_terminal_set_background_image_file()
3454 * being called from update_wall_picture().)
3455 */
3456 if (PVT(terminal)->image && strncmp(path, "pixmap:", 7) != 0) {
3457 g_object_unref(PVT(terminal)->image);
3458 PVT(terminal)->image = NULL;
3459 }
3460
3461 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3462 ui_screen_set_config(PVT(terminal)->screen, NULL, "wall_picture", path);
3463 } else {
3464 free(PVT(terminal)->screen->pic_file_path);
3465 PVT(terminal)->screen->pic_file_path = (*path == '\0') ? NULL : strdup(path);
3466 }
3467 }
3468
vte_terminal_set_background_tint_color(VteTerminal * terminal,const GdkColor * color)3469 void vte_terminal_set_background_tint_color(VteTerminal *terminal, const GdkColor *color) {}
3470
vte_terminal_set_background_saturation(VteTerminal * terminal,double saturation)3471 void vte_terminal_set_background_saturation(VteTerminal *terminal, double saturation) {
3472 #ifdef DEBUG
3473 bl_debug_printf(BL_DEBUG_TAG " SATURATION => %f\n", saturation);
3474 #endif
3475
3476 if (PVT(terminal)->screen->pic_file_path || PVT(terminal)->screen->window.is_transparent) {
3477 set_alpha(terminal, 255 * (1.0 - saturation));
3478 }
3479 }
3480
vte_terminal_set_background_transparent(VteTerminal * terminal,gboolean transparent)3481 void vte_terminal_set_background_transparent(VteTerminal *terminal, gboolean transparent) {
3482 #ifdef DEBUG
3483 bl_debug_printf(BL_DEBUG_TAG " Pseudo transparent %s.\n", transparent ? "on" : "off");
3484 #endif
3485
3486 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3487 char *value;
3488
3489 if (transparent) {
3490 value = "true";
3491 } else {
3492 value = "false";
3493 }
3494
3495 ui_screen_set_config(PVT(terminal)->screen, NULL, "use_transbg", value);
3496 } else if (transparent) {
3497 ui_window_set_transparent(&PVT(terminal)->screen->window,
3498 ui_screen_get_picture_modifier(PVT(terminal)->screen));
3499 }
3500 }
3501
vte_terminal_set_opacity(VteTerminal * terminal,guint16 opacity)3502 void vte_terminal_set_opacity(VteTerminal *terminal, guint16 opacity) {
3503 u_int8_t alpha;
3504
3505 #ifdef DEBUG
3506 bl_debug_printf(BL_DEBUG_TAG " OPACITY => %x\n", opacity);
3507 #endif
3508
3509 alpha = ((opacity >> 8) & 0xff);
3510
3511 if (!PVT(terminal)->screen->pic_file_path && !PVT(terminal)->screen->window.is_transparent) {
3512 set_alpha(terminal, alpha);
3513 }
3514 }
3515
3516 #if VTE_CHECK_VERSION(0, 17, 1)
vte_terminal_set_cursor_blink_mode(VteTerminal * terminal,VteCursorBlinkMode mode)3517 void vte_terminal_set_cursor_blink_mode(VteTerminal *terminal, VteCursorBlinkMode mode) {
3518 char *value;
3519
3520 if (mode == VTE_CURSOR_BLINK_OFF) {
3521 value = "false";
3522 } else {
3523 value = "true";
3524 }
3525
3526 ui_screen_set_config(PVT(terminal)->screen, NULL, "blink_cursor", value);
3527 }
3528
vte_terminal_get_cursor_blink_mode(VteTerminal * terminal)3529 VteCursorBlinkMode vte_terminal_get_cursor_blink_mode(VteTerminal *terminal) {
3530 if (vt_term_get_cursor_style(PVT(terminal)->term) & CS_BLINK) {
3531 return VTE_CURSOR_BLINK_ON;
3532 } else {
3533 return VTE_CURSOR_BLINK_OFF;
3534 }
3535 }
3536 #endif
3537
3538 #if VTE_CHECK_VERSION(0, 20, 0)
vte_terminal_set_cursor_shape(VteTerminal * terminal,VteCursorShape shape)3539 void vte_terminal_set_cursor_shape(VteTerminal *terminal, VteCursorShape shape) {}
3540
vte_terminal_get_cursor_shape(VteTerminal * terminal)3541 VteCursorShape vte_terminal_get_cursor_shape(VteTerminal *terminal) {
3542 return VTE_CURSOR_SHAPE_IBEAM;
3543 }
3544 #endif
3545
vte_terminal_set_scrollback_lines(VteTerminal * terminal,glong lines)3546 void vte_terminal_set_scrollback_lines(VteTerminal *terminal, glong lines) {
3547 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3548 char value[DIGIT_STR_LEN(glong) + 1];
3549
3550 sprintf(value, "%ld", lines);
3551
3552 ui_screen_set_config(PVT(terminal)->screen, NULL, "logsize", value);
3553 } else {
3554 vt_term_change_log_size(PVT(terminal)->term, lines);
3555 }
3556 }
3557
3558 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_im_append_menuitems(VteTerminal * terminal,GtkMenuShell * menushell)3559 void vte_terminal_im_append_menuitems(VteTerminal *terminal, GtkMenuShell *menushell) {}
3560 #endif
3561
vte_terminal_set_font_from_string(VteTerminal * terminal,const char * name)3562 void vte_terminal_set_font_from_string(VteTerminal *terminal, const char *name) {
3563 char *p;
3564 int font_changed;
3565
3566 #ifdef DEBUG
3567 bl_debug_printf(BL_DEBUG_TAG " set_font_from_string %s\n", name);
3568 #endif
3569
3570 if (!name || strcmp(name, "(null)") == 0) {
3571 name = "monospace";
3572 } else {
3573 p = name + strlen(name) - 1;
3574 if ('0' <= *p && *p <= '9') {
3575 int fontsize;
3576
3577 do {
3578 p--;
3579 } while ('0' <= *p && *p <= '9');
3580
3581 if ((fontsize = atoi(p + 1)) > 0) {
3582 /* XXX Screen is redraw in ui_screen_reset_view() below. */
3583 ui_change_font_size(PVT(terminal)->screen->font_man, atoi(p + 1));
3584 }
3585 }
3586
3587 if ((p = strchr(name, ','))) {
3588 /*
3589 * name contains font list like "Ubuntu Mono,monospace 13"
3590 * (see manual of pango_font_description_from_string())
3591 */
3592 char *new_name;
3593
3594 if (!(new_name = alloca(p - name + 1))) {
3595 return;
3596 }
3597
3598 memcpy(new_name, name, p - name);
3599 new_name[p - name] = '\0';
3600
3601 name = new_name;
3602 }
3603 }
3604
3605 font_changed = ui_customize_font_file("aafont", "DEFAULT", name, 0);
3606 font_changed |= ui_customize_font_file("aafont", "ISO10646_UCS4_1", name, 0);
3607 if (font_changed) {
3608 ui_font_cache_unload_all();
3609
3610 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3611 ui_screen_reset_view(PVT(terminal)->screen);
3612 } else {
3613 /*
3614 * XXX
3615 * Forcibly fix width and height members of ui_window_t,
3616 * or widget->requisition is not set correctly in
3617 * reset_vte_size_member.
3618 */
3619 PVT(terminal)->screen->window.width =
3620 ui_col_width(PVT(terminal)->screen) * vt_term_get_cols(PVT(terminal)->term);
3621 PVT(terminal)->screen->window.height =
3622 ui_line_height(PVT(terminal)->screen) * vt_term_get_rows(PVT(terminal)->term);
3623
3624 PVT(terminal)->screen->window.width_inc = PVT(terminal)->screen->window.min_width =
3625 ui_col_width(PVT(terminal)->screen);
3626 PVT(terminal)->screen->window.height_inc = PVT(terminal)->screen->window.min_height =
3627 ui_line_height(PVT(terminal)->screen);
3628 }
3629
3630 reset_vte_size_member(terminal);
3631
3632 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3633 /*
3634 * gnome-terminal(2.29.6 or later?) is not resized correctly
3635 * without this.
3636 */
3637 gtk_widget_queue_resize_no_redraw(GTK_WIDGET(terminal));
3638 }
3639 }
3640 }
3641
vte_terminal_set_font(VteTerminal * terminal,const PangoFontDescription * font_desc)3642 void vte_terminal_set_font(VteTerminal *terminal, const PangoFontDescription *font_desc) {
3643 char *name;
3644
3645 name = pango_font_description_to_string(font_desc);
3646
3647 #ifdef DEBUG
3648 bl_debug_printf(BL_DEBUG_TAG " set_font %s\n", name);
3649 #endif
3650
3651 vte_terminal_set_font_from_string(terminal, name);
3652
3653 g_free(name);
3654 }
3655
vte_terminal_get_font(VteTerminal * terminal)3656 const PangoFontDescription *vte_terminal_get_font(VteTerminal *terminal) { return NULL; }
3657
vte_terminal_set_allow_bold(VteTerminal * terminal,gboolean allow_bold)3658 void vte_terminal_set_allow_bold(VteTerminal *terminal, gboolean allow_bold) {}
3659
vte_terminal_get_allow_bold(VteTerminal * terminal)3660 gboolean vte_terminal_get_allow_bold(VteTerminal *terminal) { return TRUE; }
3661
vte_terminal_get_has_selection(VteTerminal * terminal)3662 gboolean vte_terminal_get_has_selection(VteTerminal *terminal) {
3663 if (PVT(terminal)->screen->sel.sel_str && PVT(terminal)->screen->sel.sel_len > 0) {
3664 return TRUE;
3665 } else {
3666 return FALSE;
3667 }
3668 }
3669
3670 #if VTE_CHECK_VERSION(0, 40, 0)
vte_terminal_set_word_char_exceptions(VteTerminal * terminal,const char * exception)3671 void vte_terminal_set_word_char_exceptions(VteTerminal *terminal, const char *exception) {
3672 char *seps;
3673
3674 if (!exception || !*exception) {
3675 vt_set_word_separators(NULL);
3676
3677 return;
3678 }
3679
3680 if ((seps = alloca(strlen(vt_get_word_separators()) + 1))) {
3681 char *p = strcpy(seps, vt_get_word_separators());
3682 char *end = seps + strlen(seps) - 1;
3683 int do_replace = 0;
3684
3685 while (*p) {
3686 if (strchr(exception, *p)) {
3687 *p = *end;
3688 *(end--) = '\0';
3689 do_replace = 1;
3690 }
3691 p ++;
3692 }
3693
3694 if (do_replace) {
3695 vt_set_word_separators(seps);
3696 }
3697 }
3698 }
3699
vte_terminal_get_word_chars_exceptions(VteTerminal * terminal)3700 const char *vte_terminal_get_word_chars_exceptions(VteTerminal *terminal) {
3701 return "";
3702 }
3703 #endif
3704
3705 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_word_chars(VteTerminal * terminal,const char * spec)3706 void vte_terminal_set_word_chars(VteTerminal *terminal, const char *spec) {
3707 char *sep;
3708
3709 if (!spec || !*spec) {
3710 sep = ",. ";
3711 } else if ((sep = alloca(0x5f))) {
3712 char *sep_p;
3713 char c;
3714
3715 sep_p = sep;
3716 c = 0x20;
3717
3718 do {
3719 const char *spec_p;
3720
3721 spec_p = spec;
3722
3723 while (*spec_p) {
3724 if (*spec_p == '-' && spec_p > spec && *(spec_p + 1) != '\0') {
3725 if (*(spec_p - 1) < c && c < *(spec_p + 1)) {
3726 goto next;
3727 }
3728 } else if (*spec_p == c) {
3729 goto next;
3730 }
3731
3732 spec_p++;
3733 }
3734
3735 *(sep_p++) = c;
3736
3737 next:
3738 c++;
3739 } while (c < 0x7f);
3740
3741 *(sep_p) = '\0';
3742 } else {
3743 return;
3744 }
3745
3746 vt_set_word_separators(sep);
3747 }
3748
vte_terminal_is_word_char(VteTerminal * terminal,gunichar c)3749 gboolean vte_terminal_is_word_char(VteTerminal *terminal, gunichar c) { return TRUE; }
3750 #endif
3751
vte_terminal_set_backspace_binding(VteTerminal * terminal,VteEraseBinding binding)3752 void vte_terminal_set_backspace_binding(VteTerminal *terminal, VteEraseBinding binding) {
3753 char *seq;
3754
3755 #ifdef DEBUG
3756 bl_debug_printf(BL_DEBUG_TAG " set backtrace binding => %d\n", binding);
3757 #endif
3758
3759 if (binding == VTE_ERASE_ASCII_BACKSPACE) {
3760 seq = "\x08";
3761 } else if (binding == VTE_ERASE_ASCII_DELETE) {
3762 seq = "\x7f";
3763 } else if (binding == VTE_ERASE_DELETE_SEQUENCE) {
3764 seq = "\x1b[3~";
3765 }
3766 #if VTE_CHECK_VERSION(0, 20, 4)
3767 else if (binding == VTE_ERASE_TTY) {
3768 return;
3769 }
3770 #endif
3771 else {
3772 return;
3773 }
3774
3775 vt_termcap_set_key_seq(PVT(terminal)->term->parser->termcap, SPKEY_BACKSPACE, seq);
3776 }
3777
vte_terminal_set_delete_binding(VteTerminal * terminal,VteEraseBinding binding)3778 void vte_terminal_set_delete_binding(VteTerminal *terminal, VteEraseBinding binding) {
3779 char *seq;
3780
3781 if (binding == VTE_ERASE_ASCII_BACKSPACE) {
3782 seq = "\x08";
3783 } else if (binding == VTE_ERASE_ASCII_DELETE) {
3784 seq = "\x7f";
3785 } else if (binding == VTE_ERASE_DELETE_SEQUENCE) {
3786 seq = "\x1b[3~";
3787 }
3788 #if VTE_CHECK_VERSION(0, 20, 4)
3789 else if (binding == VTE_ERASE_TTY) {
3790 return;
3791 }
3792 #endif
3793 else {
3794 return;
3795 }
3796
3797 vt_termcap_set_key_seq(PVT(terminal)->term->parser->termcap, SPKEY_DELETE, seq);
3798 }
3799
vte_terminal_set_mouse_autohide(VteTerminal * terminal,gboolean setting)3800 void vte_terminal_set_mouse_autohide(VteTerminal *terminal, gboolean setting) {}
3801
vte_terminal_get_mouse_autohide(VteTerminal * terminal)3802 gboolean vte_terminal_get_mouse_autohide(VteTerminal *terminal) { return TRUE; }
3803
vte_terminal_reset(VteTerminal * terminal,gboolean full,gboolean clear_history)3804 void vte_terminal_reset(VteTerminal *terminal, gboolean full, gboolean clear_history) {
3805 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
3806 ui_screen_exec_cmd(PVT(terminal)->screen, "full_reset");
3807 }
3808 }
3809
vte_terminal_get_text(VteTerminal * terminal,gboolean (* is_selected)(VteTerminal * terminal,glong column,glong row,gpointer data),gpointer data,GArray * attributes)3810 char *vte_terminal_get_text(VteTerminal *terminal,
3811 gboolean (*is_selected)(VteTerminal *terminal, glong column, glong row,
3812 gpointer data),
3813 gpointer data, GArray *attributes) {
3814 return NULL;
3815 }
3816
vte_terminal_get_text_include_trailing_spaces(VteTerminal * terminal,gboolean (* is_selected)(VteTerminal * terminal,glong column,glong row,gpointer data),gpointer data,GArray * attributes)3817 char *vte_terminal_get_text_include_trailing_spaces(VteTerminal *terminal,
3818 gboolean (*is_selected)(VteTerminal *terminal,
3819 glong column, glong row,
3820 gpointer data),
3821 gpointer data, GArray *attributes) {
3822 return NULL;
3823 }
3824
vte_terminal_get_text_range(VteTerminal * terminal,glong start_row,glong start_col,glong end_row,glong end_col,gboolean (* is_selected)(VteTerminal * terminal,glong column,glong row,gpointer data),gpointer data,GArray * attributes)3825 char *vte_terminal_get_text_range(VteTerminal *terminal, glong start_row, glong start_col,
3826 glong end_row, glong end_col,
3827 gboolean (*is_selected)(VteTerminal *terminal, glong column,
3828 glong row, gpointer data),
3829 gpointer data, GArray *attributes) {
3830 return NULL;
3831 }
3832
vte_terminal_get_cursor_position(VteTerminal * terminal,glong * column,glong * row)3833 void vte_terminal_get_cursor_position(VteTerminal *terminal, glong *column, glong *row) {
3834 *column = vt_term_cursor_col(PVT(terminal)->term);
3835 *row = vt_term_cursor_row(PVT(terminal)->term);
3836 }
3837
3838 #if GLIB_CHECK_VERSION(2, 14, 0)
vte_terminal_match_add_gregex(VteTerminal * terminal,GRegex * regex,GRegexMatchFlags flags)3839 int vte_terminal_match_add_gregex(VteTerminal *terminal, GRegex *regex, GRegexMatchFlags flags) {
3840 /* XXX */
3841 void *p;
3842
3843 if ((p = realloc(PVT(terminal)->match_gregexes,
3844 sizeof(GRegex*) * (PVT(terminal)->num_match_gregexes + 1))) == NULL) {
3845 return 0;
3846 }
3847 PVT(terminal)->match_gregexes = p;
3848 PVT(terminal)->match_gregexes[PVT(terminal)->num_match_gregexes++] = regex;
3849 g_regex_ref(regex);
3850
3851 if (strstr(g_regex_get_pattern(regex), "http")) {
3852 /* tag == 1 */
3853 return 1;
3854 } else {
3855 /* tag == 0 */
3856 return 0;
3857 }
3858 }
3859 #endif
3860
vte_terminal_match_set_cursor(VteTerminal * terminal,int tag,GdkCursor * cursor)3861 void vte_terminal_match_set_cursor(VteTerminal *terminal, int tag, GdkCursor *cursor) {}
3862
vte_terminal_match_set_cursor_type(VteTerminal * terminal,int tag,GdkCursorType cursor_type)3863 void vte_terminal_match_set_cursor_type(VteTerminal *terminal, int tag, GdkCursorType cursor_type) {
3864 }
3865
vte_terminal_match_set_cursor_name(VteTerminal * terminal,int tag,const char * cursor_name)3866 void vte_terminal_match_set_cursor_name(VteTerminal *terminal, int tag, const char *cursor_name) {}
3867
3868 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_match_remove_all(VteTerminal * terminal)3869 void vte_terminal_match_remove_all(VteTerminal *terminal)
3870 #else
3871 void vte_terminal_match_clear_all(VteTerminal *terminal)
3872 #endif
3873 {
3874 #if GLIB_CHECK_VERSION(2, 14, 0)
3875 if (PVT(terminal)->match_gregexes) {
3876 u_int count;
3877
3878 for (count = 0; count < PVT(terminal)->num_match_gregexes; count++) {
3879 g_regex_unref(PVT(terminal)->match_gregexes[count]);
3880 }
3881 free(PVT(terminal)->match_gregexes);
3882 PVT(terminal)->match_gregexes = NULL;
3883 }
3884
3885 #if VTE_CHECK_VERSION(0, 46, 0)
3886 if (PVT(terminal)->match_vregexes) {
3887 u_int count;
3888
3889 for (count = 0; count < PVT(terminal)->num_match_vregexes; count++) {
3890 vte_regex_unref(PVT(terminal)->match_vregexes[count]);
3891 }
3892 free(PVT(terminal)->match_vregexes);
3893 PVT(terminal)->match_vregexes = NULL;
3894 }
3895 #endif
3896 #endif
3897 }
3898
vte_terminal_match_remove(VteTerminal * terminal,int tag)3899 void vte_terminal_match_remove(VteTerminal *terminal, int tag) {}
3900
vte_terminal_match_check(VteTerminal * terminal,glong column,glong row,int * tag)3901 char *vte_terminal_match_check(VteTerminal *terminal, glong column, glong row, int *tag) {
3902 ef_conv_t *conv;
3903 ef_parser_t *parser;
3904 u_char *buf;
3905 size_t len;
3906
3907 if (!vte_terminal_get_has_selection(terminal) ||
3908 !(conv = ui_get_selection_conv(1)) /* utf8 */ ||
3909 !(parser = vt_str_parser_new())) {
3910 return NULL;
3911 }
3912
3913 len = PVT(terminal)->screen->sel.sel_len * VTCHAR_UTF_MAX_SIZE + 1;
3914 if ((buf = g_malloc(len))) {
3915 (*parser->init)(parser);
3916 vt_str_parser_set_str(parser, PVT(terminal)->screen->sel.sel_str,
3917 PVT(terminal)->screen->sel.sel_len);
3918
3919 (*conv->init)(conv);
3920 *(buf + (*conv->convert)(conv, buf, len, parser)) = '\0';
3921
3922 /* XXX */
3923 if (tag) {
3924 *tag = 1; /* For pattern including "http" (see vte_terminal_match_add_gregex) */
3925 }
3926 }
3927
3928 (*parser->destroy)(parser);
3929
3930 return buf;
3931 }
3932
3933 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_match_check_event(VteTerminal * terminal,GdkEvent * event,int * tag)3934 char *vte_terminal_match_check_event(VteTerminal *terminal, GdkEvent *event, int *tag) {
3935 return NULL;
3936 }
3937 #endif
3938
3939 #if GLIB_CHECK_VERSION(2, 14, 0)
3940 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_search_set_gregex(VteTerminal * terminal,GRegex * regex,GRegexMatchFlags flags)3941 void vte_terminal_search_set_gregex(VteTerminal *terminal, GRegex *regex, GRegexMatchFlags flags)
3942 #else
3943 void vte_terminal_search_set_gregex(VteTerminal *terminal, GRegex *regex)
3944 #endif
3945 {
3946 if (regex) {
3947 if (!PVT(terminal)->gregex) {
3948 vt_term_search_init(PVT(terminal)->term, -1, -1, match_gregex);
3949 }
3950 } else {
3951 vt_term_search_final(PVT(terminal)->term);
3952 }
3953
3954 PVT(terminal)->gregex = regex;
3955 }
3956
vte_terminal_search_get_gregex(VteTerminal * terminal)3957 GRegex *vte_terminal_search_get_gregex(VteTerminal *terminal) { return PVT(terminal)->gregex; }
3958
vte_terminal_search_find_previous(VteTerminal * terminal)3959 gboolean vte_terminal_search_find_previous(VteTerminal *terminal) {
3960 return search_find(terminal, 1);
3961 }
3962
vte_terminal_search_find_next(VteTerminal * terminal)3963 gboolean vte_terminal_search_find_next(VteTerminal *terminal) { return search_find(terminal, 0); }
3964 #endif /* VTE_CHECK_VERSION(0, 40, 0) */
3965
3966 #if VTE_CHECK_VERSION(0, 44, 0)
vte_terminal_event_check_gregex_simple(VteTerminal * terminal,GdkEvent * event,GRegex ** regexes,gsize n_regexes,GRegexMatchFlags match_flags,char ** matches)3967 gboolean vte_terminal_event_check_gregex_simple(VteTerminal *terminal, GdkEvent *event,
3968 GRegex **regexes, gsize n_regexes,
3969 GRegexMatchFlags match_flags, char **matches) {
3970 return FALSE;
3971 }
3972 #endif
3973
vte_terminal_search_set_wrap_around(VteTerminal * terminal,gboolean wrap_around)3974 void vte_terminal_search_set_wrap_around(VteTerminal *terminal, gboolean wrap_around) {}
3975
vte_terminal_search_get_wrap_around(VteTerminal * terminal)3976 gboolean vte_terminal_search_get_wrap_around(VteTerminal *terminal) { return FALSE; }
3977
3978 #if VTE_CHECK_VERSION(0, 28, 0)
vte_get_user_shell(void)3979 char *vte_get_user_shell(void) { return NULL; }
3980 #endif
3981
3982 #if VTE_CHECK_VERSION(0, 44, 0)
vte_get_features(void)3983 const char *vte_get_features(void) { return "-GNUTLS"; }
3984 #endif
3985
3986 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_emulation(VteTerminal * terminal,const char * emulation)3987 void vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation) {}
3988
vte_terminal_get_emulation(VteTerminal * terminal)3989 const char *vte_terminal_get_emulation(VteTerminal *terminal) { return main_config.term_type; }
3990
vte_terminal_get_default_emulation(VteTerminal * terminal)3991 const char *vte_terminal_get_default_emulation(VteTerminal *terminal) {
3992 return main_config.term_type;
3993 }
3994 #endif
3995
3996 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_encoding(VteTerminal * terminal,const char * codeset,GError ** error)3997 gboolean vte_terminal_set_encoding(VteTerminal *terminal, const char *codeset, GError **error)
3998 #else
3999 void vte_terminal_set_encoding(VteTerminal *terminal, const char *codeset)
4000 #endif
4001 {
4002 if (codeset == NULL) {
4003 codeset = "AUTO";
4004 }
4005
4006 if (GTK_WIDGET_REALIZED(GTK_WIDGET(terminal))) {
4007 ui_screen_set_config(PVT(terminal)->screen, NULL, "encoding", codeset);
4008 } else {
4009 vt_term_change_encoding(PVT(terminal)->term, vt_get_char_encoding(codeset));
4010 }
4011
4012 #if VTE_CHECK_VERSION(0, 38, 0)
4013 if (error) {
4014 *error = NULL;
4015 }
4016 #endif
4017
4018 g_signal_emit_by_name(terminal, "encoding-changed");
4019
4020 #if VTE_CHECK_VERSION(0, 38, 0)
4021 return TRUE;
4022 #endif
4023 }
4024
vte_terminal_get_encoding(VteTerminal * terminal)4025 const char *vte_terminal_get_encoding(VteTerminal *terminal) {
4026 return vt_get_char_encoding_name(vt_term_get_encoding(PVT(terminal)->term));
4027 }
4028
4029 #if VTE_CHECK_VERSION(0, 24, 0)
4030 gboolean
4031 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_write_contents_sync(VteTerminal * terminal,GOutputStream * stream,VteWriteFlags flags,GCancellable * cancellable,GError ** error)4032 vte_terminal_write_contents_sync(VteTerminal *terminal, GOutputStream *stream, VteWriteFlags flags,
4033 GCancellable *cancellable, GError **error)
4034 #else
4035 vte_terminal_write_contents(VteTerminal *terminal, GOutputStream *stream,
4036 VteTerminalWriteFlags flags, GCancellable *cancellable, GError **error)
4037 #endif
4038 {
4039 char cmd[] = "snapshot vtetmp UTF8";
4040 char *path;
4041 gboolean ret;
4042
4043 vt_term_exec_cmd(PVT(terminal)->term, cmd);
4044
4045 if (error) {
4046 *error = NULL;
4047 }
4048
4049 ret = TRUE;
4050
4051 if ((path = bl_get_user_rc_path("mlterm/vtetmp.snp"))) {
4052 FILE *fp;
4053
4054 if ((fp = fopen(path, "r"))) {
4055 char buf[10240];
4056 size_t len;
4057
4058 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
4059 gsize bytes_written;
4060
4061 if (!g_output_stream_write_all(stream, buf, len, &bytes_written, cancellable, error)) {
4062 ret = FALSE;
4063 break;
4064 }
4065 }
4066
4067 fclose(fp);
4068 unlink(path);
4069 }
4070
4071 free(path);
4072 }
4073
4074 return ret;
4075 }
4076 #endif
4077
4078 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_cjk_ambiguous_width(VteTerminal * terminal,int width)4079 void vte_terminal_set_cjk_ambiguous_width(VteTerminal *terminal, int width) {
4080 vt_term_set_config(PVT(terminal)->term, "col_size_of_width_a", width == 2 ? "2" : "1");
4081 }
4082
vte_terminal_get_cjk_ambiguous_width(VteTerminal * terminal)4083 int vte_terminal_get_cjk_ambiguous_width(VteTerminal *terminal) {
4084 return PVT(terminal)->term->parser->col_size_of_width_a;
4085 }
4086 #endif
4087
4088 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_get_status_line(VteTerminal * terminal)4089 const char *vte_terminal_get_status_line(VteTerminal *terminal) { return ""; }
4090
vte_terminal_get_padding(VteTerminal * terminal,int * xpad,int * ypad)4091 void vte_terminal_get_padding(VteTerminal *terminal, int *xpad, int *ypad) {
4092 *xpad = PVT(terminal)->screen->window.hmargin * 2 /* left + right */;
4093 *ypad = PVT(terminal)->screen->window.vmargin * 2 /* top + bottom */;
4094 }
4095
vte_terminal_set_pty(VteTerminal * terminal,int pty_master)4096 void vte_terminal_set_pty(VteTerminal *terminal, int pty_master) {}
4097
vte_terminal_get_pty(VteTerminal * terminal)4098 int vte_terminal_get_pty(VteTerminal *terminal) {
4099 return vt_term_get_master_fd(PVT(terminal)->term);
4100 }
4101
vte_terminal_get_adjustment(VteTerminal * terminal)4102 GtkAdjustment *vte_terminal_get_adjustment(VteTerminal *terminal) { return ADJUSTMENT(terminal); }
4103 #endif
4104
vte_terminal_get_char_width(VteTerminal * terminal)4105 glong vte_terminal_get_char_width(VteTerminal *terminal) { return CHAR_WIDTH(terminal); }
4106
vte_terminal_get_char_height(VteTerminal * terminal)4107 glong vte_terminal_get_char_height(VteTerminal *terminal) { return CHAR_HEIGHT(terminal); }
4108
vte_terminal_get_row_count(VteTerminal * terminal)4109 glong vte_terminal_get_row_count(VteTerminal *terminal) { return ROW_COUNT(terminal); }
4110
vte_terminal_get_column_count(VteTerminal * terminal)4111 glong vte_terminal_get_column_count(VteTerminal *terminal) { return COLUMN_COUNT(terminal); }
4112
vte_terminal_get_window_title(VteTerminal * terminal)4113 const char *vte_terminal_get_window_title(VteTerminal *terminal) {
4114 return WINDOW_TITLE(terminal);
4115 }
4116
vte_terminal_get_icon_title(VteTerminal * terminal)4117 const char *vte_terminal_get_icon_title(VteTerminal *terminal) { return ICON_TITLE(terminal); }
4118
vte_terminal_get_child_exit_status(VteTerminal * terminal)4119 int vte_terminal_get_child_exit_status(VteTerminal *terminal) { return 0; }
4120
4121 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_cursor_blinks(VteTerminal * terminal,gboolean blink)4122 void vte_terminal_set_cursor_blinks(VteTerminal *terminal, gboolean blink) {
4123 ui_screen_set_config(PVT(terminal)->screen, NULL, "blink_cursor", blink ? "true" : "false");
4124 }
4125
vte_terminal_get_using_xft(VteTerminal * terminal)4126 gboolean vte_terminal_get_using_xft(VteTerminal *terminal) {
4127 if (ui_get_type_engine(PVT(terminal)->screen->font_man) == TYPE_XFT) {
4128 return TRUE;
4129 } else {
4130 return FALSE;
4131 }
4132 }
4133
vte_terminal_match_add(VteTerminal * terminal,const char * match)4134 int vte_terminal_match_add(VteTerminal *terminal, const char *match) { return 1; }
4135
vte_terminal_get_char_descent(VteTerminal * terminal)4136 glong vte_terminal_get_char_descent(VteTerminal *terminal) { return terminal->char_descent; }
4137
vte_terminal_get_char_ascent(VteTerminal * terminal)4138 glong vte_terminal_get_char_ascent(VteTerminal *terminal) { return terminal->char_ascent; }
4139
set_anti_alias(VteTerminal * terminal,VteTerminalAntiAlias antialias)4140 static void set_anti_alias(VteTerminal *terminal, VteTerminalAntiAlias antialias) {
4141 char *value;
4142 int term_is_null;
4143
4144 if (antialias == VTE_ANTI_ALIAS_FORCE_ENABLE) {
4145 value = "true";
4146 } else if (antialias == VTE_ANTI_ALIAS_FORCE_ENABLE) {
4147 value = "false";
4148 } else {
4149 return;
4150 }
4151
4152 /*
4153 * XXX
4154 * Hack for the case of calling this function before fork pty because
4155 * change_font_present() in ui_screen.c calls vt_term_get_vertical_mode().
4156 */
4157 if (PVT(terminal)->screen->term == NULL) {
4158 PVT(terminal)->screen->term = PVT(terminal)->term;
4159 term_is_null = 1;
4160 } else {
4161 term_is_null = 0;
4162 }
4163
4164 ui_screen_set_config(PVT(terminal)->screen, NULL, "use_anti_alias", value);
4165
4166 if (term_is_null) {
4167 PVT(terminal)->screen->term = NULL;
4168 }
4169 }
4170
vte_terminal_set_font_full(VteTerminal * terminal,const PangoFontDescription * font_desc,VteTerminalAntiAlias antialias)4171 void vte_terminal_set_font_full(VteTerminal *terminal, const PangoFontDescription *font_desc,
4172 VteTerminalAntiAlias antialias) {
4173 set_anti_alias(terminal, antialias);
4174 vte_terminal_set_font(terminal, font_desc);
4175 }
4176
vte_terminal_set_font_from_string_full(VteTerminal * terminal,const char * name,VteTerminalAntiAlias antialias)4177 void vte_terminal_set_font_from_string_full(VteTerminal *terminal, const char *name,
4178 VteTerminalAntiAlias antialias) {
4179 set_anti_alias(terminal, antialias);
4180 vte_terminal_set_font_from_string(terminal, name);
4181 }
4182 #endif
4183
4184 #if VTE_CHECK_VERSION(0, 26, 0)
4185
4186 #include <sys/ioctl.h>
4187 #include <vt_pty_intern.h> /* XXX in order to operate vt_pty_t::child_pid directly. */
4188 #include <pobl/bl_config.h> /* HAVE_SETSID */
4189
4190 struct _VtePty {
4191 GObject parent_instance;
4192
4193 VteTerminal *terminal;
4194 VtePtyFlags flags;
4195 };
4196
4197 struct _VtePtyClass {
4198 GObjectClass parent_class;
4199 };
4200
4201 G_DEFINE_TYPE(VtePty, vte_pty, G_TYPE_OBJECT);
4202
vte_pty_init(VtePty * pty)4203 static void vte_pty_init(VtePty *pty) {}
4204
vte_pty_class_init(VtePtyClass * kclass)4205 static void vte_pty_class_init(VtePtyClass *kclass) {}
4206
4207 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_pty_new_sync(VteTerminal * terminal,VtePtyFlags flags,GCancellable * cancellable,GError ** error)4208 VtePty *vte_terminal_pty_new_sync(VteTerminal *terminal, VtePtyFlags flags,
4209 GCancellable *cancellable, GError **error) {
4210 VtePty *pty;
4211
4212 if (error) {
4213 *error = NULL;
4214 }
4215
4216 if (PVT(terminal)->pty) {
4217 return PVT(terminal)->pty;
4218 }
4219
4220 if (!(pty = vte_pty_new_sync(flags, cancellable, error))) {
4221 return NULL;
4222 }
4223
4224 vte_terminal_set_pty(terminal, pty);
4225
4226 return pty;
4227 }
4228 #else
vte_terminal_pty_new(VteTerminal * terminal,VtePtyFlags flags,GError ** error)4229 VtePty *vte_terminal_pty_new(VteTerminal *terminal, VtePtyFlags flags, GError **error) {
4230 VtePty *pty;
4231
4232 if (error) {
4233 *error = NULL;
4234 }
4235
4236 if (PVT(terminal)->pty) {
4237 return PVT(terminal)->pty;
4238 }
4239
4240 if (!(pty = vte_pty_new(flags, error))) {
4241 return NULL;
4242 }
4243
4244 vte_terminal_set_pty_object(terminal, pty);
4245
4246 return pty;
4247 }
4248 #endif
4249
4250 #if !VTE_CHECK_VERSION(0, 38, 0)
vte_pty_set_term(VtePty * pty,const char * emulation)4251 void vte_pty_set_term(VtePty *pty, const char *emulation) {
4252 if (pty->terminal) {
4253 vte_terminal_set_emulation(pty->terminal, emulation);
4254 }
4255 }
4256 #endif
4257
4258 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_get_pty(VteTerminal * terminal)4259 VtePty *vte_terminal_get_pty(VteTerminal *terminal)
4260 #else
4261 VtePty *vte_terminal_get_pty_object(VteTerminal *terminal)
4262 #endif
4263 {
4264 return PVT(terminal)->pty;
4265 }
4266
4267 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_pty(VteTerminal * terminal,VtePty * pty)4268 void vte_terminal_set_pty(VteTerminal *terminal, VtePty *pty)
4269 #else
4270 void vte_terminal_set_pty_object(VteTerminal *terminal, VtePty *pty)
4271 #endif
4272 {
4273 pid_t pid;
4274
4275 if (PVT(terminal)->pty || !pty) {
4276 return;
4277 }
4278
4279 pty->terminal = terminal;
4280 PVT(terminal)->pty = g_object_ref(pty);
4281
4282 #if !VTE_CHECK_VERSION(0, 38, 0)
4283 vte_pty_set_term(pty, vte_terminal_get_emulation(terminal));
4284 #endif
4285
4286 pid = vte_terminal_forkpty(terminal, NULL, NULL, (pty->flags & VTE_PTY_NO_LASTLOG) ? FALSE : TRUE,
4287 (pty->flags & VTE_PTY_NO_UTMP) ? FALSE : TRUE,
4288 (pty->flags & VTE_PTY_NO_WTMP) ? FALSE : TRUE);
4289
4290 if (pid == 0) {
4291 /* Child process exits, but master and slave fds survives. */
4292 exit(0);
4293 }
4294
4295 #if 1
4296 if (pid > 0) {
4297 waitpid(pid, NULL, WNOHANG);
4298 }
4299 #else
4300 if (PVT(terminal)->term->pty) {
4301 /* Don't catch exit(0) above. */
4302 PVT(terminal)->term->pty->child_pid = -1;
4303 }
4304 #endif
4305 }
4306
4307 VtePty *
4308 #if VTE_CHECK_VERSION(0, 38, 0)
vte_pty_new_sync(VtePtyFlags flags,GCancellable * cancellable,GError ** error)4309 vte_pty_new_sync(VtePtyFlags flags, GCancellable *cancellable, GError **error)
4310 #else
4311 vte_pty_new(VtePtyFlags flags, GError **error)
4312 #endif
4313 {
4314 VtePty *pty;
4315
4316 if ((pty = g_object_new(VTE_TYPE_PTY, NULL))) {
4317 pty->flags = flags;
4318 pty->terminal = NULL;
4319 }
4320
4321 if (error) {
4322 *error = NULL;
4323 }
4324
4325 return pty;
4326 }
4327
4328 VtePty *
4329 #if VTE_CHECK_VERSION(0, 38, 0)
vte_pty_new_foreign_sync(int fd,GCancellable * cancellable,GError ** error)4330 vte_pty_new_foreign_sync(int fd, GCancellable *cancellable, GError **error)
4331 #else
4332 vte_pty_new_foreign(int fd, GError **error)
4333 #endif
4334 {
4335 if (error) {
4336 error = NULL;
4337 }
4338
4339 return NULL;
4340 }
4341
vte_pty_close(VtePty * pty)4342 void vte_pty_close(VtePty *pty) {}
4343
4344 #if VTE_CHECK_VERSION(0, 48, 0)
vte_pty_spawn_async(VtePty * pty,const char * working_directory,char ** argv,char ** envv,GSpawnFlags spawn_flags,GSpawnChildSetupFunc child_setup,gpointer child_setup_data,GDestroyNotify child_setup_data_destroy,int timeout,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)4345 void vte_pty_spawn_async(VtePty *pty, const char *working_directory, char **argv,
4346 char **envv, GSpawnFlags spawn_flags,
4347 GSpawnChildSetupFunc child_setup, gpointer child_setup_data,
4348 GDestroyNotify child_setup_data_destroy, int timeout,
4349 GCancellable *cancellable, GAsyncReadyCallback callback,
4350 gpointer user_data) {}
4351
vte_pty_spawn_finish(VtePty * pty,GAsyncResult * result,GPid * child_pid,GError ** error)4352 gboolean vte_pty_spawn_finish(VtePty *pty, GAsyncResult *result, GPid *child_pid, GError **error) {
4353 if (error) {
4354 *error = NULL;
4355 }
4356
4357 return FALSE;
4358 }
4359
4360 #endif
4361
4362 #if (!defined(HAVE_SETSID) && defined(TIOCNOTTY)) || !defined(TIOCSCTTY)
4363 #include <fcntl.h>
4364 #endif
4365
4366 /* Child process (before exec()) */
vte_pty_child_setup(VtePty * pty)4367 void vte_pty_child_setup(VtePty *pty) {
4368 int slave;
4369 int master;
4370 #if (!defined(HAVE_SETSID) && defined(TIOCNOTTY)) || !defined(TIOCSCTTY)
4371 int fd;
4372 #endif
4373
4374 if (!pty->terminal) {
4375 return;
4376 }
4377
4378 #ifdef HAVE_SETSID
4379 setsid();
4380 #else
4381 #ifdef TIOCNOTTY
4382 if ((fd = open("/dev/tty", O_RDWR | O_NOCTTY)) >= 0) {
4383 ioctl(fd, TIOCNOTTY, NULL);
4384 close(fd);
4385 }
4386 #endif
4387 #endif
4388
4389 master = vt_term_get_master_fd(PVT(pty->terminal)->term);
4390 slave = vt_term_get_slave_fd(PVT(pty->terminal)->term);
4391
4392 #ifdef TIOCSCTTY
4393 while (ioctl(slave, TIOCSCTTY, NULL) == -1) {
4394 /*
4395 * Child process which exits in vte_terminal_set_pty() may still have
4396 * controll terminal.
4397 */
4398 bl_usleep(100);
4399 }
4400 #else
4401 if ((fd = open("/dev/tty", O_RDWR | O_NOCTTY)) >= 0) {
4402 close(fd);
4403 }
4404 if ((fd = open(ptsname(master), O_RDWR)) >= 0) {
4405 close(fd);
4406 }
4407 if ((fd = open("/dev/tty", O_WRONLY)) >= 0) {
4408 close(fd);
4409 }
4410 #endif
4411
4412 dup2(slave, 0);
4413 dup2(slave, 1);
4414 dup2(slave, 2);
4415
4416 if (slave > STDERR_FILENO) {
4417 close(slave);
4418 }
4419
4420 close(master);
4421 }
4422
vte_pty_get_fd(VtePty * pty)4423 int vte_pty_get_fd(VtePty *pty) {
4424 /*
4425 * XXX
4426 * sakura 3.6.0 calls vte_pty_get_fd(NULL) if "Close tab" of right-click menu is selected.
4427 * (This is because vte_pty_get_pty() in this file can return NULL.)
4428 */
4429 if (!pty || !pty->terminal) {
4430 return -1;
4431 }
4432
4433 return vt_term_get_master_fd(PVT(pty->terminal)->term);
4434 }
4435
vte_pty_set_size(VtePty * pty,int rows,int columns,GError ** error)4436 gboolean vte_pty_set_size(VtePty *pty, int rows, int columns, GError **error) {
4437 if (error) {
4438 *error = NULL;
4439 }
4440
4441 if (!pty->terminal) {
4442 return FALSE;
4443 }
4444
4445 vte_terminal_set_size(pty->terminal, columns, rows);
4446
4447 return TRUE;
4448 }
4449
vte_pty_get_size(VtePty * pty,int * rows,int * columns,GError ** error)4450 gboolean vte_pty_get_size(VtePty *pty, int *rows, int *columns, GError **error) {
4451 if (error) {
4452 *error = NULL;
4453 }
4454
4455 if (!pty->terminal) {
4456 return FALSE;
4457 }
4458
4459 *columns = COLUMN_COUNT(pty->terminal);
4460 *rows = ROW_COUNT(pty->terminal);
4461
4462 return TRUE;
4463 }
4464
vte_pty_set_utf8(VtePty * pty,gboolean utf8,GError ** error)4465 gboolean vte_pty_set_utf8(VtePty *pty, gboolean utf8, GError **error) {
4466 if (error) {
4467 *error = NULL;
4468 }
4469
4470 if (!pty->terminal) {
4471 return FALSE;
4472 }
4473
4474 return vt_term_change_encoding(PVT(pty->terminal)->term,
4475 utf8 ? VT_UTF8 : vt_get_char_encoding("auto"));
4476 }
4477
vte_terminal_watch_child(VteTerminal * terminal,GPid child_pid)4478 void vte_terminal_watch_child(VteTerminal *terminal, GPid child_pid) {
4479 vte_reaper_add_child(child_pid);
4480
4481 if (PVT(terminal)->term->pty) {
4482 PVT(terminal)->term->pty->child_pid = child_pid;
4483 }
4484 }
4485
4486 #endif
4487
4488 #if VTE_CHECK_VERSION(0, 38, 0)
vte_terminal_set_input_enabled(VteTerminal * terminal,gboolean enabled)4489 void vte_terminal_set_input_enabled(VteTerminal *terminal, gboolean enabled) {}
4490
vte_terminal_get_input_enabled(VteTerminal * terminal)4491 gboolean vte_terminal_get_input_enabled(VteTerminal *terminal) { return TRUE; }
4492
vte_terminal_get_geometry_hints(VteTerminal * terminal,GdkGeometry * hints,int min_rows,int min_columns)4493 void vte_terminal_get_geometry_hints(VteTerminal *terminal, GdkGeometry *hints, int min_rows,
4494 int min_columns) {
4495 hints->base_width = PVT(terminal)->screen->window.hmargin * 2;
4496 hints->base_height = PVT(terminal)->screen->window.vmargin * 2;
4497 hints->width_inc = CHAR_WIDTH(terminal);
4498 hints->height_inc = CHAR_HEIGHT(terminal);
4499 hints->min_width = hints->base_width + hints->width_inc * min_columns;
4500 hints->min_height = hints->base_height + hints->height_inc * min_rows;
4501 }
4502
vte_terminal_set_geometry_hints_for_window(VteTerminal * terminal,GtkWindow * window)4503 void vte_terminal_set_geometry_hints_for_window(VteTerminal *terminal, GtkWindow *window) {
4504 GdkGeometry hints;
4505
4506 vte_terminal_get_geometry_hints(terminal, &hints, 1, 1);
4507 gtk_window_set_geometry_hints(window,
4508 #if GTK_CHECK_VERSION(3, 19, 5)
4509 NULL,
4510 #else
4511 GTK_WIDGET(terminal),
4512 #endif
4513 &hints,
4514 (GdkWindowHints)(GDK_HINT_RESIZE_INC |
4515 GDK_HINT_MIN_SIZE |
4516 GDK_HINT_BASE_SIZE));
4517 }
4518 #endif
4519
4520 #if VTE_CHECK_VERSION(0, 62, 0)
vte_get_feature_flags(void)4521 VteFeatureFlags vte_get_feature_flags(void) {
4522 return
4523 #if 1
4524 VTE_FEATURE_FLAG_BIDI |
4525 #endif
4526 #if 0
4527 VTE_FEATURE_FLAG_ICU |
4528 #endif
4529 #if 0
4530 VTE_FEATURE_FLAG_SYSTEMD
4531 #endif
4532 0;
4533 }
4534 #endif
4535
4536 #if VTE_CHECK_VERSION(0, 39, 0)
vte_get_major_version(void)4537 guint vte_get_major_version(void) { return VTE_MAJOR_VERSION; }
4538
vte_get_minor_version(void)4539 guint vte_get_minor_version(void) { return VTE_MINOR_VERSION; }
4540
vte_get_micro_version(void)4541 guint vte_get_micro_version(void) { return VTE_MICRO_VERSION; }
4542 #endif
4543
4544 #if VTE_CHECK_VERSION(0, 34, 0)
vte_terminal_get_current_directory_uri(VteTerminal * terminal)4545 const char *vte_terminal_get_current_directory_uri(VteTerminal *terminal) { return NULL; }
4546
vte_terminal_get_current_file_uri(VteTerminal * terminal)4547 const char *vte_terminal_get_current_file_uri(VteTerminal *terminal) { return NULL; }
4548 #endif
4549
4550 /* Ubuntu original function ? */
vte_terminal_set_alternate_screen_scroll(VteTerminal * terminal,gboolean scroll)4551 void vte_terminal_set_alternate_screen_scroll(VteTerminal *terminal, gboolean scroll) {}
4552
4553 /* Hack for input method module */
4554
4555 static GIOChannel *gio;
4556 static guint src_id;
4557
ui_event_source_add_fd(int fd,void (* handler)(void))4558 int ui_event_source_add_fd(int fd, void (*handler)(void)) {
4559 if (gio) {
4560 #ifdef DEBUG
4561 bl_debug_printf(BL_DEBUG_TAG " ui_event_source_add_fd failed\n");
4562 #endif
4563
4564 return 0;
4565 }
4566
4567 gio = g_io_channel_unix_new(fd);
4568 src_id = g_io_add_watch(gio, G_IO_IN, (GIOFunc)handler, NULL);
4569
4570 return 1;
4571 }
4572
ui_event_source_remove_fd(int fd)4573 int ui_event_source_remove_fd(int fd) {
4574 if (gio && g_io_channel_unix_get_fd(gio) == fd) {
4575 g_source_destroy(g_main_context_find_source_by_id(NULL, src_id));
4576 g_io_channel_unref(gio);
4577
4578 gio = NULL;
4579 }
4580
4581 return 1;
4582 }
4583
4584 /*
4585 * GTK+-3.0 supports XInput2 which enables multi device.
4586 * But XInput2 disables popup menu and shortcut key which applications
4587 * using libvte show, because mlterm doesn't support it.
4588 * So multi device is disabled for now.
4589 *
4590 * __attribute__((constructor)) hack is necessary because
4591 * gdk_disable_multidevice() must be called before gtk_init().
4592 */
4593 #if GTK_CHECK_VERSION(2, 90, 0) && __GNUC__
init_vte(void)4594 static void __attribute__((constructor)) init_vte(void) {
4595 #if 0
4596 setenv("GDK_CORE_DEVICE_EVENTS", "1", 1);
4597 #else
4598 gdk_disable_multidevice();
4599 #endif
4600 }
4601 #endif
4602
4603 #if VTE_CHECK_VERSION(0, 46, 0)
vte_regex_ref(VteRegex * regex)4604 VteRegex *vte_regex_ref(VteRegex *regex) {
4605 g_return_val_if_fail(regex, NULL);
4606
4607 g_atomic_int_inc(®ex->ref_count);
4608
4609 return regex;
4610 }
4611
vte_regex_unref(VteRegex * regex)4612 VteRegex *vte_regex_unref(VteRegex *regex) {
4613 g_return_val_if_fail(regex, NULL);
4614
4615 if (g_atomic_int_dec_and_test(®ex->ref_count)) {
4616 g_regex_unref(regex->gregex);
4617 g_slice_free(VteRegex, regex);
4618 }
4619
4620 return NULL;
4621 }
4622
vte_regex_new_for_match(const char * pattern,gssize pattern_length,guint32 flags,GError ** error)4623 VteRegex *vte_regex_new_for_match(const char *pattern, gssize pattern_length,
4624 guint32 flags, GError **error) {
4625 VteRegex *regex = g_slice_new(VteRegex);
4626 regex->ref_count = 1;
4627 regex->gregex = g_regex_new(pattern, 0, 0, error);
4628
4629 return regex;
4630 }
4631
vte_regex_new_for_search(const char * pattern,gssize pattern_length,guint32 flags,GError ** error)4632 VteRegex *vte_regex_new_for_search(const char *pattern, gssize pattern_length,
4633 guint32 flags, GError **error) {
4634 VteRegex *regex = g_slice_new(VteRegex);
4635 regex->ref_count = 1;
4636 regex->gregex = g_regex_new(pattern, 0, 0, error);
4637
4638 return regex;
4639 }
4640
vte_regex_jit(VteRegex * regex,guint32 flags,GError ** error)4641 gboolean vte_regex_jit(VteRegex *regex, guint32 flags, GError **error) {
4642 if (error) {
4643 *error = NULL;
4644 }
4645
4646 return TRUE;
4647 }
4648
vte_terminal_match_add_regex(VteTerminal * terminal,VteRegex * regex,guint32 flags)4649 int vte_terminal_match_add_regex(VteTerminal *terminal, VteRegex *regex, guint32 flags) {
4650 /* XXX */
4651 void *p;
4652
4653 if ((p = realloc(PVT(terminal)->match_vregexes,
4654 sizeof(VteRegex*) * (PVT(terminal)->num_match_vregexes + 1))) == NULL) {
4655 return 0;
4656 }
4657 PVT(terminal)->match_vregexes = p;
4658 PVT(terminal)->match_vregexes[PVT(terminal)->num_match_vregexes++] = regex;
4659 vte_regex_ref(regex);
4660
4661 if (strstr(g_regex_get_pattern(regex->gregex), "http")) {
4662 /* tag == 1 */
4663 return 1;
4664 } else {
4665 /* tag == 0 */
4666 return 0;
4667 }
4668 }
4669
vte_terminal_event_check_regex_simple(VteTerminal * terminal,GdkEvent * event,VteRegex ** regexes,gsize n_regexes,guint32 match_flags,char ** matches)4670 gboolean vte_terminal_event_check_regex_simple(VteTerminal *terminal, GdkEvent *event,
4671 VteRegex **regexes, gsize n_regexes,
4672 guint32 match_flags, char **matches) {
4673 return FALSE;
4674 }
4675
vte_terminal_search_set_regex(VteTerminal * terminal,VteRegex * regex,guint32 flags)4676 void vte_terminal_search_set_regex(VteTerminal *terminal, VteRegex *regex, guint32 flags) {
4677 if (regex) {
4678 if (!PVT(terminal)->vregex) {
4679 vt_term_search_init(PVT(terminal)->term, -1, -1, match_vteregex);
4680 }
4681 vte_regex_ref(regex);
4682 } else {
4683 vt_term_search_final(PVT(terminal)->term);
4684 if (PVT(terminal)->vregex) {
4685 vte_regex_unref(PVT(terminal)->vregex);
4686 }
4687 }
4688
4689 PVT(terminal)->vregex = regex;
4690 }
4691
vte_terminal_search_get_regex(VteTerminal * terminal)4692 VteRegex *vte_terminal_search_get_regex(VteTerminal *terminal) { return PVT(terminal)->vregex; }
4693 #endif
4694
4695 #if VTE_CHECK_VERSION(0, 50, 0)
vte_terminal_get_allow_hyperlink(VteTerminal * terminal)4696 gboolean vte_terminal_get_allow_hyperlink(VteTerminal *terminal) {
4697 return FALSE;
4698 }
4699
vte_terminal_set_allow_hyperlink(VteTerminal * terminal,gboolean allow_hyperlink)4700 void vte_terminal_set_allow_hyperlink(VteTerminal *terminal, gboolean allow_hyperlink) {}
4701
vte_terminal_hyperlink_check_event(VteTerminal * terminal,GdkEvent * event)4702 char *vte_terminal_hyperlink_check_event(VteTerminal *terminal, GdkEvent *event) { return NULL; }
4703 #endif
4704
4705 #if VTE_CHECK_VERSION(0, 62, 0)
vte_terminal_event_check_regex_array(VteTerminal * terminal,GdkEvent * event,VteRegex ** regexes,gsize n_regexes,guint32 match_flags,gsize * n_matches)4706 char **vte_terminal_event_check_regex_array(VteTerminal *terminal,
4707 GdkEvent *event,
4708 VteRegex **regexes,
4709 gsize n_regexes,
4710 guint32 match_flags,
4711 gsize *n_matches) {
4712 return NULL;
4713 }
4714 #endif
4715
4716 #if VTE_CHECK_VERSION(0, 52, 0)
vte_terminal_set_bold_is_bright(VteTerminal * terminal,gboolean bold_is_bright)4717 void vte_terminal_set_bold_is_bright(VteTerminal *terminal, gboolean bold_is_bright) {};
4718
vte_terminal_get_bold_is_bright(VteTerminal * terminal)4719 gboolean vte_terminal_get_bold_is_bright(VteTerminal *terminal) { return TRUE; };
4720
vte_terminal_set_cell_width_scale(VteTerminal * terminal,double scale)4721 void vte_terminal_set_cell_width_scale(VteTerminal *terminal, double scale) {};
4722
vte_terminal_get_cell_width_scale(VteTerminal * terminal)4723 double vte_terminal_get_cell_width_scale(VteTerminal *terminal) {
4724 return ui_col_width(PVT(terminal)->screen);
4725 }
4726
vte_terminal_set_cell_height_scale(VteTerminal * terminal,double scale)4727 void vte_terminal_set_cell_height_scale(VteTerminal *terminal, double scale) {};
4728
vte_terminal_get_cell_height_scale(VteTerminal * terminal)4729 double vte_terminal_get_cell_height_scale(VteTerminal *terminal) {
4730 return ui_line_height(PVT(terminal)->screen);
4731 }
4732
vte_terminal_set_text_blink_mode(VteTerminal * terminal,VteTextBlinkMode text_blink_mode)4733 void vte_terminal_set_text_blink_mode(VteTerminal *terminal,
4734 VteTextBlinkMode text_blink_mode) {}
4735
vte_terminal_get_text_blink_mode(VteTerminal * terminal)4736 VteTextBlinkMode vte_terminal_get_text_blink_mode(VteTerminal *terminal) {
4737 return VTE_TEXT_BLINK_FOCUSED;
4738 }
4739 #endif
4740
4741 #if VTE_CHECK_VERSION(0, 54, 0)
vte_set_test_flags(guint64 flags)4742 void vte_set_test_flags(guint64 flags) {}
4743
vte_terminal_get_color_background_for_draw(VteTerminal * terminal,GdkRGBA * color)4744 void vte_terminal_get_color_background_for_draw(VteTerminal* terminal, GdkRGBA* color) {}
4745 #endif
4746
4747 #if VTE_CHECK_VERSION(0, 62, 0)
vte_terminal_set_enable_sixel(VteTerminal * terminal,gboolean enabled)4748 void vte_terminal_set_enable_sixel(VteTerminal *terminal, gboolean enabled) {}
4749
vte_terminal_get_enable_sixel(VteTerminal * terminal)4750 gboolean vte_terminal_get_enable_sixel(VteTerminal *terminal) {
4751 return TRUE;
4752 }
4753 #endif
4754
4755 #if VTE_CHECK_VERSION(0, 56, 0)
vte_regex_substitute(VteRegex * regex,const char * subject,const char * replacement,guint32 flags,GError ** error)4756 char *vte_regex_substitute(VteRegex *regex, const char *subject, const char *replacement,
4757 guint32 flags, GError **error) {
4758 return NULL;
4759 }
4760 #endif
4761
4762 #if VTE_CHECK_VERSION(0, 58, 0)
vte_terminal_set_enable_bidi(VteTerminal * terminal,gboolean enable_bidi)4763 void vte_terminal_set_enable_bidi(VteTerminal *terminal, gboolean enable_bidi) {
4764 /* Prefer setting in ~/.mlterm/main. */
4765 #if 0
4766 if (PVT(terminal)->screen->term) {
4767 ui_screen_set_config(PVT(terminal)->screen, NULL, "use_ctl", enable_bidi ? "true" : "false");
4768 }
4769 #endif
4770 }
4771
vte_terminal_get_enable_bidi(VteTerminal * terminal)4772 gboolean vte_terminal_get_enable_bidi(VteTerminal *terminal) {
4773 if (vt_term_is_using_ctl(PVT(terminal)->screen->term)) {
4774 return TRUE;
4775 } else {
4776 return FALSE;
4777 }
4778 }
4779
vte_terminal_set_enable_shaping(VteTerminal * terminal,gboolean enable_shaping)4780 void vte_terminal_set_enable_shaping(VteTerminal *terminal, gboolean enable_shaping) {}
4781
vte_terminal_get_enable_shaping(VteTerminal * terminal)4782 gboolean vte_terminal_get_enable_shaping(VteTerminal *terminal) {
4783 return vte_terminal_get_enable_bidi(terminal);
4784 }
4785 #endif
4786
4787 #if VTE_CHECK_VERSION(0, 60, 0)
vte_get_encodings(gboolean include_aliases)4788 char **vte_get_encodings(gboolean include_aliases) {
4789 return calloc(1, sizeof(char*));
4790 }
4791
vte_get_encoding_supported(const char * encoding)4792 gboolean vte_get_encoding_supported(const char *encoding) {
4793 return FALSE;
4794 }
4795 #endif
4796