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 }