mudgangster

Log | Files | Refs

commit 9741d0926801db1406ba3c0c42bccf2b44b5de39
parent b8b371a77637031c93df7450756f38395058483f
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Mon,  5 May 2014 11:13:55 +0100

Add statusbar code

Diffstat:
main.lua | 4+++-
src/script.c | 42+++++++++++++++++++++++++++++++++++++++++-
src/ui.c | 64+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
src/ui.h | 6++++++
status.lua | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 172 insertions(+), 9 deletions(-)

diff --git a/main.lua b/main.lua @@ -18,7 +18,7 @@ require( "connect" ).init( handlers.data ) local xFD, handleXEvents, printMain, newlineMain, drawMain, printChat, newlineChat, drawChat, - setHandlers, urgent = ... + setHandlers, urgent, setStatus = ... mud.printMain = printMain mud.newlineMain = newlineMain @@ -30,6 +30,8 @@ mud.drawChat = drawChat mud.urgent = urgent +require( "status" ).init( setStatus ) + setHandlers( handlers.input, handlers.macro, handlers.close ) local loop = ev.Loop.default diff --git a/src/script.c b/src/script.c @@ -121,6 +121,44 @@ static int mud_drawChat( lua_State* L ) return 0; } +static int mud_setStatus( lua_State* L ) +{ + luaL_argcheck( L, lua_type( L, 1 ) == LUA_TTABLE, 1, "expected function" ); + + size_t len = lua_objlen( L, 1 ); + + ui_statusClear(); + + for( size_t i = 0; i < len; i++ ) + { + lua_pushnumber( L, i + 1 ); + lua_gettable( L, 1 ); + + lua_pushliteral( L, "text" ); + lua_gettable( L, 2 ); + size_t seglen; + const char* str = lua_tolstring( L, -1, &seglen ); + + lua_pushliteral( L, "fg" ); + lua_gettable( L, 2 ); + const Colour fg = lua_tointeger( L, -1 ); + + lua_pushliteral( L, "fg" ); + lua_gettable( L, 2 ); + const bool bold = lua_toboolean( L, -1 ); + + for( size_t j = 0; j < seglen; j++ ) { + ui_statusAdd( str[ j ], fg, bold ); + } + + lua_pop( L, 4 ); + } + + ui_statusDraw(); + + return 0; +} + static int mud_setHandlers( lua_State* L ) { luaL_argcheck( L, lua_type( L, 1 ) == LUA_TFUNCTION, 1, "expected function" ); @@ -181,7 +219,9 @@ void script_init() lua_pushcfunction( L, mud_urgent ); - if( lua_pcall( L, 10, 0, -11 ) ) + lua_pushcfunction( L, mud_setStatus ); + + if( lua_pcall( L, 11, 0, -13 ) ) { printf( "Error running main.lua: %s\n", lua_tostring( L, -1 ) ); diff --git a/src/ui.c b/src/ui.c @@ -1,6 +1,6 @@ #include <stdio.h> #include <stdlib.h> -#include <assert.h> +#include <err.h> #include <X11/Xutil.h> #include <X11/XKBlib.h> @@ -13,15 +13,58 @@ Atom wmDeleteWindow; -void statusDraw() +typedef struct { + char c; + + Colour fg; + bool bold; +} StatusChar; + +static StatusChar* statusContents = NULL; +static size_t statusCapacity = 256; +static size_t statusLen = 0; + +void ui_statusDraw() { 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 ) ); - XSetForeground( UI.display, UI.gc, Style.statusFG ); - XDrawString( UI.display, UI.window, UI.gc, PADDING, UI.height - ( PADDING * 3 ) - Style.font.height - Style.font.descent, STRL( "legit statusbar" ) ); + 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 ); + } +} + +void ui_statusClear() +{ + statusLen = 0; +} + +void ui_statusAdd( const char c, const Colour fg, const bool bold ) +{ + if( ( statusLen + 1 ) * sizeof( StatusChar ) > statusCapacity ) + { + size_t newcapacity = statusCapacity * 2; + StatusChar* newcontents = realloc( statusContents, newcapacity ); + + if( !newcontents ) + { + return err( 1, "oom" ); + } - // TODO + statusContents = newcontents; + statusCapacity = newcapacity; + } + + statusContents[ statusLen ] = ( StatusChar ) { c, fg, bold }; + statusLen++; } void ui_draw() @@ -29,7 +72,7 @@ void ui_draw() XClearWindow( UI.display, UI.window ); input_draw(); - statusDraw(); + ui_statusDraw(); textbox_draw( UI.textChat ); textbox_draw( UI.textMain ); @@ -319,7 +362,7 @@ void initStyle() SETXCOLOR( Style.bg, Style.xBG, "#1a1a1a" ); SETXCOLOR( Style.fg, Style.xFG, "#b6c2c4" ); - + SETCOLOR( Style.cursor, "#00ff00" ); SETCOLOR( Style.statusBG, "#333333" ); @@ -366,6 +409,11 @@ void ui_init() UI.textMain = textbox_new( OUTPUT_MAX_LINES ); UI.textChat = textbox_new( OUTPUT_MAX_LINES ); + statusContents = malloc( statusCapacity * sizeof( StatusChar ) ); + + if( statusContents == NULL ) { + err( 1, "oom" ); + } initStyle(); @@ -397,6 +445,8 @@ void ui_init() void ui_end() { textbox_free( UI.textMain ); + textbox_free( UI.textChat ); + free( statusContents ); XFreeFont( UI.display, Style.font.font ); XFreeFont( UI.display, Style.fontBold.font ); diff --git a/src/ui.h b/src/ui.h @@ -1,8 +1,14 @@ #ifndef _UI_H_ #define _UI_H_ +#include "common.h" + void ui_handleXEvents(); +void ui_statusDraw(); +void ui_statusClear(); +void ui_statusAdd( const char c, const Colour fg, const bool bold ); + void ui_draw(); void ui_init(); diff --git a/status.lua b/status.lua @@ -0,0 +1,65 @@ +local setStatus +local barItems = { } + +local function drawBar() + local status = { } + + for _, item in ipairs( barItems ) do + local fg = 7 + local bold = false + + for text, opts, escape in ( item.text .. "\27[m" ):gmatch( "(.-)\27%[([%d;]*)(%a)" ) do + if text ~= "" then + table.insert( status, { + text = text, + fg = fg, + bold = bold, + } ) + end + + for opt in opts:gmatch( "([^;]+)" ) do + if opt == "0" then + fg = 7 + bold = false + elseif opt == "1" then + bold = true + else + opt = tonumber( opt ) + + if opt and opt >= 30 and opt <= 37 then + fg = opt - 30 + end + end + end + end + end + + setStatus( status ) +end + +function mud.bar( priority ) + local item = { + priority = priority, + text = "", + + set = function( self, text ) + enforce( text, "text", "string" ) + + self.text = string.parseColours( text ) + drawBar() + end, + } + + table.insert( barItems, item ) + table.sort( barItems, function( a, b ) + return a.priority < b.priority + end ) + + return item +end + +return { + init = function( set ) + setStatus = set + end, +}