From c7740d43fe616889aa89ac82a1dd631ef54193b5 Mon Sep 17 00:00:00 2001 From: matheusfillipe Date: Sat, 11 Dec 2021 17:49:09 -0300 Subject: [PATCH 1/2] Improve cursor style handling --- src/terminal/terminaldisplay.cc | 15 +++++++++++++++ src/terminal/terminaldisplay.h | 1 + src/terminal/terminalframebuffer.cc | 2 ++ src/terminal/terminalframebuffer.h | 13 +++++++++++++ src/terminal/terminalfunctions.cc | 20 ++++++++++++++++++++ 5 files changed, 51 insertions(+) diff --git a/src/terminal/terminaldisplay.cc b/src/terminal/terminaldisplay.cc index e7595c248..903407208 100644 --- a/src/terminal/terminaldisplay.cc +++ b/src/terminal/terminaldisplay.cc @@ -154,6 +154,12 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const frame.append( "\033[?25l" ); } + /* is cursor style initialized? */ + if ( !initialized ) { + frame.cursor_style = Terminal::CursorStyle::BLINKING_BLOCK; + frame.append( "\033[0 q" ); + } + int frame_y = 0; Framebuffer::row_pointer blank_row; Framebuffer::rows_type rows( frame.last_frame.get_rows() ); @@ -286,6 +292,14 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const } } + /* has cursor style changed? */ + if ( (!initialized) + || (f.ds.cursor_style != frame.cursor_style) ) { + char cursor_style_sequence_buf[6]; + snprintf( cursor_style_sequence_buf, sizeof cursor_style_sequence_buf, "\033[%d q", f.ds.cursor_style ); + frame.append( cursor_style_sequence_buf ); + } + /* have renditions changed? */ frame.update_rendition( f.ds.get_renditions(), !initialized ); @@ -483,6 +497,7 @@ bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f FrameState::FrameState( const Framebuffer &s_last ) : str(), cursor_x(0), cursor_y(0), current_rendition( 0 ), cursor_visible( s_last.ds.cursor_visible ), + cursor_style( s_last.ds.cursor_style ), last_frame( s_last ) { /* Preallocate for better performance. Make a guess-- doesn't matter for correctness */ diff --git a/src/terminal/terminaldisplay.h b/src/terminal/terminaldisplay.h index 81009b014..0d6335d43 100644 --- a/src/terminal/terminaldisplay.h +++ b/src/terminal/terminaldisplay.h @@ -44,6 +44,7 @@ namespace Terminal { int cursor_x, cursor_y; Renditions current_rendition; bool cursor_visible; + int cursor_style; const Framebuffer &last_frame; diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index 2751f3b7d..7b7d076c9 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -69,6 +69,7 @@ DrawState::DrawState( int s_width, int s_height ) combining_char_col( 0 ), combining_char_row( 0 ), default_tabs( true ), tabs( s_width ), scrolling_region_top_row( 0 ), scrolling_region_bottom_row( height - 1 ), renditions( 0 ), save(), + cursor_style( Terminal::CursorStyle::BLINKING_BLOCK ), next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ), insert_mode( false ), cursor_visible( true ), reverse_video( false ), bracketed_paste( false ), mouse_reporting_mode( MOUSE_REPORTING_NONE ), mouse_focus_event( false ), @@ -392,6 +393,7 @@ void Framebuffer::soft_reset( void ) ds.insert_mode = false; ds.origin_mode = false; ds.cursor_visible = true; /* per xterm and gnome-terminal */ + ds.cursor_style = Terminal::CursorStyle::BLINKING_BLOCK; ds.application_mode_cursor_keys = false; ds.set_scrolling_region( 0, ds.get_height() - 1 ); ds.add_rendition( 0 ); diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index de9386977..4c2345be5 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -51,6 +51,16 @@ namespace Terminal { using shared::make_shared; typedef uint32_t color_type; + enum CursorStyle { + BLINKING_BLOCK = 0, + BLINKING_BLOCK_DEFAULT = 1, + STEADY_BLOCK = 2, + BLINKING_UNDERLINE = 3, + STEADY_UNDERLINE = 4, + BLINKING_BAR = 5, + STEADY_BAR = 6, + }; + class Renditions { public: typedef enum { bold, faint, italic, underlined, blink, inverse, invisible, SIZE } attribute_type; @@ -275,6 +285,8 @@ namespace Terminal { SavedCursor save; public: + int cursor_style; + bool next_print_will_wrap; bool origin_mode; bool auto_wrap_mode; @@ -351,6 +363,7 @@ namespace Terminal { return ( width == x.width ) && ( height == x.height ) && ( cursor_col == x.cursor_col ) && ( cursor_row == x.cursor_row ) && ( cursor_visible == x.cursor_visible ) && ( reverse_video == x.reverse_video ) && ( renditions == x.renditions ) && + ( cursor_style == x.cursor_style ) && ( bracketed_paste == x.bracketed_paste ) && ( mouse_reporting_mode == x.mouse_reporting_mode ) && ( mouse_focus_event == x.mouse_focus_event ) && ( mouse_alternate_scroll == x.mouse_alternate_scroll) && ( mouse_encoding_mode == x.mouse_encoding_mode ); diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc index ca141dd35..7cf6e58f2 100644 --- a/src/terminal/terminalfunctions.cc +++ b/src/terminal/terminalfunctions.cc @@ -50,6 +50,26 @@ static void clearline( Framebuffer *fb, int row, int start, int end ) } } +/* cursor style */ +static void CSI_DECSCUSR( Framebuffer *fb, Dispatcher *dispatch ) { + int style = dispatch->getparam( 0, 0 ); + switch ( style ) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + fb->ds.cursor_style = style; + break; + default: + break; + } +} + +static Function func_CSI_DECSCUSR( CSI, " q", CSI_DECSCUSR ); + /* erase in line */ static void CSI_EL( Framebuffer *fb, Dispatcher *dispatch ) { From b0eb2e52ca98b564916b892f98f4da0573df302e Mon Sep 17 00:00:00 2001 From: Mahdi Nazemi Date: Wed, 30 Aug 2023 15:05:24 -0700 Subject: [PATCH 2/2] Clang formatting --- .clang-format | 23 + src/terminal/terminaldisplay.cc | 321 +++++------ src/terminal/terminaldisplay.h | 75 +-- src/terminal/terminalframebuffer.cc | 256 +++++---- src/terminal/terminalframebuffer.h | 859 ++++++++++++++-------------- src/terminal/terminalfunctions.cc | 398 ++++++------- 6 files changed, 984 insertions(+), 948 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..71acd6782 --- /dev/null +++ b/.clang-format @@ -0,0 +1,23 @@ +--- +Language: Cpp +BasedOnStyle: Mozilla +ColumnLimit: 116 +SpacesInParentheses: true +AlwaysBreakAfterReturnType: None +AlwaysBreakAfterDefinitionReturnType: None +SpaceBeforeCpp11BracedList: true +BreakBeforeBinaryOperators: All +Cpp11BracedListStyle: true +AllowShortBlocksOnASingleLine: Always +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: true + AfterControlStatement: Never + AfterFunction: true + AfterStruct: true + AfterEnum: true + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakConstructorInitializers: BeforeColon +... diff --git a/src/terminal/terminaldisplay.cc b/src/terminal/terminaldisplay.cc index 903407208..bbade56ca 100644 --- a/src/terminal/terminaldisplay.cc +++ b/src/terminal/terminaldisplay.cc @@ -39,7 +39,7 @@ using namespace Terminal; /* Print a new "frame" to the terminal, using ANSI/ECMA-48 escape codes. */ -static const Renditions & initial_rendition( void ) +static const Renditions& initial_rendition( void ) { const static Renditions blank = Renditions( 0 ); return blank; @@ -53,16 +53,16 @@ std::string Display::open() const std::string Display::close() const { return std::string( "\033[?1l\033[0m\033[?25h" - "\033[?1003l\033[?1002l\033[?1001l\033[?1000l" - "\033[?1015l\033[?1006l\033[?1005l" ) + - std::string( rmcup ? rmcup : "" ); + "\033[?1003l\033[?1002l\033[?1001l\033[?1000l" + "\033[?1015l\033[?1006l\033[?1005l" ) + + std::string( rmcup ? rmcup : "" ); } -std::string Display::new_frame( bool initialized, const Framebuffer &last, const Framebuffer &f ) const +std::string Display::new_frame( bool initialized, const Framebuffer& last, const Framebuffer& f ) const { FrameState frame( last ); - char tmp[ 64 ]; + char tmp[64]; /* has bell been rung? */ if ( f.get_bell_count() != frame.last_frame.get_bell_count() ) { @@ -71,69 +71,57 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const typedef Terminal::Framebuffer::title_type title_type; /* has icon name or window title changed? */ - if ( has_title && f.is_title_initialized() && - ( (!initialized) - || (f.get_icon_name() != frame.last_frame.get_icon_name()) - || (f.get_window_title() != frame.last_frame.get_window_title()) ) ) { - /* set icon name and window title */ + if ( has_title && f.is_title_initialized() + && ( ( !initialized ) || ( f.get_icon_name() != frame.last_frame.get_icon_name() ) + || ( f.get_window_title() != frame.last_frame.get_window_title() ) ) ) { + /* set icon name and window title */ if ( f.get_icon_name() == f.get_window_title() ) { /* write combined Icon Name and Window Title */ frame.append( "\033]0;" ); - const title_type &window_title( f.get_window_title() ); - for ( title_type::const_iterator i = window_title.begin(); - i != window_title.end(); - i++ ) { - frame.append( *i ); + const title_type& window_title( f.get_window_title() ); + for ( title_type::const_iterator i = window_title.begin(); i != window_title.end(); i++ ) { + frame.append( *i ); } frame.append( '\007' ); /* ST is more correct, but BEL more widely supported */ } else { /* write Icon Name */ frame.append( "\033]1;" ); - const title_type &icon_name( f.get_icon_name() ); - for ( title_type::const_iterator i = icon_name.begin(); - i != icon_name.end(); - i++ ) { - frame.append( *i ); + const title_type& icon_name( f.get_icon_name() ); + for ( title_type::const_iterator i = icon_name.begin(); i != icon_name.end(); i++ ) { + frame.append( *i ); } frame.append( '\007' ); frame.append( "\033]2;" ); - const title_type &window_title( f.get_window_title() ); - for ( title_type::const_iterator i = window_title.begin(); - i != window_title.end(); - i++ ) { - frame.append( *i ); + const title_type& window_title( f.get_window_title() ); + for ( title_type::const_iterator i = window_title.begin(); i != window_title.end(); i++ ) { + frame.append( *i ); } frame.append( '\007' ); } - } /* has clipboard changed? */ - if (f.get_clipboard() != frame.last_frame.get_clipboard()) { + if ( f.get_clipboard() != frame.last_frame.get_clipboard() ) { frame.append( "\033]52;c;" ); - const title_type &clipboard( f.get_clipboard() ); - for ( title_type::const_iterator i = clipboard.begin(); - i != clipboard.end(); - i++ ) { + const title_type& clipboard( f.get_clipboard() ); + for ( title_type::const_iterator i = clipboard.begin(); i != clipboard.end(); i++ ) { frame.append( *i ); } frame.append( '\007' ); } /* has reverse video state changed? */ - if ( (!initialized) - || (f.ds.reverse_video != frame.last_frame.ds.reverse_video) ) { + if ( ( !initialized ) || ( f.ds.reverse_video != frame.last_frame.ds.reverse_video ) ) { /* set reverse video */ - snprintf( tmp, 64, "\033[?5%c", (f.ds.reverse_video ? 'h' : 'l') ); + snprintf( tmp, 64, "\033[?5%c", ( f.ds.reverse_video ? 'h' : 'l' ) ); frame.append( tmp ); } /* has size changed? */ - if ( (!initialized) - || (f.ds.get_width() != frame.last_frame.ds.get_width()) - || (f.ds.get_height() != frame.last_frame.ds.get_height()) ) { + if ( ( !initialized ) || ( f.ds.get_width() != frame.last_frame.ds.get_width() ) + || ( f.ds.get_height() != frame.last_frame.ds.get_height() ) ) { /* reset scrolling region */ frame.append( "\033[r" ); @@ -167,7 +155,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const if ( frame.last_frame.ds.get_width() < f.ds.get_width() ) { for ( Framebuffer::rows_type::iterator p = rows.begin(); p != rows.end(); p++ ) { *p = make_shared( **p ); - (*p)->cells.resize( f.ds.get_width(), Cell( f.ds.get_background_rendition() ) ); + ( *p )->cells.resize( f.ds.get_width(), Cell( f.ds.get_background_rendition() ) ); } } /* Add rows if we've gotten a resize and new is taller than old */ @@ -185,29 +173,26 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const int scroll_height = 0; for ( int row = 0; row < f.ds.get_height(); row++ ) { - const Row *new_row = f.get_row( 0 ); - const Row *old_row = &*rows.at( row ); - if ( ! ( new_row == old_row || *new_row == *old_row ) ) { - continue; + const Row* new_row = f.get_row( 0 ); + const Row* old_row = &*rows.at( row ); + if ( !( new_row == old_row || *new_row == *old_row ) ) { + continue; } /* if row 0, we're looking at ourselves and probably didn't scroll */ if ( row == 0 ) { - break; + break; } /* found a scroll */ lines_scrolled = row; scroll_height = 1; /* how big is the region that was scrolled? */ - for ( int region_height = 1; - lines_scrolled + region_height < f.ds.get_height(); - region_height++ ) { - if ( *f.get_row( region_height ) - == *rows.at( lines_scrolled + region_height ) ) { - scroll_height = region_height + 1; - } else { - break; - } + for ( int region_height = 1; lines_scrolled + region_height < f.ds.get_height(); region_height++ ) { + if ( *f.get_row( region_height ) == *rows.at( lines_scrolled + region_height ) ) { + scroll_height = region_height + 1; + } else { + break; + } } break; @@ -217,54 +202,52 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const frame_y = scroll_height; if ( lines_scrolled ) { - /* Now we need a proper blank row. */ - if ( blank_row.get() == NULL ) { - const size_t w = f.ds.get_width(); - const color_type c = 0; - blank_row = make_shared( w, c ); - } - frame.update_rendition( initial_rendition(), true ); - - int top_margin = 0; - int bottom_margin = top_margin + lines_scrolled + scroll_height - 1; - - assert( bottom_margin < f.ds.get_height() ); - - /* Common case: if we're already on the bottom line and we're scrolling the whole - * screen, just do a CR and LFs. - */ - if ( scroll_height + lines_scrolled == f.ds.get_height() - && frame.cursor_y + 1 == f.ds.get_height() ) { - frame.append( '\r' ); - frame.append( lines_scrolled, '\n' ); - frame.cursor_x = 0; - } else { - /* set scrolling region */ - snprintf( tmp, 64, "\033[%d;%dr", - top_margin + 1, bottom_margin + 1); - frame.append( tmp ); - - /* go to bottom of scrolling region */ - frame.cursor_x = frame.cursor_y = -1; - frame.append_silent_move( bottom_margin, 0 ); - - /* scroll */ - frame.append( lines_scrolled, '\n' ); - - /* reset scrolling region */ - frame.append( "\033[r" ); - /* invalidate cursor position after unsetting scrolling region */ - frame.cursor_x = frame.cursor_y = -1; - } - - /* do the move in our local index */ - for ( int i = top_margin; i <= bottom_margin; i++ ) { - if ( i + lines_scrolled <= bottom_margin ) { - rows.at( i ) = rows.at( i + lines_scrolled ); - } else { - rows.at( i ) = blank_row; - } - } + /* Now we need a proper blank row. */ + if ( blank_row.get() == NULL ) { + const size_t w = f.ds.get_width(); + const color_type c = 0; + blank_row = make_shared( w, c ); + } + frame.update_rendition( initial_rendition(), true ); + + int top_margin = 0; + int bottom_margin = top_margin + lines_scrolled + scroll_height - 1; + + assert( bottom_margin < f.ds.get_height() ); + + /* Common case: if we're already on the bottom line and we're scrolling the whole + * screen, just do a CR and LFs. + */ + if ( scroll_height + lines_scrolled == f.ds.get_height() && frame.cursor_y + 1 == f.ds.get_height() ) { + frame.append( '\r' ); + frame.append( lines_scrolled, '\n' ); + frame.cursor_x = 0; + } else { + /* set scrolling region */ + snprintf( tmp, 64, "\033[%d;%dr", top_margin + 1, bottom_margin + 1 ); + frame.append( tmp ); + + /* go to bottom of scrolling region */ + frame.cursor_x = frame.cursor_y = -1; + frame.append_silent_move( bottom_margin, 0 ); + + /* scroll */ + frame.append( lines_scrolled, '\n' ); + + /* reset scrolling region */ + frame.append( "\033[r" ); + /* invalidate cursor position after unsetting scrolling region */ + frame.cursor_x = frame.cursor_y = -1; + } + + /* do the move in our local index */ + for ( int i = top_margin; i <= bottom_margin; i++ ) { + if ( i + lines_scrolled <= bottom_margin ) { + rows.at( i ) = rows.at( i + lines_scrolled ); + } else { + rows.at( i ) = blank_row; + } + } } } } @@ -276,15 +259,13 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const } /* has cursor location changed? */ - if ( (!initialized) - || (f.ds.get_cursor_row() != frame.cursor_y) - || (f.ds.get_cursor_col() != frame.cursor_x) ) { + if ( ( !initialized ) || ( f.ds.get_cursor_row() != frame.cursor_y ) + || ( f.ds.get_cursor_col() != frame.cursor_x ) ) { frame.append_move( f.ds.get_cursor_row(), f.ds.get_cursor_col() ); } /* has cursor visibility changed? */ - if ( (!initialized) - || (f.ds.cursor_visible != frame.cursor_visible) ) { + if ( ( !initialized ) || ( f.ds.cursor_visible != frame.cursor_visible ) ) { if ( f.ds.cursor_visible ) { frame.append( "\033[?25h" ); } else { @@ -293,8 +274,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const } /* has cursor style changed? */ - if ( (!initialized) - || (f.ds.cursor_style != frame.cursor_style) ) { + if ( ( !initialized ) || ( f.ds.cursor_style != frame.cursor_style ) ) { char cursor_style_sequence_buf[6]; snprintf( cursor_style_sequence_buf, sizeof cursor_style_sequence_buf, "\033[%d q", f.ds.cursor_style ); frame.append( cursor_style_sequence_buf ); @@ -304,67 +284,68 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const frame.update_rendition( f.ds.get_renditions(), !initialized ); /* has bracketed paste mode changed? */ - if ( (!initialized) - || (f.ds.bracketed_paste != frame.last_frame.ds.bracketed_paste) ) { + if ( ( !initialized ) || ( f.ds.bracketed_paste != frame.last_frame.ds.bracketed_paste ) ) { frame.append( f.ds.bracketed_paste ? "\033[?2004h" : "\033[?2004l" ); } /* has mouse reporting mode changed? */ - if ( (!initialized) - || (f.ds.mouse_reporting_mode != frame.last_frame.ds.mouse_reporting_mode) ) { - if (f.ds.mouse_reporting_mode == DrawState::MOUSE_REPORTING_NONE) { - frame.append("\033[?1003l"); - frame.append("\033[?1002l"); - frame.append("\033[?1001l"); - frame.append("\033[?1000l"); + if ( ( !initialized ) || ( f.ds.mouse_reporting_mode != frame.last_frame.ds.mouse_reporting_mode ) ) { + if ( f.ds.mouse_reporting_mode == DrawState::MOUSE_REPORTING_NONE ) { + frame.append( "\033[?1003l" ); + frame.append( "\033[?1002l" ); + frame.append( "\033[?1001l" ); + frame.append( "\033[?1000l" ); } else { - if (frame.last_frame.ds.mouse_reporting_mode != DrawState::MOUSE_REPORTING_NONE) { - snprintf(tmp, sizeof(tmp), "\033[?%dl", frame.last_frame.ds.mouse_reporting_mode); - frame.append(tmp); + if ( frame.last_frame.ds.mouse_reporting_mode != DrawState::MOUSE_REPORTING_NONE ) { + snprintf( tmp, sizeof( tmp ), "\033[?%dl", frame.last_frame.ds.mouse_reporting_mode ); + frame.append( tmp ); } - snprintf(tmp, sizeof(tmp), "\033[?%dh", f.ds.mouse_reporting_mode); - frame.append(tmp); + snprintf( tmp, sizeof( tmp ), "\033[?%dh", f.ds.mouse_reporting_mode ); + frame.append( tmp ); } } /* has mouse focus mode changed? */ - if ( (!initialized) - || (f.ds.mouse_focus_event != frame.last_frame.ds.mouse_focus_event) ) { + if ( ( !initialized ) || ( f.ds.mouse_focus_event != frame.last_frame.ds.mouse_focus_event ) ) { frame.append( f.ds.mouse_focus_event ? "\033[?1004h" : "\033[?1004l" ); } /* has mouse encoding mode changed? */ - if ( (!initialized) - || (f.ds.mouse_encoding_mode != frame.last_frame.ds.mouse_encoding_mode) ) { - if (f.ds.mouse_encoding_mode == DrawState::MOUSE_ENCODING_DEFAULT) { - frame.append("\033[?1015l"); - frame.append("\033[?1006l"); - frame.append("\033[?1005l"); + if ( ( !initialized ) || ( f.ds.mouse_encoding_mode != frame.last_frame.ds.mouse_encoding_mode ) ) { + if ( f.ds.mouse_encoding_mode == DrawState::MOUSE_ENCODING_DEFAULT ) { + frame.append( "\033[?1015l" ); + frame.append( "\033[?1006l" ); + frame.append( "\033[?1005l" ); } else { - if (frame.last_frame.ds.mouse_encoding_mode != DrawState::MOUSE_ENCODING_DEFAULT) { - snprintf(tmp, sizeof(tmp), "\033[?%dl", frame.last_frame.ds.mouse_encoding_mode); - frame.append(tmp); + if ( frame.last_frame.ds.mouse_encoding_mode != DrawState::MOUSE_ENCODING_DEFAULT ) { + snprintf( tmp, sizeof( tmp ), "\033[?%dl", frame.last_frame.ds.mouse_encoding_mode ); + frame.append( tmp ); } - snprintf(tmp, sizeof(tmp), "\033[?%dh", f.ds.mouse_encoding_mode); - frame.append(tmp); + snprintf( tmp, sizeof( tmp ), "\033[?%dh", f.ds.mouse_encoding_mode ); + frame.append( tmp ); } } return frame.str; } -bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f, int frame_y, const Row &old_row, bool wrap ) const +bool Display::put_row( bool initialized, + FrameState& frame, + const Framebuffer& f, + int frame_y, + const Row& old_row, + bool wrap ) const { - char tmp[ 64 ]; + char tmp[64]; int frame_x = 0; - const Row &row = *f.get_row( frame_y ); - const Row::cells_type &cells = row.cells; - const Row::cells_type &old_cells = old_row.cells; + const Row& row = *f.get_row( frame_y ); + const Row::cells_type& cells = row.cells; + const Row::cells_type& old_cells = old_row.cells; /* If we're forced to write the first column because of wrap, go ahead and do so. */ if ( wrap ) { - const Cell &cell = cells.at( 0 ); + const Cell& cell = cells.at( 0 ); frame.update_rendition( cell.get_renditions() ); frame.append_cell( cell ); frame_x += cell.get_width(); @@ -372,7 +353,7 @@ bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f } /* If rows are the same object, we don't need to do anything at all. */ - if (initialized && &row == &old_row ) { + if ( initialized && &row == &old_row ) { return false; } @@ -385,12 +366,10 @@ bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f /* iterate for every cell */ while ( frame_x < row_width ) { - const Cell &cell = cells.at( frame_x ); + const Cell& cell = cells.at( frame_x ); /* Does cell need to be drawn? Skip all this. */ - if ( initialized - && !clear_count - && ( cell == old_cells.at( frame_x ) ) ) { + if ( initialized && !clear_count && ( cell == old_cells.at( frame_x ) ) ) { frame_x += cell.get_width(); continue; } @@ -398,13 +377,13 @@ bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f /* Slurp up all the empty cells */ if ( cell.empty() ) { if ( !clear_count ) { - blank_renditions = cell.get_renditions(); + blank_renditions = cell.get_renditions(); } if ( cell.get_renditions() == blank_renditions ) { - /* Remember run of blank cells */ - clear_count++; - frame_x++; - continue; + /* Remember run of blank cells */ + clear_count++; + frame_x++; + continue; } } @@ -415,24 +394,23 @@ bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f frame.update_rendition( blank_renditions ); bool can_use_erase = has_bce || ( frame.current_rendition == initial_rendition() ); if ( can_use_erase && has_ech && clear_count > 4 ) { - snprintf( tmp, 64, "\033[%dX", clear_count ); - frame.append( tmp ); + snprintf( tmp, 64, "\033[%dX", clear_count ); + frame.append( tmp ); } else { - frame.append( clear_count, ' ' ); - frame.cursor_x = frame_x; + frame.append( clear_count, ' ' ); + frame.cursor_x = frame_x; } clear_count = 0; // If the current character is *another* empty cell in a different rendition, // we restart counting and continue here if ( cell.empty() ) { - blank_renditions = cell.get_renditions(); - clear_count = 1; - frame_x++; - continue; + blank_renditions = cell.get_renditions(); + clear_count = 1; + frame_x++; + continue; } } - /* Now draw a character cell. */ /* Move to the right position. */ const int cell_width = cell.get_width(); @@ -474,8 +452,7 @@ bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f } } - if ( ! ( wrote_last_cell - && (frame_y < f.ds.get_height() - 1) ) ) { + if ( !( wrote_last_cell && ( frame_y < f.ds.get_height() - 1 ) ) ) { return false; } /* To hint that a word-select should group the end of one line @@ -494,11 +471,9 @@ bool Display::put_row( bool initialized, FrameState &frame, const Framebuffer &f return false; } -FrameState::FrameState( const Framebuffer &s_last ) - : str(), cursor_x(0), cursor_y(0), current_rendition( 0 ), - cursor_visible( s_last.ds.cursor_visible ), - cursor_style( s_last.ds.cursor_style ), - last_frame( s_last ) +FrameState::FrameState( const Framebuffer& s_last ) + : str(), cursor_x( 0 ), cursor_y( 0 ), current_rendition( 0 ), cursor_visible( s_last.ds.cursor_visible ), + cursor_style( s_last.ds.cursor_style ), last_frame( s_last ) { /* Preallocate for better performance. Make a guess-- doesn't matter for correctness */ str.reserve( last_frame.ds.get_width() * last_frame.ds.get_height() * 4 ); @@ -506,7 +481,8 @@ FrameState::FrameState( const Framebuffer &s_last ) void FrameState::append_silent_move( int y, int x ) { - if ( cursor_x == x && cursor_y == y ) return; + if ( cursor_x == x && cursor_y == y ) + return; /* turn off cursor if necessary before moving cursor */ if ( cursor_visible ) { append( "\033[?25l" ); @@ -526,7 +502,7 @@ void FrameState::append_move( int y, int x ) // Can we use CR and/or LF? They're cheap and easier to trace. if ( x == 0 && y - last_y >= 0 && y - last_y < 5 ) { if ( last_x != 0 ) { - append( '\r' ); + append( '\r' ); } append( y - last_y, '\n' ); return; @@ -538,13 +514,14 @@ void FrameState::append_move( int y, int x ) } // More optimizations are possible. } - char tmp[ 64 ]; + char tmp[64]; snprintf( tmp, 64, "\033[%d;%dH", y + 1, x + 1 ); append( tmp ); } -void FrameState::update_rendition(const Renditions &r, bool force) { - if ( force || !(current_rendition == r) ) { +void FrameState::update_rendition( const Renditions& r, bool force ) +{ + if ( force || !( current_rendition == r ) ) { /* print renditions */ append_string( r.sgr() ); current_rendition = r; diff --git a/src/terminal/terminaldisplay.h b/src/terminal/terminaldisplay.h index 0d6335d43..24506b9d7 100644 --- a/src/terminal/terminaldisplay.h +++ b/src/terminal/terminaldisplay.h @@ -36,53 +36,60 @@ #include "terminalframebuffer.h" namespace Terminal { - /* variables used within a new_frame */ - class FrameState { - public: - std::string str; +/* variables used within a new_frame */ +class FrameState +{ +public: + std::string str; - int cursor_x, cursor_y; - Renditions current_rendition; - bool cursor_visible; - int cursor_style; + int cursor_x, cursor_y; + Renditions current_rendition; + bool cursor_visible; + int cursor_style; - const Framebuffer &last_frame; + const Framebuffer& last_frame; - FrameState( const Framebuffer &s_last ); + FrameState( const Framebuffer& s_last ); - void append( char c ) { str.append( 1, c ); } - void append( size_t s, char c ) { str.append( s, c ); } - void append( wchar_t wc ) { Cell::append_to_str( str, wc ); } - void append( const char * s ) { str.append( s ); } - void append_string( const std::string &append ) { str.append(append); } + void append( char c ) { str.append( 1, c ); } + void append( size_t s, char c ) { str.append( s, c ); } + void append( wchar_t wc ) { Cell::append_to_str( str, wc ); } + void append( const char* s ) { str.append( s ); } + void append_string( const std::string& append ) { str.append( append ); } - void append_cell(const Cell & cell) { cell.print_grapheme( str ); } - void append_silent_move( int y, int x ); - void append_move( int y, int x ); - void update_rendition( const Renditions &r, bool force = false ); - }; + void append_cell( const Cell& cell ) { cell.print_grapheme( str ); } + void append_silent_move( int y, int x ); + void append_move( int y, int x ); + void update_rendition( const Renditions& r, bool force = false ); +}; - class Display { - private: - bool has_ech; /* erase character is part of vt200 but not supported by tmux - (or by "screen" terminfo entry, which is what tmux advertises) */ +class Display +{ +private: + bool has_ech; /* erase character is part of vt200 but not supported by tmux + (or by "screen" terminfo entry, which is what tmux advertises) */ - bool has_bce; /* erases result in cell filled with background color */ + bool has_bce; /* erases result in cell filled with background color */ - bool has_title; /* supports window title and icon name */ + bool has_title; /* supports window title and icon name */ - const char *smcup, *rmcup; /* enter and exit alternate screen mode */ + const char *smcup, *rmcup; /* enter and exit alternate screen mode */ - bool put_row( bool initialized, FrameState &frame, const Framebuffer &f, int frame_y, const Row &old_row, bool wrap ) const; + bool put_row( bool initialized, + FrameState& frame, + const Framebuffer& f, + int frame_y, + const Row& old_row, + bool wrap ) const; - public: - std::string open() const; - std::string close() const; +public: + std::string open() const; + std::string close() const; - std::string new_frame( bool initialized, const Framebuffer &last, const Framebuffer &f ) const; + std::string new_frame( bool initialized, const Framebuffer& last, const Framebuffer& f ) const; - Display( bool use_environment ); - }; + Display( bool use_environment ); +}; } #endif diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index 7b7d076c9..475e84bd7 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -39,11 +39,7 @@ using namespace Terminal; Cell::Cell( color_type background_color ) - : contents(), - renditions( background_color ), - wide( false ), - fallback( false ), - wrap( false ) + : contents(), renditions( background_color ), wide( false ), fallback( false ), wrap( false ) {} void Cell::reset( color_type background_color ) @@ -59,47 +55,45 @@ void DrawState::reinitialize_tabs( unsigned int start ) { assert( default_tabs ); for ( unsigned int i = start; i < tabs.size(); i++ ) { - tabs[ i ] = ( (i % 8) == 0 ); + tabs[i] = ( ( i % 8 ) == 0 ); } } DrawState::DrawState( int s_width, int s_height ) - : width( s_width ), height( s_height ), - cursor_col( 0 ), cursor_row( 0 ), - combining_char_col( 0 ), combining_char_row( 0 ), default_tabs( true ), tabs( s_width ), - scrolling_region_top_row( 0 ), scrolling_region_bottom_row( height - 1 ), - renditions( 0 ), save(), - cursor_style( Terminal::CursorStyle::BLINKING_BLOCK ), - next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ), - insert_mode( false ), cursor_visible( true ), reverse_video( false ), + : width( s_width ), height( s_height ), cursor_col( 0 ), cursor_row( 0 ), combining_char_col( 0 ), + combining_char_row( 0 ), default_tabs( true ), tabs( s_width ), scrolling_region_top_row( 0 ), + scrolling_region_bottom_row( height - 1 ), renditions( 0 ), save(), + cursor_style( Terminal::CursorStyle::BLINKING_BLOCK ), next_print_will_wrap( false ), origin_mode( false ), + auto_wrap_mode( true ), insert_mode( false ), cursor_visible( true ), reverse_video( false ), bracketed_paste( false ), mouse_reporting_mode( MOUSE_REPORTING_NONE ), mouse_focus_event( false ), - mouse_alternate_scroll( false ), mouse_encoding_mode( MOUSE_ENCODING_DEFAULT ), application_mode_cursor_keys( false ) + mouse_alternate_scroll( false ), mouse_encoding_mode( MOUSE_ENCODING_DEFAULT ), + application_mode_cursor_keys( false ) { reinitialize_tabs( 0 ); } Framebuffer::Framebuffer( int s_width, int s_height ) - : rows(), icon_name(), window_title(), clipboard(), bell_count( 0 ), title_initialized( false ), ds( s_width, s_height ) + : rows(), icon_name(), window_title(), clipboard(), bell_count( 0 ), title_initialized( false ), + ds( s_width, s_height ) { assert( s_height > 0 ); assert( s_width > 0 ); const size_t w = s_width; const color_type c = 0; - rows = rows_type(s_height, row_pointer(make_shared( w, c ))); + rows = rows_type( s_height, row_pointer( make_shared( w, c ) ) ); } -Framebuffer::Framebuffer( const Framebuffer &other ) +Framebuffer::Framebuffer( const Framebuffer& other ) : rows( other.rows ), icon_name( other.icon_name ), window_title( other.window_title ), - clipboard( other.clipboard ), bell_count( other.bell_count ), - title_initialized( other.title_initialized ), ds( other.ds ) -{ -} + clipboard( other.clipboard ), bell_count( other.bell_count ), title_initialized( other.title_initialized ), + ds( other.ds ) +{} -Framebuffer & Framebuffer::operator=( const Framebuffer &other ) +Framebuffer& Framebuffer::operator=( const Framebuffer& other ) { if ( this != &other ) { rows = other.rows; - icon_name = other.icon_name; + icon_name = other.icon_name; window_title = other.window_title; clipboard = other.clipboard; bell_count = other.bell_count; @@ -121,15 +115,19 @@ void Framebuffer::scroll( int N ) void DrawState::new_grapheme( void ) { combining_char_col = cursor_col; - combining_char_row = cursor_row; + combining_char_row = cursor_row; } void DrawState::snap_cursor_to_border( void ) { - if ( cursor_row < limit_top() ) cursor_row = limit_top(); - if ( cursor_row > limit_bottom() ) cursor_row = limit_bottom(); - if ( cursor_col < 0 ) cursor_col = 0; - if ( cursor_col >= width ) cursor_col = width - 1; + if ( cursor_row < limit_top() ) + cursor_row = limit_top(); + if ( cursor_row > limit_bottom() ) + cursor_row = limit_bottom(); + if ( cursor_col < 0 ) + cursor_col = 0; + if ( cursor_col >= width ) + cursor_col = width - 1; } void DrawState::move_row( int N, bool relative ) @@ -158,7 +156,7 @@ void DrawState::move_col( int N, bool relative, bool implicit ) } if ( implicit ) { - next_print_will_wrap = (cursor_col >= width); + next_print_will_wrap = ( cursor_col >= width ); } snap_cursor_to_border(); @@ -171,8 +169,8 @@ void DrawState::move_col( int N, bool relative, bool implicit ) void Framebuffer::move_rows_autoscroll( int rows ) { /* don't scroll if outside the scrolling region */ - if ( (ds.get_cursor_row() < ds.get_scrolling_region_top_row()) - || (ds.get_cursor_row() > ds.get_scrolling_region_bottom_row()) ) { + if ( ( ds.get_cursor_row() < ds.get_scrolling_region_top_row() ) + || ( ds.get_cursor_row() > ds.get_scrolling_region_bottom_row() ) ) { ds.move_row( rows, true ); return; } @@ -190,12 +188,11 @@ void Framebuffer::move_rows_autoscroll( int rows ) ds.move_row( rows, true ); } -Cell *Framebuffer::get_combining_cell( void ) +Cell* Framebuffer::get_combining_cell( void ) { - if ( (ds.get_combining_char_col() < 0) - || (ds.get_combining_char_row() < 0) - || (ds.get_combining_char_col() >= ds.get_width()) - || (ds.get_combining_char_row() >= ds.get_height()) ) { + if ( ( ds.get_combining_char_col() < 0 ) || ( ds.get_combining_char_row() < 0 ) + || ( ds.get_combining_char_col() >= ds.get_width() ) + || ( ds.get_combining_char_row() >= ds.get_height() ) ) { return NULL; } /* can happen if a resize came in between */ @@ -204,26 +201,26 @@ Cell *Framebuffer::get_combining_cell( void ) void DrawState::set_tab( void ) { - tabs[ cursor_col ] = true; + tabs[cursor_col] = true; } void DrawState::clear_tab( int col ) { - tabs[ col ] = false; + tabs[col] = false; } int DrawState::get_next_tab( int count ) const { if ( count >= 0 ) { for ( int i = cursor_col + 1; i < width; i++ ) { - if ( tabs[ i ] && --count == 0 ) { - return i; + if ( tabs[i] && --count == 0 ) { + return i; } } return -1; } for ( int i = cursor_col - 1; i > 0; i-- ) { - if ( tabs[ i ] && ++count == 0 ) { + if ( tabs[i] && ++count == 0 ) { return i; } } @@ -239,8 +236,10 @@ void DrawState::set_scrolling_region( int top, int bottom ) scrolling_region_top_row = top; scrolling_region_bottom_row = bottom; - if ( scrolling_region_top_row < 0 ) scrolling_region_top_row = 0; - if ( scrolling_region_bottom_row >= height ) scrolling_region_bottom_row = height - 1; + if ( scrolling_region_top_row < 0 ) + scrolling_region_top_row = 0; + if ( scrolling_region_bottom_row >= height ) + scrolling_region_bottom_row = height - 1; if ( scrolling_region_bottom_row < scrolling_region_top_row ) scrolling_region_bottom_row = scrolling_region_top_row; @@ -262,19 +261,16 @@ int DrawState::limit_bottom( void ) const return origin_mode ? scrolling_region_bottom_row : height - 1; } -void Framebuffer::apply_renditions_to_cell( Cell *cell ) +void Framebuffer::apply_renditions_to_cell( Cell* cell ) { - if (!cell) { + if ( !cell ) { cell = get_mutable_cell(); } cell->set_renditions( ds.get_renditions() ); } SavedCursor::SavedCursor() - : cursor_col( 0 ), cursor_row( 0 ), - renditions( 0 ), - auto_wrap_mode( true ), - origin_mode( false ) + : cursor_col( 0 ), cursor_row( 0 ), renditions( 0 ), auto_wrap_mode( true ), origin_mode( false ) {} void DrawState::save_cursor( void ) @@ -300,8 +296,8 @@ void DrawState::restore_cursor( void ) void Framebuffer::insert_line( int before_row, int count ) { - if ( (before_row < ds.get_scrolling_region_top_row()) - || (before_row > ds.get_scrolling_region_bottom_row() + 1) ) { + if ( ( before_row < ds.get_scrolling_region_top_row() ) + || ( before_row > ds.get_scrolling_region_bottom_row() + 1 ) ) { return; } @@ -319,13 +315,12 @@ void Framebuffer::insert_line( int before_row, int count ) rows.erase( start, start + scroll ); // insert new rows start = rows.begin() + before_row; - rows.insert( start, scroll, newrow()); + rows.insert( start, scroll, newrow() ); } void Framebuffer::delete_line( int row, int count ) { - if ( (row < ds.get_scrolling_region_top_row()) - || (row > ds.get_scrolling_region_bottom_row()) ) { + if ( ( row < ds.get_scrolling_region_top_row() ) || ( row > ds.get_scrolling_region_bottom_row() ) ) { return; } @@ -343,7 +338,7 @@ void Framebuffer::delete_line( int row, int count ) rows.erase( start, start + scroll ); // insert a block of dummy rows start = rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - scroll; - rows.insert( start, scroll, newrow()); + rows.insert( start, scroll, newrow() ); } Row::Row( const size_t s_width, const color_type background_color ) @@ -409,26 +404,23 @@ void Framebuffer::resize( int s_width, int s_height ) int oldwidth = ds.get_width(); ds.resize( s_width, s_height ); - row_pointer blankrow( newrow()); + row_pointer blankrow( newrow() ); if ( oldheight != s_height ) { rows.resize( s_height, blankrow ); } - if (oldwidth == s_width) { + if ( oldwidth == s_width ) { return; } - for ( rows_type::iterator i = rows.begin(); - i != rows.end() && *i != blankrow; - i++ ) { + for ( rows_type::iterator i = rows.begin(); i != rows.end() && *i != blankrow; i++ ) { *i = make_shared( **i ); - (*i)->set_wrap( false ); - (*i)->cells.resize( s_width, Cell( ds.get_background_rendition() ) ); + ( *i )->set_wrap( false ); + ( *i )->cells.resize( s_width, Cell( ds.get_background_rendition() ) ); } } void DrawState::resize( int s_width, int s_height ) { - if ( (width != s_width) - || (height != s_height) ) { + if ( ( width != s_width ) || ( height != s_height ) ) { /* reset entire scrolling region on any resize */ /* xterm and rxvt-unicode do this. gnome-terminal only resets scrolling region if it has to become smaller in resize */ @@ -449,15 +441,13 @@ void DrawState::resize( int s_width, int s_height ) /* saved cursor will be snapped to border on restore */ /* invalidate combining char cell if necessary */ - if ( (combining_char_col >= width) - || (combining_char_row >= height) ) { + if ( ( combining_char_col >= width ) || ( combining_char_row >= height ) ) { combining_char_col = combining_char_row = -1; } } Renditions::Renditions( color_type s_background ) - : foreground_color( 0 ), background_color( s_background ), - attributes( 0 ) + : foreground_color( 0 ), background_color( s_background ), attributes( 0 ) {} /* This routine cannot be used to set a color beyond the 16-color set. */ @@ -477,35 +467,54 @@ void Renditions::set_rendition( color_type num ) return; } - if ( (30 <= num) && (num <= 37) ) { /* foreground color in 8-color set */ + if ( ( 30 <= num ) && ( num <= 37 ) ) { /* foreground color in 8-color set */ foreground_color = num; return; - } else if ( (40 <= num) && (num <= 47) ) { /* background color in 8-color set */ + } else if ( ( 40 <= num ) && ( num <= 47 ) ) { /* background color in 8-color set */ background_color = num; return; - } else if ( (90 <= num) && (num <= 97) ) { /* foreground color in 16-color set */ + } else if ( ( 90 <= num ) && ( num <= 97 ) ) { /* foreground color in 16-color set */ foreground_color = num - 90 + 38; return; - } else if ( (100 <= num) && (num <= 107) ) { /* background color in 16-color set */ + } else if ( ( 100 <= num ) && ( num <= 107 ) ) { /* background color in 16-color set */ background_color = num - 100 + 48; return; } bool value = num < 9; switch ( num ) { - case 1: case 22: set_attribute(bold, value); break; - case 3: case 23: set_attribute(italic, value); break; - case 4: case 24: set_attribute(underlined, value); break; - case 5: case 25: set_attribute(blink, value); break; - case 7: case 27: set_attribute(inverse, value); break; - case 8: case 28: set_attribute(invisible, value); break; - default: break; /* ignore unknown rendition */ + case 1: + case 22: + set_attribute( bold, value ); + break; + case 3: + case 23: + set_attribute( italic, value ); + break; + case 4: + case 24: + set_attribute( underlined, value ); + break; + case 5: + case 25: + set_attribute( blink, value ); + break; + case 7: + case 27: + set_attribute( inverse, value ); + break; + case 8: + case 28: + set_attribute( invisible, value ); + break; + default: + break; /* ignore unknown rendition */ } } void Renditions::set_foreground_color( int num ) { - if ( (0 <= num) && (num <= 255) ) { + if ( ( 0 <= num ) && ( num <= 255 ) ) { foreground_color = 30 + num; } else if ( is_true_color( num ) ) { foreground_color = num; @@ -514,7 +523,7 @@ void Renditions::set_foreground_color( int num ) void Renditions::set_background_color( int num ) { - if ( (0 <= num) && (num <= 255) ) { + if ( ( 0 <= num ) && ( num <= 255 ) ) { background_color = 40 + num; } else if ( is_true_color( num ) ) { background_color = num; @@ -527,19 +536,27 @@ std::string Renditions::sgr( void ) const char col[64]; ret.append( "\033[0" ); - if ( get_attribute( bold ) ) ret.append( ";1" ); - if ( get_attribute( italic ) ) ret.append( ";3" ); - if ( get_attribute( underlined ) ) ret.append( ";4" ); - if ( get_attribute( blink ) ) ret.append( ";5" ); - if ( get_attribute( inverse ) ) ret.append( ";7" ); - if ( get_attribute( invisible ) ) ret.append( ";8" ); + if ( get_attribute( bold ) ) + ret.append( ";1" ); + if ( get_attribute( italic ) ) + ret.append( ";3" ); + if ( get_attribute( underlined ) ) + ret.append( ";4" ); + if ( get_attribute( blink ) ) + ret.append( ";5" ); + if ( get_attribute( inverse ) ) + ret.append( ";7" ); + if ( get_attribute( invisible ) ) + ret.append( ";8" ); if ( foreground_color ) { if ( is_true_color( foreground_color ) ) { - snprintf( col, sizeof( col ), ";38;2;%u;%u;%u", - (foreground_color >> 16) & 0xff, - (foreground_color >> 8) & 0xff, - foreground_color & 0xff); + snprintf( col, + sizeof( col ), + ";38;2;%u;%u;%u", + ( foreground_color >> 16 ) & 0xff, + ( foreground_color >> 8 ) & 0xff, + foreground_color & 0xff ); } else if ( foreground_color > 37 ) { /* use 256-color set */ snprintf( col, sizeof( col ), ";38;5;%u", foreground_color - 30 ); } else { /* ANSI foreground color */ @@ -549,10 +566,12 @@ std::string Renditions::sgr( void ) const } if ( background_color ) { if ( is_true_color( background_color ) ) { - snprintf( col, sizeof( col ), ";48;2;%u;%u;%u", - (background_color >> 16) & 0xff, - (background_color >> 8) & 0xff, - background_color & 0xff); + snprintf( col, + sizeof( col ), + ";48;2;%u;%u;%u", + ( background_color >> 16 ) & 0xff, + ( background_color >> 8 ) & 0xff, + background_color & 0xff ); } else if ( background_color > 47 ) { /* use 256-color set */ snprintf( col, sizeof( col ), ";48;5;%u", background_color - 40 ); } else { /* ANSI background color */ @@ -568,20 +587,18 @@ std::string Renditions::sgr( void ) const void Row::reset( color_type background_color ) { gen = get_gen(); - for ( cells_type::iterator i = cells.begin(); - i != cells.end(); - i++ ) { + for ( cells_type::iterator i = cells.begin(); i != cells.end(); i++ ) { i->reset( background_color ); } } -void Framebuffer::prefix_window_title( const title_type &s ) +void Framebuffer::prefix_window_title( const title_type& s ) { if ( icon_name == window_title ) { /* preserve equivalence */ - icon_name.insert(icon_name.begin(), s.begin(), s.end() ); + icon_name.insert( icon_name.begin(), s.begin(), s.end() ); } - window_title.insert(window_title.begin(), s.begin(), s.end() ); + window_title.insert( window_title.begin(), s.begin(), s.end() ); } std::string Cell::debug_contents( void ) const @@ -592,13 +609,11 @@ std::string Cell::debug_contents( void ) const std::string chars( 1, '\'' ); print_grapheme( chars ); chars.append( "' [" ); - const char *lazycomma = ""; + const char* lazycomma = ""; char buf[64]; - for ( content_type::const_iterator i = contents.begin(); - i < contents.end(); - i++ ) { + for ( content_type::const_iterator i = contents.begin(); i < contents.end(); i++ ) { - snprintf( buf, sizeof buf, "%s0x%02x", lazycomma, static_cast(*i) ); + snprintf( buf, sizeof buf, "%s0x%02x", lazycomma, static_cast( *i ) ); chars.append( buf ); lazycomma = ", "; } @@ -606,7 +621,7 @@ std::string Cell::debug_contents( void ) const return chars; } -bool Cell::compare( const Cell &other ) const +bool Cell::compare( const Cell& other ) const { bool ret = false; @@ -617,40 +632,37 @@ bool Cell::compare( const Cell &other ) const if ( grapheme != other_grapheme ) { ret = true; - fprintf( stderr, "Graphemes: '%s' vs. '%s'\n", - grapheme.c_str(), other_grapheme.c_str() ); + fprintf( stderr, "Graphemes: '%s' vs. '%s'\n", grapheme.c_str(), other_grapheme.c_str() ); } if ( !contents_match( other ) ) { // ret = true; - fprintf( stderr, "Contents: %s (%ld) vs. %s (%ld)\n", - debug_contents().c_str(), - static_cast( contents.size() ), - other.debug_contents().c_str(), - static_cast( other.contents.size() ) ); + fprintf( stderr, + "Contents: %s (%ld) vs. %s (%ld)\n", + debug_contents().c_str(), + static_cast( contents.size() ), + other.debug_contents().c_str(), + static_cast( other.contents.size() ) ); } if ( fallback != other.fallback ) { // ret = true; - fprintf( stderr, "fallback: %d vs. %d\n", - fallback, other.fallback ); + fprintf( stderr, "fallback: %d vs. %d\n", fallback, other.fallback ); } if ( wide != other.wide ) { ret = true; - fprintf( stderr, "width: %d vs. %d\n", - wide, other.wide ); + fprintf( stderr, "width: %d vs. %d\n", wide, other.wide ); } - if ( !(renditions == other.renditions) ) { + if ( !( renditions == other.renditions ) ) { ret = true; fprintf( stderr, "renditions differ\n" ); } if ( wrap != other.wrap ) { ret = true; - fprintf( stderr, "wrap: %d vs. %d\n", - wrap, other.wrap ); + fprintf( stderr, "wrap: %d vs. %d\n", wrap, other.wrap ); } return ret; diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index 4c2345be5..6771bbe92 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -37,454 +37,469 @@ #include #include -#include #include -#include #include +#include +#include #include "shared.h" /* Terminal framebuffer */ namespace Terminal { - using shared::shared_ptr; - using shared::make_shared; - typedef uint32_t color_type; - - enum CursorStyle { - BLINKING_BLOCK = 0, - BLINKING_BLOCK_DEFAULT = 1, - STEADY_BLOCK = 2, - BLINKING_UNDERLINE = 3, - STEADY_UNDERLINE = 4, - BLINKING_BAR = 5, - STEADY_BAR = 6, - }; - - class Renditions { - public: - typedef enum { bold, faint, italic, underlined, blink, inverse, invisible, SIZE } attribute_type; - - private: - static const uint64_t true_color_mask = 0x1000000; - uint64_t foreground_color : 25; - uint64_t background_color : 25; - uint64_t attributes : 8; - - public: - Renditions( color_type s_background ); - void set_foreground_color( int num ); - void set_background_color( int num ); - void set_rendition( color_type num ); - std::string sgr( void ) const; - - static unsigned int make_true_color( unsigned int r, unsigned int g, unsigned int b ) { - return true_color_mask | (r << 16) | (g << 8) | b; - } - - static bool is_true_color(unsigned int color) { - return (color & true_color_mask) != 0; - } - - // unsigned int get_foreground_rendition() const { return foreground_color; } - unsigned int get_background_rendition() const { return background_color; } - - bool operator==( const Renditions &x ) const - { - return ( attributes == x.attributes ) - && ( foreground_color == x.foreground_color ) - && ( background_color == x.background_color ); - } - void set_attribute( attribute_type attr, bool val ) - { - attributes = val ? - ( attributes | (1 << attr) ) : - ( attributes & ~(1 << attr) ); - } - bool get_attribute( attribute_type attr ) const { return attributes & ( 1 << attr ); } - void clear_attributes() { attributes = 0; } - }; - - class Cell { - private: - typedef std::string content_type; /* can be std::string, std::vector, or __gnu_cxx::__vstring */ - content_type contents; - Renditions renditions; - unsigned int wide : 1; /* 0 = narrow, 1 = wide */ - unsigned int fallback : 1; /* first character is combining character */ - unsigned int wrap : 1; - - private: - Cell(); - public: - Cell( color_type background_color ); - - void reset( color_type background_color ); - - bool operator==( const Cell &x ) const - { - return ( (contents == x.contents) - && (fallback == x.fallback) - && (wide == x.wide) - && (renditions == x.renditions) - && (wrap == x.wrap) ); - } - - bool operator!=( const Cell &x ) const { return !operator==( x ); } - - /* Accessors for contents field */ - std::string debug_contents( void ) const; - - bool empty( void ) const { return contents.empty(); } - /* 32 seems like a reasonable limit on combining characters */ - bool full( void ) const { return contents.size() >= 32; } - void clear( void ) { contents.clear(); } - - bool is_blank( void ) const - { - // XXX fix. - return ( contents.empty() - || contents == " " - || contents == "\xC2\xA0" ); - } - - bool contents_match ( const Cell &other ) const - { - return ( is_blank() && other.is_blank() ) - || ( contents == other.contents ); +using shared::make_shared; +using shared::shared_ptr; +typedef uint32_t color_type; + +enum CursorStyle +{ + BLINKING_BLOCK = 0, + BLINKING_BLOCK_DEFAULT = 1, + STEADY_BLOCK = 2, + BLINKING_UNDERLINE = 3, + STEADY_UNDERLINE = 4, + BLINKING_BAR = 5, + STEADY_BAR = 6, +}; + +class Renditions +{ +public: + typedef enum + { + bold, + faint, + italic, + underlined, + blink, + inverse, + invisible, + SIZE + } attribute_type; + +private: + static const uint64_t true_color_mask = 0x1000000; + uint64_t foreground_color : 25; + uint64_t background_color : 25; + uint64_t attributes : 8; + +public: + Renditions( color_type s_background ); + void set_foreground_color( int num ); + void set_background_color( int num ); + void set_rendition( color_type num ); + std::string sgr( void ) const; + + static unsigned int make_true_color( unsigned int r, unsigned int g, unsigned int b ) + { + return true_color_mask | ( r << 16 ) | ( g << 8 ) | b; + } + + static bool is_true_color( unsigned int color ) { return ( color & true_color_mask ) != 0; } + + // unsigned int get_foreground_rendition() const { return foreground_color; } + unsigned int get_background_rendition() const { return background_color; } + + bool operator==( const Renditions& x ) const + { + return ( attributes == x.attributes ) && ( foreground_color == x.foreground_color ) + && ( background_color == x.background_color ); + } + void set_attribute( attribute_type attr, bool val ) + { + attributes = val ? ( attributes | ( 1 << attr ) ) : ( attributes & ~( 1 << attr ) ); + } + bool get_attribute( attribute_type attr ) const { return attributes & ( 1 << attr ); } + void clear_attributes() { attributes = 0; } +}; + +class Cell +{ +private: + typedef std::string content_type; /* can be std::string, std::vector, or __gnu_cxx::__vstring */ + content_type contents; + Renditions renditions; + unsigned int wide : 1; /* 0 = narrow, 1 = wide */ + unsigned int fallback : 1; /* first character is combining character */ + unsigned int wrap : 1; + +private: + Cell(); + +public: + Cell( color_type background_color ); + + void reset( color_type background_color ); + + bool operator==( const Cell& x ) const + { + return ( ( contents == x.contents ) && ( fallback == x.fallback ) && ( wide == x.wide ) + && ( renditions == x.renditions ) && ( wrap == x.wrap ) ); + } + + bool operator!=( const Cell& x ) const { return !operator==( x ); } + + /* Accessors for contents field */ + std::string debug_contents( void ) const; + + bool empty( void ) const { return contents.empty(); } + /* 32 seems like a reasonable limit on combining characters */ + bool full( void ) const { return contents.size() >= 32; } + void clear( void ) { contents.clear(); } + + bool is_blank( void ) const + { + // XXX fix. + return ( contents.empty() || contents == " " || contents == "\xC2\xA0" ); + } + + bool contents_match( const Cell& other ) const + { + return ( is_blank() && other.is_blank() ) || ( contents == other.contents ); + } + + bool compare( const Cell& other ) const; + + // Is this a printing ISO 8859-1 character? + static bool isprint_iso8859_1( const wchar_t c ) + { + return ( c <= 0xff && c >= 0xa0 ) || ( c <= 0x7e && c >= 0x20 ); + } + + static void append_to_str( std::string& dest, const wchar_t c ) + { + /* ASCII? Cheat. */ + if ( static_cast( c ) <= 0x7f ) { + dest.push_back( static_cast( c ) ); + return; } - - bool compare( const Cell &other ) const; - - // Is this a printing ISO 8859-1 character? - static bool isprint_iso8859_1( const wchar_t c ) - { - return ( c <= 0xff && c >= 0xa0 ) || ( c <= 0x7e && c >= 0x20 ); + static mbstate_t ps = mbstate_t(); + char tmp[MB_LEN_MAX]; + size_t ignore = wcrtomb( NULL, 0, &ps ); + (void)ignore; + size_t len = wcrtomb( tmp, c, &ps ); + dest.append( tmp, len ); + } + + void append( const wchar_t c ) + { + /* ASCII? Cheat. */ + if ( static_cast( c ) <= 0x7f ) { + contents.push_back( static_cast( c ) ); + return; } - - static void append_to_str( std::string &dest, const wchar_t c ) - { - /* ASCII? Cheat. */ - if ( static_cast(c) <= 0x7f ) { - dest.push_back( static_cast(c) ); - return; - } - static mbstate_t ps = mbstate_t(); - char tmp[MB_LEN_MAX]; - size_t ignore = wcrtomb(NULL, 0, &ps); - (void)ignore; - size_t len = wcrtomb(tmp, c, &ps); - dest.append( tmp, len ); + static mbstate_t ps = mbstate_t(); + char tmp[MB_LEN_MAX]; + size_t ignore = wcrtomb( NULL, 0, &ps ); + (void)ignore; + size_t len = wcrtomb( tmp, c, &ps ); + contents.insert( contents.end(), tmp, tmp + len ); + } + + void print_grapheme( std::string& output ) const + { + if ( contents.empty() ) { + output.append( 1, ' ' ); + return; } - - void append( const wchar_t c ) - { - /* ASCII? Cheat. */ - if ( static_cast(c) <= 0x7f ) { - contents.push_back( static_cast(c) ); - return; - } - static mbstate_t ps = mbstate_t(); - char tmp[MB_LEN_MAX]; - size_t ignore = wcrtomb(NULL, 0, &ps); - (void)ignore; - size_t len = wcrtomb(tmp, c, &ps); - contents.insert( contents.end(), tmp, tmp+len ); + /* + * cells that begin with combining character get combiner + * attached to no-break space + */ + if ( fallback ) { + output.append( "\xC2\xA0" ); } - - void print_grapheme( std::string &output ) const - { - if ( contents.empty() ) { - output.append( 1, ' ' ); - return; - } - /* - * cells that begin with combining character get combiner - * attached to no-break space - */ - if ( fallback ) { - output.append( "\xC2\xA0" ); - } - output.append( contents ); - } - - /* Other accessors */ - const Renditions& get_renditions( void ) const { return renditions; } - Renditions& get_renditions( void ) { return renditions; } - void set_renditions( const Renditions& r ) { renditions = r; } - bool get_wide( void ) const { return wide; } - void set_wide( bool w ) { wide = w; } - unsigned int get_width( void ) const { return wide + 1; } - bool get_fallback( void ) const { return fallback; } - void set_fallback( bool f ) { fallback = f; } - bool get_wrap( void ) const { return wrap; } - void set_wrap( bool f ) { wrap = f; } - }; - - class Row { - public: - typedef std::vector cells_type; - cells_type cells; - // gen is a generation counter. It can be used to quickly rule - // out the possibility of two rows being identical; this is useful - // in scrolling. - uint64_t gen; - - private: - Row(); - public: - Row( const size_t s_width, const color_type background_color ); - - void insert_cell( int col, color_type background_color ); - void delete_cell( int col, color_type background_color ); - - void reset( color_type background_color ); - - bool operator==( const Row &x ) const - { - return ( gen == x.gen && cells == x.cells ); + output.append( contents ); + } + + /* Other accessors */ + const Renditions& get_renditions( void ) const { return renditions; } + Renditions& get_renditions( void ) { return renditions; } + void set_renditions( const Renditions& r ) { renditions = r; } + bool get_wide( void ) const { return wide; } + void set_wide( bool w ) { wide = w; } + unsigned int get_width( void ) const { return wide + 1; } + bool get_fallback( void ) const { return fallback; } + void set_fallback( bool f ) { fallback = f; } + bool get_wrap( void ) const { return wrap; } + void set_wrap( bool f ) { wrap = f; } +}; + +class Row +{ +public: + typedef std::vector cells_type; + cells_type cells; + // gen is a generation counter. It can be used to quickly rule + // out the possibility of two rows being identical; this is useful + // in scrolling. + uint64_t gen; + +private: + Row(); + +public: + Row( const size_t s_width, const color_type background_color ); + + void insert_cell( int col, color_type background_color ); + void delete_cell( int col, color_type background_color ); + + void reset( color_type background_color ); + + bool operator==( const Row& x ) const { return ( gen == x.gen && cells == x.cells ); } + + bool get_wrap( void ) const { return cells.back().get_wrap(); } + void set_wrap( bool w ) { cells.back().set_wrap( w ); } + + uint64_t get_gen() const; +}; + +class SavedCursor +{ +public: + int cursor_col, cursor_row; + Renditions renditions; + /* not implemented: character set shift state */ + bool auto_wrap_mode; + bool origin_mode; + /* not implemented: state of selective erase */ + + SavedCursor(); +}; + +class DrawState +{ +private: + int width, height; + + void new_grapheme( void ); + void snap_cursor_to_border( void ); + + int cursor_col, cursor_row; + int combining_char_col, combining_char_row; + + bool default_tabs; + std::vector tabs; + + void reinitialize_tabs( unsigned int start ); + + int scrolling_region_top_row, scrolling_region_bottom_row; + + Renditions renditions; + + SavedCursor save; + +public: + int cursor_style; + + bool next_print_will_wrap; + bool origin_mode; + bool auto_wrap_mode; + bool insert_mode; + bool cursor_visible; + bool reverse_video; + bool bracketed_paste; + + enum MouseReportingMode + { + MOUSE_REPORTING_NONE = 0, + MOUSE_REPORTING_X10 = 9, + MOUSE_REPORTING_VT220 = 1000, + MOUSE_REPORTING_VT220_HILIGHT = 1001, + MOUSE_REPORTING_BTN_EVENT = 1002, + MOUSE_REPORTING_ANY_EVENT = 1003 + } mouse_reporting_mode; + + bool mouse_focus_event; // 1004 + bool mouse_alternate_scroll; // 1007 + + enum MouseEncodingMode + { + MOUSE_ENCODING_DEFAULT = 0, + MOUSE_ENCODING_UTF8 = 1005, + MOUSE_ENCODING_SGR = 1006, + MOUSE_ENCODING_URXVT = 1015 + } mouse_encoding_mode; + + bool application_mode_cursor_keys; + + /* bold, etc. */ + + void move_row( int N, bool relative = false ); + void move_col( int N, bool relative = false, bool implicit = false ); + + int get_cursor_col( void ) const { return cursor_col; } + int get_cursor_row( void ) const { return cursor_row; } + int get_combining_char_col( void ) const { return combining_char_col; } + int get_combining_char_row( void ) const { return combining_char_row; } + int get_width( void ) const { return width; } + int get_height( void ) const { return height; } + + void set_tab( void ); + void clear_tab( int col ); + void clear_default_tabs( void ) { default_tabs = false; } + /* Default tabs can't be restored without resetting the draw state. */ + int get_next_tab( int count ) const; + + void set_scrolling_region( int top, int bottom ); + + int get_scrolling_region_top_row( void ) const { return scrolling_region_top_row; } + int get_scrolling_region_bottom_row( void ) const { return scrolling_region_bottom_row; } + + int limit_top( void ) const; + int limit_bottom( void ) const; + + void set_foreground_color( int x ) { renditions.set_foreground_color( x ); } + void set_background_color( int x ) { renditions.set_background_color( x ); } + void add_rendition( color_type x ) { renditions.set_rendition( x ); } + const Renditions& get_renditions( void ) const { return renditions; } + Renditions& get_renditions( void ) { return renditions; } + int get_background_rendition( void ) const { return renditions.get_background_rendition(); } + + void save_cursor( void ); + void restore_cursor( void ); + void clear_saved_cursor( void ) { save = SavedCursor(); } + + void resize( int s_width, int s_height ); + + DrawState( int s_width, int s_height ); + + bool operator==( const DrawState& x ) const + { + /* only compare fields that affect display */ + return ( width == x.width ) && ( height == x.height ) && ( cursor_col == x.cursor_col ) + && ( cursor_row == x.cursor_row ) && ( cursor_visible == x.cursor_visible ) + && ( reverse_video == x.reverse_video ) && ( renditions == x.renditions ) + && ( cursor_style == x.cursor_style ) && ( bracketed_paste == x.bracketed_paste ) + && ( mouse_reporting_mode == x.mouse_reporting_mode ) && ( mouse_focus_event == x.mouse_focus_event ) + && ( mouse_alternate_scroll == x.mouse_alternate_scroll ) + && ( mouse_encoding_mode == x.mouse_encoding_mode ); + } +}; + +class Framebuffer +{ + // To minimize copying of rows and cells, we use shared_ptr to + // share unchanged rows between multiple Framebuffers. If we + // write to a row in a Framebuffer and it is shared with other + // owners, we copy it first. The shared_ptr naturally manages the + // usage of the actual rows themselves. + // + // We gain a couple of free extras by doing this: + // + // * A quick check for equality between rows in different + // Framebuffers is to simply compare the pointer values. If they + // are equal, then the rows are obviously identical. + // * If no row is shared, the frame has not been modified. +public: + typedef std::vector title_type; + typedef shared_ptr row_pointer; + typedef std::vector rows_type; /* can be either std::vector or std::deque */ + +private: + rows_type rows; + title_type icon_name; + title_type window_title; + title_type clipboard; + unsigned int bell_count; + bool title_initialized; /* true if the window title has been set via an OSC */ + + row_pointer newrow( void ) + { + const size_t w = ds.get_width(); + const color_type c = ds.get_background_rendition(); + return make_shared( w, c ); + } + +public: + Framebuffer( int s_width, int s_height ); + Framebuffer( const Framebuffer& other ); + Framebuffer& operator=( const Framebuffer& other ); + DrawState ds; + + const rows_type& get_rows() const { return rows; } + + void scroll( int N ); + void move_rows_autoscroll( int rows ); + + inline const Row* get_row( int row ) const + { + if ( row == -1 ) + row = ds.get_cursor_row(); + + return rows.at( row ).get(); + } + + inline const Cell* get_cell( int row = -1, int col = -1 ) const + { + if ( row == -1 ) + row = ds.get_cursor_row(); + if ( col == -1 ) + col = ds.get_cursor_col(); + + return &rows.at( row )->cells.at( col ); + } + + Row* get_mutable_row( int row ) + { + if ( row == -1 ) + row = ds.get_cursor_row(); + row_pointer& mutable_row = rows.at( row ); + // If the row is shared, copy it. + if ( !mutable_row.unique() ) { + mutable_row = make_shared( *mutable_row ); } + return mutable_row.get(); + } - bool get_wrap( void ) const { return cells.back().get_wrap(); } - void set_wrap( bool w ) { cells.back().set_wrap( w ); } - - uint64_t get_gen() const; - }; - - class SavedCursor { - public: - int cursor_col, cursor_row; - Renditions renditions; - /* not implemented: character set shift state */ - bool auto_wrap_mode; - bool origin_mode; - /* not implemented: state of selective erase */ - - SavedCursor(); - }; - - class DrawState { - private: - int width, height; - - void new_grapheme( void ); - void snap_cursor_to_border( void ); - - int cursor_col, cursor_row; - int combining_char_col, combining_char_row; - - bool default_tabs; - std::vector tabs; - - void reinitialize_tabs( unsigned int start ); - - int scrolling_region_top_row, scrolling_region_bottom_row; + Cell* get_mutable_cell( int row = -1, int col = -1 ) + { + if ( row == -1 ) + row = ds.get_cursor_row(); + if ( col == -1 ) + col = ds.get_cursor_col(); - Renditions renditions; + return &get_mutable_row( row )->cells.at( col ); + } - SavedCursor save; + Cell* get_combining_cell( void ); - public: - int cursor_style; + void apply_renditions_to_cell( Cell* cell ); - bool next_print_will_wrap; - bool origin_mode; - bool auto_wrap_mode; - bool insert_mode; - bool cursor_visible; - bool reverse_video; - bool bracketed_paste; + void insert_line( int before_row, int count ); + void delete_line( int row, int count ); - enum MouseReportingMode { - MOUSE_REPORTING_NONE = 0, - MOUSE_REPORTING_X10 = 9, - MOUSE_REPORTING_VT220 = 1000, - MOUSE_REPORTING_VT220_HILIGHT = 1001, - MOUSE_REPORTING_BTN_EVENT = 1002, - MOUSE_REPORTING_ANY_EVENT = 1003 - } mouse_reporting_mode; + void insert_cell( int row, int col ); + void delete_cell( int row, int col ); - bool mouse_focus_event; // 1004 - bool mouse_alternate_scroll; // 1007 + void reset( void ); + void soft_reset( void ); - enum MouseEncodingMode { - MOUSE_ENCODING_DEFAULT = 0, - MOUSE_ENCODING_UTF8 = 1005, - MOUSE_ENCODING_SGR = 1006, - MOUSE_ENCODING_URXVT = 1015 - } mouse_encoding_mode; + void set_title_initialized( void ) { title_initialized = true; } + bool is_title_initialized( void ) const { return title_initialized; } + void set_icon_name( const title_type& s ) { icon_name = s; } + void set_window_title( const title_type& s ) { window_title = s; } + void set_clipboard( const title_type& s ) { clipboard = s; } + const title_type& get_icon_name( void ) const { return icon_name; } + const title_type& get_window_title( void ) const { return window_title; } + const title_type& get_clipboard( void ) const { return clipboard; } - bool application_mode_cursor_keys; + void prefix_window_title( const title_type& s ); - /* bold, etc. */ + void resize( int s_width, int s_height ); - void move_row( int N, bool relative = false ); - void move_col( int N, bool relative = false, bool implicit = false ); + void reset_cell( Cell* c ) { c->reset( ds.get_background_rendition() ); } + void reset_row( Row* r ) { r->reset( ds.get_background_rendition() ); } - int get_cursor_col( void ) const { return cursor_col; } - int get_cursor_row( void ) const { return cursor_row; } - int get_combining_char_col( void ) const { return combining_char_col; } - int get_combining_char_row( void ) const { return combining_char_row; } - int get_width( void ) const { return width; } - int get_height( void ) const { return height; } + void ring_bell( void ) { bell_count++; } + unsigned int get_bell_count( void ) const { return bell_count; } - void set_tab( void ); - void clear_tab( int col ); - void clear_default_tabs( void ) { default_tabs = false; } - /* Default tabs can't be restored without resetting the draw state. */ - int get_next_tab( int count ) const; - - void set_scrolling_region( int top, int bottom ); - - int get_scrolling_region_top_row( void ) const { return scrolling_region_top_row; } - int get_scrolling_region_bottom_row( void ) const { return scrolling_region_bottom_row; } - - int limit_top( void ) const; - int limit_bottom( void ) const; - - void set_foreground_color( int x ) { renditions.set_foreground_color( x ); } - void set_background_color( int x ) { renditions.set_background_color( x ); } - void add_rendition( color_type x ) { renditions.set_rendition( x ); } - const Renditions& get_renditions( void ) const { return renditions; } - Renditions& get_renditions( void ) { return renditions; } - int get_background_rendition( void ) const { return renditions.get_background_rendition(); } - - void save_cursor( void ); - void restore_cursor( void ); - void clear_saved_cursor( void ) { save = SavedCursor(); } - - void resize( int s_width, int s_height ); - - DrawState( int s_width, int s_height ); - - bool operator==( const DrawState &x ) const - { - /* only compare fields that affect display */ - return ( width == x.width ) && ( height == x.height ) && ( cursor_col == x.cursor_col ) - && ( cursor_row == x.cursor_row ) && ( cursor_visible == x.cursor_visible ) && - ( reverse_video == x.reverse_video ) && ( renditions == x.renditions ) && - ( cursor_style == x.cursor_style ) && - ( bracketed_paste == x.bracketed_paste ) && ( mouse_reporting_mode == x.mouse_reporting_mode ) && - ( mouse_focus_event == x.mouse_focus_event ) && ( mouse_alternate_scroll == x.mouse_alternate_scroll) && - ( mouse_encoding_mode == x.mouse_encoding_mode ); - } - }; - - class Framebuffer { - // To minimize copying of rows and cells, we use shared_ptr to - // share unchanged rows between multiple Framebuffers. If we - // write to a row in a Framebuffer and it is shared with other - // owners, we copy it first. The shared_ptr naturally manages the - // usage of the actual rows themselves. - // - // We gain a couple of free extras by doing this: - // - // * A quick check for equality between rows in different - // Framebuffers is to simply compare the pointer values. If they - // are equal, then the rows are obviously identical. - // * If no row is shared, the frame has not been modified. - public: - typedef std::vector title_type; - typedef shared_ptr row_pointer; - typedef std::vector rows_type; /* can be either std::vector or std::deque */ - - private: - rows_type rows; - title_type icon_name; - title_type window_title; - title_type clipboard; - unsigned int bell_count; - bool title_initialized; /* true if the window title has been set via an OSC */ - - row_pointer newrow( void ) - { - const size_t w = ds.get_width(); - const color_type c = ds.get_background_rendition(); - return make_shared( w, c ); - } - - public: - Framebuffer( int s_width, int s_height ); - Framebuffer( const Framebuffer &other ); - Framebuffer &operator=( const Framebuffer &other ); - DrawState ds; - - const rows_type &get_rows() const { return rows; } - - void scroll( int N ); - void move_rows_autoscroll( int rows ); - - inline const Row *get_row( int row ) const - { - if ( row == -1 ) row = ds.get_cursor_row(); - - return rows.at( row ).get(); - } - - inline const Cell *get_cell( int row = -1, int col = -1 ) const - { - if ( row == -1 ) row = ds.get_cursor_row(); - if ( col == -1 ) col = ds.get_cursor_col(); - - return &rows.at( row )->cells.at( col ); - } - - Row *get_mutable_row( int row ) - { - if ( row == -1 ) row = ds.get_cursor_row(); - row_pointer &mutable_row = rows.at( row ); - // If the row is shared, copy it. - if (!mutable_row.unique()) { - mutable_row = make_shared( *mutable_row ); - } - return mutable_row.get(); - } - - Cell *get_mutable_cell( int row = -1, int col = -1 ) - { - if ( row == -1 ) row = ds.get_cursor_row(); - if ( col == -1 ) col = ds.get_cursor_col(); - - return &get_mutable_row( row )->cells.at( col ); - } - - Cell *get_combining_cell( void ); - - void apply_renditions_to_cell( Cell *cell ); - - void insert_line( int before_row, int count ); - void delete_line( int row, int count ); - - void insert_cell( int row, int col ); - void delete_cell( int row, int col ); - - void reset( void ); - void soft_reset( void ); - - void set_title_initialized( void ) { title_initialized = true; } - bool is_title_initialized( void ) const { return title_initialized; } - void set_icon_name( const title_type &s ) { icon_name = s; } - void set_window_title( const title_type &s ) { window_title = s; } - void set_clipboard( const title_type &s ) { clipboard = s; } - const title_type & get_icon_name( void ) const { return icon_name; } - const title_type & get_window_title( void ) const { return window_title; } - const title_type & get_clipboard( void ) const { return clipboard; } - - void prefix_window_title( const title_type &s ); - - void resize( int s_width, int s_height ); - - void reset_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); } - void reset_row( Row *r ) { r->reset( ds.get_background_rendition() ); } - - void ring_bell( void ) { bell_count++; } - unsigned int get_bell_count( void ) const { return bell_count; } - - bool operator==( const Framebuffer &x ) const - { - return ( rows == x.rows ) && ( window_title == x.window_title ) && ( clipboard == x.clipboard ) && ( bell_count == x.bell_count ) && ( ds == x.ds ); - } - }; + bool operator==( const Framebuffer& x ) const + { + return ( rows == x.rows ) && ( window_title == x.window_title ) && ( clipboard == x.clipboard ) + && ( bell_count == x.bell_count ) && ( ds == x.ds ); + } +}; } #endif diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc index 7cf6e58f2..76fd7f58b 100644 --- a/src/terminal/terminalfunctions.cc +++ b/src/terminal/terminalfunctions.cc @@ -30,20 +30,20 @@ also delete it here. */ -#include #include -#include #include +#include +#include +#include "parseraction.h" #include "terminaldispatcher.h" #include "terminalframebuffer.h" -#include "parseraction.h" using namespace Terminal; /* Terminal functions -- routines activated by CSI, escape or a control char */ -static void clearline( Framebuffer *fb, int row, int start, int end ) +static void clearline( Framebuffer* fb, int row, int start, int end ) { for ( int col = start; col <= end; col++ ) { fb->reset_cell( fb->get_mutable_cell( row, col ) ); @@ -51,97 +51,99 @@ static void clearline( Framebuffer *fb, int row, int start, int end ) } /* cursor style */ -static void CSI_DECSCUSR( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_DECSCUSR( Framebuffer* fb, Dispatcher* dispatch ) +{ int style = dispatch->getparam( 0, 0 ); switch ( style ) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - fb->ds.cursor_style = style; - break; - default: - break; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + fb->ds.cursor_style = style; + break; + default: + break; } } static Function func_CSI_DECSCUSR( CSI, " q", CSI_DECSCUSR ); /* erase in line */ -static void CSI_EL( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_EL( Framebuffer* fb, Dispatcher* dispatch ) { switch ( dispatch->getparam( 0, 0 ) ) { - case 0: /* default: active position to end of line, inclusive */ - clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); - break; - case 1: /* start of screen to active position, inclusive */ - clearline( fb, -1, 0, fb->ds.get_cursor_col() ); - break; - case 2: /* all of line */ - fb->reset_row( fb->get_mutable_row( -1 ) ); - break; - default: - break; + case 0: /* default: active position to end of line, inclusive */ + clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); + break; + case 1: /* start of screen to active position, inclusive */ + clearline( fb, -1, 0, fb->ds.get_cursor_col() ); + break; + case 2: /* all of line */ + fb->reset_row( fb->get_mutable_row( -1 ) ); + break; + default: + break; } } static Function func_CSI_EL( CSI, "K", CSI_EL ); /* erase in display */ -static void CSI_ED( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_ED( Framebuffer* fb, Dispatcher* dispatch ) +{ switch ( dispatch->getparam( 0, 0 ) ) { - case 0: /* active position to end of screen, inclusive */ - clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); - for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - break; - case 1: /* start of screen to active position, inclusive */ - for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - clearline( fb, -1, 0, fb->ds.get_cursor_col() ); - break; - case 2: /* entire screen */ - for ( int y = 0; y < fb->ds.get_height(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - break; - default: - break; + case 0: /* active position to end of screen, inclusive */ + clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); + for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + break; + case 1: /* start of screen to active position, inclusive */ + for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + clearline( fb, -1, 0, fb->ds.get_cursor_col() ); + break; + case 2: /* entire screen */ + for ( int y = 0; y < fb->ds.get_height(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + break; + default: + break; } } static Function func_CSI_ED( CSI, "J", CSI_ED ); /* cursor movement -- relative and absolute */ -static void CSI_cursormove( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_cursormove( Framebuffer* fb, Dispatcher* dispatch ) { int num = dispatch->getparam( 0, 1 ); - switch ( dispatch->get_dispatch_chars()[ 0 ] ) { - case 'A': - fb->ds.move_row( -num, true ); - break; - case 'B': - fb->ds.move_row( num, true ); - break; - case 'C': - fb->ds.move_col( num, true ); - break; - case 'D': - fb->ds.move_col( -num, true ); - break; - case 'H': - case 'f': - fb->ds.move_row( dispatch->getparam( 0, 1 ) - 1 ); - fb->ds.move_col( dispatch->getparam( 1, 1 ) - 1 ); - break; - default: - break; + switch ( dispatch->get_dispatch_chars()[0] ) { + case 'A': + fb->ds.move_row( -num, true ); + break; + case 'B': + fb->ds.move_row( num, true ); + break; + case 'C': + fb->ds.move_col( num, true ); + break; + case 'D': + fb->ds.move_col( -num, true ); + break; + case 'H': + case 'f': + fb->ds.move_row( dispatch->getparam( 0, 1 ) - 1 ); + fb->ds.move_col( dispatch->getparam( 1, 1 ) - 1 ); + break; + default: + break; } } @@ -153,7 +155,7 @@ static Function func_CSI_cursormove_H( CSI, "H", CSI_cursormove ); static Function func_CSI_cursormove_f( CSI, "f", CSI_cursormove ); /* device attributes */ -static void CSI_DA( Framebuffer *fb __attribute((unused)), Dispatcher *dispatch ) +static void CSI_DA( Framebuffer* fb __attribute( ( unused ) ), Dispatcher* dispatch ) { dispatch->terminal_to_host.append( "\033[?62c" ); /* plain vt220 */ } @@ -161,7 +163,7 @@ static void CSI_DA( Framebuffer *fb __attribute((unused)), Dispatcher *dispatch static Function func_CSI_DA( CSI, "c", CSI_DA ); /* secondary device attributes */ -static void CSI_SDA( Framebuffer *fb __attribute((unused)), Dispatcher *dispatch ) +static void CSI_SDA( Framebuffer* fb __attribute( ( unused ) ), Dispatcher* dispatch ) { dispatch->terminal_to_host.append( "\033[>1;10;0c" ); /* plain vt220 */ } @@ -169,7 +171,7 @@ static void CSI_SDA( Framebuffer *fb __attribute((unused)), Dispatcher *dispatch static Function func_CSI_SDA( CSI, ">c", CSI_SDA ); /* screen alignment diagnostic */ -static void Esc_DECALN( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Esc_DECALN( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { for ( int y = 0; y < fb->ds.get_height(); y++ ) { for ( int x = 0; x < fb->ds.get_width(); x++ ) { @@ -182,7 +184,7 @@ static void Esc_DECALN( Framebuffer *fb, Dispatcher *dispatch __attribute((unuse static Function func_Esc_DECALN( ESCAPE, "#8", Esc_DECALN ); /* line feed */ -static void Ctrl_LF( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Ctrl_LF( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->move_rows_autoscroll( 1 ); } @@ -194,7 +196,7 @@ static Function func_Ctrl_VT( CONTROL, "\x0b", Ctrl_LF ); static Function func_Ctrl_FF( CONTROL, "\x0c", Ctrl_LF ); /* carriage return */ -static void Ctrl_CR( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Ctrl_CR( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->ds.move_col( 0 ); } @@ -202,7 +204,7 @@ static void Ctrl_CR( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) static Function func_Ctrl_CR( CONTROL, "\x0d", Ctrl_CR ); /* backspace */ -static void Ctrl_BS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Ctrl_BS( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->ds.move_col( -1, true ); } @@ -210,7 +212,7 @@ static void Ctrl_BS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) static Function func_Ctrl_BS( CONTROL, "\x08", Ctrl_BS ); /* reverse index -- like a backwards line feed */ -static void Ctrl_RI( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Ctrl_RI( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->move_rows_autoscroll( -1 ); } @@ -218,7 +220,7 @@ static void Ctrl_RI( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) static Function func_Ctrl_RI( CONTROL, "\x8D", Ctrl_RI ); /* newline */ -static void Ctrl_NEL( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Ctrl_NEL( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->ds.move_col( 0 ); fb->move_rows_autoscroll( 1 ); @@ -227,7 +229,7 @@ static void Ctrl_NEL( Framebuffer *fb, Dispatcher *dispatch __attribute((unused) static Function func_Ctrl_NEL( CONTROL, "\x85", Ctrl_NEL ); /* horizontal tab */ -static void HT_n( Framebuffer *fb, size_t count ) +static void HT_n( Framebuffer* fb, size_t count ) { int col = fb->ds.get_next_tab( count ); if ( col == -1 ) { /* no tabs, go to end of line */ @@ -242,16 +244,16 @@ static void HT_n( Framebuffer *fb, size_t count ) fb->ds.next_print_will_wrap = wrap_state_save; } -static void Ctrl_HT( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Ctrl_HT( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { HT_n( fb, 1 ); } static Function func_Ctrl_HT( CONTROL, "\x09", Ctrl_HT, false ); -static void CSI_CxT( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_CxT( Framebuffer* fb, Dispatcher* dispatch ) { int param = dispatch->getparam( 0, 1 ); - if ( dispatch->get_dispatch_chars()[ 0 ] == 'Z' ) { + if ( dispatch->get_dispatch_chars()[0] == 'Z' ) { param = -param; } if ( param == 0 ) { @@ -264,7 +266,7 @@ static Function func_CSI_CHT( CSI, "I", CSI_CxT, false ); static Function func_CSI_CBT( CSI, "Z", CSI_CxT, false ); /* horizontal tab set */ -static void Ctrl_HTS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Ctrl_HTS( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->ds.set_tab(); } @@ -272,76 +274,79 @@ static void Ctrl_HTS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused) static Function func_Ctrl_HTS( CONTROL, "\x88", Ctrl_HTS ); /* tabulation clear */ -static void CSI_TBC( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_TBC( Framebuffer* fb, Dispatcher* dispatch ) { int param = dispatch->getparam( 0, 0 ); switch ( param ) { - case 0: /* clear this tab stop */ - fb->ds.clear_tab( fb->ds.get_cursor_col() ); - break; - case 3: /* clear all tab stops */ - fb->ds.clear_default_tabs(); - for ( int x = 0; x < fb->ds.get_width(); x++ ) { - fb->ds.clear_tab( x ); - } - break; - default: - break; + case 0: /* clear this tab stop */ + fb->ds.clear_tab( fb->ds.get_cursor_col() ); + break; + case 3: /* clear all tab stops */ + fb->ds.clear_default_tabs(); + for ( int x = 0; x < fb->ds.get_width(); x++ ) { + fb->ds.clear_tab( x ); + } + break; + default: + break; } } /* TBC preserves wrap state */ static Function func_CSI_TBC( CSI, "g", CSI_TBC, false ); -static bool *get_DEC_mode( int param, Framebuffer *fb ) { +static bool* get_DEC_mode( int param, Framebuffer* fb ) +{ switch ( param ) { - case 1: /* cursor key mode */ - return &(fb->ds.application_mode_cursor_keys); - case 3: /* 80/132. Ignore but clear screen. */ - /* clear screen */ - fb->ds.move_row( 0 ); - fb->ds.move_col( 0 ); - for ( int y = 0; y < fb->ds.get_height(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - return NULL; - case 5: /* reverse video */ - return &(fb->ds.reverse_video); - case 6: /* origin */ - fb->ds.move_row( 0 ); - fb->ds.move_col( 0 ); - return &(fb->ds.origin_mode); - case 7: /* auto wrap */ - return &(fb->ds.auto_wrap_mode); - case 25: - return &(fb->ds.cursor_visible); - case 1004: /* xterm mouse focus event */ - return &(fb->ds.mouse_focus_event); - case 1007: /* xterm mouse alternate scroll */ - return &(fb->ds.mouse_alternate_scroll); - case 2004: /* bracketed paste */ - return &(fb->ds.bracketed_paste); - default: - break; + case 1: /* cursor key mode */ + return &( fb->ds.application_mode_cursor_keys ); + case 3: /* 80/132. Ignore but clear screen. */ + /* clear screen */ + fb->ds.move_row( 0 ); + fb->ds.move_col( 0 ); + for ( int y = 0; y < fb->ds.get_height(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + return NULL; + case 5: /* reverse video */ + return &( fb->ds.reverse_video ); + case 6: /* origin */ + fb->ds.move_row( 0 ); + fb->ds.move_col( 0 ); + return &( fb->ds.origin_mode ); + case 7: /* auto wrap */ + return &( fb->ds.auto_wrap_mode ); + case 25: + return &( fb->ds.cursor_visible ); + case 1004: /* xterm mouse focus event */ + return &( fb->ds.mouse_focus_event ); + case 1007: /* xterm mouse alternate scroll */ + return &( fb->ds.mouse_alternate_scroll ); + case 2004: /* bracketed paste */ + return &( fb->ds.bracketed_paste ); + default: + break; } return NULL; } /* helper for CSI_DECSM and CSI_DECRM */ -static void set_if_available( bool *mode, bool value ) +static void set_if_available( bool* mode, bool value ) { - if ( mode ) { *mode = value; } + if ( mode ) { + *mode = value; + } } /* set private mode */ -static void CSI_DECSM( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_DECSM( Framebuffer* fb, Dispatcher* dispatch ) { for ( int i = 0; i < dispatch->param_count(); i++ ) { int param = dispatch->getparam( i, 0 ); - if (param == 9 || (param >= 1000 && param <= 1003)) { - fb->ds.mouse_reporting_mode = (Terminal::DrawState::MouseReportingMode) param; - } else if (param == 1005 || param == 1006 || param == 1015) { - fb->ds.mouse_encoding_mode = (Terminal::DrawState::MouseEncodingMode) param; + if ( param == 9 || ( param >= 1000 && param <= 1003 ) ) { + fb->ds.mouse_reporting_mode = (Terminal::DrawState::MouseReportingMode)param; + } else if ( param == 1005 || param == 1006 || param == 1015 ) { + fb->ds.mouse_encoding_mode = (Terminal::DrawState::MouseEncodingMode)param; } else { set_if_available( get_DEC_mode( param, fb ), true ); } @@ -349,13 +354,13 @@ static void CSI_DECSM( Framebuffer *fb, Dispatcher *dispatch ) } /* clear private mode */ -static void CSI_DECRM( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_DECRM( Framebuffer* fb, Dispatcher* dispatch ) { for ( int i = 0; i < dispatch->param_count(); i++ ) { int param = dispatch->getparam( i, 0 ); - if (param == 9 || (param >= 1000 && param <= 1003)) { + if ( param == 9 || ( param >= 1000 && param <= 1003 ) ) { fb->ds.mouse_reporting_mode = Terminal::DrawState::MOUSE_REPORTING_NONE; - } else if (param == 1005 || param == 1006 || param == 1015) { + } else if ( param == 1005 || param == 1006 || param == 1015 ) { fb->ds.mouse_encoding_mode = Terminal::DrawState::MOUSE_ENCODING_DEFAULT; } else { set_if_available( get_DEC_mode( param, fb ), false ); @@ -367,18 +372,19 @@ static void CSI_DECRM( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_DECSM( CSI, "?h", CSI_DECSM, false ); static Function func_CSI_DECRM( CSI, "?l", CSI_DECRM, false ); -static bool *get_ANSI_mode( int param, Framebuffer *fb ) { +static bool* get_ANSI_mode( int param, Framebuffer* fb ) +{ if ( param == 4 ) { /* insert/replace mode */ - return &(fb->ds.insert_mode); + return &( fb->ds.insert_mode ); } return NULL; } /* set mode */ -static void CSI_SM( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_SM( Framebuffer* fb, Dispatcher* dispatch ) { for ( int i = 0; i < dispatch->param_count(); i++ ) { - bool *mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); + bool* mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); if ( mode ) { *mode = true; } @@ -386,10 +392,10 @@ static void CSI_SM( Framebuffer *fb, Dispatcher *dispatch ) } /* clear mode */ -static void CSI_RM( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_RM( Framebuffer* fb, Dispatcher* dispatch ) { for ( int i = 0; i < dispatch->param_count(); i++ ) { - bool *mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); + bool* mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); if ( mode ) { *mode = false; } @@ -400,14 +406,12 @@ static Function func_CSI_SM( CSI, "h", CSI_SM ); static Function func_CSI_RM( CSI, "l", CSI_RM ); /* set top and bottom margins */ -static void CSI_DECSTBM( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_DECSTBM( Framebuffer* fb, Dispatcher* dispatch ) { int top = dispatch->getparam( 0, 1 ); int bottom = dispatch->getparam( 1, fb->ds.get_height() ); - if ( (bottom <= top) - || (top > fb->ds.get_height()) - || (top == 0 && bottom == 1) ) { + if ( ( bottom <= top ) || ( top > fb->ds.get_height() ) || ( top == 0 && bottom == 1 ) ) { return; /* invalid, xterm ignores */ } @@ -419,14 +423,15 @@ static void CSI_DECSTBM( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_DECSTMB( CSI, "r", CSI_DECSTBM ); /* terminal bell */ -static void Ctrl_BEL( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) { +static void Ctrl_BEL( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ring_bell(); } static Function func_Ctrl_BEL( CONTROL, "\x07", Ctrl_BEL ); /* select graphics rendition -- e.g., bold, blinking, etc. */ -static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_SGR( Framebuffer* fb, Dispatcher* dispatch ) { for ( int i = 0; i < dispatch->param_count(); i++ ) { int rendition = dispatch->getparam( i, 0 ); @@ -434,23 +439,20 @@ static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) because Ps of 0 in that case does not mean reset to default, even though it means that otherwise (as usually renditions are applied in order). */ - if ((rendition == 38 || rendition == 48) && - (dispatch->param_count() - i >= 3) && - (dispatch->getparam( i+1, -1 ) == 5)) { - (rendition == 38) ? - fb->ds.set_foreground_color( dispatch->getparam( i+2, 0 ) ) : - fb->ds.set_background_color( dispatch->getparam( i+2, 0 ) ); + if ( ( rendition == 38 || rendition == 48 ) && ( dispatch->param_count() - i >= 3 ) + && ( dispatch->getparam( i + 1, -1 ) == 5 ) ) { + ( rendition == 38 ) ? fb->ds.set_foreground_color( dispatch->getparam( i + 2, 0 ) ) + : fb->ds.set_background_color( dispatch->getparam( i + 2, 0 ) ); i += 2; continue; } /* True color support: ESC[ ... [34]8;2;;; ... m */ - if ( (rendition == 38 || rendition == 48) && - (dispatch->param_count() - i >= 5) && - (dispatch->getparam( i+1, -1 ) == 2)) { - unsigned int red = dispatch->getparam(i+2, 0); - unsigned int green = dispatch->getparam(i+3, 0); - unsigned int blue = dispatch->getparam(i+4, 0); + if ( ( rendition == 38 || rendition == 48 ) && ( dispatch->param_count() - i >= 5 ) + && ( dispatch->getparam( i + 1, -1 ) == 2 ) ) { + unsigned int red = dispatch->getparam( i + 2, 0 ); + unsigned int green = dispatch->getparam( i + 3, 0 ); + unsigned int blue = dispatch->getparam( i + 4, 0 ); unsigned int color; color = Renditions::make_true_color( red, green, blue ); @@ -471,12 +473,12 @@ static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_SGR( CSI, "m", CSI_SGR, false ); /* changing renditions doesn't clear wrap flag */ /* save and restore cursor */ -static void Esc_DECSC( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Esc_DECSC( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->ds.save_cursor(); } -static void Esc_DECRC( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Esc_DECRC( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->ds.restore_cursor(); } @@ -485,30 +487,28 @@ static Function func_Esc_DECSC( ESCAPE, "7", Esc_DECSC ); static Function func_Esc_DECRC( ESCAPE, "8", Esc_DECRC ); /* device status report -- e.g., cursor position (used by resize) */ -static void CSI_DSR( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_DSR( Framebuffer* fb, Dispatcher* dispatch ) { int param = dispatch->getparam( 0, 0 ); switch ( param ) { - case 5: /* device status report requested */ - dispatch->terminal_to_host.append( "\033[0n" ); - break; - case 6: /* report of active position requested */ - char cpr[ 32 ]; - snprintf( cpr, 32, "\033[%d;%dR", - fb->ds.get_cursor_row() + 1, - fb->ds.get_cursor_col() + 1 ); - dispatch->terminal_to_host.append( cpr ); - break; - default: - break; + case 5: /* device status report requested */ + dispatch->terminal_to_host.append( "\033[0n" ); + break; + case 6: /* report of active position requested */ + char cpr[32]; + snprintf( cpr, 32, "\033[%d;%dR", fb->ds.get_cursor_row() + 1, fb->ds.get_cursor_col() + 1 ); + dispatch->terminal_to_host.append( cpr ); + break; + default: + break; } } static Function func_CSI_DSR( CSI, "n", CSI_DSR ); /* insert line */ -static void CSI_IL( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_IL( Framebuffer* fb, Dispatcher* dispatch ) { int lines = dispatch->getparam( 0, 1 ); @@ -522,7 +522,7 @@ static void CSI_IL( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_IL( CSI, "L", CSI_IL ); /* delete line */ -static void CSI_DL( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_DL( Framebuffer* fb, Dispatcher* dispatch ) { int lines = dispatch->getparam( 0, 1 ); @@ -536,7 +536,7 @@ static void CSI_DL( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_DL( CSI, "M", CSI_DL ); /* insert characters */ -static void CSI_ICH( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_ICH( Framebuffer* fb, Dispatcher* dispatch ) { int cells = dispatch->getparam( 0, 1 ); @@ -548,7 +548,7 @@ static void CSI_ICH( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_ICH( CSI, "@", CSI_ICH ); /* delete character */ -static void CSI_DCH( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_DCH( Framebuffer* fb, Dispatcher* dispatch ) { int cells = dispatch->getparam( 0, 1 ); @@ -560,7 +560,7 @@ static void CSI_DCH( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_DCH( CSI, "P", CSI_DCH ); /* line position absolute */ -static void CSI_VPA( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_VPA( Framebuffer* fb, Dispatcher* dispatch ) { int row = dispatch->getparam( 0, 1 ); fb->ds.move_row( row - 1 ); @@ -569,17 +569,17 @@ static void CSI_VPA( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_VPA( CSI, "d", CSI_VPA ); /* character position absolute */ -static void CSI_HPA( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_HPA( Framebuffer* fb, Dispatcher* dispatch ) { int col = dispatch->getparam( 0, 1 ); fb->ds.move_col( col - 1 ); } -static Function func_CSI_CHA( CSI, "G", CSI_HPA ); /* ECMA-48 name: CHA */ +static Function func_CSI_CHA( CSI, "G", CSI_HPA ); /* ECMA-48 name: CHA */ static Function func_CSI_HPA( CSI, "\x60", CSI_HPA ); /* ECMA-48 name: HPA */ /* erase character */ -static void CSI_ECH( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_ECH( Framebuffer* fb, Dispatcher* dispatch ) { int num = dispatch->getparam( 0, 1 ); int limit = fb->ds.get_cursor_col() + num - 1; @@ -593,7 +593,7 @@ static void CSI_ECH( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_ECH( CSI, "X", CSI_ECH ); /* reset to initial state */ -static void Esc_RIS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void Esc_RIS( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->reset(); } @@ -601,7 +601,7 @@ static void Esc_RIS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) static Function func_Esc_RIS( ESCAPE, "c", Esc_RIS ); /* soft reset */ -static void CSI_DECSTR( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) +static void CSI_DECSTR( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) { fb->soft_reset(); } @@ -609,45 +609,47 @@ static void CSI_DECSTR( Framebuffer *fb, Dispatcher *dispatch __attribute((unuse static Function func_CSI_DECSTR( CSI, "!p", CSI_DECSTR ); /* xterm uses an Operating System Command to set the window title */ -void Dispatcher::OSC_dispatch( const Parser::OSC_End *act __attribute((unused)), Framebuffer *fb ) +void Dispatcher::OSC_dispatch( const Parser::OSC_End* act __attribute( ( unused ) ), Framebuffer* fb ) { /* handle osc copy clipboard sequence 52;c; */ - if ( OSC_string.size() >= 5 && OSC_string[ 0 ] == L'5' && - OSC_string[ 1 ] == L'2' && OSC_string[ 2 ] == L';' && - OSC_string[ 3 ] == L'c' && OSC_string[ 4 ] == L';') { - Terminal::Framebuffer::title_type clipboard( - OSC_string.begin() + 5, OSC_string.end() ); - fb->set_clipboard( clipboard ); - /* handle osc terminal title sequence */ + if ( OSC_string.size() >= 5 && OSC_string[0] == L'5' && OSC_string[1] == L'2' && OSC_string[2] == L';' + && OSC_string[3] == L'c' && OSC_string[4] == L';' ) { + Terminal::Framebuffer::title_type clipboard( OSC_string.begin() + 5, OSC_string.end() ); + fb->set_clipboard( clipboard ); + /* handle osc terminal title sequence */ } else if ( OSC_string.size() >= 1 ) { long cmd_num = -1; int offset = 0; - if ( OSC_string[ 0 ] == L';' ) { + if ( OSC_string[0] == L';' ) { /* OSC of the form "\033];\007" */ cmd_num = 0; /* treat it as as a zero */ offset = 1; - } else if ( (OSC_string.size() >= 2) && (OSC_string[ 1 ] == L';') ) { + } else if ( ( OSC_string.size() >= 2 ) && ( OSC_string[1] == L';' ) ) { /* OSC of the form "\033]X;<title>\007" where X can be: * 0: set icon name and window title * 1: set icon name * 2: set window title */ - cmd_num = OSC_string[ 0 ] - L'0'; + cmd_num = OSC_string[0] - L'0'; offset = 2; } bool set_icon = cmd_num == 0 || cmd_num == 1; bool set_title = cmd_num == 0 || cmd_num == 2; if ( set_icon || set_title ) { fb->set_title_initialized(); - int title_length = std::min(OSC_string.size(), (size_t)256); + int title_length = std::min( OSC_string.size(), (size_t)256 ); Terminal::Framebuffer::title_type newtitle( OSC_string.begin() + offset, OSC_string.begin() + title_length ); - if ( set_icon ) { fb->set_icon_name( newtitle ); } - if ( set_title ) { fb->set_window_title( newtitle ); } + if ( set_icon ) { + fb->set_icon_name( newtitle ); + } + if ( set_title ) { + fb->set_window_title( newtitle ); + } } } } /* scroll down or terminfo indn */ -static void CSI_SD( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_SD( Framebuffer* fb, Dispatcher* dispatch ) { fb->scroll( dispatch->getparam( 0, 1 ) ); } @@ -655,7 +657,7 @@ static void CSI_SD( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_SD( CSI, "S", CSI_SD ); /* scroll up or terminfo rin */ -static void CSI_SU( Framebuffer *fb, Dispatcher *dispatch ) +static void CSI_SU( Framebuffer* fb, Dispatcher* dispatch ) { fb->scroll( -dispatch->getparam( 0, 1 ) ); }