From 46fa2dd2f0d104471bbb00b8e119decd91cda71d Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 27 Dec 2011 18:41:38 -0800 Subject: [PATCH] Migration of screen away from ad-hoc lists --- common.h | 2 +- env.cpp | 41 +++----- env_universal.cpp | 30 ++++-- env_universal.h | 3 + env_universal_common.cpp | 24 +++++ env_universal_common.h | 3 + reader.cpp | 22 ++-- screen.cpp | 212 +++++++++++++-------------------------- screen.h | 120 ++++++++++++++-------- 9 files changed, 228 insertions(+), 229 deletions(-) diff --git a/common.h b/common.h index d45667f45..b9a59e8dd 100644 --- a/common.h +++ b/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. */ void tokenize_variable_array( const wchar_t *val, array_list_t *out ); -void tokenize_variable_array2( const wcstring &val, std::vector &out); +void tokenize_variable_array2( const wcstring &val, wcstring_list_t &out); /** Make sure the specified direcotry exists. If needed, try to create diff --git a/env.cpp b/env.cpp index f603e7b8d..4392aa6e1 100644 --- a/env.cpp +++ b/env.cpp @@ -428,8 +428,9 @@ static void setup_path() { wchar_t *path; - int i, j; - array_list_t l; + size_t i; + int j; + wcstring_list_t lst; const wchar_t *path_el[] = { @@ -441,12 +442,10 @@ static void setup_path() ; path = env_get( L"PATH" ); - - al_init( &l ); if( path ) { - tokenize_variable_array( path, &l ); + tokenize_variable_array2( path, lst ); } for( j=0; path_el[j]; j++ ) @@ -454,10 +453,10 @@ static void setup_path() int has_el=0; - for( i=0; i 0) && (el[len-1]==L'/') ) { @@ -465,7 +464,7 @@ static void setup_path() } 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; } @@ -473,33 +472,25 @@ static void setup_path() if( !has_el ) { - string_buffer_t b; + wcstring buffer; debug( 3, L"directory %ls was missing", path_el[j] ); - sb_init( &b ); if( path ) { - sb_append( &b, path ); + buffer += path; } - sb_append( &b, - ARRAY_SEP_STR, - path_el[j] ); + buffer += ARRAY_SEP_STR; + buffer += path_el[j]; - env_set( L"PATH", (wchar_t *)b.buff, ENV_GLOBAL | ENV_EXPORT ); - - sb_destroy( &b ); - - al_foreach( &l, &free ); + env_set( L"PATH", buffer.c_str(), ENV_GLOBAL | ENV_EXPORT ); + path = env_get( L"PATH" ); - al_truncate( &l, 0 ); - tokenize_variable_array( path, &l ); + lst.resize(0); + tokenize_variable_array2( path, lst ); } } - - al_foreach( &l, &free ); - al_destroy( &l ); } int env_set_pwd() diff --git a/env_universal.cpp b/env_universal.cpp index d1726aa5a..c6fee60e2 100644 --- a/env_universal.cpp +++ b/env_universal.cpp @@ -208,22 +208,17 @@ static void check_connection() */ static void env_universal_remove_all() { - array_list_t lst; - int i; + size_t i; - al_init( &lst ); - - env_universal_common_get_names( &lst, + wcstring_list_t lst; + env_universal_common_get_names2( lst, 1, 1 ); - - for( i=0; iexportv && 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, int show_exported, int show_unexported ) @@ -919,6 +930,19 @@ void env_universal_common_get_names( array_list_t *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 ) { var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name ); diff --git a/env_universal_common.h b/env_universal_common.h index 808c6d00e..42200b7eb 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -152,6 +152,9 @@ void env_universal_common_destroy(); void env_universal_common_get_names( array_list_t *l, int show_exported, int show_unexported ); +void env_universal_common_get_names2( wcstring_list_t &lst, + int show_exported, + int show_unexported ); /** Perform the specified variable assignment. diff --git a/reader.cpp b/reader.cpp index 74f783070..61186627a 100644 --- a/reader.cpp +++ b/reader.cpp @@ -177,8 +177,10 @@ commence. states can be stacked, in case reader_readline() calls are nested. This happens when the 'read' builtin is used. */ -typedef struct reader_data +class reader_data_t { + public: + /** Buffer containing the whole current commandline */ @@ -289,7 +291,7 @@ typedef struct 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 @@ -302,8 +304,7 @@ typedef struct reader_data which is known to require a repaint. */ int repaint_needed; -} - reader_data_t; +}; /** The current interactive reading context @@ -2267,20 +2268,20 @@ static int default_test( wchar_t *b ) void reader_push( const wchar_t *name ) { - reader_data_t *n = (reader_data_t *)calloc( 1, sizeof( reader_data_t ) ); - - if( !n ) + // use placement new to guarantee zero initialization :( + void *buff = calloc(1, sizeof(reader_data_t)); + if( !buff ) { DIE_MEM(); } - + reader_data_t *n = new(buff) reader_data_t; + n->name = wcsdup( name ); n->next = data; sb_init( &n->kill_item ); data=n; - s_init( &data->screen ); sb_init( &data->prompt_buff ); check_size(); @@ -2324,7 +2325,6 @@ void reader_pop() sb_destroy( &n->search_buff ); sb_destroy( &n->kill_item ); - s_destroy( &n->screen ); sb_destroy( &n->prompt_buff ); /* @@ -2334,6 +2334,8 @@ void reader_pop() al_destroy( &n->search_prev ); free( (void *)n->token_history_buff); + /* Invoke the destructor to balance our placement new */ + n->~reader_data_t(); free(n); if( data == 0 ) diff --git a/screen.cpp b/screen.cpp index c8322f883..24caf8ef8 100644 --- a/screen.cpp +++ b/screen.cpp @@ -340,64 +340,13 @@ static void s_check_status( screen_t *s) earlier value. */ - int prev_line = s->actual_cursor[1]; + int prev_line = s->actual.cursor[1]; write_loop( 1, "\r", 1 ); 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 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 prompt_width ) { - int line_no = s->desired_cursor[1]; + int line_no = s->desired.cursor[1]; switch( b ) { case L'\n': { int i; - line_t *current = s_create_line(); - al_push( &s->desired, current ); - s->desired_cursor[1]++; - s->desired_cursor[0]=0; + s->desired.add_line(); + s->desired.cursor[1]++; + s->desired.cursor[0]=0; for( i=0; i < prompt_width+indent*INDENT_STEP; i++ ) { 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': { - line_t *current; - current = (line_t *)al_get( &s->desired, line_no ); - al_truncate( ¤t->text, 0 ); - al_truncate( ¤t->color, 0 ); - s->desired_cursor[0]=0; + line_t ¤t = s->desired.line(line_no); + current.resize(0); + s->desired.cursor[0] = 0; break; } default: { - line_t *current; int screen_width = common_get_width(); int cw = wcwidth(b); int ew = wcwidth( ellipsis_char ); int i; - current = (line_t *)al_get( &s->desired, line_no ); - - if( !current ) - { - current = s_create_line(); - al_push( &s->desired, current ); - } + s->desired.create_line(line_no); /* Check if we are at the end of the line. If so, print an 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 ); - al_set_long( ¤t->color, s->desired_cursor[0], HIGHLIGHT_COMMENT ); - - current = s_create_line(); - al_push( &s->desired, current ); - s->desired_cursor[1]++; - s->desired_cursor[0]=0; + line_entry_t &entry = s->desired.line(line_no).create_entry(s->desired.cursor[0]); + entry.text = ellipsis_char; + entry.color = HIGHLIGHT_COMMENT; + + line_no = s->desired.line_count(); + s->desired.add_line(); + s->desired.cursor[1]++; + s->desired.cursor[0]=0; for( i=0; i < (prompt_width-ew); i++ ) { 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 ); } - al_set_long( ¤t->text, s->desired_cursor[0], b ); - al_set_long( ¤t->color, s->desired_cursor[0], c ); - s->desired_cursor[0]+= cw; + line_t &line = s->desired.line(line_no); + line.create_entry(s->desired.cursor[0]).text = b; + line.create_entry(s->desired.cursor[0]).color = c; + s->desired.cursor[0]+= cw; 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 ); 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)) { @@ -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 behaviour... */ - s->actual_cursor[0]=0; + s->actual.cursor[0]=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 ) { @@ -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[1] = new_y; + s->actual.cursor[0] = new_x; + s->actual.cursor[1] = new_y; 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 ); s_writeb_buffer = b; - s->actual_cursor[0]+=wcwidth( c ); + s->actual.cursor[0]+=wcwidth( c ); writech( c ); @@ -669,19 +610,18 @@ static void s_update( screen_t *scr, wchar_t *prompt ) 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_write_str( &output, prompt ); - sb_clear( &scr->actual_prompt ); - sb_append( &scr->actual_prompt, prompt ); - scr->actual_cursor[0] = prompt_width; + scr->actual_prompt = prompt; + 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 *s_line = (line_t *)al_get( &scr->actual, i ); + line_t &o_line = scr->desired.line(i); + line_t &s_line = scr->actual.create_line(i); int start_pos = (i==0?prompt_width:0); 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_write_mbs( &output, clr_eol); - if( s_line ) - { - al_truncate( &s_line->text, 0 ); - al_truncate( &s_line->color, 0 ); - } + s_line.resize(0); } - - if( !s_line ) - { - s_line = s_create_line(); - al_push( &scr->actual, s_line ); - } - - for( j=start_pos; jtext ); 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; jtext ) == j ) + if( s_line.entry_count() == j ) { s_move( scr, &output, current_width, i ); s_set_color( scr, &output, o_c ); s_write_char( scr, &output, o ); - al_set_long( &s_line->text, j, o ); - al_set_long( &s_line->color, j, o_c ); + s_line.create_entry(j).text = o; + s_line.create_entry(j).color = o_c; } else { - wchar_t s = (wchar_t)(intptr_t)al_get( &s_line->text, j ); - int s_c = (int)(intptr_t)al_get( &s_line->color, j ); + line_entry_t &entry = s_line.create_entry(j); + wchar_t s = entry.text; + int s_c = entry.color; + if( o != s || o_c != s_c ) { s_move( scr, &output, current_width, i ); s_set_color( scr, &output, o_c ); 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; ktext, current_width+k, L'\0' ); + s_line.create_entry(current_width+k).text = L'\0'; } } 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_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_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); @@ -864,8 +796,8 @@ void s_write( screen_t *s, if( current_line_width > max_line_width ) max_line_width = current_line_width; - s_reset_arr( &s->desired ); - s->desired_cursor[0] = s->desired_cursor[1] = 0; + s->desired.resize(0); + s->desired.cursor[0] = s->desired.cursor[1] = 0; /* If overflowing, give the prompt its own line to improve the @@ -897,13 +829,13 @@ void s_write( screen_t *s, if( i == cursor ) { - cursor_arr[0] = s->desired_cursor[0]; - cursor_arr[1] = s->desired_cursor[1]; + cursor_arr[0] = s->desired.cursor[0]; + cursor_arr[1] = s->desired.cursor[1]; } 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 @@ -911,17 +843,17 @@ void s_write( screen_t *s, cursor won't be on the ellipsis which looks unintuitive. */ - cursor_arr[0] = s->desired_cursor[0] - wcwidth(b[i]); - cursor_arr[1] = s->desired_cursor[1]; + cursor_arr[0] = s->desired.cursor[0] - wcwidth(b[i]); + cursor_arr[1] = s->desired.cursor[1]; } } 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_save_status( s ); } @@ -930,10 +862,10 @@ void s_reset( screen_t *s, int reset_cursor ) { CHECK( s, ); - int prev_line = s->actual_cursor[1]; - s_reset_arr( &s->actual ); - s->actual_cursor[0] = s->actual_cursor[1] = 0; - sb_clear( &s->actual_prompt ); + int prev_line = s->actual.cursor[1]; + s->actual.resize(0); + s->actual.cursor[0] = s->actual.cursor[1] = 0; + s->actual_prompt = L""; s->need_clear=1; if( !reset_cursor ) @@ -943,7 +875,7 @@ void s_reset( screen_t *s, int reset_cursor ) next repaint. */ write_loop( 1, "\r", 1 ); - s->actual_cursor[1] = prev_line; + s->actual.cursor[1] = prev_line; } fstat( 1, &s->prev_buff_1 ); fstat( 2, &s->prev_buff_2 ); diff --git a/screen.h b/screen.h index 0e2c798a3..291f35c64 100644 --- a/screen.h +++ b/screen.h @@ -12,6 +12,79 @@ #ifndef FISH_SCREEN_H #define FISH_SCREEN_H +#include + +struct line_entry_t +{ + wchar_t text; + int color; +}; + + +/** + A class representing a single line of a screen. +*/ +class line_t +{ + public: + std::vector 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_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. */ @@ -20,24 +93,17 @@ typedef struct /** The internal representation of the desired screen contents. */ - array_list_t desired; + screen_data_t desired; /** The internal representation of the actual screen contents. */ - array_list_t actual; + screen_data_t actual; + /** - The desired cursor position. - */ - int desired_cursor[2]; - /** - The actual cursor position. - */ - int actual_cursor[2]; - /** - A stringbuffer containing the prompt which was last printed to + A string containing the prompt which was last printed to the screen. */ - string_buffer_t actual_prompt; + wcstring actual_prompt; /** The actual width of the screen at the time of the last screen @@ -61,36 +127,6 @@ typedef struct } 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 to define the desired contents of the screen. The screen command