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,
+}