mudgangster

Log | Files | Refs

commit 53eec1720c481047f5ee0d801c4321cdba6f6b96
parent cf18b48305c098e53122e7445237a2c680718794
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Tue,  4 Sep 2018 07:43:06 +0300

Run everything through ui_draw_*

Diffstat:
src/common.h | 4++++
src/textbox.h | 5+++++
src/ui.h | 4++++
src/x11.cc | 255+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
4 files changed, 166 insertions(+), 102 deletions(-)

diff --git a/src/common.h b/src/common.h @@ -42,4 +42,8 @@ enum Colour { SYSTEM, NUM_COLOURS, + + COLOUR_BG, + COLOUR_STATUSBG, + COLOUR_CURSOR, }; diff --git a/src/textbox.h b/src/textbox.h @@ -20,6 +20,11 @@ struct TextBuffer { size_t head; size_t num_lines; size_t max_lines; + + // int x, y; + // int w, h; + // size_t scroll_offset; + // bool dirty; }; void text_init( TextBuffer * tb, size_t scrollback ); diff --git a/src/ui.h b/src/ui.h @@ -18,6 +18,10 @@ void ui_chat_draw(); void ui_chat_newline(); void ui_chat_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ); +void ui_fill_rect( int left, int top, int width, int height, Colour colour, bool bold ); +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? + bool ui_urgent(); int ui_display_fd(); // TODO: very x11 specific! diff --git a/src/x11.cc b/src/x11.cc @@ -27,6 +27,8 @@ struct { Display * display; int screen; + Pixmap back_buffer; + GC gc; Colormap colorMap; @@ -38,6 +40,10 @@ struct { int width; int height; int depth; + int max_width, max_height; + + bool dirty; + int dirty_left, dirty_top, dirty_right, dirty_bottom; bool has_focus; } UI; @@ -54,16 +60,7 @@ struct MudFont { struct { ulong bg; - ulong fg; - - XColor xBG; - XColor xFG; - - ulong statusBG; - ulong statusFG; - - ulong inputBG; - ulong inputFG; + ulong status_bg; ulong cursor; MudFont font; @@ -96,14 +93,72 @@ struct { }; } Style; +static void set_fg( Colour colour, bool bold ) { + ulong c; + + switch( colour ) { + case SYSTEM: + c = Style.Colours.system; + break; + + case COLOUR_BG: + c = Style.bg; + break; + + case COLOUR_STATUSBG: + c = Style.status_bg; + break; + + case COLOUR_CURSOR: + c = Style.cursor; + break; + + default: + c = Style.colours[ bold ][ colour ]; + break; + } + + XSetForeground( UI.display, UI.gc, c ); +} + +void ui_fill_rect( int left, int top, int width, int height, Colour colour, bool bold ) { + set_fg( colour, bold ); + XFillRectangle( UI.display, UI.back_buffer, UI.gc, left, top, width, height ); +} + +void ui_draw_char( int left, int top, char c, Colour colour, bool bold ) { + XSetFont( UI.display, UI.gc, ( bold ? Style.fontBold : Style.font ).font->fid ); + set_fg( colour, bold ); + XDrawString( UI.display, UI.back_buffer, UI.gc, left, top + Style.font.ascent + SPACING, &c, 1 ); +} + +void ui_dirty( int left, int top, int width, int height ) { + XCopyArea( UI.display, UI.back_buffer, UI.window, UI.gc, left, top, width, height, left, top ); + + // int right = left + width; + // int bottom = top + height; + // + // printf( "make dirty %d %d %d %d\n", left, top, right, bottom ); + // if( !UI.dirty ) { + // UI.dirty = true; + // UI.dirty_left = left; + // UI.dirty_top = top; + // UI.dirty_right = right; + // UI.dirty_bottom = bottom; + // return; + // } + // + // UI.dirty_left = min( UI.dirty_left, left ); + // UI.dirty_top = min( UI.dirty_top, top ); + // UI.dirty_right = max( UI.dirty_right, right ); + // UI.dirty_bottom = max( UI.dirty_bottom, bottom ); +} + static void textview_draw( const TextBufferView * tv ) { if( tv->width == 0 || tv->height == 0 ) return; - Pixmap doublebuf = XCreatePixmap( UI.display, UI.window, tv->width, tv->height, UI.depth ); - - XSetForeground( UI.display, UI.gc, Style.bg ); - XFillRectangle( UI.display, doublebuf, UI.gc, 0, 0, tv->width, tv->height ); + ui_fill_rect( tv->x, tv->y, tv->width, tv->height, COLOUR_BG, false ); /* * lines refers to lines of text sent from the game @@ -136,23 +191,20 @@ static void textview_draw( const TextBufferView * tv ) { 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; - XSetForeground( UI.display, UI.gc, bg == SYSTEM ? Style.Colours.system : Style.colours[ 0 ][ bg ] ); - XFillRectangle( UI.display, doublebuf, UI.gc, left, top - top_spacing, Style.font.width, Style.font.height + bot_spacing ); + ui_fill_rect( tv->x + left, tv->y + top - top_spacing, Style.font.width, Style.font.height + bot_spacing, Colour( bg ), false ); // fg - XSetFont( UI.display, UI.gc, ( bold ? Style.fontBold : Style.font ).font->fid ); - XSetForeground( UI.display, UI.gc, fg == SYSTEM ? Style.Colours.system : Style.colours[ bold ][ fg ] ); - XDrawString( UI.display, doublebuf, UI.gc, left, top + Style.font.ascent + SPACING, &glyph.ch, 1 ); + ui_draw_char( tv->x + left, tv->y + top, glyph.ch, Colour( fg ), bold ); } lines_drawn++; rows_drawn += line_rows; } - XCopyArea( UI.display, doublebuf, UI.window, UI.gc, 0, 0, tv->width, tv->height, tv->x, tv->y ); - XFreePixmap( UI.display, doublebuf ); + ui_dirty( tv->x, tv->y, tv->x + tv->width, tv->y + tv->height ); } static void textview_scroll( TextBufferView * tv, int offset ) { @@ -220,19 +272,17 @@ void ui_statusAdd( const char c, const Colour fg, const bool bold ) { } void ui_draw_status() { - XSetForeground( UI.display, UI.gc, Style.statusBG ); - XFillRectangle( UI.display, UI.window, UI.gc, 0, UI.height - ( PADDING * 4 ) - ( Style.font.height * 2 ), UI.width, Style.font.height + ( PADDING * 2 ) ); + ui_fill_rect( 0, UI.height - PADDING * 4 - Style.font.height * 2, UI.width, Style.font.height + PADDING * 2, COLOUR_STATUSBG, false ); for( size_t i = 0; i < statusLen; i++ ) { StatusChar sc = statusContents[ i ]; - XSetFont( UI.display, UI.gc, ( sc.bold ? Style.fontBold : Style.font ).font->fid ); - XSetForeground( UI.display, UI.gc, Style.colours[ sc.bold ][ sc.fg ] ); - int x = PADDING + i * Style.font.width; - int y = UI.height - ( PADDING * 3 ) - Style.font.height - Style.font.descent; - XDrawString( UI.display, UI.window, UI.gc, x, y, &sc.c, 1 ); + int y = UI.height - ( PADDING * 3 ) - Style.font.height * 2 - SPACING; + ui_draw_char( x, y, sc.c, sc.fg, sc.bold ); } + + ui_dirty( 0, UI.height - ( PADDING * 4 ) - ( Style.font.height * 2 ), UI.width, Style.font.height + ( PADDING * 2 ) ); } void draw_input() { @@ -240,23 +290,23 @@ void draw_input() { XSetFont( UI.display, UI.gc, Style.font.font->fid ); - XSetForeground( UI.display, UI.gc, Style.bg ); - XFillRectangle( UI.display, UI.window, UI.gc, PADDING, UI.height - ( PADDING + Style.font.height ), UI.width - 6, Style.font.height ); + int top = UI.height - PADDING - Style.font.height; + ui_fill_rect( PADDING, top, UI.width - PADDING * 2, Style.font.height, COLOUR_BG, false ); - XSetForeground( UI.display, UI.gc, Style.fg ); - XDrawString( UI.display, UI.window, UI.gc, PADDING, UI.height - ( PADDING + Style.font.descent ), input.buf, input.len ); + for( size_t i = 0; i < input.len; i++ ) + ui_draw_char( PADDING + i * Style.font.width, top - SPACING, input.buf[ i ], WHITE, false ); - XSetForeground( UI.display, UI.gc, Style.cursor ); - XFillRectangle( UI.display, UI.window, UI.gc, PADDING + Style.font.width * input.cursor_pos, UI.height - ( PADDING + Style.font.height ), Style.font.width, Style.font.height ); + ui_fill_rect( PADDING + input.cursor_pos * Style.font.width, top, Style.font.width, Style.font.height, COLOUR_CURSOR, false ); if( input.cursor_pos < input.len ) { - XSetForeground( UI.display, UI.gc, Style.bg ); - XDrawString( UI.display, UI.window, UI.gc, PADDING + Style.font.width * input.cursor_pos, UI.height - ( PADDING + Style.font.descent ), input.buf + input.cursor_pos, 1 ); + ui_draw_char( PADDING + input.cursor_pos * Style.font.width, top - SPACING, input.buf[ input.cursor_pos ], COLOUR_BG, false ); } + + ui_dirty( PADDING, UI.height - ( PADDING + Style.font.height ), UI.width - PADDING * 2, Style.font.height ); } void ui_draw() { - XClearWindow( UI.display, UI.window ); + ui_fill_rect( 0, 0, UI.width, UI.height, COLOUR_BG, false ); draw_input(); ui_draw_status(); @@ -265,8 +315,9 @@ void ui_draw() { textview_draw( &UI.main_text_view ); int spacerY = ( 2 * PADDING ) + ( Style.font.height + SPACING ) * CHAT_ROWS; - XSetForeground( UI.display, UI.gc, Style.statusBG ); - XFillRectangle( UI.display, UI.window, UI.gc, 0, spacerY, UI.width, 1 ); + ui_fill_rect( 0, spacerY, UI.width, 1, COLOUR_STATUSBG, false ); + + ui_dirty( 0, 0, UI.width, UI.height ); } static void eventButtonPress( XEvent * event ) { } @@ -280,14 +331,26 @@ static void eventMessage( XEvent * event ) { } static void eventResize( XEvent * event ) { - int newWidth = event->xconfigure.width; - int newHeight = event->xconfigure.height; + int old_width = UI.width; + int old_height = UI.height; + + UI.width = event->xconfigure.width; + UI.height = event->xconfigure.height; - if( newWidth == UI.width && newHeight == UI.height ) + if( UI.width == old_width && UI.height == old_height ) return; - UI.width = newWidth; - UI.height = newHeight; + int old_max_width = UI.max_width; + int old_max_height = UI.max_height; + UI.max_width = max( UI.max_width, UI.width ); + UI.max_height = max( UI.max_height, UI.height ); + + if( UI.max_width != old_max_width || UI.max_height != old_max_height ) { + if( old_width != -1 ) { + XFreePixmap( UI.display, UI.back_buffer ); + } + UI.back_buffer = XCreatePixmap( UI.display, UI.window, UI.max_width, UI.max_height, UI.depth ); + } XSetForeground( UI.display, UI.gc, Style.bg ); XFillRectangle( UI.display, UI.window, UI.gc, 0, 0, UI.width, UI.height ); @@ -428,7 +491,7 @@ static void eventKeyPress( XEvent * event ) { if( ctrl || alt ) { script_doMacro( keyBuffer, len, shift, ctrl, alt ); } - else { + else if( len > 0 ) { input_add( keyBuffer, len ); draw_input(); } @@ -453,22 +516,27 @@ static void eventFocusIn( XEvent * event ) { } void ui_handleXEvents() { - void ( *EventHandler[ LASTEvent ] )( XEvent * ) = { }; - EventHandler[ ButtonPress ] = eventButtonPress; - EventHandler[ ButtonRelease ] = eventButtonRelease; - EventHandler[ ClientMessage ] = eventMessage; - EventHandler[ ConfigureNotify ] = eventResize; - EventHandler[ Expose ] = eventExpose; - EventHandler[ KeyPress ] = eventKeyPress; - EventHandler[ FocusOut ] = eventFocusOut; - EventHandler[ FocusIn ] = eventFocusIn; + void ( *event_handlers[ LASTEvent ] )( XEvent * ) = { }; + event_handlers[ ButtonPress ] = eventButtonPress; + event_handlers[ ButtonRelease ] = eventButtonRelease; + event_handlers[ ClientMessage ] = eventMessage; + event_handlers[ ConfigureNotify ] = eventResize; + event_handlers[ Expose ] = eventExpose; + event_handlers[ KeyPress ] = eventKeyPress; + event_handlers[ FocusOut ] = eventFocusOut; + event_handlers[ FocusIn ] = eventFocusIn; while( XPending( UI.display ) ) { XEvent event; XNextEvent( UI.display, &event ); - if( EventHandler[ event.type ] != NULL ) - EventHandler[ event.type ]( &event ); + if( event_handlers[ event.type ] != NULL ) + event_handlers[ event.type ]( &event ); + } + + if( UI.dirty ) { + XCopyArea( UI.display, UI.back_buffer, UI.window, UI.gc, UI.dirty_left, UI.dirty_top, UI.dirty_right - UI.dirty_left, UI.dirty_bottom - UI.dirty_top, UI.dirty_left, UI.dirty_top ); + UI.dirty = false; } } @@ -492,51 +560,36 @@ static MudFont loadFont( const char * fontStr ) { return font; } +static ulong make_color( const char * hex ) { + XColor color; + XAllocNamedColor( UI.display, UI.colorMap, hex, &color, &color ); + return color.pixel; +} + static void initStyle() { - #define SETCOLOR( x, c ) \ - do { \ - XColor color; \ - XAllocNamedColor( UI.display, UI.colorMap, c, &color, &color ); \ - x = color.pixel; \ - } while( false ) - #define SETXCOLOR( x, y, c ) \ - do { \ - XColor color; \ - XAllocNamedColor( UI.display, UI.colorMap, c, &color, &color ); \ - x = color.pixel; \ - y = color; \ - } while( false ) - - SETXCOLOR( Style.bg, Style.xBG, "#1a1a1a" ); - SETXCOLOR( Style.fg, Style.xFG, "#b6c2c4" ); - - SETCOLOR( Style.cursor, "#00ff00" ); - - SETCOLOR( Style.statusBG, "#333333" ); - SETCOLOR( Style.statusFG, "#ffffff" ); - - SETCOLOR( Style.Colours.black, "#1a1a1a" ); - SETCOLOR( Style.Colours.red, "#ca4433" ); - SETCOLOR( Style.Colours.green, "#178a3a" ); - SETCOLOR( Style.Colours.yellow, "#dc7c2a" ); - SETCOLOR( Style.Colours.blue, "#415e87" ); - SETCOLOR( Style.Colours.magenta, "#5e468c" ); - SETCOLOR( Style.Colours.cyan, "#35789b" ); - SETCOLOR( Style.Colours.white, "#b6c2c4" ); - - SETCOLOR( Style.Colours.lblack, "#666666" ); - SETCOLOR( Style.Colours.lred, "#ff2954" ); - SETCOLOR( Style.Colours.lgreen, "#5dd030" ); - SETCOLOR( Style.Colours.lyellow, "#fafc4f" ); - SETCOLOR( Style.Colours.lblue, "#3581e1" ); - SETCOLOR( Style.Colours.lmagenta, "#875fff" ); - SETCOLOR( Style.Colours.lcyan, "#29fbff" ); - SETCOLOR( Style.Colours.lwhite, "#cedbde" ); - - SETCOLOR( Style.Colours.system, "#ffffff" ); - - #undef SETCOLOR - #undef SETXCOLOR + Style.bg = make_color( "#1a1a1a" ); + Style.status_bg = make_color( "#333333" ); + Style.cursor = make_color( "#00ff00" ); + + Style.Colours.black = make_color( "#1a1a1a" ); + Style.Colours.red = make_color( "#ca4433" ); + Style.Colours.green = make_color( "#178a3a" ); + Style.Colours.yellow = make_color( "#dc7c2a" ); + Style.Colours.blue = make_color( "#415e87" ); + Style.Colours.magenta = make_color( "#5e468c" ); + Style.Colours.cyan = make_color( "#35789b" ); + Style.Colours.white = make_color( "#b6c2c4" ); + + Style.Colours.lblack = make_color( "#666666" ); + Style.Colours.lred = make_color( "#ff2954" ); + Style.Colours.lgreen = make_color( "#5dd030" ); + Style.Colours.lyellow = make_color( "#fafc4f" ); + Style.Colours.lblue = make_color( "#3581e1" ); + Style.Colours.lmagenta = make_color( "#875fff" ); + Style.Colours.lcyan = make_color( "#29fbff" ); + Style.Colours.lwhite = make_color( "#cedbde" ); + + Style.Colours.system = make_color( "#ffffff" ); Style.font = loadFont( "-windows-dina-medium-r-normal--10-*-*-*-c-0-*-*" ); Style.fontBold = loadFont( "-windows-dina-bold-r-normal--10-*-*-*-c-0-*-*" ); @@ -566,7 +619,6 @@ void ui_init() { initStyle(); XSetWindowAttributes attr = { }; - attr.background_pixel = Style.bg, attr.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask, attr.colormap = UI.colorMap, @@ -579,7 +631,6 @@ void ui_init() { Cursor cursor = XCreateFontCursor( UI.display, XC_xterm ); XDefineCursor( UI.display, UI.window, cursor ); - XRecolorCursor( UI.display, cursor, &Style.xFG, &Style.xBG ); XStoreName( UI.display, UI.window, "Mud Gangster" ); XMapWindow( UI.display, UI.window );