1 /*
2  * Copyright (C) 2001-2004 Red Hat, Inc.
3  *
4  * This library is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #pragma once
19 
20 /* BEGIN sanity checks */
21 
22 #ifndef __EXCEPTIONS
23 #error You MUST NOT use -fno-exceptions to build vte! Fix your build; and DO NOT file a bug upstream!
24 #endif
25 
26 #ifndef __GXX_RTTI
27 #error You MUST NOT use -fno-rtti to build vte! Fix your build system; and DO NOT file a bug upstream!
28 #endif
29 
30 /* END sanity checks */
31 
32 #include <glib.h>
33 #include "glib-glue.hh"
34 #include "pango-glue.hh"
35 
36 #include "debug.h"
37 #include "clipboard-gtk.hh"
38 #include "drawing-cairo.hh"
39 #include "vtedefines.hh"
40 #include "vtetypes.hh"
41 #include "reaper.hh"
42 #include "ring.hh"
43 #include "ringview.hh"
44 #include "buffer.h"
45 #include "parser.hh"
46 #include "parser-glue.hh"
47 #include "modes.hh"
48 #include "tabstops.hh"
49 #include "refptr.hh"
50 #include "fwd.hh"
51 
52 #include "pcre2-glue.hh"
53 #include "vteregexinternal.hh"
54 
55 #include "chunk.hh"
56 #include "pty.hh"
57 #include "utf8.hh"
58 
59 #include <list>
60 #include <queue>
61 #include <optional>
62 #include <string>
63 #include <variant>
64 #include <vector>
65 
66 #ifdef WITH_ICU
67 #include "icu-converter.hh"
68 #endif
69 
70 enum {
71         VTE_BIDI_FLAG_IMPLICIT   = 1 << 0,
72         VTE_BIDI_FLAG_RTL        = 1 << 1,
73         VTE_BIDI_FLAG_AUTO       = 1 << 2,
74         VTE_BIDI_FLAG_BOX_MIRROR = 1 << 3,
75         VTE_BIDI_FLAG_ALL        = (1 << 4) - 1,
76 };
77 
78 namespace vte {
79 
80 namespace platform {
81 
82 /*
83  * Cursor:
84  *
85  * Holds a platform cursor. This is either a named cursor (string),
86  * a reference to a GdkCursor*, or a cursor type.
87  */
88 using Cursor = std::variant<std::string,
89                             vte::glib::RefPtr<GdkCursor>,
90                             GdkCursorType>;
91 
92 } // namespace platform
93 } // namespace vte
94 
95 typedef enum _VteCharacterReplacement {
96         VTE_CHARACTER_REPLACEMENT_NONE,
97         VTE_CHARACTER_REPLACEMENT_LINE_DRAWING
98 } VteCharacterReplacement;
99 
100 typedef struct _VtePaletteColor {
101 	struct {
102 		vte::color::rgb color;
103 		gboolean is_set;
104 	} sources[2];
105 } VtePaletteColor;
106 
107 struct VteScreen {
108 public:
VteScreenVteScreen109         VteScreen(gulong max_rows,
110                   bool has_streams) :
111                 m_ring{max_rows, has_streams},
112                 row_data(&m_ring),
113                 cursor{0,0}
114         {
115         }
116 
117         vte::base::Ring m_ring; /* buffer contents */
118         VteRing* row_data;
119         VteVisualPosition cursor;  /* absolute value, from the beginning of the terminal history */
120         double scroll_delta{0.0}; /* scroll offset */
121         long insert_delta{0}; /* insertion offset */
122 
123         /* Stuff saved along with the cursor */
124         struct {
125                 VteVisualPosition cursor;  /* onscreen coordinate, that is, relative to insert_delta */
126                 uint8_t modes_ecma;
127                 bool reverse_mode;
128                 bool origin_mode;
129                 VteCell defaults;
130                 VteCell color_defaults;
131                 VteCharacterReplacement character_replacements[2];
132                 VteCharacterReplacement *character_replacement;
133         } saved;
134 };
135 
136 struct vte_scrolling_region {
137         int start, end;
138 };
139 
140 namespace vte {
141 
142 namespace platform {
143 class Widget;
144 enum class ClipboardType;
145 }
146 
147 namespace terminal {
148 
149 class Terminal {
150         friend class vte::platform::Widget;
151 
152 private:
153         class ProcessingContext;
154 
155         /* These correspond to the parameters for DECSCUSR (Set cursor style). */
156         enum class CursorStyle {
157                 /* We treat 0 and 1 differently, assuming that the VT510 does so too.
158                  *
159                  * See, according to the "VT510 Video Terminal Programmer Information",
160                  * from vt100.net, paragraph "2.5.7 Cursor Display", there was a menu
161                  * item in the "Terminal Set-Up" to set the cursor's style. It looks
162                  * like that defaulted to blinking block. So it makes sense for 0 to
163                  * mean "set cursor style to default (set by Set-Up)" and 1 to mean
164                  * "set cursor style to blinking block", since that default need not be
165                  * blinking block. Access to a VT510 is needed to test this theory,
166                  * but it seems plausible. And, anyhow, we can even decide we know
167                  * better than the VT510 designers!
168                  */
169                 eTERMINAL_DEFAULT = 0,
170                 eBLINK_BLOCK      = 1,
171                 eSTEADY_BLOCK     = 2,
172                 eBLINK_UNDERLINE  = 3,
173                 eSTEADY_UNDERLINE = 4,
174                 /* *_IBEAM are xterm extensions */
175                 eBLINK_IBEAM      = 5,
176                 eSTEADY_IBEAM     = 6,
177         };
178 
179         /* The order is important */
180         enum class MouseTrackingMode {
181 	        eNONE,
182                 eSEND_XY_ON_CLICK,
183                 eSEND_XY_ON_BUTTON,
184                 eHILITE_TRACKING,
185                 eCELL_MOTION_TRACKING,
186                 eALL_MOTION_TRACKING,
187         };
188 
189         enum class SelectionType {
190                eCHAR,
191                eWORD,
192                eLINE,
193         };
194 
195 protected:
196 
197         /* NOTE: This needs to be kept in sync with the public VteCursorBlinkMode enum */
198         enum class CursorBlinkMode {
199                 eSYSTEM,
200                 eON,
201                 eOFF
202         };
203 
204         /* NOTE: This needs to be kept in sync with the public VteCursorShape enum */
205         enum class CursorShape {
206                 eBLOCK,
207                 eIBEAM,
208                 eUNDERLINE
209         };
210 
211         /* NOTE: This needs to be kept in sync with the public VteEraseMode enum */
212         enum EraseMode {
213                 eAUTO,
214                 eASCII_BACKSPACE,
215                 eASCII_DELETE,
216                 eDELETE_SEQUENCE,
217                 eTTY,
218         };
219 
220         /* NOTE: This needs to be kept in sync with the public VteTextBlinkMode enum */
221         enum class TextBlinkMode {
222                 eNEVER     = 0,
223                 eFOCUSED   = 1,
224                 eUNFOCUSED = 2,
225                 eALWAYS    = 3
226         };
227 
228 public:
229         Terminal(vte::platform::Widget* w,
230                  VteTerminal *t);
231         ~Terminal();
232 
233 public:
234         vte::platform::Widget* m_real_widget{nullptr};
widget() const235         inline constexpr auto widget() const noexcept { return m_real_widget; }
236 
237         VteTerminal *m_terminal{nullptr};
vte_terminal() const238         inline constexpr auto vte_terminal() const noexcept { return m_terminal; }
239 
240         GtkWidget *m_widget{nullptr};
gtk_widget() const241         inline constexpr auto gtk_widget() const noexcept { return m_widget; }
242 
243         void unset_widget() noexcept;
244 
245         /* Metric and sizing data: dimensions of the window */
246         vte::grid::row_t m_row_count{VTE_ROWS};
247         vte::grid::column_t m_column_count{VTE_COLUMNS};
248 
249         vte::terminal::Tabstops m_tabstops{};
250 
251         vte::parser::Parser m_parser; /* control sequence state machine */
252 
253         vte::terminal::modes::ECMA m_modes_ecma{};
254         vte::terminal::modes::Private m_modes_private{};
255 
256 	/* PTY handling data. */
257         vte::base::RefPtr<vte::base::Pty> m_pty{};
pty() const258         inline constexpr auto& pty() const noexcept { return m_pty; }
259 
260         void unset_pty(bool notify_widget = true);
261         bool set_pty(vte::base::Pty* pty);
262 
263         guint m_pty_input_source{0};
264         guint m_pty_output_source{0};
265         bool m_pty_input_active{false};
266         pid_t m_pty_pid{-1};           /* pid of child process */
267         int m_child_exit_status{-1};   /* pid's exit status, or -1 */
268         bool m_eos_pending{false};
269         bool m_child_exited_after_eos_pending{false};
270         bool child_exited_eos_wait_callback();
271         vte::glib::Timer m_child_exited_eos_wait_timer{std::bind(&Terminal::child_exited_eos_wait_callback,
272                                                                  this),
273                                                        "child-exited-eos-wait-timer"};
274         VteReaper *m_reaper;
275 
276 	/* Queue of chunks of data read from the PTY.
277          * Chunks are inserted at the back, and processed from the front.
278          */
279         std::queue<vte::base::Chunk::unique_type, std::list<vte::base::Chunk::unique_type>> m_incoming_queue;
280 
281         vte::base::UTF8Decoder m_utf8_decoder;
282 
283         enum class DataSyntax {
284                 /* The primary data syntax is always one of the following: */
285                 ECMA48_UTF8,
286                 #ifdef WITH_ICU
287                 ECMA48_PCTERM,
288                 #endif
289                 /* ECMA48_ECMA35, not supported */
290 
291                 /* The following can never be primary data syntax: */
292         };
293 
294         DataSyntax m_primary_data_syntax{DataSyntax::ECMA48_UTF8};
295         DataSyntax m_current_data_syntax{DataSyntax::ECMA48_UTF8};
296 
primary_data_syntax() const297         auto primary_data_syntax() const noexcept { return m_primary_data_syntax; }
current_data_syntax() const298         auto current_data_syntax() const noexcept { return m_current_data_syntax; }
299 
push_data_syntax(DataSyntax syntax)300         void push_data_syntax(DataSyntax syntax) noexcept
301         {
302                 _vte_debug_print(VTE_DEBUG_IO, "Pushing data syntax %d -> %d\n",
303                                  int(m_current_data_syntax), int(syntax));
304                 m_current_data_syntax = syntax;
305         }
306 
pop_data_syntax()307         void pop_data_syntax() noexcept
308         {
309                 _vte_debug_print(VTE_DEBUG_IO, "Popping data syntax %d -> %d\n",
310                                  int(m_current_data_syntax), int(m_primary_data_syntax));
311                 m_current_data_syntax = m_primary_data_syntax;
312         }
313 
314         void reset_data_syntax();
315 
316         int m_utf8_ambiguous_width{VTE_DEFAULT_UTF8_AMBIGUOUS_WIDTH};
317         gunichar m_last_graphic_character{0}; /* for REP */
318         /* Array of dirty rectangles in view coordinates; need to
319          * add allocation origin and padding when passing to gtk.
320          */
321         GArray *m_update_rects;
322         bool m_invalidated_all{false};       /* pending refresh of entire terminal */
323         /* If non-nullptr, contains the GList element for @this in g_active_terminals
324          * and means that this terminal is processing data.
325          */
326         GList *m_active_terminals_link;
327         // FIXMEchpe should these two be g[s]size ?
328         size_t m_input_bytes;
329         long m_max_input_bytes{VTE_MAX_INPUT_READ};
330 
331 	/* Output data queue. */
332         VteByteArray *m_outgoing; /* pending input characters */
333 
334 #ifdef WITH_ICU
335         /* Legacy charset support */
336         std::unique_ptr<vte::base::ICUConverter> m_converter;
337 #endif /* WITH_ICU */
338 
encoding() const339         char const* encoding() const noexcept
340         {
341                 switch (primary_data_syntax()) {
342                 case DataSyntax::ECMA48_UTF8:   return "UTF-8";
343                 #ifdef WITH_ICU
344                 case DataSyntax::ECMA48_PCTERM: return m_converter->charset().c_str();
345                 #endif
346                 default: g_assert_not_reached(); return nullptr;
347                 }
348         }
349 
350 	/* Screen data.  We support the normal screen, and an alternate
351 	 * screen, which seems to be a DEC-specific feature. */
352         VteScreen m_normal_screen;
353         VteScreen m_alternate_screen;
354         VteScreen *m_screen; /* points to either m_normal_screen or m_alternate_screen */
355 
356         VteCell m_defaults;        /* Default characteristics for insertion of new characters:
357                                       colors (fore, back, deco) and other attributes (bold, italic,
358                                       explicit hyperlink etc.). */
359         VteCell m_color_defaults;  /* Default characteristics for erasing characters:
360                                       colors (fore, back, deco) but no other attributes,
361                                       and the U+0000 character that denotes erased cells. */
362 
363         /* charsets in the G0 and G1 slots */
364         VteCharacterReplacement m_character_replacements[2] = { VTE_CHARACTER_REPLACEMENT_NONE,
365                                                                 VTE_CHARACTER_REPLACEMENT_NONE };
366         /* pointer to the active one */
367         VteCharacterReplacement *m_character_replacement{&m_character_replacements[0]};
368 
369         /* Word chars */
370         std::vector<char32_t> m_word_char_exceptions;
371 
372 	/* Selection information. */
373         gboolean m_selecting;
374         gboolean m_will_select_after_threshold;
375         gboolean m_selecting_had_delta;
376         bool m_selection_block_mode{false};  // FIXMEegmont move it into a 4th value in SelectionType?
377         SelectionType m_selection_type{SelectionType::eCHAR};
378         vte::grid::halfcoords m_selection_origin, m_selection_last;  /* BiDi: logical in normal modes, visual in m_selection_block_mode */
379         vte::grid::span m_selection_resolved;
380 
381 	/* Clipboard data information. */
382         bool m_selection_owned[2]{false, false};
383         bool m_changing_selection{false};
384         vte::platform::ClipboardFormat m_selection_format[2];
385         GString *m_selection[2];  // FIXMEegmont rename this so that m_selection_resolved can become m_selection?
386 
387 	/* Miscellaneous options. */
388         EraseMode m_backspace_binding{EraseMode::eAUTO};
389         EraseMode m_delete_binding{EraseMode::eAUTO};
390         bool m_audible_bell{true};
391         bool m_allow_bold{true};
392         bool m_bold_is_bright{false};
393         bool m_rewrap_on_resize{true};
394         gboolean m_text_modified_flag;
395         gboolean m_text_inserted_flag;
396         gboolean m_text_deleted_flag;
397 
398 	/* Scrolling options. */
399         bool m_fallback_scrolling{true};
400         bool m_scroll_on_output{false};
401         bool m_scroll_on_keystroke{true};
402         vte::grid::row_t m_scrollback_lines{0};
403 
404         /* Restricted scrolling */
405         struct vte_scrolling_region m_scrolling_region;     /* the region we scroll in */
406         gboolean m_scrolling_restricted;
407 
408 	/* Cursor shape, as set via API */
409         CursorShape m_cursor_shape{CursorShape::eBLOCK};
410         double m_cursor_aspect_ratio{0.04};
411 
412 	/* Cursor blinking */
413         bool cursor_blink_timer_callback();
414         vte::glib::Timer m_cursor_blink_timer{std::bind(&Terminal::cursor_blink_timer_callback,
415                                                         this),
416                                               "cursor-blink-timer"};
417         CursorBlinkMode m_cursor_blink_mode{CursorBlinkMode::eSYSTEM};
418         bool m_cursor_blink_state{false};
419         bool m_cursor_blinks{false};           /* whether the cursor is actually blinking */
420         gint m_cursor_blink_cycle;          /* gtk-cursor-blink-time / 2 */
421         int m_cursor_blink_timeout{500};        /* gtk-cursor-blink-timeout */
422         gint64 m_cursor_blink_time;         /* how long the cursor has been blinking yet */
423         bool m_has_focus{false};            /* is the widget focused */
424 
425         /* Contents blinking */
426         bool text_blink_timer_callback();
427         vte::glib::Timer m_text_blink_timer{std::bind(&Terminal::text_blink_timer_callback,
428                                                       this),
429                                             "text-blink-timer"};
430         bool m_text_blink_state{false};  /* whether blinking text should be visible at this very moment */
431         bool m_text_to_blink{false};     /* drawing signals here if it encounters any cell with blink attribute */
432         TextBlinkMode m_text_blink_mode{TextBlinkMode::eALWAYS};
433         gint m_text_blink_cycle;  /* gtk-cursor-blink-time / 2 */
434 
435         /* DECSCUSR cursor style (shape and blinking possibly overridden
436          * via escape sequence) */
437 
438         CursorStyle m_cursor_style{CursorStyle::eTERMINAL_DEFAULT};
439 
440 	/* Input device options. */
441         bool m_input_enabled{true};
442         time_t m_last_keypress_time;
443 
444         MouseTrackingMode m_mouse_tracking_mode{MouseTrackingMode::eNONE};
445         guint m_mouse_pressed_buttons;      /* bits 0, 1, 2 resp. for buttons 1, 2, 3 */
446         guint m_mouse_handled_buttons;      /* similar bitmap for buttons we handled ourselves */
447         /* The last known position the mouse pointer from an event. We don't store
448          * this in grid coordinates because we want also to check if they were outside
449          * the viewable area, and also want to catch in-cell movements if they make the pointer visible.
450          */
451         vte::view::coords m_mouse_last_position{-1, -1};
452         double m_mouse_smooth_scroll_delta{0.0};
453         bool mouse_autoscroll_timer_callback();
454         vte::glib::Timer m_mouse_autoscroll_timer{std::bind(&Terminal::mouse_autoscroll_timer_callback,
455                                                             this),
456                                                   "mouse-autoscroll-timer"};
457 
458 	/* State variables for handling match checks. */
459         int m_match_regex_next_tag{0};
regex_match_next_tag()460         auto regex_match_next_tag() noexcept { return m_match_regex_next_tag++; }
461 
462         class MatchRegex {
463         public:
464                 MatchRegex() = default;
465                 MatchRegex(MatchRegex&&) = default;
466                 MatchRegex& operator= (MatchRegex&&) = default;
467 
468                 MatchRegex(MatchRegex const&) = delete;
469                 MatchRegex& operator= (MatchRegex const&) = delete;
470 
MatchRegex(vte::base::RefPtr<vte::base::Regex> && regex,uint32_t match_flags,vte::platform::Cursor && cursor,int tag=-1)471                 MatchRegex(vte::base::RefPtr<vte::base::Regex>&& regex,
472                            uint32_t match_flags,
473                            vte::platform::Cursor&& cursor,
474                            int tag = -1)
475                         : m_regex{std::move(regex)},
476                           m_match_flags{match_flags},
477                           m_cursor{std::move(cursor)},
478                           m_tag{tag}
479                 {
480                 }
481 
regex() const482                 auto regex() const noexcept { return m_regex.get(); }
match_flags() const483                 auto match_flags() const noexcept { return m_match_flags; }
cursor() const484                 auto const& cursor() const noexcept { return m_cursor; }
tag() const485                 auto tag() const noexcept { return m_tag; }
486 
set_cursor(vte::platform::Cursor && cursor)487                 void set_cursor(vte::platform::Cursor&& cursor) { m_cursor = std::move(cursor); }
488 
489         private:
490                 vte::base::RefPtr<vte::base::Regex> m_regex{};
491                 uint32_t m_match_flags{0};
492                 vte::platform::Cursor m_cursor{VTE_DEFAULT_CURSOR};
493                 int m_tag{-1};
494         };
495 
496         MatchRegex const* m_match_current{nullptr};
regex_match_has_current() const497         bool regex_match_has_current() const noexcept { return m_match_current != nullptr; }
regex_match_current() const498         auto const* regex_match_current() const noexcept { return m_match_current; }
499 
500         std::vector<MatchRegex> m_match_regexes{};
501 
502         // m_match_current points into m_match_regex, so every write access to
503         // m_match_regex must go through this function that clears m_current_match
match_regexes_writable()504         auto& match_regexes_writable() noexcept
505         {
506                 match_hilite_clear();
507                 return m_match_regexes;
508         }
509 
regex_match_get_iter(int tag)510         auto regex_match_get_iter(int tag) noexcept
511         {
512                 return std::find_if(std::begin(m_match_regexes), std::end(m_match_regexes),
513                                     [tag](MatchRegex const& rem) { return rem.tag() == tag; });
514         }
515 
regex_match_get(int tag)516         MatchRegex* regex_match_get(int tag) noexcept
517         {
518                 auto i = regex_match_get_iter(tag);
519                 if (i == std::end(m_match_regexes))
520                         return nullptr;
521 
522                 return std::addressof(*i);
523         }
524 
525         template<class... Args>
regex_match_add(Args &&...args)526         auto& regex_match_add(Args&&... args)
527         {
528                 return match_regexes_writable().emplace_back(std::forward<Args>(args)...);
529         }
530 
531         char* m_match_contents;
532         GArray* m_match_attributes;
533         char* m_match;
534         /* If m_match non-null, then m_match_span contains the region of the match.
535          * If m_match is null, and m_match_span is not .empty(), then it contains
536          * the minimal region around the last checked coordinates that don't contain
537          * a match for any of the dingu regexes.
538          */
539         vte::grid::span m_match_span;
540 
541 	/* Search data. */
542         vte::base::RefPtr<vte::base::Regex> m_search_regex{};
543         uint32_t m_search_regex_match_flags{0};
544         gboolean m_search_wrap_around;
545         GArray* m_search_attrs; /* Cache attrs */
546 
547 	/* Data used when rendering the text which does not require server
548 	 * resources and which can be kept after unrealizing. */
549         vte::Freeable<PangoFontDescription> m_api_font_desc{};
550         vte::Freeable<PangoFontDescription> m_unscaled_font_desc{};
551         vte::Freeable<PangoFontDescription> m_fontdesc{};
552         double m_font_scale{1.};
553 
unscaled_font_description() const554         auto unscaled_font_description() const noexcept { return m_unscaled_font_desc.get(); }
555 
556         /* First, the dimensions of ASCII characters are measured. The result
557          * could probably be called char_{width,height} or font_{width,height}
558          * but these aren't stored directly here, not to accidentally be confused
559          * with m_cell_{width_height}. The values are stored in FontInfo.
560          *
561          * Then in case of nondefault m_cell_{width,height}_scale an additional
562          * m_char_padding is added, resulting in m_cell_{width,height} which are
563          * hence potentially larger than the characters. This is to implement
564          * line spacing and letter spacing, primarly for accessibility (bug 781479).
565          *
566          * Char width/height, if really needed, can be computed by subtracting
567          * the char padding from the cell dimensions. Char height can also be
568          * reconstructed from m_char_{ascent,descent}, one of which is redundant,
569          * stored for convenience only.
570          */
571         long m_char_ascent{0};
572         long m_char_descent{0};
573         double m_cell_width_scale{1.};
574         double m_cell_height_scale{1.};
575         GtkBorder m_char_padding{0, 0, 0, 0};
576         long m_cell_width{0};
577         long m_cell_height{0};
578         long m_cell_width_unscaled{0};
579         long m_cell_height_unscaled{0};
580 
581         /* We allow the cell's text to draw a bit outside the cell at the top
582          * and bottom. The following two functions return how much is the
583          * maximally allowed overdraw (in px).
584          */
cell_overflow_top() const585         inline constexpr auto cell_overflow_top() const noexcept
586         {
587                 /* Allow overdrawing up into the underline of the cell on top */
588                 return int(m_cell_height - m_underline_position);
589         }
590 
cell_overflow_bottom() const591         inline constexpr auto cell_overflow_bottom() const noexcept
592         {
593                 /* Allow overdrawing up into the overline of the cell on bottom */
594                 return int(m_overline_position + m_overline_thickness);
595         }
596 
597 	/* Data used when rendering */
598         vte::view::DrawingContext m_draw{};
599         bool m_clear_background{true};
600 
601         VtePaletteColor m_palette[VTE_PALETTE_SIZE];
602 
603 	/* Mouse cursors. */
604         gboolean m_mouse_cursor_over_widget; /* as per enter and leave events */
605         gboolean m_mouse_autohide;           /* the API setting */
606         gboolean m_mouse_cursor_autohidden;  /* whether the autohiding logic wants to hide it; even if autohiding is disabled via API */
607 
608 	/* Input method support. */
609         bool m_im_preedit_active;
610         std::string m_im_preedit;
611         vte::Freeable<PangoAttrList> m_im_preedit_attrs{};
612         int m_im_preedit_cursor;
613 
614         #ifdef WITH_A11Y
615         gboolean m_accessible_emit;
616         #endif
617 
618         /* Adjustment updates pending. */
619         gboolean m_adjustment_changed_pending;
620         gboolean m_adjustment_value_changed_pending;
621         gboolean m_cursor_moved_pending;
622         gboolean m_contents_changed_pending;
623 
624         std::string m_window_title{};
625         std::string m_current_directory_uri{};
626         std::string m_current_file_uri{};
627         std::string m_window_title_pending{};
628         std::string m_current_directory_uri_pending{};
629         std::string m_current_file_uri_pending{};
630 
631         std::vector<std::string> m_window_title_stack{};
632 
633         enum class PendingChanges {
634                 TITLE = 1u << 0,
635                 CWD   = 1u << 1,
636                 CWF   = 1u << 2,
637         };
638         unsigned m_pending_changes{0};
639 
640 	/* Background */
641         double m_background_alpha{1.};
642 
643         /* Bell */
644         int64_t m_bell_timestamp;
645         bool m_bell_pending{false};
646 
647 	/* Key modifiers. */
648         guint m_modifiers;
649 
650 	/* Font stuff. */
651         bool m_has_fonts{false};
652         bool m_fontdirty{true};
653         long m_line_thickness{VTE_LINE_WIDTH};
654         long m_underline_position{0};
655         long m_underline_thickness{VTE_LINE_WIDTH};
656         long m_double_underline_position{0};
657         long m_double_underline_thickness{VTE_LINE_WIDTH};
658         long m_strikethrough_position{0};
659         long m_strikethrough_thickness{VTE_LINE_WIDTH};
660         long m_overline_position{0};
661         long m_overline_thickness{VTE_LINE_WIDTH};
662         long m_regex_underline_position{0};
663         long m_regex_underline_thickness{VTE_LINE_WIDTH};
664         double m_undercurl_position{0.};
665         double m_undercurl_thickness{VTE_LINE_WIDTH};
666 
667         /* Style stuff */
668         GtkBorder m_padding{1, 1, 1, 1};
padding() const669         auto padding() const noexcept { return &m_padding; }
670 
671         vte::glib::RefPtr<GtkAdjustment> m_vadjustment{};
vadjustment()672         auto vadjustment() noexcept { return m_vadjustment.get(); }
673 
674         /* Hyperlinks */
675         bool m_allow_hyperlink{false};
676         vte::base::Ring::hyperlink_idx_t m_hyperlink_hover_idx;
677         const char *m_hyperlink_hover_uri; /* data is owned by the ring */
678         long m_hyperlink_auto_id{0};
679 
680         /* RingView and friends */
681         vte::base::RingView m_ringview;
682         bool m_enable_bidi{true};
683         bool m_enable_shaping{true};
684 
685         /* BiDi parameters outside of ECMA and DEC private modes */
686         guint m_bidi_rtl : 1;
687 
688 public:
689 
690         // FIXMEchpe inline!
691         /* inline */ VteRowData* ring_insert(vte::grid::row_t position,
692                                        bool fill);
693         /* inline */ VteRowData* ring_append(bool fill);
694         /* inline */ void ring_remove(vte::grid::row_t position);
695         inline VteRowData const* find_row_data(vte::grid::row_t row) const;
696         inline VteRowData* find_row_data_writable(vte::grid::row_t row) const;
697         inline VteCell const* find_charcell(vte::grid::column_t col,
698                                             vte::grid::row_t row) const;
699         inline vte::grid::column_t find_start_column(vte::grid::column_t col,
700                                                      vte::grid::row_t row) const;
701         inline vte::grid::column_t find_end_column(vte::grid::column_t col,
702                                                    vte::grid::row_t row) const;
703 
704         inline vte::view::coord_t scroll_delta_pixel() const;
705         inline vte::grid::row_t pixel_to_row(vte::view::coord_t y) const;
706         inline vte::view::coord_t row_to_pixel(vte::grid::row_t row) const;
707         inline vte::grid::row_t first_displayed_row() const;
708         inline vte::grid::row_t last_displayed_row() const;
709         inline bool cursor_is_onscreen() const noexcept;
710 
711         inline VteRowData *insert_rows (guint cnt);
712         VteRowData *ensure_row();
713         VteRowData *ensure_cursor();
714         void update_insert_delta();
715 
716         void set_hard_wrapped(vte::grid::row_t row);
717         void set_soft_wrapped(vte::grid::row_t row);
718 
719         void cleanup_fragments(long start,
720                                long end);
721 
722         void cursor_down(bool explicit_sequence);
723         void drop_scrollback();
724 
725         void restore_cursor(VteScreen *screen__);
726         void save_cursor(VteScreen *screen__);
727 
728         void insert_char(gunichar c,
729                          bool insert,
730                          bool invalidate_now);
731 
732         void invalidate_row(vte::grid::row_t row);
733         void invalidate_rows(vte::grid::row_t row_start,
734                              vte::grid::row_t row_end /* inclusive */);
735         void invalidate_row_and_context(vte::grid::row_t row);
736         void invalidate_rows_and_context(vte::grid::row_t row_start,
737                                          vte::grid::row_t row_end /* inclusive */);
738         void invalidate(vte::grid::span const& s);
739         void invalidate_symmetrical_difference(vte::grid::span const& a, vte::grid::span const& b, bool block);
740         void invalidate_match_span();
741         void invalidate_all();
742 
743         guint8 get_bidi_flags() const noexcept;
744         void apply_bidi_attributes(vte::grid::row_t start, guint8 bidi_flags, guint8 bidi_flags_mask);
745         void maybe_apply_bidi_attributes(guint8 bidi_flags_mask);
746 
747         void reset_update_rects();
748         bool invalidate_dirty_rects_and_process_updates();
749         void time_process_incoming();
750         void process_incoming();
751         void process_incoming_utf8(ProcessingContext& context,
752                                    vte::base::Chunk& chunk);
753         #ifdef WITH_ICU
754         void process_incoming_pcterm(ProcessingContext& context,
755                                      vte::base::Chunk& chunk);
756         #endif
757         bool process(bool emit_adj_changed);
is_processing() const758         inline bool is_processing() const { return m_active_terminals_link != nullptr; }
759         void start_processing();
760 
761         gssize get_preedit_width(bool left_only);
762         gssize get_preedit_length(bool left_only);
763 
764         void invalidate_cursor_once(bool periodic = false);
765         void check_cursor_blink();
766         void add_cursor_timeout();
767         void remove_cursor_timeout();
768         void update_cursor_blinks();
769         CursorBlinkMode decscusr_cursor_blink() const noexcept;
770         CursorShape decscusr_cursor_shape() const noexcept;
771 
772         /* The allocation of the widget */
773         cairo_rectangle_int_t m_allocated_rect;
774         /* The usable view area. This is the allocation, minus the padding, but
775          * including additional right/bottom area if the allocation is not grid aligned.
776          */
777         vte::view::extents m_view_usable_extents;
778 
set_allocated_rect(cairo_rectangle_int_t const & r)779         void set_allocated_rect(cairo_rectangle_int_t const& r) { m_allocated_rect = r; update_view_extents(); }
update_view_extents()780         void update_view_extents() {
781                 m_view_usable_extents =
782                         vte::view::extents(m_allocated_rect.width - m_padding.left - m_padding.right,
783                                            m_allocated_rect.height - m_padding.top - m_padding.bottom);
784         }
785 
786         bool widget_realized() const noexcept;
get_allocated_rect() const787         inline cairo_rectangle_int_t const& get_allocated_rect() const { return m_allocated_rect; }
get_allocated_width() const788         inline vte::view::coord_t get_allocated_width() const { return m_allocated_rect.width; }
get_allocated_height() const789         inline vte::view::coord_t get_allocated_height() const { return m_allocated_rect.height; }
790 
791         vte::view::coords view_coords_from_event(vte::platform::MouseEvent const& event) const;
792         vte::grid::coords grid_coords_from_event(vte::platform::MouseEvent const& event) const;
793 
794         vte::view::coords view_coords_from_grid_coords(vte::grid::coords const& rowcol) const;
795         vte::grid::coords grid_coords_from_view_coords(vte::view::coords const& pos) const;
796 
797         vte::grid::halfcoords selection_grid_halfcoords_from_view_coords(vte::view::coords const& pos) const;
798         bool view_coords_visible(vte::view::coords const& pos) const;
799         bool grid_coords_visible(vte::grid::coords const& rowcol) const;
800 
grid_coords_in_scrollback(vte::grid::coords const & rowcol) const801         inline bool grid_coords_in_scrollback(vte::grid::coords const& rowcol) const { return rowcol.row() < m_screen->insert_delta; }
802 
803         vte::grid::row_t confine_grid_row(vte::grid::row_t const& row) const;
804         vte::grid::coords confine_grid_coords(vte::grid::coords const& rowcol) const;
805         vte::grid::coords confined_grid_coords_from_event(vte::platform::MouseEvent const&) const;
806         vte::grid::coords confined_grid_coords_from_view_coords(vte::view::coords const& pos) const;
807 
808         void confine_coordinates(long *xp,
809                                  long *yp);
810 
811         void set_border_padding(GtkBorder const* padding);
812         void set_cursor_aspect(float aspect);
813 
814         void widget_copy(vte::platform::ClipboardType selection,
815                          vte::platform::ClipboardFormat format);
816 
817         void widget_clipboard_text_received(vte::platform::Clipboard const& clipboard,
818                                             std::string_view const& text);
819 
820         std::optional<std::string_view> widget_clipboard_data_get(vte::platform::Clipboard const& clipboard,
821                                                                   vte::platform::ClipboardFormat format);
822         void widget_clipboard_data_clear(vte::platform::Clipboard const& clipboard);
823 
824         void widget_set_vadjustment(vte::glib::RefPtr<GtkAdjustment>&& adjustment);
825 
826         void widget_realize();
827         void widget_unrealize();
828         void widget_unmap();
829         void widget_style_updated();
830         void widget_focus_in();
831         void widget_focus_out();
832         bool widget_key_press(vte::platform::KeyEvent const& event);
833         bool widget_key_release(vte::platform::KeyEvent const& event);
834         bool widget_mouse_motion(vte::platform::MouseEvent const& event);
835         bool widget_mouse_press(vte::platform::MouseEvent const& event);
836         bool widget_mouse_release(vte::platform::MouseEvent const& event);
837         void widget_mouse_enter(vte::platform::MouseEvent const& event);
838         void widget_mouse_leave(vte::platform::MouseEvent const& event);
839         bool widget_mouse_scroll(vte::platform::ScrollEvent const& event);
840         void widget_draw(cairo_t *cr);
841         void widget_get_preferred_width(int *minimum_width,
842                                         int *natural_width);
843         void widget_get_preferred_height(int *minimum_height,
844                                          int *natural_height);
845         void widget_size_allocate(GtkAllocation *allocation);
846 
847         void set_blink_settings(bool blink,
848                                 int blink_time,
849                                 int blink_timeout) noexcept;
850 
851         void paint_cursor();
852         void paint_im_preedit_string();
853         void draw_cells(vte::view::DrawingContext::TextRequest* items,
854                         gssize n,
855                         uint32_t fore,
856                         uint32_t back,
857                         uint32_t deco,
858                         bool clear,
859                         bool draw_default_bg,
860                         uint32_t attr,
861                         bool hyperlink,
862                         bool hilite,
863                         int column_width,
864                         int row_height);
865         void fudge_pango_colors(GSList *attributes,
866                                 VteCell *cells,
867                                 gsize n);
868         void apply_pango_attr(PangoAttribute *attr,
869                               VteCell *cells,
870                               gsize n_cells);
871         void translate_pango_cells(PangoAttrList *attrs,
872                                    VteCell *cells,
873                                    gsize n_cells);
874         void draw_cells_with_attributes(vte::view::DrawingContext::TextRequest* items,
875                                         gssize n,
876                                         PangoAttrList *attrs,
877                                         bool draw_default_bg,
878                                         int column_width,
879                                         int height);
880         void draw_rows(VteScreen *screen,
881                        cairo_region_t const* region,
882                        vte::grid::row_t start_row,
883                        long row_count,
884                        gint start_y,
885                        gint column_width,
886                        gint row_height);
887 
888         void start_autoscroll();
stop_autoscroll()889         void stop_autoscroll() noexcept { m_mouse_autoscroll_timer.abort(); }
890 
891         void connect_pty_read();
892         void disconnect_pty_read();
893 
894         void connect_pty_write();
895         void disconnect_pty_write();
896 
897         void pty_termios_changed();
898         void pty_scroll_lock_changed(bool locked);
899 
900         void pty_channel_eof();
901         bool pty_io_read(int const fd,
902                          GIOCondition const condition);
903         bool pty_io_write(int const fd,
904                           GIOCondition const condition);
905 
906         void send_child(std::string_view const& data);
907 
908         void watch_child (pid_t child_pid);
909         bool terminate_child () noexcept;
910         void child_watch_done(pid_t pid,
911                               int status);
912         void emit_child_exited();
913 
914         void im_commit(std::string_view const& str);
915         void im_preedit_set_active(bool active) noexcept;
916         void im_preedit_reset() noexcept;
917         void im_preedit_changed(std::string_view const& str,
918                                 int cursorpos,
919                                 vte::Freeable<PangoAttrList> attrs) noexcept;
920         bool im_retrieve_surrounding();
921         bool im_delete_surrounding(int offset,
922                                    int n_chars);
923         void im_reset();
924         void im_update_cursor();
925 
926         void reset(bool clear_tabstops,
927                    bool clear_history,
928                    bool from_api = false);
929         void reset_decoder();
930 
931         void feed(std::string_view const& data,
932                   bool start_processsing_ = true);
feed_child(char const * data,size_t length)933         void feed_child(char const* data,
934                         size_t length) { assert(data); feed_child({data, length}); }
935         void feed_child(std::string_view const& str);
936         void feed_child_binary(std::string_view const& data);
937 
938         bool is_word_char(gunichar c) const;
939         bool is_same_class(vte::grid::column_t acol,
940                            vte::grid::row_t arow,
941                            vte::grid::column_t bcol,
942                            vte::grid::row_t brow) const;
943 
944         GString* get_text(vte::grid::row_t start_row,
945                           vte::grid::column_t start_col,
946                           vte::grid::row_t end_row,
947                           vte::grid::column_t end_col,
948                           bool block,
949                           bool wrap,
950                           GArray* attributes = nullptr);
951 
952         GString* get_text_displayed(bool wrap,
953                                     GArray* attributes = nullptr);
954 
955         GString* get_text_displayed_a11y(bool wrap,
956                                          GArray* attributes = nullptr);
957 
958         GString* get_selected_text(GArray* attributes = nullptr);
959 
960         template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
961         inline void rgb_from_index(guint index,
962                                    vte::color::rgb& color) const;
963         inline void determine_colors(VteCellAttr const* attr,
964                                      bool selected,
965                                      bool cursor,
966                                      guint *pfore,
967                                      guint *pback,
968                                      guint *pdeco) const;
969         inline void determine_colors(VteCell const* cell,
970                                      bool selected,
971                                      guint *pfore,
972                                      guint *pback,
973                                      guint *pdeco) const;
974         inline void determine_cursor_colors(VteCell const* cell,
975                                             bool selected,
976                                             guint *pfore,
977                                             guint *pback,
978                                             guint *pdeco) const;
979 
980         void resolve_normal_colors(VteCell const* cell,
981                                    unsigned* pfore,
982                                    unsigned* pback,
983                                    vte::color::rgb& fg,
984                                    vte::color::rgb& bg);
985 
986         char *cellattr_to_html(VteCellAttr const* attr,
987                                char const* text) const;
988         VteCellAttr const* char_to_cell_attr(VteCharAttributes const* attr) const;
989 
990         GString* attributes_to_html(GString* text_string,
991                                     GArray* attrs);
992 
993         void start_selection(vte::view::coords const& pos,
994                              SelectionType type);
995         bool maybe_end_selection();
996 
997         void select_all();
998         void deselect_all();
999 
1000         vte::grid::coords resolve_selection_endpoint(vte::grid::halfcoords const& rowcolhalf, bool after) const;
1001         void resolve_selection();
1002         void selection_maybe_swap_endpoints(vte::view::coords const& pos);
1003         void modify_selection(vte::view::coords const& pos);
1004         bool cell_is_selected_log(vte::grid::column_t lcol,
1005                                   vte::grid::row_t) const;
1006         bool cell_is_selected_vis(vte::grid::column_t vcol,
1007                                   vte::grid::row_t) const;
1008 
1009         void reset_default_attributes(bool reset_hyperlink);
1010 
1011         void ensure_font();
1012         void update_font();
1013         void apply_font_metrics(int cell_width_unscaled,
1014                                 int cell_height_unscaled,
1015                                 int cell_width,
1016                                 int cell_height,
1017                                 int char_ascent,
1018                                 int char_descent,
1019                                 GtkBorder char_spacing);
1020 
1021         void refresh_size();
1022         void screen_set_size(VteScreen *screen_,
1023                              long old_columns,
1024                              long old_rows,
1025                              bool do_rewrap);
1026 
1027         void vadjustment_value_changed();
1028 
1029         unsigned translate_ctrlkey(vte::platform::KeyEvent const& event) const noexcept;
1030 
1031         void apply_mouse_cursor();
1032         void set_pointer_autohidden(bool autohidden);
1033 
1034         void beep();
1035 
1036         void emit_adjustment_changed();
1037         void emit_commit(std::string_view const& str);
1038         void emit_eof();
1039         void emit_selection_changed();
1040         void queue_adjustment_changed();
1041         void queue_adjustment_value_changed(double v);
1042         void queue_adjustment_value_changed_clamped(double v);
1043         void adjust_adjustments();
1044         void adjust_adjustments_full();
1045 
1046         void scroll_lines(long lines);
scroll_pages(long pages)1047         void scroll_pages(long pages) { scroll_lines(pages * m_row_count); }
1048         void maybe_scroll_to_top();
1049         void maybe_scroll_to_bottom();
1050 
1051         void queue_cursor_moved();
1052         void queue_contents_changed();
1053         void queue_child_exited();
1054         void queue_eof();
1055 
1056         void emit_text_deleted();
1057         void emit_text_inserted();
1058         void emit_text_modified();
1059         void emit_text_scrolled(long delta);
1060         void emit_pending_signals();
1061         void emit_char_size_changed(int width,
1062                                     int height);
1063         void emit_increase_font_size();
1064         void emit_decrease_font_size();
1065         void emit_bell();
1066 
1067         bool m_xterm_wm_iconified{false};
1068 
1069         void emit_resize_window(guint columns,
1070                                 guint rows);
1071         void emit_copy_clipboard();
1072         void emit_paste_clipboard();
1073         void emit_hyperlink_hover_uri_changed(const GdkRectangle *bbox);
1074 
1075         void hyperlink_invalidate_and_get_bbox(vte::base::Ring::hyperlink_idx_t idx, GdkRectangle *bbox);
1076         void hyperlink_hilite_update();
1077 
1078         void match_contents_clear();
1079         void match_contents_refresh();
1080         void match_hilite_clear();
1081         void match_hilite_update();
1082 
1083         bool rowcol_from_event(vte::platform::MouseEvent const& event,
1084                                long *column,
1085                                long *row);
1086 
1087         char *hyperlink_check(vte::platform::MouseEvent const& event);
1088 
1089         bool regex_match_check_extra(vte::platform::MouseEvent const& event,
1090                                      vte::base::Regex const** regexes,
1091                                      size_t n_regexes,
1092                                      uint32_t match_flags,
1093                                      char** matches);
1094 
1095         char *regex_match_check(vte::grid::column_t column,
1096                                 vte::grid::row_t row,
1097                                 int *tag);
1098         char *regex_match_check(vte::platform::MouseEvent const& event,
1099                                 int *tag);
1100         void regex_match_remove(int tag) noexcept;
1101         void regex_match_remove_all() noexcept;
1102         void regex_match_set_cursor(int tag,
1103                                     GdkCursor *gdk_cursor);
1104         void regex_match_set_cursor(int tag,
1105                                     GdkCursorType cursor_type);
1106         void regex_match_set_cursor(int tag,
1107                                     char const* cursor_name);
1108         bool match_rowcol_to_offset(vte::grid::column_t column,
1109                                     vte::grid::row_t row,
1110                                     gsize *offset_ptr,
1111                                     gsize *sattr_ptr,
1112                                     gsize *eattr_ptr);
1113 
1114         vte::Freeable<pcre2_match_context_8> create_match_context();
1115         bool match_check_pcre(pcre2_match_data_8 *match_data,
1116                               pcre2_match_context_8 *match_context,
1117                               vte::base::Regex const* regex,
1118                               uint32_t match_flags,
1119                               gsize sattr,
1120                               gsize eattr,
1121                               gsize offset,
1122                               char **result,
1123                               gsize *start,
1124                               gsize *end,
1125                               gsize *sblank_ptr,
1126                               gsize *eblank_ptr);
1127         char *match_check_internal_pcre(vte::grid::column_t column,
1128                                         vte::grid::row_t row,
1129                                         MatchRegex const** match,
1130                                         gsize *start,
1131                                         gsize *end);
1132 
1133         char *match_check_internal(vte::grid::column_t column,
1134                                    vte::grid::row_t row,
1135                                    MatchRegex const** match,
1136                                    gsize *start,
1137                                    gsize *end);
1138 
1139         bool feed_mouse_event(vte::grid::coords const& unconfined_rowcol,
1140                               int button,
1141                               bool is_drag,
1142                               bool is_release);
1143         bool maybe_send_mouse_button(vte::grid::coords const& rowcol,
1144                                      vte::platform::MouseEvent const& event);
1145         bool maybe_send_mouse_drag(vte::grid::coords const& rowcol,
1146                                    vte::platform::MouseEvent const& event);
1147 
1148         void feed_focus_event(bool in);
1149         void feed_focus_event_initial();
1150         void maybe_feed_focus_event(bool in);
1151 
1152         bool search_set_regex(vte::base::RefPtr<vte::base::Regex>&& regex,
1153                               uint32_t flags);
search_regex() const1154         auto search_regex() const noexcept { return m_search_regex.get(); }
1155 
1156         bool search_rows(pcre2_match_context_8 *match_context,
1157                          pcre2_match_data_8 *match_data,
1158                          vte::grid::row_t start_row,
1159                          vte::grid::row_t end_row,
1160                          bool backward);
1161         bool search_rows_iter(pcre2_match_context_8 *match_context,
1162                               pcre2_match_data_8 *match_data,
1163                               vte::grid::row_t start_row,
1164                               vte::grid::row_t end_row,
1165                               bool backward);
1166         bool search_find(bool backward);
1167         bool search_set_wrap_around(bool wrap);
1168 
1169         void set_size(long columns,
1170                       long rows);
1171 
1172         std::optional<std::vector<char32_t>> process_word_char_exceptions(std::string_view str) const noexcept;
1173 
get_cell_height()1174         long get_cell_height() { ensure_font(); return m_cell_height; }
get_cell_width()1175         long get_cell_width()  { ensure_font(); return m_cell_width;  }
1176 
1177         vte::color::rgb const* get_color(int entry) const;
1178         void set_color(int entry,
1179                        int source,
1180                        vte::color::rgb const& proposed);
1181         void reset_color(int entry,
1182                          int source);
1183 
1184         bool set_audible_bell(bool setting);
1185         bool set_text_blink_mode(TextBlinkMode setting);
text_blink_mode() const1186         auto text_blink_mode() const noexcept { return m_text_blink_mode; }
1187         bool set_allow_bold(bool setting);
1188         bool set_allow_hyperlink(bool setting);
1189         bool set_backspace_binding(EraseMode binding);
backspace_binding() const1190         auto backspace_binding() const noexcept { return m_backspace_binding; }
1191         bool set_background_alpha(double alpha);
1192         bool set_bold_is_bright(bool setting);
1193         bool set_cell_height_scale(double scale);
1194         bool set_cell_width_scale(double scale);
1195         bool set_cjk_ambiguous_width(int width);
1196         void set_color_background(vte::color::rgb const &color);
1197         void set_color_bold(vte::color::rgb const& color);
1198         void reset_color_bold();
1199         void set_color_cursor_background(vte::color::rgb const& color);
1200         void reset_color_cursor_background();
1201         void set_color_cursor_foreground(vte::color::rgb const& color);
1202         void reset_color_cursor_foreground();
1203         void set_color_foreground(vte::color::rgb const& color);
1204         void set_color_highlight_background(vte::color::rgb const& color);
1205         void reset_color_highlight_background();
1206         void set_color_highlight_foreground(vte::color::rgb const& color);
1207         void reset_color_highlight_foreground();
1208         void set_colors(vte::color::rgb const *foreground,
1209                         vte::color::rgb const *background,
1210                         vte::color::rgb const *palette,
1211                         gsize palette_size);
1212         void set_colors_default();
1213         bool set_cursor_blink_mode(CursorBlinkMode mode);
cursor_blink_mode() const1214         auto cursor_blink_mode() const noexcept { return m_cursor_blink_mode; }
1215         bool set_cursor_shape(CursorShape shape);
cursor_shape() const1216         auto cursor_shape() const noexcept { return m_cursor_shape; }
1217         bool set_cursor_style(CursorStyle style);
1218         bool set_delete_binding(EraseMode binding);
delete_binding() const1219         auto delete_binding() const noexcept { return m_delete_binding; }
1220         bool set_enable_bidi(bool setting);
1221         bool set_enable_shaping(bool setting);
1222         bool set_encoding(char const* codeset,
1223                           GError** error);
1224         bool set_font_desc(vte::Freeable<PangoFontDescription> desc);
1225         bool update_font_desc();
1226         bool set_font_scale(double scale);
1227         bool set_input_enabled(bool enabled);
1228         bool set_mouse_autohide(bool autohide);
1229         bool set_rewrap_on_resize(bool rewrap);
1230         bool set_scrollback_lines(long lines);
1231         bool set_fallback_scrolling(bool set);
fallback_scrolling() const1232         auto fallback_scrolling() const noexcept { return m_fallback_scrolling; }
1233         bool set_scroll_on_keystroke(bool scroll);
1234         bool set_scroll_on_output(bool scroll);
1235         bool set_images_enabled(bool enabled);
1236         bool set_word_char_exceptions(std::optional<std::string_view> stropt);
1237         void set_clear_background(bool setting);
1238 
1239         bool write_contents_sync (GOutputStream *stream,
1240                                   VteWriteFlags flags,
1241                                   GCancellable *cancellable,
1242                                   GError **error);
1243 
1244         inline void ensure_cursor_is_onscreen();
1245         inline void home_cursor();
1246         inline void clear_screen();
1247         inline void clear_current_line();
1248         inline void clear_above_current();
1249         inline void scroll_text(vte::grid::row_t scroll_amount);
1250         inline void switch_screen(VteScreen *new_screen);
1251         inline void switch_normal_screen();
1252         inline void switch_alternate_screen();
1253         inline void save_cursor();
1254         inline void restore_cursor();
1255 
1256         inline void set_mode_ecma(vte::parser::Sequence const& seq,
1257                                   bool set) noexcept;
1258         inline void set_mode_private(vte::parser::Sequence const& seq,
1259                                      bool set) noexcept;
1260         inline void set_mode_private(int mode,
1261                                      bool set) noexcept;
1262         inline void save_mode_private(vte::parser::Sequence const& seq,
1263                                       bool save) noexcept;
1264         void update_mouse_protocol() noexcept;
1265 
1266         inline void set_character_replacements(unsigned slot,
1267                                                VteCharacterReplacement replacement);
1268         inline void set_character_replacement(unsigned slot);
1269         inline void clear_to_bol();
1270         inline void clear_below_current();
1271         inline void clear_to_eol();
1272         inline void delete_character();
1273         inline void set_cursor_column(vte::grid::column_t col);
1274         inline void set_cursor_column1(vte::grid::column_t col); /* 1-based */
get_cursor_column() const1275         inline int get_cursor_column() const noexcept { return CLAMP(m_screen->cursor.col, 0, m_column_count - 1); }
get_cursor_column1() const1276         inline int get_cursor_column1() const noexcept { return get_cursor_column() + 1; }
1277         inline void set_cursor_row(vte::grid::row_t row /* relative to scrolling region */);
1278         inline void set_cursor_row1(vte::grid::row_t row /* relative to scrolling region */); /* 1-based */
get_cursor_row() const1279         inline int get_cursor_row() const noexcept { return CLAMP(m_screen->cursor.row, 0, m_row_count - 1); }
get_cursor_row1() const1280         inline int get_cursor_row1() const noexcept { return get_cursor_row() + 1; }
1281         inline void set_cursor_coords(vte::grid::row_t row /* relative to scrolling region */,
1282                                       vte::grid::column_t column);
1283         inline void set_cursor_coords1(vte::grid::row_t row /* relative to scrolling region */,
1284                                        vte::grid::column_t column); /* 1-based */
1285         inline vte::grid::row_t get_cursor_row_unclamped() const;
1286         inline vte::grid::column_t get_cursor_column_unclamped() const;
1287         inline void move_cursor_up(vte::grid::row_t rows);
1288         inline void move_cursor_down(vte::grid::row_t rows);
1289         inline void erase_characters(long count,
1290                                      bool use_basic = false);
1291         inline void insert_blank_character();
1292 
1293         template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
1294         inline bool seq_parse_sgr_color(vte::parser::Sequence const& seq,
1295                                         unsigned int& idx,
1296                                         uint32_t& color) const noexcept;
1297 
1298         inline void move_cursor_backward(vte::grid::column_t columns);
1299         inline void move_cursor_forward(vte::grid::column_t columns);
1300         inline void move_cursor_tab_backward(int count = 1);
1301         inline void move_cursor_tab_forward(int count = 1);
1302         inline void line_feed();
1303         inline void erase_in_display(vte::parser::Sequence const& seq);
1304         inline void erase_in_line(vte::parser::Sequence const& seq);
1305         inline void insert_lines(vte::grid::row_t param);
1306         inline void delete_lines(vte::grid::row_t param);
1307 
1308         unsigned int checksum_area(vte::grid::row_t start_row,
1309                                    vte::grid::column_t start_col,
1310                                    vte::grid::row_t end_row,
1311                                    vte::grid::column_t end_col);
1312 
1313         void subscribe_accessible_events();
1314         void select_text(vte::grid::column_t start_col,
1315                          vte::grid::row_t start_row,
1316                          vte::grid::column_t end_col,
1317                          vte::grid::row_t end_row);
1318         void select_empty(vte::grid::column_t col,
1319                           vte::grid::row_t row);
1320 
1321         void send(vte::parser::u8SequenceBuilder const& builder,
1322                   bool c1 = true,
1323                   vte::parser::u8SequenceBuilder::Introducer introducer = vte::parser::u8SequenceBuilder::Introducer::DEFAULT,
1324                   vte::parser::u8SequenceBuilder::ST st = vte::parser::u8SequenceBuilder::ST::DEFAULT) noexcept;
1325         void send(vte::parser::Sequence const& seq,
1326                   vte::parser::u8SequenceBuilder const& builder) noexcept;
1327         void send(unsigned int type,
1328                   std::initializer_list<int> params) noexcept;
1329         void reply(vte::parser::Sequence const& seq,
1330                    unsigned int type,
1331                    std::initializer_list<int> params) noexcept;
1332         void reply(vte::parser::Sequence const& seq,
1333                    unsigned int type,
1334                    std::initializer_list<int> params,
1335                    vte::parser::ReplyBuilder const& builder) noexcept;
1336         #if 0
1337         void reply(vte::parser::Sequence const& seq,
1338                    unsigned int type,
1339                    std::initializer_list<int> params,
1340                    std::string const& str) noexcept;
1341         #endif
1342         void reply(vte::parser::Sequence const& seq,
1343                    unsigned int type,
1344                    std::initializer_list<int> params,
1345                    char const* format,
1346                    ...) noexcept G_GNUC_PRINTF(5, 6);
1347 
1348         /* OSC handler helpers */
1349         bool get_osc_color_index(int osc,
1350                                  int value,
1351                                  int& index) const noexcept;
1352         void set_color_index(vte::parser::Sequence const& seq,
1353                              vte::parser::StringTokeniser::const_iterator& token,
1354                              vte::parser::StringTokeniser::const_iterator const& endtoken,
1355                              int number,
1356                              int index,
1357                              int index_fallback,
1358                              int osc) noexcept;
1359 
1360         /* OSC handlers */
1361         void set_color(vte::parser::Sequence const& seq,
1362                        vte::parser::StringTokeniser::const_iterator& token,
1363                        vte::parser::StringTokeniser::const_iterator const& endtoken,
1364                        int osc) noexcept;
1365         void set_special_color(vte::parser::Sequence const& seq,
1366                                vte::parser::StringTokeniser::const_iterator& token,
1367                                vte::parser::StringTokeniser::const_iterator const& endtoken,
1368                                int index,
1369                                int index_fallback,
1370                                int osc) noexcept;
1371         void reset_color(vte::parser::Sequence const& seq,
1372                          vte::parser::StringTokeniser::const_iterator& token,
1373                          vte::parser::StringTokeniser::const_iterator const& endtoken,
1374                          int osc) noexcept;
1375         void set_current_directory_uri(vte::parser::Sequence const& seq,
1376                                        vte::parser::StringTokeniser::const_iterator& token,
1377                                        vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
1378         void set_current_file_uri(vte::parser::Sequence const& seq,
1379                                   vte::parser::StringTokeniser::const_iterator& token,
1380                                   vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
1381         void set_current_hyperlink(vte::parser::Sequence const& seq,
1382                                    vte::parser::StringTokeniser::const_iterator& token,
1383                                    vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
1384 
1385         void ringview_update();
1386 
1387         /* Sequence handlers */
1388         bool m_line_wrapped; // signals line wrapped from character insertion
1389         // Note: inlining the handlers seems to worsen the performance, so we don't do that
1390 #define _VTE_CMD_HANDLER(cmd) \
1391 	/* inline */ void cmd (vte::parser::Sequence const& seq);
1392 #define _VTE_CMD_HANDLER_NOP(cmd) \
1393 	/* inline */ void cmd (vte::parser::Sequence const& seq);
1394 #define _VTE_CMD_HANDLER_R(cmd) \
1395 	/* inline */ bool cmd (vte::parser::Sequence const& seq);
1396 #include "parser-cmd-handlers.hh"
1397 #undef _VTE_CMD_HANDLER
1398 #undef _VTE_CMD_HANDLER_NOP
1399 #undef _VTE_CMD_HANDLER_R
1400 };
1401 
1402 } // namespace terminal
1403 } // namespace vte
1404 
1405 extern GTimer *process_timer;
1406 
1407 vte::terminal::Terminal* _vte_terminal_get_impl(VteTerminal *terminal);
1408 
1409 static inline bool
_vte_double_equal(double a,double b)1410 _vte_double_equal(double a,
1411                   double b)
1412 {
1413 #pragma GCC diagnostic push
1414 #pragma GCC diagnostic ignored "-Wfloat-equal"
1415         return a == b;
1416 #pragma GCC diagnostic pop
1417 }
1418 
1419 #define VTE_TEST_FLAG_DECRQCRA (G_GUINT64_CONSTANT(1) << 0)
1420 
1421 extern uint64_t g_test_flags;
1422