mudgangster

Tiny, scriptable MUD client
Log | Files | Refs | README

ui.cc (9737B)


      1 #include "platform_ui.h"
      2 #include "array.h"
      3 #include "input.h"
      4 #include "textbox.h"
      5 #include "gitversion.h"
      6 
      7 static TextBox main_text;
      8 static TextBox chat_text;
      9 
     10 static int window_width, window_height;
     11 
     12 typedef struct {
     13 	char c;
     14 
     15 	Colour fg;
     16 	bool bold;
     17 } StatusChar;
     18 
     19 static DynamicArray< StatusChar > status;
     20 static bool status_dirty = false;
     21 
     22 void ui_init() {
     23 	ZoneScoped;
     24 
     25 	textbox_init( &main_text, SCROLLBACK_SIZE );
     26 	textbox_init( &chat_text, CHAT_ROWS );
     27 
     28 	ui_main_print( "> Mud Gangster ", 0, SYSTEM, BLACK, false );
     29 	ui_main_print( APP_VERSION, 0, SYSTEM, BLACK, true );
     30 }
     31 
     32 void ui_term() {
     33 	textbox_destroy( &main_text );
     34 	textbox_destroy( &chat_text );
     35 }
     36 
     37 void ui_fill_rect( int left, int top, int width, int height, Colour colour, bool bold ) {
     38 	platform_fill_rect( left, top, width, height, colour, bold );
     39 }
     40 
     41 void ui_draw_char( int left, int top, char c, Colour colour, bool bold, bool force_bold_font ) {
     42 	int fw, fh;
     43 	ui_get_font_size( &fw, &fh );
     44 
     45 	int left_spacing = fw / 2;
     46 	int right_spacing = fw - left_spacing;
     47 	int line_height = fh + SPACING;
     48 	int top_spacing = line_height / 2;
     49 	int bot_spacing = line_height - top_spacing;
     50 
     51 	// TODO: not the right char...
     52 	// if( u8( c ) == 155 ) { // fill
     53 	// 	ui_fill_rect( left, top, fw, fh, colour, bold );
     54 	// 	return;
     55 	// }
     56 
     57 	// TODO: this has a vertical seam. using textbox-space coordinates would help
     58 	if( u8( c ) == 176 ) { // light shade
     59 		for( int y = 0; y < fh; y += 3 ) {
     60 			for( int x = y % 6 == 0 ? 0 : 1; x < fw; x += 2 ) {
     61 				ui_fill_rect( left + x, top + y, 1, 1, colour, bold );
     62 			}
     63 		}
     64 		return;
     65 	}
     66 
     67 	// TODO: this has a horizontal seam but so does mm2k
     68 	if( u8( c ) == 177 ) { // medium shade
     69 		for( int y = 0; y < fh; y += 2 ) {
     70 			for( int x = y % 4 == 0 ? 1 : 0; x < fw; x += 2 ) {
     71 				ui_fill_rect( left + x, top + y, 1, 1, colour, bold );
     72 			}
     73 		}
     74 		return;
     75 	}
     76 
     77 	// TODO: this probably has a horizontal seam
     78 	if( u8( c ) == 178 ) { // heavy shade
     79 		for( int y = 0; y < fh + SPACING; y++ ) {
     80 			for( int x = y % 2 == 0 ? 1 : 0; x < fw; x += 2 ) {
     81 				ui_fill_rect( left + x, top + y, 1, 1, colour, bold );
     82 			}
     83 		}
     84 		return;
     85 	}
     86 
     87 	if( u8( c ) == 179 ) { // vertical
     88 		ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold );
     89 		return;
     90 		// set_fg( colour, bold );
     91 		// const char asdf[] = "│";
     92 		// Xutf8DrawString( UI.display, UI.back_buffer, ( bold ? Style.fontBold : Style.font ).font, UI.gc, left, top + Style.font.ascent + SPACING, asdf, sizeof( asdf ) - 1 );
     93 	}
     94 
     95 	if( u8( c ) == 180 ) { // right stopper
     96 		ui_fill_rect( left, top + top_spacing, left_spacing, 1, colour, bold );
     97 		ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold );
     98 		return;
     99 	}
    100 
    101 	if( u8( c ) == 186 ) { // double vertical
    102 		ui_fill_rect( left + left_spacing - 1, top, 1, line_height, colour, bold );
    103 		ui_fill_rect( left + left_spacing + 1, top, 1, line_height, colour, bold );
    104 		return;
    105 	}
    106 
    107 	if( u8( c ) == 187 ) { // double top right
    108 		ui_fill_rect( left, top + top_spacing - 1, right_spacing + 1, 1, colour, bold );
    109 		ui_fill_rect( left + left_spacing + 1, top + top_spacing - 1, 1, bot_spacing + 1, colour, bold );
    110 		ui_fill_rect( left, top + top_spacing + 1, right_spacing - 1, 1, colour, bold );
    111 		ui_fill_rect( left + left_spacing - 1, top + top_spacing + 1, 1, bot_spacing - 1, colour, bold );
    112 		return;
    113 	}
    114 
    115 	if( u8( c ) == 188 ) { // double bottom right
    116 		ui_fill_rect( left, top + top_spacing + 1, right_spacing + 1, 1, colour, bold );
    117 		ui_fill_rect( left + left_spacing + 1, top, 1, top_spacing + 1, colour, bold );
    118 		ui_fill_rect( left, top + top_spacing - 1, right_spacing - 1, 1, colour, bold );
    119 		ui_fill_rect( left + left_spacing - 1, top, 1, top_spacing - 1, colour, bold );
    120 		return;
    121 	}
    122 
    123 	if( u8( c ) == 191 ) { // top right
    124 		ui_fill_rect( left, top + top_spacing, left_spacing, 1, colour, bold );
    125 		ui_fill_rect( left + left_spacing, top + top_spacing, 1, bot_spacing, colour, bold );
    126 		return;
    127 	}
    128 
    129 	if( u8( c ) == 192 ) { // bottom left
    130 		ui_fill_rect( left + left_spacing, top + top_spacing, right_spacing, 1, colour, bold );
    131 		ui_fill_rect( left + left_spacing, top, 1, top_spacing, colour, bold );
    132 		return;
    133 	}
    134 
    135 	if( u8( c ) == 193 ) { // bottom stopper
    136 		ui_fill_rect( left + left_spacing, top, 1, top_spacing, colour, bold );
    137 		ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold );
    138 		return;
    139 	}
    140 
    141 	if( u8( c ) == 194 ) { // top stopper
    142 		ui_fill_rect( left + left_spacing, top + top_spacing, 1, bot_spacing, colour, bold );
    143 		ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold );
    144 		return;
    145 	}
    146 
    147 	if( u8( c ) == 195 ) { // left stopper
    148 		ui_fill_rect( left + left_spacing, top + top_spacing, right_spacing, 1, colour, bold );
    149 		ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold );
    150 		return;
    151 	}
    152 
    153 	if( u8( c ) == 196 ) { // horizontal
    154 		ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold );
    155 		return;
    156 	}
    157 
    158 	if( u8( c ) == 197 ) { // cross
    159 		ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold );
    160 		ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold );
    161 		return;
    162 	}
    163 
    164 	if( u8( c ) == 200 ) { // double bottom left
    165 		ui_fill_rect( left + left_spacing - 1, top + top_spacing + 1, right_spacing + 1, 1, colour, bold );
    166 		ui_fill_rect( left + left_spacing - 1, top, 1, top_spacing + 1, colour, bold );
    167 		ui_fill_rect( left + left_spacing + 1, top + top_spacing - 1, right_spacing - 1, 1, colour, bold );
    168 		ui_fill_rect( left + left_spacing + 1, top, 1, top_spacing - 1, colour, bold );
    169 		return;
    170 	}
    171 
    172 	if( u8( c ) == 201 ) { // double top left
    173 		ui_fill_rect( left + left_spacing - 1, top + top_spacing - 1, right_spacing + 1, 1, colour, bold );
    174 		ui_fill_rect( left + left_spacing - 1, top + top_spacing - 1, 1, bot_spacing + 1, colour, bold );
    175 		ui_fill_rect( left + left_spacing + 1, top + top_spacing + 1, right_spacing - 1, 1, colour, bold );
    176 		ui_fill_rect( left + left_spacing + 1, top + top_spacing + 1, 1, bot_spacing - 1, colour, bold );
    177 		return;
    178 	}
    179 
    180 	if( u8( c ) == 205 ) { // double horizontal
    181 		ui_fill_rect( left, top + top_spacing - 1, fw, 1, colour, bold );
    182 		ui_fill_rect( left, top + top_spacing + 1, fw, 1, colour, bold );
    183 		return;
    184 	}
    185 
    186 	if( u8( c ) == 217 ) { // bottom right
    187 		ui_fill_rect( left, top + top_spacing, right_spacing, 1, colour, bold );
    188 		ui_fill_rect( left + left_spacing, top, 1, top_spacing, colour, bold );
    189 		return;
    190 	}
    191 
    192 	if( u8( c ) == 218 ) { // top left
    193 		ui_fill_rect( left + left_spacing, top + top_spacing, right_spacing, 1, colour, bold );
    194 		ui_fill_rect( left + left_spacing, top + top_spacing, 1, bot_spacing, colour, bold );
    195 		return;
    196 	}
    197 
    198 	platform_draw_char( left, top, c, colour, bold, force_bold_font );
    199 }
    200 
    201 void ui_clear_status() {
    202 	status.clear();
    203 	status_dirty = true;
    204 }
    205 
    206 void ui_statusAdd( char c, Colour fg, bool bold ) {
    207 	status.add( { c, fg, bold } );
    208 	status_dirty = true;
    209 }
    210 
    211 void ui_draw_status() {
    212 	int fw, fh;
    213 	ui_get_font_size( &fw, &fh );
    214 
    215 	ui_fill_rect( 0, window_height - PADDING * 4 - fh * 2, window_width, fh + PADDING * 2, COLOUR_STATUSBG, false );
    216 
    217 	for( size_t i = 0; i < status.size(); i++ ) {
    218 		StatusChar sc = status[ i ];
    219 
    220 		int x = PADDING + i * fw;
    221 		int y = window_height - ( PADDING * 3 ) - fh * 2 - SPACING;
    222 		ui_draw_char( x, y, sc.c, sc.fg, sc.bold );
    223 	}
    224 
    225 	platform_make_dirty( 0, window_height - PADDING * 4 - fh * 2, window_width, fh + PADDING * 2 );
    226 
    227 	status_dirty = false;
    228 }
    229 
    230 void ui_redraw_dirty() {
    231 	if( main_text.dirty )
    232 		textbox_draw( &main_text );
    233 	if( chat_text.dirty )
    234 		textbox_draw( &chat_text );
    235 	if( input_is_dirty() )
    236 		input_draw();
    237 	if( status_dirty )
    238 		ui_draw_status();
    239 }
    240 
    241 void ui_redraw_everything() {
    242 	int fw, fh;
    243 	ui_get_font_size( &fw, &fh );
    244 
    245 	ui_fill_rect( 0, 0, window_width, window_height, COLOUR_BG, false );
    246 
    247 	input_draw();
    248 	ui_draw_status();
    249 
    250 	textbox_draw( &main_text );
    251 	textbox_draw( &chat_text );
    252 
    253 	int spacerY = ( 2 * PADDING ) + ( fh + SPACING ) * CHAT_ROWS;
    254 	ui_fill_rect( 0, spacerY, window_width, 1, COLOUR_STATUSBG, false );
    255 }
    256 
    257 void ui_main_newline() {
    258 	textbox_newline( &main_text );
    259 }
    260 
    261 void ui_main_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ) {
    262 	textbox_add( &main_text, str, len, fg, bg, bold );
    263 }
    264 
    265 void ui_chat_newline() {
    266 	textbox_newline( &chat_text );
    267 }
    268 
    269 void ui_chat_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ) {
    270 	textbox_add( &chat_text, str, len, fg, bg, bold );
    271 }
    272 
    273 void ui_update_layout() {
    274 	int fw, fh;
    275 	ui_get_font_size( &fw, &fh );
    276 
    277 	textbox_set_pos( &chat_text, PADDING, PADDING );
    278 	textbox_set_size( &chat_text, window_width - ( 2 * PADDING ), ( fh + SPACING ) * CHAT_ROWS );
    279 
    280 	textbox_set_pos( &main_text, PADDING, ( PADDING * 2 ) + CHAT_ROWS * ( fh + SPACING ) + 1 );
    281 	textbox_set_size( &main_text, window_width - ( 2 * PADDING ), window_height
    282 		- ( ( ( fh + SPACING ) * CHAT_ROWS ) + ( PADDING * 2 ) )
    283 		- ( ( fh * 2 ) + ( PADDING * 5 ) ) - 1
    284 	);
    285 
    286 	input_set_pos( PADDING, window_height - PADDING - fh );
    287 	input_set_size( window_width - PADDING * 2, fh );
    288 }
    289 
    290 void ui_resize( int width, int height ) {
    291 	int old_width = window_width;
    292 	int old_height = window_height;
    293 
    294 	window_width = width;
    295 	window_height = height;
    296 
    297 	if( window_width == old_width && window_height == old_height )
    298 		return;
    299 
    300 	ui_update_layout();
    301 }
    302 
    303 void ui_scroll( int offset ) {
    304 	textbox_scroll( &main_text, offset );
    305 }
    306 
    307 void ui_page_down() {
    308 	textbox_page_down( &main_text );
    309 }
    310 
    311 void ui_page_up() {
    312 	textbox_page_up( &main_text );
    313 }
    314 
    315 void ui_mouse_down( int x, int y ) {
    316 	textbox_mouse_down( &main_text, x, y );
    317 	textbox_mouse_down( &chat_text, x, y );
    318 }
    319 
    320 void ui_mouse_up( int x, int y ) {
    321 	textbox_mouse_up( &main_text, x, y );
    322 	textbox_mouse_up( &chat_text, x, y );
    323 }
    324 
    325 void ui_mouse_move( int x, int y ) {
    326 	textbox_mouse_move( &main_text, x, y );
    327 	textbox_mouse_move( &chat_text, x, y );
    328 }