mudgangster

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

input.cc (3126B)


      1 #include <stdlib.h>
      2 #include <string.h>
      3 
      4 #include "common.h"
      5 #include "array.h"
      6 #include "input.h"
      7 #include "script.h"
      8 #include "ui.h"
      9 
     10 #include "platform_ui.h"
     11 
     12 static Span< char > history[ MAX_INPUT_HISTORY ] = { };
     13 static size_t history_head = 0;
     14 static size_t history_count = 0;
     15 static size_t history_delta = 0;
     16 
     17 static DynamicArray< char > input;
     18 
     19 static size_t cursor_pos = 0;
     20 
     21 static int left, top;
     22 static int width, height;
     23 
     24 static bool dirty = false;
     25 
     26 void input_return() {
     27 	if( input.size() > 0 ) {
     28 		Span< const char > last_cmd = history_count == 0 ? Span< const char >() : history[ ( history_head + history_count - 1 ) % MAX_INPUT_HISTORY ];
     29 
     30 		if( history_count == 0 || input.size() != last_cmd.n || memcmp( input.ptr(), last_cmd.ptr, last_cmd.num_bytes() ) != 0 ) {
     31 			size_t pos = ( history_head + history_count ) % MAX_INPUT_HISTORY;
     32 
     33 			if( history_count == MAX_INPUT_HISTORY ) {
     34 				history_head++;
     35 			}
     36 			else {
     37 				history_count++;
     38 			}
     39 
     40 			free( history[ pos ].ptr );
     41 			history[ pos ] = alloc_span< char >( input.size() );
     42 			memcpy( history[ pos ].ptr, input.ptr(), input.num_bytes() );
     43 		}
     44 	}
     45 
     46 	script_handleInput( input.ptr(), input.size() );
     47 
     48 	input.clear();
     49 	history_delta = 0;
     50 	cursor_pos = 0;
     51 	dirty = true;
     52 }
     53 
     54 void input_backspace() {
     55 	if( cursor_pos == 0 )
     56 		return;
     57 	cursor_pos--;
     58 	input.remove( cursor_pos );
     59 	dirty = true;
     60 }
     61 
     62 void input_delete() {
     63 	if( input.remove( cursor_pos ) ) {
     64 		dirty = true;
     65 	}
     66 }
     67 
     68 static void input_from_history() {
     69 	if( history_delta == 0 ) {
     70 		input.clear();
     71 	}
     72 	else {
     73 		Span< const char > cmd = history[ ( history_head + history_count - history_delta ) % MAX_INPUT_HISTORY ];
     74 		input.from_span( cmd );
     75 	}
     76 
     77 	cursor_pos = input.size();
     78 	dirty = true;
     79 }
     80 
     81 void input_up() {
     82 	if( history_delta >= history_count )
     83 		return;
     84 	history_delta++;
     85 	input_from_history();
     86 }
     87 
     88 void input_down() {
     89 	if( history_delta == 0 )
     90 		return;
     91 	history_delta--;
     92 	input_from_history();
     93 }
     94 
     95 void input_left() {
     96 	if( cursor_pos > 0 ) {
     97 		cursor_pos--;
     98 		dirty = true;
     99 	}
    100 }
    101 
    102 void input_right() {
    103 	cursor_pos = min( cursor_pos + 1, input.size() );
    104 	dirty = true;
    105 }
    106 
    107 void input_add( const char * buffer, int len ) {
    108 	for( int i = 0; i < len; i++ ) {
    109 		input.insert( buffer[ i ], cursor_pos );
    110 		cursor_pos++;
    111 	}
    112 
    113 	dirty = true;
    114 }
    115 
    116 void input_set_pos( int x, int y ) {
    117 	left = x;
    118 	top = y;
    119 }
    120 
    121 void input_set_size( int w, int h ) {
    122 	width = w;
    123 	height = h;
    124 }
    125 
    126 bool input_is_dirty() {
    127 	return dirty;
    128 }
    129 
    130 void input_draw() {
    131 	int fw, fh;
    132 	ui_get_font_size( &fw, &fh );
    133 
    134 	ui_fill_rect( left, top, width, height, COLOUR_BG, false );
    135 
    136 	size_t chars_that_fit = width / size_t( fw );
    137 	size_t chars_to_draw = min( input.size(), chars_that_fit );
    138 
    139 	for( size_t i = 0; i < chars_to_draw; i++ ) {
    140 		ui_draw_char( PADDING + i * fw, top - SPACING, input[ i ], WHITE, false );
    141 	}
    142 
    143 	if( cursor_pos < chars_that_fit ) {
    144 		ui_fill_rect( PADDING + cursor_pos * fw, top, fw, fh, COLOUR_CURSOR, false );
    145 
    146 		if( cursor_pos < input.size() ) {
    147 			ui_draw_char( PADDING + cursor_pos * fw, top - SPACING, input[ cursor_pos ], COLOUR_BG, false );
    148 		}
    149 	}
    150 
    151 	platform_make_dirty( left, top, width, height );
    152 
    153 	dirty = false;
    154 }