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