LCOV - code coverage report
Current view: top level - src/terminal - terminalframebuffer.cc (source / functions) Hit Total Coverage
Test: mosh-1.3.2 Code Coverage Lines: 314 390 80.5 %
Date: 2022-02-06 20:19:53 Functions: 30 45 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :     Mosh: the mobile shell
       3             :     Copyright 2012 Keith Winstein
       4             : 
       5             :     This program is free software: you can redistribute it and/or modify
       6             :     it under the terms of the GNU General Public License as published by
       7             :     the Free Software Foundation, either version 3 of the License, or
       8             :     (at your option) any later version.
       9             : 
      10             :     This program is distributed in the hope that it will be useful,
      11             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :     GNU General Public License for more details.
      14             : 
      15             :     You should have received a copy of the GNU General Public License
      16             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17             : 
      18             :     In addition, as a special exception, the copyright holders give
      19             :     permission to link the code of portions of this program with the
      20             :     OpenSSL library under certain conditions as described in each
      21             :     individual source file, and distribute linked combinations including
      22             :     the two.
      23             : 
      24             :     You must obey the GNU General Public License in all respects for all
      25             :     of the code used other than OpenSSL. If you modify file(s) with this
      26             :     exception, you may extend this exception to your version of the
      27             :     file(s), but you are not obligated to do so. If you do not wish to do
      28             :     so, delete this exception statement from your version. If you delete
      29             :     this exception statement from all source files in the program, then
      30             :     also delete it here.
      31             : */
      32             : 
      33             : #include <assert.h>
      34             : #include <stdio.h>
      35             : #include <stdlib.h>
      36             : 
      37             : #include "terminalframebuffer.h"
      38             : 
      39             : using namespace Terminal;
      40             : 
      41    23883993 : Cell::Cell( color_type background_color )
      42    23881689 :   : contents(),
      43    23883993 :     renditions( background_color ),
      44    23883993 :     wide( false ),
      45    23883993 :     fallback( false ),
      46    23883993 :     wrap( false )
      47        2304 : {}
      48             : 
      49    24451736 : void Cell::reset( color_type background_color )
      50             : {
      51    24451736 :   contents.clear();
      52    24451736 :   renditions = Renditions( background_color );
      53    24451736 :   wide = false;
      54    24451736 :   fallback = false;
      55    24451736 :   wrap = false;
      56    24179896 : }
      57             : 
      58       14030 : void DrawState::reinitialize_tabs( unsigned int start )
      59             : {
      60       14030 :   assert( default_tabs );
      61      980308 :   for ( unsigned int i = start; i < tabs.size(); i++ ) {
      62      966278 :     tabs[ i ] = ( (i % 8) == 0 );
      63             :   }
      64       14030 : }
      65             : 
      66       13446 : DrawState::DrawState( int s_width, int s_height )
      67       13446 :   : width( s_width ), height( s_height ),
      68       13446 :     cursor_col( 0 ), cursor_row( 0 ),
      69       13446 :     combining_char_col( 0 ), combining_char_row( 0 ), default_tabs( true ), tabs( s_width ),
      70       13446 :     scrolling_region_top_row( 0 ), scrolling_region_bottom_row( height - 1 ),
      71       13446 :     renditions( 0 ), save(),
      72       13446 :     next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ),
      73       13446 :     insert_mode( false ), cursor_visible( true ), reverse_video( false ),
      74       13446 :     bracketed_paste( false ), mouse_reporting_mode( MOUSE_REPORTING_NONE ), mouse_focus_event( false ),
      75       13446 :     mouse_alternate_scroll( false ), mouse_encoding_mode( MOUSE_ENCODING_DEFAULT ), application_mode_cursor_keys( false )
      76             : {
      77       13446 :   reinitialize_tabs( 0 );
      78       13446 : }
      79             : 
      80       13446 : Framebuffer::Framebuffer( int s_width, int s_height )
      81       13446 :   : rows(), icon_name(), window_title(), clipboard(), bell_count( 0 ), title_initialized( false ), ds( s_width, s_height )
      82             : {
      83       13446 :   assert( s_height > 0 );
      84       13446 :   assert( s_width > 0 );
      85       13446 :   const size_t w = s_width;
      86       13446 :   const color_type c = 0;
      87       26892 :   rows = rows_type(s_height, row_pointer(make_shared<Row>( w, c )));
      88       13446 : }
      89             : 
      90       20841 : Framebuffer::Framebuffer( const Framebuffer &other )
      91       20841 :   : rows( other.rows ), icon_name( other.icon_name ), window_title( other.window_title ),
      92       20841 :     clipboard( other.clipboard ), bell_count( other.bell_count ),
      93       20841 :     title_initialized( other.title_initialized ), ds( other.ds )
      94             : {
      95       20841 : }
      96             : 
      97       37121 : Framebuffer & Framebuffer::operator=( const Framebuffer &other )
      98             : {
      99       37121 :   if ( this != &other ) {
     100       37121 :     rows = other.rows;
     101       37121 :     icon_name =  other.icon_name;
     102       37121 :     window_title = other.window_title;
     103       37121 :     clipboard = other.clipboard;
     104       37121 :     bell_count = other.bell_count;
     105       37121 :     title_initialized = other.title_initialized;
     106       37121 :     ds = other.ds;
     107             :   }
     108       37121 :   return *this;
     109             : }
     110             : 
     111    23864531 : void Framebuffer::scroll( int N )
     112             : {
     113    23864531 :   if ( N >= 0 ) {
     114    23864529 :     delete_line( ds.get_scrolling_region_top_row(), N );
     115             :   } else {
     116           2 :     insert_line( ds.get_scrolling_region_top_row(), -N );
     117             :   }
     118    23864531 : }
     119             : 
     120    95776485 : void DrawState::new_grapheme( void )
     121             : {
     122    95776485 :   combining_char_col = cursor_col;
     123    95776485 :   combining_char_row = cursor_row;  
     124    24028346 : }
     125             : 
     126    95777069 : void DrawState::snap_cursor_to_border( void )
     127             : {
     128    95777069 :   if ( cursor_row < limit_top() ) cursor_row = limit_top();
     129    95777069 :   if ( cursor_row > limit_bottom() ) cursor_row = limit_bottom();
     130    95777069 :   if ( cursor_col < 0 ) cursor_col = 0;
     131    95777069 :   if ( cursor_col >= width ) cursor_col = width - 1;
     132    95777069 : }
     133             : 
     134    47806847 : void DrawState::move_row( int N, bool relative )
     135             : {
     136    47806847 :   if ( relative ) {
     137    47802078 :     cursor_row += N;
     138             :   } else {
     139        4769 :     cursor_row = N + limit_top();
     140             :   }
     141             : 
     142    47806847 :   snap_cursor_to_border();
     143    47806847 :   new_grapheme();
     144    47806847 :   next_print_will_wrap = false;
     145    47806847 : }
     146             : 
     147    47969638 : void DrawState::move_col( int N, bool relative, bool implicit )
     148             : {
     149    47969638 :   if ( implicit ) {
     150    24028346 :     new_grapheme();
     151             :   }
     152             : 
     153    47969638 :   if ( relative ) {
     154    24028440 :     cursor_col += N;
     155             :   } else {
     156    23941198 :     cursor_col = N;
     157             :   }
     158             : 
     159    47969638 :   if ( implicit ) {
     160    24028346 :     next_print_will_wrap = (cursor_col >= width);
     161             :   }
     162             : 
     163    47969638 :   snap_cursor_to_border();
     164    47969638 :   if ( !implicit ) {
     165    23941292 :     new_grapheme();
     166    23941292 :     next_print_will_wrap = false;
     167             :   }
     168    47969638 : }
     169             : 
     170    23937551 : void Framebuffer::move_rows_autoscroll( int rows )
     171             : {
     172             :   /* don't scroll if outside the scrolling region */
     173    23937551 :   if ( (ds.get_cursor_row() < ds.get_scrolling_region_top_row())
     174    23937551 :        || (ds.get_cursor_row() > ds.get_scrolling_region_bottom_row()) ) {
     175           0 :     ds.move_row( rows, true );
     176           0 :     return;
     177             :   }
     178             : 
     179    23937551 :   if ( ds.get_cursor_row() + rows > ds.get_scrolling_region_bottom_row() ) {
     180    23864527 :     int N = ds.get_cursor_row() + rows - ds.get_scrolling_region_bottom_row();
     181    23864527 :     scroll( N );
     182    23864527 :     ds.move_row( -N, true );
     183       73024 :   } else if ( ds.get_cursor_row() + rows < ds.get_scrolling_region_top_row() ) {
     184           0 :     int N = ds.get_cursor_row() + rows - ds.get_scrolling_region_top_row();
     185           0 :     scroll( N );
     186           0 :     ds.move_row( -N, true );
     187             :   }
     188             : 
     189    23937551 :   ds.move_row( rows, true );
     190             : }
     191             : 
     192          12 : Cell *Framebuffer::get_combining_cell( void )
     193             : {
     194          12 :   if ( (ds.get_combining_char_col() < 0)
     195          12 :        || (ds.get_combining_char_row() < 0)
     196          12 :        || (ds.get_combining_char_col() >= ds.get_width())
     197          24 :        || (ds.get_combining_char_row() >= ds.get_height()) ) {
     198             :     return NULL;
     199             :   } /* can happen if a resize came in between */
     200             : 
     201          12 :   return get_mutable_cell( ds.get_combining_char_row(), ds.get_combining_char_col() );
     202             : }
     203             : 
     204           0 : void DrawState::set_tab( void )
     205             : {
     206           0 :   tabs[ cursor_col ] = true;
     207           0 : }
     208             : 
     209           0 : void DrawState::clear_tab( int col )
     210             : {
     211           0 :   tabs[ col ] = false;
     212           0 : }
     213             : 
     214          10 : int DrawState::get_next_tab( int count ) const
     215             : {
     216          10 :   if ( count >= 0 ) {
     217         168 :     for ( int i = cursor_col + 1; i < width; i++ ) {
     218         166 :       if ( tabs[ i ] && --count == 0 ) {
     219           2 :         return i;
     220             :       }
     221             :     }
     222             :     return -1;
     223             :   }
     224          56 :   for ( int i = cursor_col - 1; i > 0; i-- ) {
     225          52 :     if ( tabs[ i ] && ++count == 0 ) {
     226           2 :       return i;
     227             :     }
     228             :   }
     229             :   return 0;
     230             : }
     231             : 
     232         144 : void DrawState::set_scrolling_region( int top, int bottom )
     233             : {
     234         144 :   if ( height < 1 ) {
     235             :     return;
     236             :   }
     237             : 
     238         144 :   scrolling_region_top_row = top;
     239         144 :   scrolling_region_bottom_row = bottom;
     240             : 
     241         144 :   if ( scrolling_region_top_row < 0 ) scrolling_region_top_row = 0;
     242         144 :   if ( scrolling_region_bottom_row >= height ) scrolling_region_bottom_row = height - 1;
     243             : 
     244         144 :   if ( scrolling_region_bottom_row < scrolling_region_top_row )
     245           0 :     scrolling_region_bottom_row = scrolling_region_top_row;
     246             :   /* real rule requires TWO-line scrolling region */
     247             : 
     248         144 :   if ( origin_mode ) {
     249           0 :     snap_cursor_to_border();
     250           0 :     new_grapheme();
     251             :   }
     252             : }
     253             : 
     254    95781838 : int DrawState::limit_top( void ) const
     255             : {
     256    95781838 :   return origin_mode ? scrolling_region_top_row : 0;
     257             : }
     258             : 
     259    95777069 : int DrawState::limit_bottom( void ) const
     260             : {
     261    95777069 :   return origin_mode ? scrolling_region_bottom_row : height - 1;
     262             : }
     263             : 
     264    24028342 : void Framebuffer::apply_renditions_to_cell( Cell *cell )
     265             : {
     266    24028342 :   if (!cell) {
     267           0 :     cell = get_mutable_cell();
     268             :   }
     269    24028342 :   cell->set_renditions( ds.get_renditions() );
     270    24028342 : }
     271             : 
     272       13446 : SavedCursor::SavedCursor()
     273       13446 :   : cursor_col( 0 ), cursor_row( 0 ),
     274       13446 :     renditions( 0 ),
     275       13446 :     auto_wrap_mode( true ),
     276       13446 :     origin_mode( false )
     277           0 : {}
     278             : 
     279           0 : void DrawState::save_cursor( void )
     280             : {
     281           0 :   save.cursor_col = cursor_col;
     282           0 :   save.cursor_row = cursor_row;
     283           0 :   save.renditions = renditions;
     284           0 :   save.auto_wrap_mode = auto_wrap_mode;
     285           0 :   save.origin_mode = origin_mode;
     286           0 : }
     287             : 
     288           0 : void DrawState::restore_cursor( void )
     289             : {
     290           0 :   cursor_col = save.cursor_col;
     291           0 :   cursor_row = save.cursor_row;
     292           0 :   renditions = save.renditions;
     293           0 :   auto_wrap_mode = save.auto_wrap_mode;
     294           0 :   origin_mode = save.origin_mode;
     295             : 
     296           0 :   snap_cursor_to_border(); /* we could have resized in between */
     297           0 :   new_grapheme();
     298           0 : }
     299             : 
     300          18 : void Framebuffer::insert_line( int before_row, int count )
     301             : {
     302          18 :   if ( (before_row < ds.get_scrolling_region_top_row())
     303          18 :        || (before_row > ds.get_scrolling_region_bottom_row() + 1) ) {
     304          18 :     return;
     305             :   }
     306             : 
     307          18 :   int scroll = ds.get_scrolling_region_bottom_row() + 1 - before_row;
     308          18 :   if ( count < scroll ) {
     309             :     scroll = count;
     310             :   }
     311             : 
     312          18 :   if ( scroll == 0 ) {
     313             :     return;
     314             :   }
     315             : 
     316             :   // delete old rows
     317          18 :   rows_type::iterator start = rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - scroll;
     318          18 :   rows.erase( start, start + scroll );
     319             :   // insert new rows
     320          18 :   start = rows.begin() + before_row;
     321          36 :   rows.insert( start, scroll, newrow());
     322             : }
     323             : 
     324    23864545 : void Framebuffer::delete_line( int row, int count )
     325             : {
     326    23864545 :   if ( (row < ds.get_scrolling_region_top_row())
     327    23864545 :        || (row > ds.get_scrolling_region_bottom_row()) ) {
     328    23864545 :     return;
     329             :   }
     330             : 
     331    23864545 :   int scroll = ds.get_scrolling_region_bottom_row() + 1 - row;
     332    23864545 :   if ( count < scroll ) {
     333             :     scroll = count;
     334             :   }
     335             : 
     336    23864545 :   if ( scroll == 0 ) {
     337             :     return;
     338             :   }
     339             : 
     340             :   // delete old rows
     341    23864545 :   rows_type::iterator start = rows.begin() + row;
     342    23864545 :   rows.erase( start, start + scroll );
     343             :   // insert a block of dummy rows
     344    23864545 :   start = rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - scroll;
     345    47729090 :   rows.insert( start, scroll, newrow());
     346             : }
     347             : 
     348    23880105 : Row::Row( const size_t s_width, const color_type background_color )
     349    23880105 :   : cells( s_width, Cell( background_color ) ), gen( get_gen() )
     350    23880105 : {}
     351             : 
     352    23884559 : uint64_t Row::get_gen() const
     353             : {
     354    23884559 :   static uint64_t gen_counter = 0;
     355    23880105 :   return gen_counter++;
     356             : }
     357             : 
     358           0 : void Row::insert_cell( int col, color_type background_color )
     359             : {
     360           0 :   cells.insert( cells.begin() + col, Cell( background_color ) );
     361           0 :   cells.pop_back();
     362           0 : }
     363             : 
     364           0 : void Row::delete_cell( int col, color_type background_color )
     365             : {
     366           0 :   cells.push_back( Cell( background_color ) );
     367           0 :   cells.erase( cells.begin() + col );
     368           0 : }
     369             : 
     370           0 : void Framebuffer::insert_cell( int row, int col )
     371             : {
     372           0 :   get_mutable_row( row )->insert_cell( col, ds.get_background_rendition() );
     373           0 : }
     374             : 
     375           0 : void Framebuffer::delete_cell( int row, int col )
     376             : {
     377           0 :   get_mutable_row( row )->delete_cell( col, ds.get_background_rendition() );
     378           0 : }
     379             : 
     380           0 : void Framebuffer::reset( void )
     381             : {
     382           0 :   int width = ds.get_width(), height = ds.get_height();
     383           0 :   ds = DrawState( width, height );
     384           0 :   rows = rows_type( height, newrow() );
     385           0 :   window_title.clear();
     386           0 :   clipboard.clear();
     387             :   /* do not reset bell_count */
     388           0 : }
     389             : 
     390           0 : void Framebuffer::soft_reset( void )
     391             : {
     392           0 :   ds.insert_mode = false;
     393           0 :   ds.origin_mode = false;
     394           0 :   ds.cursor_visible = true; /* per xterm and gnome-terminal */
     395           0 :   ds.application_mode_cursor_keys = false;
     396           0 :   ds.set_scrolling_region( 0, ds.get_height() - 1 );
     397           0 :   ds.add_rendition( 0 );
     398           0 :   ds.clear_saved_cursor();
     399           0 : }
     400             : 
     401         584 : void Framebuffer::resize( int s_width, int s_height )
     402             : {
     403         584 :   assert( s_width > 0 );
     404         584 :   assert( s_height > 0 );
     405             : 
     406         584 :   int oldheight = ds.get_height();
     407         584 :   int oldwidth = ds.get_width();
     408         584 :   ds.resize( s_width, s_height );
     409             : 
     410         584 :   row_pointer blankrow( newrow());
     411         584 :   if ( oldheight != s_height ) {
     412          66 :     rows.resize( s_height, blankrow );
     413             :   }
     414         584 :   if (oldwidth == s_width) {
     415         518 :     return;
     416             :   }
     417          66 :   for ( rows_type::iterator i = rows.begin();
     418        1584 :         i != rows.end() && *i != blankrow;
     419        1650 :         i++ ) {
     420        1584 :     *i = make_shared<Row>( **i );
     421        1584 :     (*i)->set_wrap( false );
     422        3168 :     (*i)->cells.resize( s_width, Cell( ds.get_background_rendition() ) );
     423             :   }
     424         584 : }
     425             : 
     426         584 : void DrawState::resize( int s_width, int s_height )
     427             : {
     428         584 :   if ( (width != s_width)
     429         518 :        || (height != s_height) ) {
     430             :     /* reset entire scrolling region on any resize */
     431             :     /* xterm and rxvt-unicode do this. gnome-terminal only
     432             :        resets scrolling region if it has to become smaller in resize */
     433         132 :     scrolling_region_top_row = 0;
     434         132 :     scrolling_region_bottom_row = s_height - 1;
     435             :   }
     436             : 
     437         584 :   tabs.resize( s_width );
     438         584 :   if ( default_tabs ) {
     439         584 :     reinitialize_tabs( width );
     440             :   }
     441             : 
     442         584 :   width = s_width;
     443         584 :   height = s_height;
     444             : 
     445         584 :   snap_cursor_to_border();
     446             : 
     447             :   /* saved cursor will be snapped to border on restore */
     448             : 
     449             :   /* invalidate combining char cell if necessary */
     450         584 :   if ( (combining_char_col >= width)
     451         584 :        || (combining_char_row >= height) ) {
     452          36 :     combining_char_col = combining_char_row = -1;
     453             :   }
     454         584 : }
     455             : 
     456    48374274 : Renditions::Renditions( color_type s_background )
     457    48374274 :   : foreground_color( 0 ), background_color( s_background ),
     458    23895135 :     attributes( 0 )
     459       25099 : {}
     460             : 
     461             : /* This routine cannot be used to set a color beyond the 16-color set. */
     462       14918 : void Renditions::set_rendition( color_type num )
     463             : {
     464       14918 :   if ( num == 0 ) {
     465       10550 :     clear_attributes();
     466       10550 :     foreground_color = background_color = 0;
     467       10550 :     return;
     468             :   }
     469             : 
     470             :   if ( num == 39 ) {
     471           2 :     foreground_color = 0;
     472           2 :     return;
     473             :   } else if ( num == 49 ) {
     474           2 :     background_color = 0;
     475           2 :     return;
     476             :   }
     477             : 
     478             :   if ( (30 <= num) && (num <= 37) ) { /* foreground color in 8-color set */
     479          80 :     foreground_color = num;
     480          80 :     return;
     481             :   } else if ( (40 <= num) && (num <= 47) ) { /* background color in 8-color set */
     482          94 :     background_color = num;
     483          94 :     return;
     484             :   } else if ( (90 <= num) && (num <= 97) ) { /* foreground color in 16-color set */
     485           0 :     foreground_color = num - 90 + 38;
     486           0 :     return;
     487             :   } else if ( (100 <= num) && (num <= 107) ) { /* background color in 16-color set */
     488           0 :     background_color = num - 100 + 48;
     489           0 :     return;
     490             :   }
     491             : 
     492        4190 :   bool value = num < 9;
     493        4190 :   switch ( num ) {
     494         930 :   case 1: case 22: set_attribute(bold, value); break;
     495         924 :   case 3: case 23: set_attribute(italic, value); break;
     496         930 :   case 4: case 24: set_attribute(underlined, value); break;
     497         468 :   case 5: case 25: set_attribute(blink, value); break;
     498         476 :   case 7: case 27: set_attribute(inverse, value); break;
     499         462 :   case 8: case 28: set_attribute(invisible, value); break;
     500             :   default: break; /* ignore unknown rendition */
     501             :   }
     502             : }
     503             : 
     504        5200 : void Renditions::set_foreground_color( int num )
     505             : {
     506        5200 :   if ( (0 <= num) && (num <= 255) ) {
     507        1504 :     foreground_color = 30 + num;
     508        3696 :   } else if ( is_true_color( num ) ) {
     509        3696 :     foreground_color = num;
     510             :   }
     511        5200 : }
     512             : 
     513        5212 : void Renditions::set_background_color( int num )
     514             : {
     515        5212 :   if ( (0 <= num) && (num <= 255) ) {
     516        1510 :     background_color = 40 + num;
     517        3702 :   } else if ( is_true_color( num ) ) {
     518        3702 :     background_color = num;
     519             :   }
     520        5212 : }
     521             : 
     522       31886 : std::string Renditions::sgr( void ) const
     523             : {
     524       31886 :   std::string ret;
     525       31886 :   char col[64];
     526             : 
     527       31886 :   ret.append( "\033[0" );
     528       31886 :   if ( get_attribute( bold ) ) ret.append( ";1" );
     529       31886 :   if ( get_attribute( italic ) ) ret.append( ";3" );
     530       31886 :   if ( get_attribute( underlined ) ) ret.append( ";4" );
     531       31886 :   if ( get_attribute( blink ) ) ret.append( ";5" );
     532       31886 :   if ( get_attribute( inverse ) ) ret.append( ";7" );
     533       31886 :   if ( get_attribute( invisible ) ) ret.append( ";8" );
     534             : 
     535       31886 :   if ( foreground_color ) {
     536       14734 :     if ( is_true_color( foreground_color ) ) {
     537       24590 :       snprintf( col, sizeof( col ), ";38;2;%u;%u;%u",
     538        9856 :                 (foreground_color >> 16) & 0xff,
     539        9856 :                 (foreground_color >> 8) & 0xff,
     540        9856 :                 foreground_color & 0xff);
     541        4878 :     } else if ( foreground_color > 37 ) { /* use 256-color set */
     542        4598 :       snprintf( col, sizeof( col ), ";38;5;%u", foreground_color - 30 );
     543             :     } else { /* ANSI foreground color */
     544         280 :       snprintf( col, sizeof( col ), ";%u", static_cast<unsigned int>( foreground_color ) );
     545             :     }
     546       14734 :     ret.append( col );
     547             :   }
     548       31886 :   if ( background_color ) {
     549       14827 :     if ( is_true_color( background_color ) ) {
     550       24700 :       snprintf( col, sizeof( col ), ";48;2;%u;%u;%u",
     551        9873 :                 (background_color >> 16) & 0xff,
     552        9873 :                 (background_color >> 8) & 0xff,
     553        9873 :                 background_color & 0xff);
     554        4954 :     } else if ( background_color > 47 ) { /* use 256-color set */
     555        4615 :       snprintf( col, sizeof( col ), ";48;5;%u", background_color - 40 );
     556             :     } else { /* ANSI background color */
     557         339 :       snprintf( col, sizeof( col ), ";%u", static_cast<unsigned int>( background_color ) );
     558             :     }
     559       14827 :     ret.append( col );
     560             :   }
     561       31886 :   ret.append( "m" );
     562             : 
     563       31886 :   return ret;
     564           0 : }
     565             : 
     566        4454 : void Row::reset( color_type background_color )
     567             : {
     568        4454 :   gen = get_gen();
     569      276294 :   for ( cells_type::iterator i = cells.begin();
     570      276294 :         i != cells.end();
     571      276294 :         i++ ) {
     572      271840 :     i->reset( background_color );
     573             :   }
     574        4454 : }
     575             : 
     576        6536 : void Framebuffer::prefix_window_title( const title_type &s )
     577             : {
     578        6536 :   if ( icon_name == window_title ) {
     579             :     /* preserve equivalence */
     580        6536 :     icon_name.insert(icon_name.begin(), s.begin(), s.end() );
     581             :   }
     582        6536 :   window_title.insert(window_title.begin(), s.begin(), s.end() );
     583        6536 : }
     584             : 
     585           8 : std::string Cell::debug_contents( void ) const
     586             : {
     587           8 :   if ( contents.empty() ) {
     588           0 :     return "'_' ()";
     589             :   }
     590           8 :   std::string chars( 1, '\'' );
     591           8 :   print_grapheme( chars );
     592           8 :   chars.append( "' [" );
     593           8 :   const char *lazycomma = "";
     594           8 :   char buf[64];
     595           8 :   for ( content_type::const_iterator i = contents.begin();
     596          32 :         i < contents.end();
     597          32 :         i++ ) {
     598             : 
     599          24 :     snprintf( buf, sizeof buf, "%s0x%02x", lazycomma, static_cast<uint8_t>(*i) );
     600          24 :     chars.append( buf );
     601          24 :     lazycomma = ", ";
     602             :   }
     603           8 :   chars.append( "]" );
     604          16 :   return chars;
     605           8 : }
     606             : 
     607    10256000 : bool Cell::compare( const Cell &other ) const
     608             : {
     609    10256000 :   bool ret = false;
     610             : 
     611    10256000 :   std::string grapheme, other_grapheme;
     612             : 
     613    10256000 :   print_grapheme( grapheme );
     614    10256000 :   other.print_grapheme( other_grapheme );
     615             : 
     616    10256000 :   if ( grapheme != other_grapheme ) {
     617           0 :     ret = true;
     618           0 :   fprintf( stderr, "Graphemes: '%s' vs. '%s'\n",
     619             :            grapheme.c_str(), other_grapheme.c_str() );
     620             :   }
     621             : 
     622    10256000 :   if ( !contents_match( other ) ) {
     623             :     // ret = true;
     624           8 :     fprintf( stderr, "Contents: %s (%ld) vs. %s (%ld)\n",
     625           8 :              debug_contents().c_str(),
     626           4 :              static_cast<long int>( contents.size() ),
     627           8 :              other.debug_contents().c_str(),
     628           4 :              static_cast<long int>( other.contents.size() ) );
     629             :   }
     630             : 
     631    10256000 :   if ( fallback != other.fallback ) {
     632             :     // ret = true;
     633    10256004 :     fprintf( stderr, "fallback: %d vs. %d\n",
     634           4 :              fallback, other.fallback );
     635             :   }
     636             : 
     637    10256000 :   if ( wide != other.wide ) {
     638           0 :     ret = true;
     639    10256000 :     fprintf( stderr, "width: %d vs. %d\n",
     640           0 :              wide, other.wide );
     641             :   }
     642             : 
     643    10256000 :   if ( !(renditions == other.renditions) ) {
     644           0 :     ret = true;
     645           0 :     fprintf( stderr, "renditions differ\n" );
     646             :   }
     647             : 
     648    10256000 :   if ( wrap != other.wrap ) {
     649           0 :     ret = true;
     650    10256000 :     fprintf( stderr, "wrap: %d vs. %d\n",
     651           0 :              wrap, other.wrap );
     652             :   }
     653             : 
     654    10256000 :   return ret;
     655    10256000 : }

Generated by: LCOV version 1.14