mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 13:39:02 +00:00
Migration of screen away from ad-hoc lists
This commit is contained in:
parent
451399b344
commit
46fa2dd2f0
9 changed files with 228 additions and 229 deletions
2
common.h
2
common.h
|
@ -531,7 +531,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff );
|
||||||
\param out the list in which to place the elements.
|
\param out the list in which to place the elements.
|
||||||
*/
|
*/
|
||||||
void tokenize_variable_array( const wchar_t *val, array_list_t *out );
|
void tokenize_variable_array( const wchar_t *val, array_list_t *out );
|
||||||
void tokenize_variable_array2( const wcstring &val, std::vector<wcstring> &out);
|
void tokenize_variable_array2( const wcstring &val, wcstring_list_t &out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Make sure the specified direcotry exists. If needed, try to create
|
Make sure the specified direcotry exists. If needed, try to create
|
||||||
|
|
41
env.cpp
41
env.cpp
|
@ -428,8 +428,9 @@ static void setup_path()
|
||||||
{
|
{
|
||||||
wchar_t *path;
|
wchar_t *path;
|
||||||
|
|
||||||
int i, j;
|
size_t i;
|
||||||
array_list_t l;
|
int j;
|
||||||
|
wcstring_list_t lst;
|
||||||
|
|
||||||
const wchar_t *path_el[] =
|
const wchar_t *path_el[] =
|
||||||
{
|
{
|
||||||
|
@ -441,12 +442,10 @@ static void setup_path()
|
||||||
;
|
;
|
||||||
|
|
||||||
path = env_get( L"PATH" );
|
path = env_get( L"PATH" );
|
||||||
|
|
||||||
al_init( &l );
|
|
||||||
|
|
||||||
if( path )
|
if( path )
|
||||||
{
|
{
|
||||||
tokenize_variable_array( path, &l );
|
tokenize_variable_array2( path, lst );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( j=0; path_el[j]; j++ )
|
for( j=0; path_el[j]; j++ )
|
||||||
|
@ -454,10 +453,10 @@ static void setup_path()
|
||||||
|
|
||||||
int has_el=0;
|
int has_el=0;
|
||||||
|
|
||||||
for( i=0; i<al_get_count( &l); i++ )
|
for( i=0; i<lst.size(); i++ )
|
||||||
{
|
{
|
||||||
wchar_t * el = (wchar_t *)al_get( &l, i );
|
wcstring el = lst.at(i);
|
||||||
size_t len = wcslen( el );
|
size_t len = el.size();
|
||||||
|
|
||||||
while( (len > 0) && (el[len-1]==L'/') )
|
while( (len > 0) && (el[len-1]==L'/') )
|
||||||
{
|
{
|
||||||
|
@ -465,7 +464,7 @@ static void setup_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (wcslen( path_el[j] ) == len) &&
|
if( (wcslen( path_el[j] ) == len) &&
|
||||||
(wcsncmp( el, path_el[j], len)==0) )
|
(wcsncmp( el.c_str(), path_el[j], len)==0) )
|
||||||
{
|
{
|
||||||
has_el = 1;
|
has_el = 1;
|
||||||
}
|
}
|
||||||
|
@ -473,33 +472,25 @@ static void setup_path()
|
||||||
|
|
||||||
if( !has_el )
|
if( !has_el )
|
||||||
{
|
{
|
||||||
string_buffer_t b;
|
wcstring buffer;
|
||||||
|
|
||||||
debug( 3, L"directory %ls was missing", path_el[j] );
|
debug( 3, L"directory %ls was missing", path_el[j] );
|
||||||
|
|
||||||
sb_init( &b );
|
|
||||||
if( path )
|
if( path )
|
||||||
{
|
{
|
||||||
sb_append( &b, path );
|
buffer += path;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb_append( &b,
|
buffer += ARRAY_SEP_STR;
|
||||||
ARRAY_SEP_STR,
|
buffer += path_el[j];
|
||||||
path_el[j] );
|
|
||||||
|
|
||||||
env_set( L"PATH", (wchar_t *)b.buff, ENV_GLOBAL | ENV_EXPORT );
|
env_set( L"PATH", buffer.c_str(), ENV_GLOBAL | ENV_EXPORT );
|
||||||
|
|
||||||
sb_destroy( &b );
|
|
||||||
|
|
||||||
al_foreach( &l, &free );
|
|
||||||
path = env_get( L"PATH" );
|
path = env_get( L"PATH" );
|
||||||
al_truncate( &l, 0 );
|
lst.resize(0);
|
||||||
tokenize_variable_array( path, &l );
|
tokenize_variable_array2( path, lst );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
al_foreach( &l, &free );
|
|
||||||
al_destroy( &l );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int env_set_pwd()
|
int env_set_pwd()
|
||||||
|
|
|
@ -208,22 +208,17 @@ static void check_connection()
|
||||||
*/
|
*/
|
||||||
static void env_universal_remove_all()
|
static void env_universal_remove_all()
|
||||||
{
|
{
|
||||||
array_list_t lst;
|
size_t i;
|
||||||
int i;
|
|
||||||
|
|
||||||
al_init( &lst );
|
wcstring_list_t lst;
|
||||||
|
env_universal_common_get_names2( lst,
|
||||||
env_universal_common_get_names( &lst,
|
|
||||||
1,
|
1,
|
||||||
1 );
|
1 );
|
||||||
|
for( i=0; i<lst.size(); i++ )
|
||||||
for( i=0; i<al_get_count( &lst ); i++ )
|
|
||||||
{
|
{
|
||||||
wchar_t *key = (wchar_t *)al_get( &lst, i );
|
const wcstring &key = lst.at(i);
|
||||||
env_universal_common_remove( key );
|
env_universal_common_remove( key.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
al_destroy( &lst );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,3 +476,16 @@ void env_universal_get_names( array_list_t *l,
|
||||||
show_exported,
|
show_exported,
|
||||||
show_unexported );
|
show_unexported );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void env_universal_get_names2( wcstring_list_t &lst,
|
||||||
|
int show_exported,
|
||||||
|
int show_unexported )
|
||||||
|
{
|
||||||
|
if( !init )
|
||||||
|
return;
|
||||||
|
|
||||||
|
env_universal_common_get_names2( lst,
|
||||||
|
show_exported,
|
||||||
|
show_unexported );
|
||||||
|
}
|
||||||
|
|
|
@ -63,6 +63,9 @@ int env_universal_read_all();
|
||||||
void env_universal_get_names( array_list_t *l,
|
void env_universal_get_names( array_list_t *l,
|
||||||
int show_exported,
|
int show_exported,
|
||||||
int show_unexported );
|
int show_unexported );
|
||||||
|
void env_universal_get_names2( wcstring_list_t &list,
|
||||||
|
int show_exported,
|
||||||
|
int show_unexported );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Synchronize with fishd
|
Synchronize with fishd
|
||||||
|
|
|
@ -907,6 +907,17 @@ static void add_key_to_hash( void *key,
|
||||||
al_push( (array_list_t *)aux, key );
|
al_push( (array_list_t *)aux, key );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_key_to_hash2( void *key,
|
||||||
|
void *data,
|
||||||
|
void *aux )
|
||||||
|
{
|
||||||
|
wcstring_list_t &lst = *(wcstring_list_t *)aux;
|
||||||
|
var_uni_entry_t *e = (var_uni_entry_t *)data;
|
||||||
|
if( ( e->exportv && get_names_show_exported) ||
|
||||||
|
( !e->exportv && get_names_show_unexported) )
|
||||||
|
lst.push_back((wchar_t *)key);
|
||||||
|
}
|
||||||
|
|
||||||
void env_universal_common_get_names( array_list_t *l,
|
void env_universal_common_get_names( array_list_t *l,
|
||||||
int show_exported,
|
int show_exported,
|
||||||
int show_unexported )
|
int show_unexported )
|
||||||
|
@ -919,6 +930,19 @@ void env_universal_common_get_names( array_list_t *l,
|
||||||
l );
|
l );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void env_universal_common_get_names2( wcstring_list_t &lst,
|
||||||
|
int show_exported,
|
||||||
|
int show_unexported )
|
||||||
|
{
|
||||||
|
get_names_show_exported = show_exported;
|
||||||
|
get_names_show_unexported = show_unexported;
|
||||||
|
|
||||||
|
hash_foreach2( &env_universal_var,
|
||||||
|
add_key_to_hash2,
|
||||||
|
&lst );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wchar_t *env_universal_common_get( const wchar_t *name )
|
wchar_t *env_universal_common_get( const wchar_t *name )
|
||||||
{
|
{
|
||||||
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name );
|
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name );
|
||||||
|
|
|
@ -152,6 +152,9 @@ void env_universal_common_destroy();
|
||||||
void env_universal_common_get_names( array_list_t *l,
|
void env_universal_common_get_names( array_list_t *l,
|
||||||
int show_exported,
|
int show_exported,
|
||||||
int show_unexported );
|
int show_unexported );
|
||||||
|
void env_universal_common_get_names2( wcstring_list_t &lst,
|
||||||
|
int show_exported,
|
||||||
|
int show_unexported );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Perform the specified variable assignment.
|
Perform the specified variable assignment.
|
||||||
|
|
22
reader.cpp
22
reader.cpp
|
@ -177,8 +177,10 @@ commence.
|
||||||
states can be stacked, in case reader_readline() calls are
|
states can be stacked, in case reader_readline() calls are
|
||||||
nested. This happens when the 'read' builtin is used.
|
nested. This happens when the 'read' builtin is used.
|
||||||
*/
|
*/
|
||||||
typedef struct reader_data
|
class reader_data_t
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Buffer containing the whole current commandline
|
Buffer containing the whole current commandline
|
||||||
*/
|
*/
|
||||||
|
@ -289,7 +291,7 @@ typedef struct reader_data
|
||||||
/**
|
/**
|
||||||
Pointer to previous reader_data
|
Pointer to previous reader_data
|
||||||
*/
|
*/
|
||||||
struct reader_data *next;
|
reader_data_t *next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This variable keeps state on if we are in search mode, and
|
This variable keeps state on if we are in search mode, and
|
||||||
|
@ -302,8 +304,7 @@ typedef struct reader_data
|
||||||
which is known to require a repaint.
|
which is known to require a repaint.
|
||||||
*/
|
*/
|
||||||
int repaint_needed;
|
int repaint_needed;
|
||||||
}
|
};
|
||||||
reader_data_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The current interactive reading context
|
The current interactive reading context
|
||||||
|
@ -2267,20 +2268,20 @@ static int default_test( wchar_t *b )
|
||||||
|
|
||||||
void reader_push( const wchar_t *name )
|
void reader_push( const wchar_t *name )
|
||||||
{
|
{
|
||||||
reader_data_t *n = (reader_data_t *)calloc( 1, sizeof( reader_data_t ) );
|
// use placement new to guarantee zero initialization :(
|
||||||
|
void *buff = calloc(1, sizeof(reader_data_t));
|
||||||
if( !n )
|
if( !buff )
|
||||||
{
|
{
|
||||||
DIE_MEM();
|
DIE_MEM();
|
||||||
}
|
}
|
||||||
|
reader_data_t *n = new(buff) reader_data_t;
|
||||||
|
|
||||||
n->name = wcsdup( name );
|
n->name = wcsdup( name );
|
||||||
n->next = data;
|
n->next = data;
|
||||||
sb_init( &n->kill_item );
|
sb_init( &n->kill_item );
|
||||||
|
|
||||||
data=n;
|
data=n;
|
||||||
|
|
||||||
s_init( &data->screen );
|
|
||||||
sb_init( &data->prompt_buff );
|
sb_init( &data->prompt_buff );
|
||||||
|
|
||||||
check_size();
|
check_size();
|
||||||
|
@ -2324,7 +2325,6 @@ void reader_pop()
|
||||||
sb_destroy( &n->search_buff );
|
sb_destroy( &n->search_buff );
|
||||||
sb_destroy( &n->kill_item );
|
sb_destroy( &n->kill_item );
|
||||||
|
|
||||||
s_destroy( &n->screen );
|
|
||||||
sb_destroy( &n->prompt_buff );
|
sb_destroy( &n->prompt_buff );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2334,6 +2334,8 @@ void reader_pop()
|
||||||
al_destroy( &n->search_prev );
|
al_destroy( &n->search_prev );
|
||||||
free( (void *)n->token_history_buff);
|
free( (void *)n->token_history_buff);
|
||||||
|
|
||||||
|
/* Invoke the destructor to balance our placement new */
|
||||||
|
n->~reader_data_t();
|
||||||
free(n);
|
free(n);
|
||||||
|
|
||||||
if( data == 0 )
|
if( data == 0 )
|
||||||
|
|
212
screen.cpp
212
screen.cpp
|
@ -340,64 +340,13 @@ static void s_check_status( screen_t *s)
|
||||||
earlier value.
|
earlier value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int prev_line = s->actual_cursor[1];
|
int prev_line = s->actual.cursor[1];
|
||||||
write_loop( 1, "\r", 1 );
|
write_loop( 1, "\r", 1 );
|
||||||
s_reset( s, 0 );
|
s_reset( s, 0 );
|
||||||
s->actual_cursor[1] = prev_line;
|
s->actual.cursor[1] = prev_line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Free all memory used by one line_t struct.
|
|
||||||
*/
|
|
||||||
static void free_line( void *l )
|
|
||||||
{
|
|
||||||
line_t *line = (line_t *)l;
|
|
||||||
al_destroy( &line->text );
|
|
||||||
al_destroy( &line->color );
|
|
||||||
free( line );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Clear the specified array of line_t structs.
|
|
||||||
*/
|
|
||||||
static void s_reset_arr( array_list_t *l )
|
|
||||||
{
|
|
||||||
al_foreach( l, &free_line );
|
|
||||||
al_truncate( l, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void s_init( screen_t *s )
|
|
||||||
{
|
|
||||||
CHECK( s, );
|
|
||||||
|
|
||||||
memset( s, 0, sizeof(screen_t));
|
|
||||||
sb_init( &s->actual_prompt );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void s_destroy( screen_t *s )
|
|
||||||
{
|
|
||||||
CHECK( s, );
|
|
||||||
|
|
||||||
s_reset_arr( &s->actual );
|
|
||||||
al_destroy( &s->actual );
|
|
||||||
s_reset_arr( &s->desired );
|
|
||||||
al_destroy( &s->desired );
|
|
||||||
sb_destroy( &s->actual_prompt );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Allocate a new line_t struct.
|
|
||||||
*/
|
|
||||||
static line_t *s_create_line()
|
|
||||||
{
|
|
||||||
line_t *current = (line_t *)malloc( sizeof( line_t ));
|
|
||||||
al_init( ¤t->text );
|
|
||||||
al_init( ¤t->color );
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends a character to the end of the line that the output cursor is
|
Appends a character to the end of the line that the output cursor is
|
||||||
on. This function automatically handles linebreaks and lines longer
|
on. This function automatically handles linebreaks and lines longer
|
||||||
|
@ -409,17 +358,16 @@ static void s_desired_append_char( screen_t *s,
|
||||||
int indent,
|
int indent,
|
||||||
int prompt_width )
|
int prompt_width )
|
||||||
{
|
{
|
||||||
int line_no = s->desired_cursor[1];
|
int line_no = s->desired.cursor[1];
|
||||||
|
|
||||||
switch( b )
|
switch( b )
|
||||||
{
|
{
|
||||||
case L'\n':
|
case L'\n':
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
line_t *current = s_create_line();
|
s->desired.add_line();
|
||||||
al_push( &s->desired, current );
|
s->desired.cursor[1]++;
|
||||||
s->desired_cursor[1]++;
|
s->desired.cursor[0]=0;
|
||||||
s->desired_cursor[0]=0;
|
|
||||||
for( i=0; i < prompt_width+indent*INDENT_STEP; i++ )
|
for( i=0; i < prompt_width+indent*INDENT_STEP; i++ )
|
||||||
{
|
{
|
||||||
s_desired_append_char( s, L' ', 0, indent, prompt_width );
|
s_desired_append_char( s, L' ', 0, indent, prompt_width );
|
||||||
|
@ -429,43 +377,35 @@ static void s_desired_append_char( screen_t *s,
|
||||||
|
|
||||||
case L'\r':
|
case L'\r':
|
||||||
{
|
{
|
||||||
line_t *current;
|
line_t ¤t = s->desired.line(line_no);
|
||||||
current = (line_t *)al_get( &s->desired, line_no );
|
current.resize(0);
|
||||||
al_truncate( ¤t->text, 0 );
|
s->desired.cursor[0] = 0;
|
||||||
al_truncate( ¤t->color, 0 );
|
|
||||||
s->desired_cursor[0]=0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
line_t *current;
|
|
||||||
int screen_width = common_get_width();
|
int screen_width = common_get_width();
|
||||||
int cw = wcwidth(b);
|
int cw = wcwidth(b);
|
||||||
int ew = wcwidth( ellipsis_char );
|
int ew = wcwidth( ellipsis_char );
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
current = (line_t *)al_get( &s->desired, line_no );
|
s->desired.create_line(line_no);
|
||||||
|
|
||||||
if( !current )
|
|
||||||
{
|
|
||||||
current = s_create_line();
|
|
||||||
al_push( &s->desired, current );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if we are at the end of the line. If so, print an
|
Check if we are at the end of the line. If so, print an
|
||||||
ellipsis character and continue on the next line.
|
ellipsis character and continue on the next line.
|
||||||
*/
|
*/
|
||||||
if( s->desired_cursor[0] + cw + ew > screen_width )
|
if( s->desired.cursor[0] + cw + ew > screen_width )
|
||||||
{
|
{
|
||||||
al_set_long( ¤t->text, s->desired_cursor[0], ellipsis_char );
|
line_entry_t &entry = s->desired.line(line_no).create_entry(s->desired.cursor[0]);
|
||||||
al_set_long( ¤t->color, s->desired_cursor[0], HIGHLIGHT_COMMENT );
|
entry.text = ellipsis_char;
|
||||||
|
entry.color = HIGHLIGHT_COMMENT;
|
||||||
current = s_create_line();
|
|
||||||
al_push( &s->desired, current );
|
line_no = s->desired.line_count();
|
||||||
s->desired_cursor[1]++;
|
s->desired.add_line();
|
||||||
s->desired_cursor[0]=0;
|
s->desired.cursor[1]++;
|
||||||
|
s->desired.cursor[0]=0;
|
||||||
for( i=0; i < (prompt_width-ew); i++ )
|
for( i=0; i < (prompt_width-ew); i++ )
|
||||||
{
|
{
|
||||||
s_desired_append_char( s, L' ', 0, indent, prompt_width );
|
s_desired_append_char( s, L' ', 0, indent, prompt_width );
|
||||||
|
@ -473,9 +413,10 @@ static void s_desired_append_char( screen_t *s,
|
||||||
s_desired_append_char( s, ellipsis_char, HIGHLIGHT_COMMENT, indent, prompt_width );
|
s_desired_append_char( s, ellipsis_char, HIGHLIGHT_COMMENT, indent, prompt_width );
|
||||||
}
|
}
|
||||||
|
|
||||||
al_set_long( ¤t->text, s->desired_cursor[0], b );
|
line_t &line = s->desired.line(line_no);
|
||||||
al_set_long( ¤t->color, s->desired_cursor[0], c );
|
line.create_entry(s->desired.cursor[0]).text = b;
|
||||||
s->desired_cursor[0]+= cw;
|
line.create_entry(s->desired.cursor[0]).color = c;
|
||||||
|
s->desired.cursor[0]+= cw;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,7 +458,7 @@ static void s_move( screen_t *s, buffer_t *b, int new_x, int new_y )
|
||||||
output_set_writer( &s_writeb );
|
output_set_writer( &s_writeb );
|
||||||
s_writeb_buffer = b;
|
s_writeb_buffer = b;
|
||||||
|
|
||||||
y_steps = new_y - s->actual_cursor[1];
|
y_steps = new_y - s->actual.cursor[1];
|
||||||
|
|
||||||
if( y_steps > 0 && (strcmp( cursor_down, "\n")==0))
|
if( y_steps > 0 && (strcmp( cursor_down, "\n")==0))
|
||||||
{
|
{
|
||||||
|
@ -528,7 +469,7 @@ static void s_move( screen_t *s, buffer_t *b, int new_x, int new_y )
|
||||||
as moving it down one step. The cursor_up does not have this
|
as moving it down one step. The cursor_up does not have this
|
||||||
behaviour...
|
behaviour...
|
||||||
*/
|
*/
|
||||||
s->actual_cursor[0]=0;
|
s->actual.cursor[0]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y_steps < 0 )
|
if( y_steps < 0 )
|
||||||
|
@ -547,7 +488,7 @@ static void s_move( screen_t *s, buffer_t *b, int new_x, int new_y )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
x_steps = new_x - s->actual_cursor[0];
|
x_steps = new_x - s->actual.cursor[0];
|
||||||
|
|
||||||
if( x_steps && new_x == 0 )
|
if( x_steps && new_x == 0 )
|
||||||
{
|
{
|
||||||
|
@ -570,8 +511,8 @@ static void s_move( screen_t *s, buffer_t *b, int new_x, int new_y )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
s->actual_cursor[0] = new_x;
|
s->actual.cursor[0] = new_x;
|
||||||
s->actual_cursor[1] = new_y;
|
s->actual.cursor[1] = new_y;
|
||||||
|
|
||||||
output_set_writer( writer_old );
|
output_set_writer( writer_old );
|
||||||
|
|
||||||
|
@ -605,7 +546,7 @@ static void s_write_char( screen_t *s, buffer_t *b, wchar_t c )
|
||||||
|
|
||||||
output_set_writer( &s_writeb );
|
output_set_writer( &s_writeb );
|
||||||
s_writeb_buffer = b;
|
s_writeb_buffer = b;
|
||||||
s->actual_cursor[0]+=wcwidth( c );
|
s->actual.cursor[0]+=wcwidth( c );
|
||||||
|
|
||||||
writech( c );
|
writech( c );
|
||||||
|
|
||||||
|
@ -669,19 +610,18 @@ static void s_update( screen_t *scr, wchar_t *prompt )
|
||||||
s_reset( scr, 0 );
|
s_reset( scr, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wcscmp( prompt, (wchar_t *)scr->actual_prompt.buff ) )
|
if( wcscmp( prompt, scr->actual_prompt.c_str() ) )
|
||||||
{
|
{
|
||||||
s_move( scr, &output, 0, 0 );
|
s_move( scr, &output, 0, 0 );
|
||||||
s_write_str( &output, prompt );
|
s_write_str( &output, prompt );
|
||||||
sb_clear( &scr->actual_prompt );
|
scr->actual_prompt = prompt;
|
||||||
sb_append( &scr->actual_prompt, prompt );
|
scr->actual.cursor[0] = prompt_width;
|
||||||
scr->actual_cursor[0] = prompt_width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i=0; i< al_get_count( &scr->desired ); i++ )
|
for (i=0; i < scr->desired.line_count(); i++)
|
||||||
{
|
{
|
||||||
line_t *o_line = (line_t *)al_get( &scr->desired, i );
|
line_t &o_line = scr->desired.line(i);
|
||||||
line_t *s_line = (line_t *)al_get( &scr->actual, i );
|
line_t &s_line = scr->actual.create_line(i);
|
||||||
int start_pos = (i==0?prompt_width:0);
|
int start_pos = (i==0?prompt_width:0);
|
||||||
current_width = start_pos;
|
current_width = start_pos;
|
||||||
|
|
||||||
|
@ -689,72 +629,64 @@ static void s_update( screen_t *scr, wchar_t *prompt )
|
||||||
{
|
{
|
||||||
s_move( scr, &output, start_pos, i );
|
s_move( scr, &output, start_pos, i );
|
||||||
s_write_mbs( &output, clr_eol);
|
s_write_mbs( &output, clr_eol);
|
||||||
if( s_line )
|
s_line.resize(0);
|
||||||
{
|
|
||||||
al_truncate( &s_line->text, 0 );
|
|
||||||
al_truncate( &s_line->color, 0 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !s_line )
|
|
||||||
{
|
|
||||||
s_line = s_create_line();
|
|
||||||
al_push( &scr->actual, s_line );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( j=start_pos; j<al_get_count( &o_line->text ); j++ )
|
|
||||||
{
|
|
||||||
wchar_t o = (wchar_t)(intptr_t)al_get( &o_line->text, j );
|
|
||||||
int o_c = (int)(intptr_t)al_get( &o_line->color, j );
|
|
||||||
|
|
||||||
|
for( j=start_pos; j<o_line.entry_count(); j++)
|
||||||
|
{
|
||||||
|
line_entry_t &entry = o_line.entry(j);
|
||||||
|
wchar_t o = entry.text;
|
||||||
|
int o_c = entry.color;
|
||||||
if( !o )
|
if( !o )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( al_get_count( &s_line->text ) == j )
|
if( s_line.entry_count() == j )
|
||||||
{
|
{
|
||||||
s_move( scr, &output, current_width, i );
|
s_move( scr, &output, current_width, i );
|
||||||
s_set_color( scr, &output, o_c );
|
s_set_color( scr, &output, o_c );
|
||||||
s_write_char( scr, &output, o );
|
s_write_char( scr, &output, o );
|
||||||
al_set_long( &s_line->text, j, o );
|
s_line.create_entry(j).text = o;
|
||||||
al_set_long( &s_line->color, j, o_c );
|
s_line.create_entry(j).color = o_c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wchar_t s = (wchar_t)(intptr_t)al_get( &s_line->text, j );
|
line_entry_t &entry = s_line.create_entry(j);
|
||||||
int s_c = (int)(intptr_t)al_get( &s_line->color, j );
|
wchar_t s = entry.text;
|
||||||
|
int s_c = entry.color;
|
||||||
|
|
||||||
if( o != s || o_c != s_c )
|
if( o != s || o_c != s_c )
|
||||||
{
|
{
|
||||||
s_move( scr, &output, current_width, i );
|
s_move( scr, &output, current_width, i );
|
||||||
s_set_color( scr, &output, o_c );
|
s_set_color( scr, &output, o_c );
|
||||||
s_write_char( scr, &output, o );
|
s_write_char( scr, &output, o );
|
||||||
al_set_long( &s_line->text, current_width, o );
|
|
||||||
al_set_long( &s_line->color, current_width, o_c );
|
s_line.create_entry(current_width).text = o;
|
||||||
|
s_line.create_entry(current_width).color = o_c;
|
||||||
for( k=1; k<wcwidth(o); k++ )
|
for( k=1; k<wcwidth(o); k++ )
|
||||||
al_set_long( &s_line->text, current_width+k, L'\0' );
|
s_line.create_entry(current_width+k).text = L'\0';
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_width += wcwidth( o );
|
current_width += wcwidth( o );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( al_get_count( &s_line->text ) > al_get_count( &o_line->text ) )
|
if ( s_line.entry_count() > o_line.entry_count() )
|
||||||
{
|
{
|
||||||
s_move( scr, &output, current_width, i );
|
s_move( scr, &output, current_width, i );
|
||||||
s_write_mbs( &output, clr_eol);
|
s_write_mbs( &output, clr_eol);
|
||||||
al_truncate( &s_line->text, al_get_count( &o_line->text ) );
|
s_line.resize(o_line.entry_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
for( i=al_get_count( &scr->desired ); i< al_get_count( &scr->actual ); i++ )
|
for( i=scr->desired.line_count(); i < scr->actual.line_count(); i++ )
|
||||||
{
|
{
|
||||||
line_t *s_line = (line_t *)al_get( &scr->actual, i );
|
line_t &s_line = scr->actual.create_line(i);
|
||||||
s_move( scr, &output, 0, i );
|
s_move( scr, &output, 0, i );
|
||||||
s_write_mbs( &output, clr_eol);
|
s_write_mbs( &output, clr_eol);
|
||||||
al_truncate( &s_line->text, 0 );
|
s_line.resize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_move( scr, &output, scr->desired_cursor[0], scr->desired_cursor[1] );
|
s_move( scr, &output, scr->desired.cursor[0], scr->desired.cursor[1] );
|
||||||
|
|
||||||
s_set_color( scr, &output, 0xffffffff);
|
s_set_color( scr, &output, 0xffffffff);
|
||||||
|
|
||||||
|
@ -864,8 +796,8 @@ void s_write( screen_t *s,
|
||||||
if( current_line_width > max_line_width )
|
if( current_line_width > max_line_width )
|
||||||
max_line_width = current_line_width;
|
max_line_width = current_line_width;
|
||||||
|
|
||||||
s_reset_arr( &s->desired );
|
s->desired.resize(0);
|
||||||
s->desired_cursor[0] = s->desired_cursor[1] = 0;
|
s->desired.cursor[0] = s->desired.cursor[1] = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If overflowing, give the prompt its own line to improve the
|
If overflowing, give the prompt its own line to improve the
|
||||||
|
@ -897,13 +829,13 @@ void s_write( screen_t *s,
|
||||||
|
|
||||||
if( i == cursor )
|
if( i == cursor )
|
||||||
{
|
{
|
||||||
cursor_arr[0] = s->desired_cursor[0];
|
cursor_arr[0] = s->desired.cursor[0];
|
||||||
cursor_arr[1] = s->desired_cursor[1];
|
cursor_arr[1] = s->desired.cursor[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
s_desired_append_char( s, b[i], col, indent[i], prompt_width );
|
s_desired_append_char( s, b[i], col, indent[i], prompt_width );
|
||||||
|
|
||||||
if( i== cursor && s->desired_cursor[1] != cursor_arr[1] && b[i] != L'\n' )
|
if( i== cursor && s->desired.cursor[1] != cursor_arr[1] && b[i] != L'\n' )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Ugh. We are placed exactly at the wrapping point of a
|
Ugh. We are placed exactly at the wrapping point of a
|
||||||
|
@ -911,17 +843,17 @@ void s_write( screen_t *s,
|
||||||
cursor won't be on the ellipsis which looks
|
cursor won't be on the ellipsis which looks
|
||||||
unintuitive.
|
unintuitive.
|
||||||
*/
|
*/
|
||||||
cursor_arr[0] = s->desired_cursor[0] - wcwidth(b[i]);
|
cursor_arr[0] = s->desired.cursor[0] - wcwidth(b[i]);
|
||||||
cursor_arr[1] = s->desired_cursor[1];
|
cursor_arr[1] = s->desired.cursor[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if( i == cursor )
|
if( i == cursor )
|
||||||
{
|
{
|
||||||
memcpy(cursor_arr, s->desired_cursor, sizeof(int)*2);
|
memcpy(cursor_arr, s->desired.cursor, sizeof(int)*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy( s->desired_cursor, cursor_arr, sizeof(int)*2 );
|
memcpy( s->desired.cursor, cursor_arr, sizeof(int)*2 );
|
||||||
s_update( s, prompt );
|
s_update( s, prompt );
|
||||||
s_save_status( s );
|
s_save_status( s );
|
||||||
}
|
}
|
||||||
|
@ -930,10 +862,10 @@ void s_reset( screen_t *s, int reset_cursor )
|
||||||
{
|
{
|
||||||
CHECK( s, );
|
CHECK( s, );
|
||||||
|
|
||||||
int prev_line = s->actual_cursor[1];
|
int prev_line = s->actual.cursor[1];
|
||||||
s_reset_arr( &s->actual );
|
s->actual.resize(0);
|
||||||
s->actual_cursor[0] = s->actual_cursor[1] = 0;
|
s->actual.cursor[0] = s->actual.cursor[1] = 0;
|
||||||
sb_clear( &s->actual_prompt );
|
s->actual_prompt = L"";
|
||||||
s->need_clear=1;
|
s->need_clear=1;
|
||||||
|
|
||||||
if( !reset_cursor )
|
if( !reset_cursor )
|
||||||
|
@ -943,7 +875,7 @@ void s_reset( screen_t *s, int reset_cursor )
|
||||||
next repaint.
|
next repaint.
|
||||||
*/
|
*/
|
||||||
write_loop( 1, "\r", 1 );
|
write_loop( 1, "\r", 1 );
|
||||||
s->actual_cursor[1] = prev_line;
|
s->actual.cursor[1] = prev_line;
|
||||||
}
|
}
|
||||||
fstat( 1, &s->prev_buff_1 );
|
fstat( 1, &s->prev_buff_1 );
|
||||||
fstat( 2, &s->prev_buff_2 );
|
fstat( 2, &s->prev_buff_2 );
|
||||||
|
|
120
screen.h
120
screen.h
|
@ -12,6 +12,79 @@
|
||||||
#ifndef FISH_SCREEN_H
|
#ifndef FISH_SCREEN_H
|
||||||
#define FISH_SCREEN_H
|
#define FISH_SCREEN_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct line_entry_t
|
||||||
|
{
|
||||||
|
wchar_t text;
|
||||||
|
int color;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
A class representing a single line of a screen.
|
||||||
|
*/
|
||||||
|
class line_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<struct line_entry_t> entries;
|
||||||
|
|
||||||
|
void resize(size_t size) {
|
||||||
|
entries.resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_entry_t &entry(size_t idx) {
|
||||||
|
return entries.at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_entry_t &create_entry(size_t idx) {
|
||||||
|
if (idx >= entries.size()) {
|
||||||
|
entries.resize(idx + 1);
|
||||||
|
}
|
||||||
|
return entries.at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t entry_count(void) {
|
||||||
|
return entries.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
A class representing screen contents.
|
||||||
|
*/
|
||||||
|
class screen_data_t
|
||||||
|
{
|
||||||
|
std::vector<line_t> line_datas;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
int cursor[2];
|
||||||
|
|
||||||
|
line_t &add_line(void) {
|
||||||
|
line_datas.resize(line_datas.size() + 1);
|
||||||
|
return line_datas.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t size) {
|
||||||
|
line_datas.resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_t &create_line(size_t idx) {
|
||||||
|
if (idx >= line_datas.size()) {
|
||||||
|
line_datas.resize(idx + 1);
|
||||||
|
}
|
||||||
|
return line_datas.at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
line_t &line(size_t idx) {
|
||||||
|
return line_datas.at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t line_count(void) {
|
||||||
|
return line_datas.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The struct representing the current and desired screen contents.
|
The struct representing the current and desired screen contents.
|
||||||
*/
|
*/
|
||||||
|
@ -20,24 +93,17 @@ typedef struct
|
||||||
/**
|
/**
|
||||||
The internal representation of the desired screen contents.
|
The internal representation of the desired screen contents.
|
||||||
*/
|
*/
|
||||||
array_list_t desired;
|
screen_data_t desired;
|
||||||
/**
|
/**
|
||||||
The internal representation of the actual screen contents.
|
The internal representation of the actual screen contents.
|
||||||
*/
|
*/
|
||||||
array_list_t actual;
|
screen_data_t actual;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The desired cursor position.
|
A string containing the prompt which was last printed to
|
||||||
*/
|
|
||||||
int desired_cursor[2];
|
|
||||||
/**
|
|
||||||
The actual cursor position.
|
|
||||||
*/
|
|
||||||
int actual_cursor[2];
|
|
||||||
/**
|
|
||||||
A stringbuffer containing the prompt which was last printed to
|
|
||||||
the screen.
|
the screen.
|
||||||
*/
|
*/
|
||||||
string_buffer_t actual_prompt;
|
wcstring actual_prompt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The actual width of the screen at the time of the last screen
|
The actual width of the screen at the time of the last screen
|
||||||
|
@ -61,36 +127,6 @@ typedef struct
|
||||||
}
|
}
|
||||||
screen_t;
|
screen_t;
|
||||||
|
|
||||||
/**
|
|
||||||
A struct representing a single line of a screen. Consists of two
|
|
||||||
array_lists, which must always be of the same length.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
The text contents of the line. Each element of the array
|
|
||||||
represents on column of output. Because some characters are two
|
|
||||||
columns wide, it is perfectly possible for some of the comumns
|
|
||||||
to be empty.
|
|
||||||
*/
|
|
||||||
array_list_t text;
|
|
||||||
/**
|
|
||||||
Highlight information for the line
|
|
||||||
*/
|
|
||||||
array_list_t color;
|
|
||||||
}
|
|
||||||
line_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Initialize a new screen struct
|
|
||||||
*/
|
|
||||||
void s_init( screen_t *s );
|
|
||||||
|
|
||||||
/**
|
|
||||||
Free all memory used by the specified screen struct
|
|
||||||
*/
|
|
||||||
void s_destroy( screen_t *s );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This is the main function for the screen putput library. It is used
|
This is the main function for the screen putput library. It is used
|
||||||
to define the desired contents of the screen. The screen command
|
to define the desired contents of the screen. The screen command
|
||||||
|
|
Loading…
Reference in a new issue