mudgangster

Log | Files | Refs

commit 44418efb7e40e8200bedc673965b75250d1352a0
parent 0f71a3ba6ac8a9cd294561dfadf46f7877ca093e
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Fri,  7 Sep 2018 22:55:25 +0300

Initial attempt at building a string from a selection

Diffstat:
src/textbox.cc | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 99 insertions(+), 4 deletions(-)

diff --git a/src/textbox.cc b/src/textbox.cc @@ -4,6 +4,12 @@ #include "textbox.h" #include "ui.h" +#if PLATFORM_WINDOWS +#define NEWLINE_STRING "\r\n" +#else +#define NEWLINE_STRING "\n" +#endif + static uint8_t pack_style( Colour fg, Colour bg, bool bold ) { STATIC_ASSERT( NUM_COLOURS * NUM_COLOURS * 2 < UINT8_MAX ); @@ -140,7 +146,95 @@ void textbox_mouse_up( TextBox * tb, int window_x, int window_y ) { if( !tb->selecting ) return; - // TODO: copy the text + int fw, fh; + ui_get_font_size( &fw, &fh ); + + size_t tb_cols = tb->w / fw; + + // convert mouse start/end points to ordered start/end points + int start_row = tb->selection_start_row; + int end_row = tb->selection_end_row; + int start_col = tb->selection_start_col; + int end_col = tb->selection_end_col; + if( tb->selection_start_row == tb->selection_end_row ) { + start_col = min( tb->selection_start_col, tb->selection_end_col ); + end_col = max( tb->selection_start_col, tb->selection_end_col ); + } + else if( tb->selection_start_row < tb->selection_end_row ) { + swap( start_row, end_row ); + swap( start_col, end_col ); + } + + // find what the start/end lines/offsets are + // TODO: this is incorrect when wrapping... + int end_line = 0; + int rows = 0; + + while( rows < end_row ) { + const TextBox::Line & line = tb->lines[ ( tb->head + tb->num_lines - tb->scroll_offset - end_line ) % tb->max_lines ]; + int line_rows = 1 + line.len / tb_cols; + if( line.len > 0 && line.len % tb_cols == 0 ) + line_rows--; + rows += line_rows; + end_line++; + } + + size_t end_line_offset = ( rows - end_row ) * tb_cols + end_col + 1; + int start_line = end_line; + + while( rows < start_row ) { + const TextBox::Line & line = tb->lines[ ( tb->head + tb->num_lines - tb->scroll_offset - start_line ) % tb->max_lines ]; + int line_rows = 1 + line.len / tb_cols; + if( line.len > 0 && line.len % tb_cols == 0 ) + line_rows--; + rows += line_rows; + start_line++; + } + + size_t start_line_offset = ( rows - start_row ) * tb_cols + start_col; + + // first pass to get the length of the selected string + size_t selected_length = 1; // include space for \0 + for( int i = start_line; i >= end_line; i-- ) { + const TextBox::Line & line = tb->lines[ ( tb->head + tb->num_lines - tb->scroll_offset - i ) % tb->max_lines ]; + size_t start_offset = i == start_line ? start_line_offset : 0; + size_t end_offset = i == end_line ? end_line_offset : line.len; + printf( "%d: %zu-%zu\n", i, start_offset, end_offset ); + // TODO: iterate over glyphs to see when ansi codes need inserting + if( start_offset <= line.len ) { + selected_length += min( line.len, end_offset ) - start_offset; + } + if( i != end_line ) { + selected_length += sizeof( NEWLINE_STRING ) - 1; + } + } + + printf( "%d+%zu to %d+%zu\n", start_line, start_line_offset, end_line, end_line_offset ); + printf( "%zu chars\n", selected_length ); + + char * selected = ( char * ) malloc( selected_length ); + selected[ selected_length - 1 ] = '\0'; + + // second pass to copy the selection out + size_t n = 0; + for( int i = start_line; i >= end_line; i-- ) { + const TextBox::Line & line = tb->lines[ ( tb->head + tb->num_lines - tb->scroll_offset - i ) % tb->max_lines ]; + size_t start_offset = i == start_line ? start_line_offset : 0; + size_t end_offset = i == end_line ? end_line_offset : line.len; + size_t len = min( line.len, end_offset ) - start_offset; + // TODO: insert ansi codes when style changes + for( size_t j = 0; j < len; j++ ) { + selected[ n ] = line.glyphs[ j + start_offset ].ch; + n++; + } + if( i != end_line ) { + memcpy( selected + n, NEWLINE_STRING, sizeof( NEWLINE_STRING ) - 1 ); + n += sizeof( NEWLINE_STRING ) - 1; + } + } + + printf( "%s\n", selected ); + free( selected ); tb->selecting = false; tb->dirty = true; @@ -157,16 +251,17 @@ void textbox_set_size( TextBox * tb, int w, int h ) { } static bool inside_selection( int col, int row, int start_col, int start_row, int end_col, int end_row ) { - int min_col = min( start_col, end_col ); int min_row = min( start_row, end_row ); - int max_col = max( start_col, end_col ); int max_row = max( start_row, end_row ); if( row < min_row || row > max_row ) return false; - if( start_row == end_row ) + if( start_row == end_row ) { + int min_col = min( start_col, end_col ); + int max_col = max( start_col, end_col ); return col >= min_col && col <= max_col; + } if( row > min_row && row < max_row ) return true;