mudgangster

Log | Files | Refs

commit b146e8d50419daff397d16ddd9d01e633cb5e19f
parent 344d718f9762c7889aa3d9cc4b63b4342c57f460
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Tue,  4 Sep 2018 09:31:48 +0300

Merge TextBufferView back into TextBox, platform specific rendering goes through ui_draw_* now

Diffstat:
src/textbox.cc | 111++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
src/textbox.h | 27+++++++++++++++++----------
src/ui.h | 2++
src/x11.cc | 144+++++++++++++++----------------------------------------------------------------
4 files changed, 148 insertions(+), 136 deletions(-)

diff --git a/src/textbox.cc b/src/textbox.cc @@ -2,6 +2,7 @@ #include "common.h" #include "textbox.h" +#include "ui.h" static uint8_t pack_style( Colour fg, Colour bg, bool bold ) { STATIC_ASSERT( NUM_COLOURS * NUM_COLOURS * 2 < UINT8_MAX ); @@ -15,7 +16,7 @@ static uint8_t pack_style( Colour fg, Colour bg, bool bold ) { return checked_cast< uint8_t >( style ); } -void unpack_style( uint8_t style, int * fg, int * bg, int * bold ) { +static void unpack_style( uint8_t style, int * fg, int * bg, int * bold ) { *bold = style % 2; style /= 2; @@ -25,24 +26,24 @@ void unpack_style( uint8_t style, int * fg, int * bg, int * bold ) { *fg = style; } -void text_init( TextBuffer * tb, size_t scrollback ) { +void textbox_init( TextBox * tb, size_t scrollback ) { // TODO: this is kinda crap - tb->lines = ( TextBuffer::Line * ) calloc( sizeof( TextBuffer::Line ), scrollback ); + tb->lines = ( TextBox::Line * ) calloc( sizeof( TextBox::Line ), scrollback ); tb->num_lines = 1; tb->max_lines = scrollback; } -void text_destroy( TextBuffer * tb ) { +void textbox_destroy( TextBox * tb ) { free( tb->lines ); } -void text_add( TextBuffer * tb, const char * str, size_t len, Colour fg, Colour bg, bool bold ) { - TextBuffer::Line * line = &tb->lines[ ( tb->head + tb->num_lines ) % tb->max_lines ]; +void textbox_add( TextBox * tb, const char * str, size_t len, Colour fg, Colour bg, bool bold ) { + TextBox::Line * line = &tb->lines[ ( tb->head + tb->num_lines ) % tb->max_lines ]; size_t remaining = MAX_LINE_LENGTH - line->len; size_t n = min( strlen( str ), remaining ); for( size_t i = 0; i < n; i++ ) { - TextBuffer::Glyph & glyph = line->glyphs[ line->len + i ]; + TextBox::Glyph & glyph = line->glyphs[ line->len + i ]; glyph.ch = str[ i ]; glyph.style = pack_style( fg, bg, bold ); }; @@ -50,13 +51,105 @@ void text_add( TextBuffer * tb, const char * str, size_t len, Colour fg, Colour line->len += n; } -void text_newline( TextBuffer * tb ) { +void textbox_newline( TextBox * tb ) { if( tb->num_lines < tb->max_lines ) { tb->num_lines++; return; } tb->head++; - TextBuffer::Line * line = &tb->lines[ ( tb->head + tb->num_lines ) % tb->max_lines ]; + TextBox::Line * line = &tb->lines[ ( tb->head + tb->num_lines ) % tb->max_lines ]; line->len = 0; } + +void textbox_scroll( TextBox * tb, int offset ) { + if( offset < 0 ) { + tb->scroll_offset -= min( size_t( -offset ), tb->scroll_offset ); + } + else { + tb->scroll_offset = min( tb->scroll_offset + offset, tb->num_lines - 1 ); + } + + textbox_draw( tb ); +} + +static size_t num_rows( size_t h ) { + int fw, fh; + ui_get_font_size( &fw, &fh ); + return h / ( fh + SPACING ); +} + +void textbox_page_down( TextBox * tb ) { + textbox_scroll( tb, -int( num_rows( tb->h ) ) + 1 ); +} + +void textbox_page_up( TextBox * tb ) { + textbox_scroll( tb, num_rows( tb->h ) - 1 ); +} + +void textbox_set_pos( TextBox * tb, int x, int y ) { + tb->x = x; + tb->y = y; +} + +void textbox_set_size( TextBox * tb, int w, int h ) { + tb->w = w; + tb->h = h; +} + +void textbox_draw( const TextBox * tb ) { + if( tb->w == 0 || tb->h == 0 ) + return; + + ui_fill_rect( tb->x, tb->y, tb->w, tb->h, COLOUR_BG, false ); + + /* + * lines refers to lines of text sent from the game + * rows refers to visual rows of text in the client, so when lines get + * wrapped they have more than one row + */ + + int fw, fh; + ui_get_font_size( &fw, &fh ); + + size_t lines_drawn = 0; + size_t rows_drawn = 0; + size_t tb_rows = num_rows( tb->h ); + size_t tb_cols = tb->w / fw; + + while( rows_drawn < tb_rows && lines_drawn < tb->num_lines ) { + const TextBox::Line & line = tb->lines[ ( tb->head + tb->num_lines - tb->scroll_offset - lines_drawn ) % tb->max_lines ]; + + size_t line_rows = 1 + line.len / tb_cols; + if( line.len > 0 && line.len % tb_cols == 0 ) + line_rows--; + + for( size_t i = 0; i < line.len; i++ ) { + const TextBox::Glyph & glyph = line.glyphs[ i ]; + + size_t row = i / tb_cols; + + int left = ( i % tb_cols ) * fw; + int top = tb->h - ( rows_drawn + line_rows - row ) * ( fh + SPACING ); + if( top < 0 ) + continue; + + int fg, bg, bold; + unpack_style( glyph.style, &fg, &bg, &bold ); + + // bg + // TODO: top/bottom spacing seems to be inconsistent here, try with large spacing + int top_spacing = SPACING / 2; + int bot_spacing = SPACING - top_spacing; + ui_fill_rect( tb->x + left, tb->y + top - top_spacing, fw, fh + bot_spacing, Colour( bg ), false ); + + // fg + ui_draw_char( tb->x + left, tb->y + top, glyph.ch, Colour( fg ), bold ); + } + + lines_drawn++; + rows_drawn += line_rows; + } + + ui_dirty( tb->x, tb->y, tb->x + tb->w, tb->y + tb->h ); +} diff --git a/src/textbox.h b/src/textbox.h @@ -5,7 +5,7 @@ constexpr size_t MAX_LINE_LENGTH = 2048; constexpr size_t SCROLLBACK_SIZE = 1 << 16; -struct TextBuffer { +struct TextBox { struct Glyph { char ch; uint8_t style; @@ -21,16 +21,23 @@ struct TextBuffer { size_t num_lines; size_t max_lines; - // int x, y; - // int w, h; - // size_t scroll_offset; - // bool dirty; + int x, y; + int w, h; + size_t scroll_offset; }; -void text_init( TextBuffer * tb, size_t scrollback ); +void textbox_init( TextBox * tb, size_t scrollback ); -void text_add( TextBuffer * tb, const char * str, size_t len, Colour fg, Colour bg, bool bold ); -void text_newline( TextBuffer * tb ); -void unpack_style( uint8_t style, int * fg, int * bg, int * bold ); +void textbox_add( TextBox * tb, const char * str, size_t len, Colour fg, Colour bg, bool bold ); +void textbox_newline( TextBox * tb ); -void text_destroy( TextBuffer * tb ); +void textbox_scroll( TextBox * tb, int offset ); +void textbox_page_down( TextBox * tb ); +void textbox_page_up( TextBox * tb ); + +void textbox_set_pos( TextBox * tb, int x, int y ); +void textbox_set_size( TextBox * tb, int w, int h ); + +void textbox_draw( const TextBox * tb ); + +void textbox_destroy( TextBox * tb ); diff --git a/src/ui.h b/src/ui.h @@ -22,6 +22,8 @@ void ui_fill_rect( int left, int top, int width, int height, Colour colour, bool void ui_draw_char( int left, int top, char c, Colour colour, bool bold ); void ui_dirty( int left, int top, int right, int bottom ); // TODO: x/y + w/h? +void ui_get_font_size( int * fw, int * fh ); + bool ui_urgent(); int ui_display_fd(); // TODO: very x11 specific! diff --git a/src/x11.cc b/src/x11.cc @@ -12,17 +12,6 @@ #include "script.h" #include "textbox.h" -struct TextBufferView { - TextBuffer text; - - int x; - int y; - int width; - int height; - - size_t scroll_offset; -}; - struct { Display * display; int screen; @@ -34,8 +23,8 @@ struct { Window window; - TextBufferView main_text_view; - TextBufferView chat_text_view; + TextBox main_text; + TextBox chat_text; int width; int height; @@ -154,90 +143,6 @@ void ui_dirty( int left, int top, int width, int height ) { // UI.dirty_bottom = max( UI.dirty_bottom, bottom ); } -static void textview_draw( const TextBufferView * tv ) { - if( tv->width == 0 || tv->height == 0 ) - return; - - ui_fill_rect( tv->x, tv->y, tv->width, tv->height, COLOUR_BG, false ); - - /* - * lines refers to lines of text sent from the game - * rows refers to visual rows of text in the client, so when lines get - * wrapped they have more than one row - */ - size_t lines_drawn = 0; - size_t rows_drawn = 0; - size_t tv_rows = tv->height / ( Style.font.height + SPACING ); - size_t tv_cols = tv->width / Style.font.width; - - while( rows_drawn < tv_rows && lines_drawn < tv->text.num_lines ) { - const TextBuffer::Line & line = tv->text.lines[ ( tv->text.head + tv->text.num_lines - tv->scroll_offset - lines_drawn ) % tv->text.max_lines ]; - - size_t line_rows = 1 + line.len / tv_cols; - if( line.len > 0 && line.len % tv_cols == 0 ) - line_rows--; - - for( size_t i = 0; i < line.len; i++ ) { - const TextBuffer::Glyph & glyph = line.glyphs[ i ]; - - size_t row = i / tv_cols; - - int left = ( i % tv_cols ) * Style.font.width; - int top = tv->height - ( rows_drawn + line_rows - row ) * ( Style.font.height + SPACING ); - if( top < 0 ) - continue; - - int fg, bg, bold; - unpack_style( glyph.style, &fg, &bg, &bold ); - - // bg - // TODO: top/bottom spacing seems to be inconsistent here, try with large spacing - int top_spacing = SPACING / 2; - int bot_spacing = SPACING - top_spacing; - ui_fill_rect( tv->x + left, tv->y + top - top_spacing, Style.font.width, Style.font.height + bot_spacing, Colour( bg ), false ); - - // fg - ui_draw_char( tv->x + left, tv->y + top, glyph.ch, Colour( fg ), bold ); - } - - lines_drawn++; - rows_drawn += line_rows; - } - - ui_dirty( tv->x, tv->y, tv->x + tv->width, tv->y + tv->height ); -} - -static void textview_scroll( TextBufferView * tv, int offset ) { - if( offset < 0 ) { - tv->scroll_offset -= min( size_t( -offset ), tv->scroll_offset ); - } - else { - tv->scroll_offset = min( tv->scroll_offset + offset, tv->text.num_lines - 1 ); - } - - textview_draw( tv ); -} - -static void textview_page_down( TextBufferView * tv ) { - size_t rows = tv->height / ( Style.font.height + SPACING ); - textview_scroll( tv, -int( rows ) + 1 ); -} - -static void textview_page_up( TextBufferView * tv ) { - size_t rows = tv->height / ( Style.font.height + SPACING ); - textview_scroll( tv, rows - 1 ); -} - -static void textview_set_pos( TextBufferView * tv, int x, int y ) { - tv->x = x; - tv->y = y; -} - -static void textview_set_size( TextBufferView * tv, int w, int h ) { - tv->width = w; - tv->height = h; -} - static Atom wmDeleteWindow; typedef struct { @@ -311,8 +216,8 @@ void ui_draw() { draw_input(); ui_draw_status(); - textview_draw( &UI.chat_text_view ); - textview_draw( &UI.main_text_view ); + textbox_draw( &UI.chat_text ); + textbox_draw( &UI.main_text ); int spacerY = ( 2 * PADDING ) + ( Style.font.height + SPACING ) * CHAT_ROWS; ui_fill_rect( 0, spacerY, UI.width, 1, COLOUR_STATUSBG, false ); @@ -352,11 +257,11 @@ static void eventResize( XEvent * event ) { UI.back_buffer = XCreatePixmap( UI.display, UI.window, UI.max_width, UI.max_height, UI.depth ); } - textview_set_pos( &UI.chat_text_view, PADDING, PADDING ); - textview_set_size( &UI.chat_text_view, UI.width - ( 2 * PADDING ), ( Style.font.height + SPACING ) * CHAT_ROWS ); + textbox_set_pos( &UI.chat_text, PADDING, PADDING ); + textbox_set_size( &UI.chat_text, UI.width - ( 2 * PADDING ), ( Style.font.height + SPACING ) * CHAT_ROWS ); - textview_set_pos( &UI.main_text_view, PADDING, ( PADDING * 2 ) + CHAT_ROWS * ( Style.font.height + SPACING ) + 1 ); - textview_set_size( &UI.main_text_view, UI.width - ( 2 * PADDING ), UI.height + textbox_set_pos( &UI.main_text, PADDING, ( PADDING * 2 ) + CHAT_ROWS * ( Style.font.height + SPACING ) + 1 ); + textbox_set_size( &UI.main_text, UI.width - ( 2 * PADDING ), UI.height - ( ( ( Style.font.height + SPACING ) * CHAT_ROWS ) + ( PADDING * 2 ) ) - ( ( Style.font.height * 2 ) + ( PADDING * 5 ) ) - 1 ); @@ -401,16 +306,16 @@ static void eventKeyPress( XEvent * event ) { case XK_Page_Up: if( shift ) - textview_scroll( &UI.main_text_view, 1 ); + textbox_scroll( &UI.main_text, 1 ); else - textview_page_up( &UI.main_text_view ); + textbox_page_up( &UI.main_text ); break; case XK_Page_Down: if( shift ) - textview_scroll( &UI.main_text_view, -1 ); + textbox_scroll( &UI.main_text, -1 ); else - textview_page_down( &UI.main_text_view ); + textbox_page_down( &UI.main_text ); break; case XK_Up: @@ -595,8 +500,8 @@ static void initStyle() { void ui_init() { UI = { }; - text_init( &UI.main_text_view.text, SCROLLBACK_SIZE ); - text_init( &UI.chat_text_view.text, CHAT_ROWS ); + textbox_init( &UI.main_text, SCROLLBACK_SIZE ); + textbox_init( &UI.chat_text, CHAT_ROWS ); UI.display = XOpenDisplay( NULL ); UI.screen = XDefaultScreen( UI.display ); UI.width = -1; @@ -637,27 +542,27 @@ void ui_init() { } void ui_main_draw() { - textview_draw( &UI.main_text_view ); + textbox_draw( &UI.main_text ); } void ui_main_newline() { - text_newline( &UI.main_text_view.text ); + textbox_newline( &UI.main_text ); } void ui_main_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ) { - text_add( &UI.main_text_view.text, str, len, fg, bg, bold ); + textbox_add( &UI.main_text, str, len, fg, bg, bold ); } void ui_chat_draw() { - textview_draw( &UI.chat_text_view ); + textbox_draw( &UI.chat_text ); } void ui_chat_newline() { - text_newline( &UI.chat_text_view.text ); + textbox_newline( &UI.chat_text ); } void ui_chat_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ) { - text_add( &UI.chat_text_view.text, str, len, fg, bg, bold ); + textbox_add( &UI.chat_text, str, len, fg, bg, bold ); } void ui_urgent() { @@ -673,9 +578,14 @@ int ui_display_fd() { return ConnectionNumber( UI.display ); } +void ui_get_font_size( int * fw, int * fh ) { + *fw = Style.font.width; + *fh = Style.font.height; +} + void ui_term() { - text_destroy( &UI.main_text_view.text ); - text_destroy( &UI.chat_text_view.text ); + textbox_destroy( &UI.main_text ); + textbox_destroy( &UI.chat_text ); free( statusContents ); XFreeFont( UI.display, Style.font.font );