LCOV - code coverage report
Current view: top level - src/terminal - terminalfunctions.cc (source / functions) Hit Total Coverage
Test: mosh-1.3.2 Code Coverage Lines: 135 296 45.6 %
Date: 2022-02-06 20:19:53 Functions: 18 40 45.0 %
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 <unistd.h>
      34             : #include <algorithm>
      35             : #include <string>
      36             : #include <stdio.h>
      37             : 
      38             : #include "terminaldispatcher.h"
      39             : #include "terminalframebuffer.h"
      40             : #include "parseraction.h"
      41             : 
      42             : using namespace Terminal;
      43             : 
      44             : /* Terminal functions -- routines activated by CSI, escape or a control char */
      45             : 
      46        2562 : static void clearline( Framebuffer *fb, int row, int start, int end )
      47             : {
      48      154116 :   for ( int col = start; col <= end; col++ ) {
      49      151554 :     fb->reset_cell( fb->get_mutable_cell( row, col ) );
      50             :   }
      51        2562 : }
      52             : 
      53             : /* erase in line */
      54        2522 : static void CSI_EL( Framebuffer *fb, Dispatcher *dispatch )
      55             : {
      56        2522 :   switch ( dispatch->getparam( 0, 0 ) ) {
      57        2522 :   case 0: /* default: active position to end of line, inclusive */
      58        2522 :     clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 );    
      59        2522 :     break;
      60           0 :   case 1: /* start of screen to active position, inclusive */
      61           0 :     clearline( fb, -1, 0, fb->ds.get_cursor_col() );
      62           0 :     break;
      63           0 :   case 2: /* all of line */
      64           0 :     fb->reset_row( fb->get_mutable_row( -1 ) );
      65             :     break;
      66             :   default:
      67             :     break;
      68             :   }
      69        2522 : }
      70             : 
      71             : static Function func_CSI_EL( CSI, "K", CSI_EL );
      72             : 
      73             : /* erase in display */
      74         216 : static void CSI_ED( Framebuffer *fb, Dispatcher *dispatch ) {
      75         216 :   switch ( dispatch->getparam( 0, 0 ) ) {
      76          38 :   case 0: /* active position to end of screen, inclusive */
      77          38 :     clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 );
      78         906 :     for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) {
      79         868 :       fb->reset_row( fb->get_mutable_row( y ) );
      80             :     }
      81             :     break;
      82             :   case 1: /* start of screen to active position, inclusive */
      83           4 :     for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) {
      84           2 :       fb->reset_row( fb->get_mutable_row( y ) );
      85             :     }
      86           2 :     clearline( fb, -1, 0, fb->ds.get_cursor_col() );
      87           2 :     break;
      88             :   case 2: /* entire screen */
      89        3760 :     for ( int y = 0; y < fb->ds.get_height(); y++ ) {
      90        3584 :       fb->reset_row( fb->get_mutable_row( y ) );
      91             :     }
      92             :     break;
      93             :   default:
      94             :     break;
      95             :   }
      96         216 : }
      97             : 
      98             : static Function func_CSI_ED( CSI, "J", CSI_ED );
      99             : 
     100             : /* cursor movement -- relative and absolute */
     101        3761 : static void CSI_cursormove( Framebuffer *fb, Dispatcher *dispatch )
     102             : {
     103        3761 :   int num = dispatch->getparam( 0, 1 );
     104             : 
     105        3761 :   switch ( dispatch->get_dispatch_chars()[ 0 ] ) {
     106           0 :   case 'A':
     107           0 :     fb->ds.move_row( -num, true );
     108           0 :     break;
     109           0 :   case 'B':
     110           0 :     fb->ds.move_row( num, true );
     111           0 :     break;
     112           0 :   case 'C':
     113           0 :     fb->ds.move_col( num, true );
     114           0 :     break;
     115           0 :   case 'D':
     116           0 :     fb->ds.move_col( -num, true );
     117           0 :     break;
     118        3761 :   case 'H':
     119        3761 :   case 'f':
     120        3761 :     fb->ds.move_row( dispatch->getparam( 0, 1 ) - 1 );
     121        3761 :     fb->ds.move_col( dispatch->getparam( 1, 1 ) - 1 );
     122        3761 :     break;
     123             :   default:
     124             :     break;
     125             :   }
     126        3761 : }
     127             : 
     128             : static Function func_CSI_cursormove_A( CSI, "A", CSI_cursormove );
     129             : static Function func_CSI_cursormove_B( CSI, "B", CSI_cursormove );
     130             : static Function func_CSI_cursormove_C( CSI, "C", CSI_cursormove );
     131             : static Function func_CSI_cursormove_D( CSI, "D", CSI_cursormove );
     132             : static Function func_CSI_cursormove_H( CSI, "H", CSI_cursormove );
     133             : static Function func_CSI_cursormove_f( CSI, "f", CSI_cursormove );
     134             : 
     135             : /* device attributes */
     136           0 : static void CSI_DA( Framebuffer *fb __attribute((unused)), Dispatcher *dispatch )
     137             : {
     138           0 :   dispatch->terminal_to_host.append( "\033[?62c" ); /* plain vt220 */
     139           0 : }
     140             : 
     141             : static Function func_CSI_DA( CSI, "c", CSI_DA );
     142             : 
     143             : /* secondary device attributes */
     144           0 : static void CSI_SDA( Framebuffer *fb __attribute((unused)), Dispatcher *dispatch )
     145             : {
     146           0 :   dispatch->terminal_to_host.append( "\033[>1;10;0c" ); /* plain vt220 */
     147           0 : }
     148             : 
     149             : static Function func_CSI_SDA( CSI, ">c", CSI_SDA );
     150             : 
     151             : /* screen alignment diagnostic */
     152           0 : static void Esc_DECALN( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     153             : {
     154           0 :   for ( int y = 0; y < fb->ds.get_height(); y++ ) {
     155           0 :     for ( int x = 0; x < fb->ds.get_width(); x++ ) {
     156           0 :       fb->reset_cell( fb->get_mutable_cell( y, x ) );
     157           0 :       fb->get_mutable_cell( y, x )->append( 'E' );
     158             :     }
     159             :   }
     160           0 : }
     161             : 
     162             : static Function func_Esc_DECALN( ESCAPE, "#8", Esc_DECALN );
     163             : 
     164             : /* line feed */
     165    23937259 : static void Ctrl_LF( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     166             : {
     167    23937259 :   fb->move_rows_autoscroll( 1 );
     168    23937259 : }
     169             : 
     170             : /* same procedure for index, vertical tab, and form feed control codes */
     171             : static Function func_Ctrl_LF( CONTROL, "\x0a", Ctrl_LF );
     172             : static Function func_Ctrl_IND( CONTROL, "\x84", Ctrl_LF );
     173             : static Function func_Ctrl_VT( CONTROL, "\x0b", Ctrl_LF );
     174             : static Function func_Ctrl_FF( CONTROL, "\x0c", Ctrl_LF );
     175             : 
     176             : /* carriage return */
     177    23936095 : static void Ctrl_CR( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     178             : {
     179    23936095 :   fb->ds.move_col( 0 );
     180    23936095 : }
     181             : 
     182             : static Function func_Ctrl_CR( CONTROL, "\x0d", Ctrl_CR );
     183             : 
     184             : /* backspace */
     185          94 : static void Ctrl_BS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     186             : {
     187          94 :   fb->ds.move_col( -1, true );
     188          94 : }
     189             : 
     190             : static Function func_Ctrl_BS( CONTROL, "\x08", Ctrl_BS );
     191             : 
     192             : /* reverse index -- like a backwards line feed */
     193           0 : static void Ctrl_RI( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     194             : {
     195           0 :   fb->move_rows_autoscroll( -1 );
     196           0 : }
     197             : 
     198             : static Function func_Ctrl_RI( CONTROL, "\x8D", Ctrl_RI );
     199             : 
     200             : /* newline */
     201           0 : static void Ctrl_NEL( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     202             : {
     203           0 :   fb->ds.move_col( 0 );
     204           0 :   fb->move_rows_autoscroll( 1 );
     205           0 : }
     206             : 
     207             : static Function func_Ctrl_NEL( CONTROL, "\x85", Ctrl_NEL );
     208             : 
     209             : /* horizontal tab */
     210          10 : static void HT_n( Framebuffer *fb, size_t count )
     211             : {
     212          10 :   int col = fb->ds.get_next_tab( count );
     213          10 :   if ( col == -1 ) { /* no tabs, go to end of line */
     214           2 :     col = fb->ds.get_width() - 1;
     215             :   }
     216             : 
     217             :   /* A horizontal tab is the only operation that preserves but
     218             :      does not set the wrap state. It also starts a new grapheme. */
     219             : 
     220          10 :   bool wrap_state_save = fb->ds.next_print_will_wrap;
     221          10 :   fb->ds.move_col( col, false );
     222          10 :   fb->ds.next_print_will_wrap = wrap_state_save;
     223          10 : }
     224             : 
     225           0 : static void Ctrl_HT( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     226             : {
     227           0 :   HT_n( fb, 1 );
     228           0 : }
     229             : static Function func_Ctrl_HT( CONTROL, "\x09", Ctrl_HT, false );
     230             : 
     231          10 : static void CSI_CxT( Framebuffer *fb, Dispatcher *dispatch )
     232             : {
     233          10 :   int param = dispatch->getparam( 0, 1 );
     234          10 :   if ( dispatch->get_dispatch_chars()[ 0 ] == 'Z' ) {
     235           6 :     param = -param;
     236             :   }
     237          10 :   if ( param == 0 ) {
     238             :     return;
     239             :   }
     240          10 :   HT_n( fb, param );
     241             : }
     242             : 
     243             : static Function func_CSI_CHT( CSI, "I", CSI_CxT, false );
     244             : static Function func_CSI_CBT( CSI, "Z", CSI_CxT, false );
     245             : 
     246             : /* horizontal tab set */
     247           0 : static void Ctrl_HTS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     248             : {
     249           0 :   fb->ds.set_tab();
     250           0 : }
     251             : 
     252             : static Function func_Ctrl_HTS( CONTROL, "\x88", Ctrl_HTS );
     253             : 
     254             : /* tabulation clear */
     255           0 : static void CSI_TBC( Framebuffer *fb, Dispatcher *dispatch )
     256             : {
     257           0 :   int param = dispatch->getparam( 0, 0 );
     258           0 :   switch ( param ) {
     259           0 :   case 0: /* clear this tab stop */
     260           0 :     fb->ds.clear_tab( fb->ds.get_cursor_col() );    
     261           0 :     break;
     262           0 :   case 3: /* clear all tab stops */
     263           0 :     fb->ds.clear_default_tabs();
     264           0 :     for ( int x = 0; x < fb->ds.get_width(); x++ ) {
     265           0 :       fb->ds.clear_tab( x );
     266             :     }
     267             :     break;
     268             :   default:
     269             :     break;
     270             :   }
     271           0 : }
     272             : 
     273             : /* TBC preserves wrap state */
     274             : static Function func_CSI_TBC( CSI, "g", CSI_TBC, false );
     275             : 
     276        8616 : static bool *get_DEC_mode( int param, Framebuffer *fb ) {
     277        8616 :   switch ( param ) {
     278           4 :   case 1: /* cursor key mode */
     279           4 :     return &(fb->ds.application_mode_cursor_keys);
     280           0 :   case 3: /* 80/132. Ignore but clear screen. */
     281             :     /* clear screen */
     282           0 :     fb->ds.move_row( 0 );
     283           0 :     fb->ds.move_col( 0 );
     284           0 :     for ( int y = 0; y < fb->ds.get_height(); y++ ) {
     285           0 :       fb->reset_row( fb->get_mutable_row( y ) );
     286             :     }
     287             :     return NULL;
     288           0 :   case 5: /* reverse video */
     289           0 :     return &(fb->ds.reverse_video);
     290           0 :   case 6: /* origin */
     291           0 :     fb->ds.move_row( 0 );
     292           0 :     fb->ds.move_col( 0 );
     293           0 :     return &(fb->ds.origin_mode);
     294           0 :   case 7: /* auto wrap */
     295           0 :     return &(fb->ds.auto_wrap_mode);
     296        8408 :   case 25:
     297        8408 :     return &(fb->ds.cursor_visible);
     298          88 :   case 1004:           /* xterm mouse focus event */
     299          88 :     return &(fb->ds.mouse_focus_event);
     300           0 :   case 1007:           /* xterm mouse alternate scroll */
     301           0 :     return &(fb->ds.mouse_alternate_scroll);
     302         112 :   case 2004: /* bracketed paste */
     303         112 :     return &(fb->ds.bracketed_paste);
     304             :   default:
     305             :     break;
     306             :   }
     307             :   return NULL;
     308             : }
     309             : 
     310             : /* helper for CSI_DECSM and CSI_DECRM */
     311        8616 : static void set_if_available( bool *mode, bool value )
     312             : {
     313        8612 :   if ( mode ) { *mode = value; }
     314             : }
     315             : 
     316             : /* set private mode */
     317        4220 : static void CSI_DECSM( Framebuffer *fb, Dispatcher *dispatch )
     318             : {
     319        8440 :   for ( int i = 0; i < dispatch->param_count(); i++ ) {
     320        4220 :     int param = dispatch->getparam( i, 0 );
     321        4220 :     if (param == 9 || (param >= 1000 && param <= 1003)) {
     322           0 :       fb->ds.mouse_reporting_mode = (Terminal::DrawState::MouseReportingMode) param;
     323        4220 :     } else if (param == 1005 || param == 1006 || param == 1015) {
     324           0 :       fb->ds.mouse_encoding_mode = (Terminal::DrawState::MouseEncodingMode) param;
     325             :     } else {
     326        8438 :       set_if_available( get_DEC_mode( param, fb ), true );
     327             :     }
     328             :   }
     329        4220 : }
     330             : 
     331             : /* clear private mode */
     332        5012 : static void CSI_DECRM( Framebuffer *fb, Dispatcher *dispatch )
     333             : {
     334       10024 :   for ( int i = 0; i < dispatch->param_count(); i++ ) {
     335        5012 :     int param = dispatch->getparam( i, 0 );
     336        5012 :     if (param == 9 || (param >= 1000 && param <= 1003)) {
     337         352 :       fb->ds.mouse_reporting_mode = Terminal::DrawState::MOUSE_REPORTING_NONE;
     338        4660 :     } else if (param == 1005 || param == 1006 || param == 1015) {
     339         264 :       fb->ds.mouse_encoding_mode = Terminal::DrawState::MOUSE_ENCODING_DEFAULT;
     340             :     } else {
     341        9406 :       set_if_available( get_DEC_mode( param, fb ), false );
     342             :     }
     343             :   }
     344        5012 : }
     345             : 
     346             : /* These functions don't clear wrap state. */
     347             : static Function func_CSI_DECSM( CSI, "?h", CSI_DECSM, false );
     348             : static Function func_CSI_DECRM( CSI, "?l", CSI_DECRM, false );
     349             : 
     350           0 : static bool *get_ANSI_mode( int param, Framebuffer *fb ) {
     351           0 :   if ( param == 4 ) { /* insert/replace mode */
     352           0 :     return &(fb->ds.insert_mode);
     353             :   }
     354             :   return NULL;
     355             : }
     356             : 
     357             : /* set mode */
     358           0 : static void CSI_SM( Framebuffer *fb, Dispatcher *dispatch )
     359             : {
     360           0 :   for ( int i = 0; i < dispatch->param_count(); i++ ) {
     361           0 :     bool *mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb );
     362           0 :     if ( mode ) {
     363           0 :       *mode = true;
     364             :     }
     365             :   }
     366           0 : }
     367             : 
     368             : /* clear mode */
     369           0 : static void CSI_RM( Framebuffer *fb, Dispatcher *dispatch )
     370             : {
     371           0 :   for ( int i = 0; i < dispatch->param_count(); i++ ) {
     372           0 :     bool *mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb );
     373           0 :     if ( mode ) {
     374           0 :       *mode = false;
     375             :     }
     376             :   }
     377           0 : }
     378             : 
     379             : static Function func_CSI_SM( CSI, "h", CSI_SM );
     380             : static Function func_CSI_RM( CSI, "l", CSI_RM );
     381             : 
     382             : /* set top and bottom margins */
     383         144 : static void CSI_DECSTBM( Framebuffer *fb, Dispatcher *dispatch )
     384             : {
     385         144 :   int top = dispatch->getparam( 0, 1 );
     386         144 :   int bottom = dispatch->getparam( 1, fb->ds.get_height() );
     387             : 
     388         144 :   if ( (bottom <= top)
     389         144 :        || (top > fb->ds.get_height())
     390         288 :        || (top == 0 && bottom == 1) ) {
     391             :     return; /* invalid, xterm ignores */
     392             :   }
     393             : 
     394         144 :   fb->ds.set_scrolling_region( top - 1, bottom - 1 );
     395         144 :   fb->ds.move_row( 0 );
     396         144 :   fb->ds.move_col( 0 );
     397             : }
     398             : 
     399             : static Function func_CSI_DECSTMB( CSI, "r", CSI_DECSTBM );
     400             : 
     401             : /* terminal bell */
     402           0 : static void Ctrl_BEL( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) {
     403           0 :   fb->ring_bell();
     404           0 : }
     405             : 
     406             : static Function func_Ctrl_BEL( CONTROL, "\x07", Ctrl_BEL );
     407             : 
     408             : /* select graphics rendition -- e.g., bold, blinking, etc. */
     409       14092 : static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch )
     410             : {
     411       39422 :   for ( int i = 0; i < dispatch->param_count(); i++ ) {
     412       25330 :     int rendition = dispatch->getparam( i, 0 );
     413             :     /* We need to special-case the handling of [34]8 ; 5 ; Ps,
     414             :        because Ps of 0 in that case does not mean reset to default, even
     415             :        though it means that otherwise (as usually renditions are applied
     416             :        in order). */
     417       38756 :     if ((rendition == 38 || rendition == 48) &&
     418       35742 :         (dispatch->param_count() - i >= 3) &&
     419       10412 :         (dispatch->getparam( i+1, -1 ) == 5)) {
     420        3014 :       (rendition == 38) ?
     421        1504 :         fb->ds.set_foreground_color( dispatch->getparam( i+2, 0 ) ) :
     422        1510 :         fb->ds.set_background_color( dispatch->getparam( i+2, 0 ) );
     423        3014 :       i += 2;
     424        3014 :       continue;
     425             :     }
     426             : 
     427             :     /* True color support: ESC[ ... [34]8;2;<r>;<g>;<b> ... m */
     428       29714 :     if ( (rendition == 38 || rendition == 48) &&
     429       29714 :          (dispatch->param_count() - i >= 5) &&
     430        7398 :          (dispatch->getparam( i+1, -1 ) == 2)) {
     431        7398 :       unsigned int red = dispatch->getparam(i+2, 0);
     432        7398 :       unsigned int green = dispatch->getparam(i+3, 0);
     433        7398 :       unsigned int blue = dispatch->getparam(i+4, 0);
     434        7398 :       unsigned int color;
     435             : 
     436        7398 :       color = Renditions::make_true_color( red, green, blue );
     437             : 
     438        7398 :       if ( rendition == 38 ) {
     439        3696 :         fb->ds.set_foreground_color( color );
     440             :       } else {
     441        3702 :         fb->ds.set_background_color( color );
     442             :       }
     443        7398 :       i += 4;
     444        7398 :       continue;
     445        7398 :     }
     446             : 
     447       25330 :     fb->ds.add_rendition( rendition );
     448             :   }
     449       14092 : }
     450             : 
     451             : static Function func_CSI_SGR( CSI, "m", CSI_SGR, false ); /* changing renditions doesn't clear wrap flag */
     452             : 
     453             : /* save and restore cursor */
     454           0 : static void Esc_DECSC( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     455             : {
     456           0 :   fb->ds.save_cursor();
     457           0 : }
     458             : 
     459           0 : static void Esc_DECRC( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     460             : {
     461           0 :   fb->ds.restore_cursor();
     462           0 : }
     463             : 
     464             : static Function func_Esc_DECSC( ESCAPE, "7", Esc_DECSC );
     465             : static Function func_Esc_DECRC( ESCAPE, "8", Esc_DECRC );
     466             : 
     467             : /* device status report -- e.g., cursor position (used by resize) */
     468           0 : static void CSI_DSR( Framebuffer *fb, Dispatcher *dispatch )
     469             : {
     470           0 :   int param = dispatch->getparam( 0, 0 );
     471             : 
     472           0 :   switch ( param ) {
     473           0 :   case 5: /* device status report requested */
     474           0 :     dispatch->terminal_to_host.append( "\033[0n" );
     475             :     break;
     476           0 :   case 6: /* report of active position requested */
     477           0 :     char cpr[ 32 ];
     478           0 :     snprintf( cpr, 32, "\033[%d;%dR",
     479           0 :               fb->ds.get_cursor_row() + 1,
     480           0 :               fb->ds.get_cursor_col() + 1 );
     481           0 :     dispatch->terminal_to_host.append( cpr );
     482             :     break;
     483             :   default:
     484             :     break;
     485             :   }
     486           0 : }
     487             : 
     488             : static Function func_CSI_DSR( CSI, "n", CSI_DSR );
     489             : 
     490             : /* insert line */
     491          16 : static void CSI_IL( Framebuffer *fb, Dispatcher *dispatch )
     492             : {
     493          16 :   int lines = dispatch->getparam( 0, 1 );
     494             : 
     495          16 :   fb->insert_line( fb->ds.get_cursor_row(), lines );
     496             : 
     497             :   /* vt220 manual and Ecma-48 say to move to first column */
     498             :   /* but xterm and gnome-terminal don't */
     499          16 :   fb->ds.move_col( 0 );
     500          16 : }
     501             : 
     502             : static Function func_CSI_IL( CSI, "L", CSI_IL );
     503             : 
     504             : /* delete line */
     505          16 : static void CSI_DL( Framebuffer *fb, Dispatcher *dispatch )
     506             : {
     507          16 :   int lines = dispatch->getparam( 0, 1 );
     508             : 
     509          16 :   fb->delete_line( fb->ds.get_cursor_row(), lines );
     510             : 
     511             :   /* same story -- xterm and gnome-terminal don't
     512             :      move to first column */
     513          16 :   fb->ds.move_col( 0 );
     514          16 : }
     515             : 
     516             : static Function func_CSI_DL( CSI, "M", CSI_DL );
     517             : 
     518             : /* insert characters */
     519           0 : static void CSI_ICH( Framebuffer *fb, Dispatcher *dispatch )
     520             : {
     521           0 :   int cells = dispatch->getparam( 0, 1 );
     522             : 
     523           0 :   for ( int i = 0; i < cells; i++ ) {
     524           0 :     fb->insert_cell( fb->ds.get_cursor_row(), fb->ds.get_cursor_col() );
     525             :   }
     526           0 : }
     527             : 
     528             : static Function func_CSI_ICH( CSI, "@", CSI_ICH );
     529             : 
     530             : /* delete character */
     531           0 : static void CSI_DCH( Framebuffer *fb, Dispatcher *dispatch )
     532             : {
     533           0 :   int cells = dispatch->getparam( 0, 1 );
     534             : 
     535           0 :   for ( int i = 0; i < cells; i++ ) {
     536           0 :     fb->delete_cell( fb->ds.get_cursor_row(), fb->ds.get_cursor_col() );
     537             :   }
     538           0 : }
     539             : 
     540             : static Function func_CSI_DCH( CSI, "P", CSI_DCH );
     541             : 
     542             : /* line position absolute */
     543           0 : static void CSI_VPA( Framebuffer *fb, Dispatcher *dispatch )
     544             : {
     545           0 :   int row = dispatch->getparam( 0, 1 );
     546           0 :   fb->ds.move_row( row - 1 );
     547           0 : }
     548             : 
     549             : static Function func_CSI_VPA( CSI, "d", CSI_VPA );
     550             : 
     551             : /* character position absolute */
     552           0 : static void CSI_HPA( Framebuffer *fb, Dispatcher *dispatch )
     553             : {
     554           0 :   int col = dispatch->getparam( 0, 1 );
     555           0 :   fb->ds.move_col( col - 1 );
     556           0 : }
     557             : 
     558             : static Function func_CSI_CHA( CSI, "G", CSI_HPA ); /* ECMA-48 name: CHA */
     559             : static Function func_CSI_HPA( CSI, "\x60", CSI_HPA ); /* ECMA-48 name: HPA */
     560             : 
     561             : /* erase character */
     562           0 : static void CSI_ECH( Framebuffer *fb, Dispatcher *dispatch )
     563             : {
     564           0 :   int num = dispatch->getparam( 0, 1 );
     565           0 :   int limit = fb->ds.get_cursor_col() + num - 1;
     566           0 :   if ( limit >= fb->ds.get_width() ) {
     567           0 :     limit = fb->ds.get_width() - 1;
     568             :   }
     569             : 
     570           0 :   clearline( fb, -1, fb->ds.get_cursor_col(), limit );
     571           0 : }
     572             : 
     573             : static Function func_CSI_ECH( CSI, "X", CSI_ECH );
     574             : 
     575             : /* reset to initial state */
     576           0 : static void Esc_RIS( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     577             : {
     578           0 :   fb->reset();
     579           0 : }
     580             : 
     581             : static Function func_Esc_RIS( ESCAPE, "c", Esc_RIS );
     582             : 
     583             : /* soft reset */
     584           0 : static void CSI_DECSTR( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) )
     585             : {
     586           0 :   fb->soft_reset();
     587           0 : }
     588             : 
     589             : static Function func_CSI_DECSTR( CSI, "!p", CSI_DECSTR );
     590             : 
     591             : /* xterm uses an Operating System Command to set the window title */
     592           0 : void Dispatcher::OSC_dispatch( const Parser::OSC_End *act __attribute((unused)), Framebuffer *fb )
     593             : {
     594             :   /* handle osc copy clipboard sequence 52;c; */
     595           0 :   if ( OSC_string.size() >= 5 && OSC_string[ 0 ] == L'5' &&
     596           0 :        OSC_string[ 1 ] == L'2' && OSC_string[ 2 ] == L';' &&
     597           0 :        OSC_string[ 3 ] == L'c' && OSC_string[ 4 ] == L';') {
     598           0 :       Terminal::Framebuffer::title_type clipboard(
     599           0 :               OSC_string.begin() + 5, OSC_string.end() );
     600           0 :       fb->set_clipboard( clipboard );
     601             :   /* handle osc terminal title sequence */
     602           0 :   } else if ( OSC_string.size() >= 1 ) {
     603           0 :     long cmd_num = -1;
     604           0 :     int offset = 0;
     605           0 :     if ( OSC_string[ 0 ] == L';' ) {
     606             :       /* OSC of the form "\033];<title>\007" */
     607             :       cmd_num = 0; /* treat it as as a zero */
     608             :       offset = 1;
     609           0 :     } else if ( (OSC_string.size() >= 2) && (OSC_string[ 1 ] == L';') ) {
     610             :       /* OSC of the form "\033]X;<title>\007" where X can be:
     611             :        * 0: set icon name and window title
     612             :        * 1: set icon name
     613             :        * 2: set window title */
     614           0 :       cmd_num = OSC_string[ 0 ] - L'0';
     615           0 :       offset = 2;
     616             :     }
     617           0 :     bool set_icon = cmd_num == 0 || cmd_num == 1;
     618           0 :     bool set_title = cmd_num == 0 || cmd_num == 2;
     619           0 :     if ( set_icon || set_title ) {
     620           0 :       fb->set_title_initialized();
     621           0 :       int title_length = std::min(OSC_string.size(), (size_t)256);
     622           0 :       Terminal::Framebuffer::title_type newtitle( OSC_string.begin() + offset, OSC_string.begin() + title_length );
     623           0 :       if ( set_icon )  { fb->set_icon_name( newtitle ); }
     624           0 :       if ( set_title ) { fb->set_window_title( newtitle ); }
     625           0 :     }
     626             :   }
     627           0 : }
     628             : 
     629             : /* scroll down or terminfo indn */
     630           2 : static void CSI_SD( Framebuffer *fb, Dispatcher *dispatch )
     631             : {
     632           2 :   fb->scroll( dispatch->getparam( 0, 1 ) );
     633           2 : }
     634             : 
     635             : static Function func_CSI_SD( CSI, "S", CSI_SD );
     636             : 
     637             : /* scroll up or terminfo rin */
     638           2 : static void CSI_SU( Framebuffer *fb, Dispatcher *dispatch )
     639             : {
     640           2 :   fb->scroll( -dispatch->getparam( 0, 1 ) );
     641           2 : }
     642             : 
     643             : static Function func_CSI_SU( CSI, "T", CSI_SU );

Generated by: LCOV version 1.14