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(&regex->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(&regex->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