2006-10-02 05:22:43 +08:00
/** \file screen.h High level library for handling the terminal screen
2012-11-18 18:23:22 +08:00
The screen library allows the interactive reader to write its
2013-01-24 19:19:49 +08:00
output to screen efficiently by keeping an internal representation
2012-11-18 18:23:22 +08:00
of the current screen contents and trying to find a reasonably
efficient way for transforming that to the desired screen content .
The current implementation is less smart than ncurses allows
and can not for example move blocks of text around to handle text
insertion .
2008-01-14 00:47:47 +08:00
*/
2006-10-02 00:02:58 +08:00
# ifndef FISH_SCREEN_H
# define FISH_SCREEN_H
2011-12-28 10:41:38 +08:00
# include <vector>
2013-12-08 04:43:40 +08:00
# include <sys/stat.h>
2014-01-15 17:01:25 +08:00
# include "highlight.h"
2011-12-28 10:41:38 +08:00
2014-01-18 04:04:03 +08:00
class page_rendering_t ;
2014-01-16 10:21:38 +08:00
2011-12-28 10:41:38 +08:00
/**
A class representing a single line of a screen .
*/
2012-07-16 01:45:18 +08:00
struct line_t
2011-12-28 10:41:38 +08:00
{
2012-07-16 01:45:18 +08:00
std : : vector < wchar_t > text ;
2014-01-15 17:01:25 +08:00
std : : vector < highlight_spec_t > colors ;
2012-10-01 18:29:18 +08:00
bool is_soft_wrapped ;
2012-11-18 18:23:22 +08:00
2012-10-01 18:29:18 +08:00
line_t ( ) : text ( ) , colors ( ) , is_soft_wrapped ( false )
{
}
2012-11-18 18:23:22 +08:00
2012-07-16 01:45:18 +08:00
void clear ( void )
{
text . clear ( ) ;
colors . clear ( ) ;
2011-12-28 10:41:38 +08:00
}
2012-11-18 18:23:22 +08:00
2014-01-15 17:01:25 +08:00
void append ( wchar_t txt , highlight_spec_t color )
2012-07-16 01:45:18 +08:00
{
text . push_back ( txt ) ;
colors . push_back ( color ) ;
}
2014-01-20 08:41:26 +08:00
void append ( const wchar_t * txt , highlight_spec_t color )
{
for ( size_t i = 0 ; txt [ i ] ; i + + )
{
text . push_back ( txt [ i ] ) ;
colors . push_back ( color ) ;
}
}
2012-11-18 18:23:22 +08:00
2012-07-16 01:45:18 +08:00
size_t size ( void ) const
{
return text . size ( ) ;
2011-12-28 10:41:38 +08:00
}
2012-11-18 18:23:22 +08:00
2012-07-16 01:45:18 +08:00
wchar_t char_at ( size_t idx ) const
{
return text . at ( idx ) ;
2011-12-28 10:41:38 +08:00
}
2012-11-18 18:23:22 +08:00
2014-01-15 17:01:25 +08:00
highlight_spec_t color_at ( size_t idx ) const
2012-07-16 01:45:18 +08:00
{
return colors . at ( idx ) ;
2011-12-28 10:41:38 +08:00
}
2014-01-14 08:41:22 +08:00
void append_line ( const line_t & line )
{
text . insert ( text . end ( ) , line . text . begin ( ) , line . text . end ( ) ) ;
colors . insert ( colors . end ( ) , line . colors . begin ( ) , line . colors . end ( ) ) ;
}
2012-11-18 18:23:22 +08:00
2011-12-28 10:41:38 +08:00
} ;
/**
A class representing screen contents .
*/
class screen_data_t
{
std : : vector < line_t > line_datas ;
2012-11-18 18:23:22 +08:00
2012-11-19 08:30:30 +08:00
public :
2012-11-18 18:23:22 +08:00
2012-11-19 08:30:30 +08:00
struct cursor_t
{
2012-08-05 04:54:20 +08:00
int x ;
int y ;
2012-10-01 18:29:18 +08:00
cursor_t ( ) : x ( 0 ) , y ( 0 ) { }
cursor_t ( int a , int b ) : x ( a ) , y ( b ) { }
2012-08-05 04:54:20 +08:00
} cursor ;
2012-11-18 18:23:22 +08:00
2012-11-19 08:30:30 +08:00
line_t & add_line ( void )
{
2011-12-28 10:41:38 +08:00
line_datas . resize ( line_datas . size ( ) + 1 ) ;
return line_datas . back ( ) ;
}
2012-11-18 18:23:22 +08:00
2012-11-19 08:30:30 +08:00
void resize ( size_t size )
{
2011-12-28 10:41:38 +08:00
line_datas . resize ( size ) ;
}
2012-11-18 18:23:22 +08:00
2012-11-19 08:30:30 +08:00
line_t & create_line ( size_t idx )
{
if ( idx > = line_datas . size ( ) )
{
2011-12-28 10:41:38 +08:00
line_datas . resize ( idx + 1 ) ;
}
return line_datas . at ( idx ) ;
}
2014-01-26 16:41:30 +08:00
line_t & insert_line_at_index ( size_t idx )
{
assert ( idx < = line_datas . size ( ) ) ;
return * line_datas . insert ( line_datas . begin ( ) + idx , line_t ( ) ) ;
}
2012-11-18 18:23:22 +08:00
2012-11-19 08:30:30 +08:00
line_t & line ( size_t idx )
{
2011-12-28 10:41:38 +08:00
return line_datas . at ( idx ) ;
}
2012-11-18 18:23:22 +08:00
2012-11-19 08:30:30 +08:00
size_t line_count ( void )
{
2011-12-28 10:41:38 +08:00
return line_datas . size ( ) ;
}
2014-01-15 07:39:53 +08:00
void append_lines ( const screen_data_t & d )
{
this - > line_datas . insert ( this - > line_datas . end ( ) , d . line_datas . begin ( ) , d . line_datas . end ( ) ) ;
}
2014-01-18 04:04:03 +08:00
bool empty ( ) const
{
return line_datas . empty ( ) ;
}
2011-12-28 10:41:38 +08:00
} ;
2006-10-02 05:22:43 +08:00
/**
2012-03-25 18:00:38 +08:00
The class representing the current and desired screen contents .
2006-10-02 05:22:43 +08:00
*/
2012-03-25 18:00:38 +08:00
class screen_t
2006-10-02 00:02:58 +08:00
{
2012-11-19 08:30:30 +08:00
public :
2011-12-28 10:41:38 +08:00
2012-10-01 18:29:18 +08:00
/** Constructor */
screen_t ( ) ;
2006-10-05 05:45:02 +08:00
2012-10-01 18:29:18 +08:00
/**
The internal representation of the desired screen contents .
*/
screen_data_t desired ;
/**
The internal representation of the actual screen contents .
*/
screen_data_t actual ;
/**
A string containing the prompt which was last printed to
the screen .
*/
2012-11-05 15:21:37 +08:00
wcstring actual_left_prompt ;
2012-11-18 18:23:22 +08:00
2012-11-08 11:59:20 +08:00
/** Last right prompt width */
size_t last_right_prompt_width ;
2012-10-01 18:29:18 +08:00
/**
The actual width of the screen at the time of the last screen
write .
*/
int actual_width ;
2012-11-18 18:23:22 +08:00
2012-10-01 18:29:18 +08:00
/** If we support soft wrapping, we can output to this location without any cursor motion. */
screen_data_t : : cursor_t soft_wrap_location ;
2013-10-27 06:27:39 +08:00
2013-08-21 11:08:56 +08:00
/** Whether the last-drawn autosuggestion (if any) is truncated, or hidden entirely */
bool autosuggestion_is_truncated ;
2006-10-05 07:33:12 +08:00
2012-10-01 18:29:18 +08:00
/**
2012-11-18 18:23:22 +08:00
This flag is set to true when there is reason to suspect that
the parts of the screen lines where the actual content is not
filled in may be non - empty . This means that a clr_eol command
2012-11-25 08:42:25 +08:00
has to be sent to the terminal at the end of each line , including
actual_lines_before_reset .
2012-11-19 08:30:30 +08:00
*/
2012-11-25 08:42:25 +08:00
bool need_clear_lines ;
2012-11-25 08:58:30 +08:00
2012-11-25 08:42:25 +08:00
/** Whether there may be yet more content after the lines, and we issue a clr_eos if possible. */
bool need_clear_screen ;
2012-11-18 18:23:22 +08:00
2012-10-03 08:30:07 +08:00
/** If we need to clear, this is how many lines the actual screen had, before we reset it. This is used when resizing the window larger: if the cursor jumps to the line above, we need to remember to clear the subsequent lines. */
size_t actual_lines_before_reset ;
2013-10-27 06:27:39 +08:00
2012-11-19 08:30:30 +08:00
/**
These status buffers are used to check if any output has occurred
other than from fish ' s main loop , in which case we need to redraw .
*/
struct stat prev_buff_1 , prev_buff_2 , post_buff_1 , post_buff_2 ;
2012-03-25 18:00:38 +08:00
} ;
2006-10-02 00:02:58 +08:00
2006-10-02 05:22:43 +08:00
/**
This is the main function for the screen putput library . It is used
to define the desired contents of the screen . The screen command
will use it ' s knowlege of the current contents of the screen in
order to render the desired output using as few terminal commands
as possible .
2012-11-18 18:23:22 +08:00
2012-07-13 03:51:47 +08:00
\ param s the screen on which to write
2012-11-05 15:21:37 +08:00
\ param left_prompt the prompt to prepend to the command line
\ param right_prompt the right prompt , or NULL if none
2012-07-13 03:51:47 +08:00
\ param commandline the command line
\ param explicit_len the number of characters of the " explicit " ( non - autosuggestion ) portion of the command line
\ param colors the colors to use for the comand line
\ param indent the indent to use for the command line
\ param cursor_pos where the cursor is
2006-10-02 05:22:43 +08:00
*/
2012-11-19 08:30:30 +08:00
void s_write ( screen_t * s ,
const wcstring & left_prompt ,
const wcstring & right_prompt ,
const wcstring & commandline ,
size_t explicit_len ,
2014-01-15 17:01:25 +08:00
const highlight_spec_t * colors ,
2012-11-19 08:30:30 +08:00
const int * indent ,
2014-01-15 07:39:53 +08:00
size_t cursor_pos ,
2014-01-18 04:04:03 +08:00
const page_rendering_t & pager_data ) ;
2012-11-08 11:59:20 +08:00
2012-11-18 18:23:22 +08:00
/**
2007-10-01 06:53:54 +08:00
This function resets the screen buffers internal knowledge about
the contents of the screen . Use this function when some other
function than s_write has written to the screen .
\ param s the screen to reset
2013-02-18 14:03:00 +08:00
\ param reset_cursor whether the line on which the cursor has changed should be assumed to have changed . If \ c reset_cursor is false , the library will attempt to make sure that the screen area does not seem to move up or down on repaint .
\ param reset_prompt whether to reset the prompt as well .
2007-10-01 06:53:54 +08:00
2013-02-18 14:03:00 +08:00
If reset_cursor is incorrectly set to false , this may result in
screen contents being erased . If it is incorrectly set to true , it
may result in one or more lines of garbage on screen on the next
2007-10-01 06:53:54 +08:00
repaint . If this happens during a loop , such as an interactive
resizing , there will be one line of garbage for every repaint ,
2013-02-18 14:03:00 +08:00
which will quickly fill the screen .
2006-10-02 05:22:43 +08:00
*/
2012-11-19 08:30:30 +08:00
void s_reset ( screen_t * s , bool reset_cursor , bool reset_prompt = true ) ;
2006-10-02 00:02:58 +08:00
2012-11-25 08:42:25 +08:00
2012-11-25 08:58:30 +08:00
enum screen_reset_mode_t
{
2012-11-25 08:42:25 +08:00
/* Do not make a new line, do not repaint the prompt. */
screen_reset_current_line_contents ,
/* Do not make a new line, do repaint the prompt. */
screen_reset_current_line_and_prompt ,
2012-11-25 08:58:30 +08:00
2012-11-25 08:42:25 +08:00
/* Abandon the current line, go to the next one, repaint the prompt */
screen_reset_abandon_line ,
2012-11-25 08:58:30 +08:00
2012-11-25 08:42:25 +08:00
/* Abandon the current line, go to the next one, clear the rest of the screen */
screen_reset_abandon_line_and_clear_to_end_of_screen
} ;
void s_reset ( screen_t * s , screen_reset_mode_t mode ) ;
2014-01-16 10:21:38 +08:00
/* Issues an immediate clr_eos, returning if it existed */
bool screen_force_clear_to_end ( ) ;
2013-09-29 17:48:35 +08:00
/* Returns the length of an escape code. Exposed for testing purposes only. */
size_t escape_code_length ( const wchar_t * code ) ;
2012-11-25 08:42:25 +08:00
2006-10-02 00:02:58 +08:00
# endif