1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
Char_Type :: u8;
UI_Line_Input :: struct {
#as using base : UI_Elem = .{type = .LINE_INPUT};
buffer : []Char_Type;
// resizeable := false;
ptr_left, ptr_right : int;
offset : int;
}
handle_key_line_input :: (ui_elem : *UI_Elem, key : Key) -> bool {
using ui_line_input := cast(*UI_Line_Input) ui_elem;
handle_inner :: (using ui_line_input : *UI_Line_Input, key : Key) -> bool {
if is_printable(key) {
return add_char(ui_line_input, xx key);
} else if key == {
case .LEFT; #through;
case .RIGHT;
return move_ptr(ui_line_input, key);
case .BACKSPACE;
return remove_char_left(ui_line_input);
case .ESCAPE;
cursor_state = .ON;
return true;
}
return false;
}
if cursor_state == .IN {
return handle_inner(ui_line_input, key);
} else if cursor_state == .ON && key == .ENTER {
cursor_state = .IN;
return true;
}
return false;
}
c_draw_line_input :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
using cast(*UI_Line_Input) ui_elem;
fix_offset :: () #expand {
if ptr_left - offset < 0 {
offset = ptr_left;
} else if ptr_left - offset >= zone.width {
offset = ptr_left - zone.width + 1;
}
}
fix_offset();
left_part, right_part : string;
left_part.data, left_part.count = buffer.data, ptr_left;
right_part.data, right_part.count = buffer.data + ptr_right + 1, (buffer.count - ptr_right - 1);
c_draw_line_ascii(canvas, left_part, zone, .{xx -offset, 0}, style.text.default);
c_draw_line_ascii(canvas, right_part, zone, .{xx (ptr_left - offset), 0}, style.text.default);
terminal_state.cursor = ifx cursor_state == .IN then zone.corner + ivec2.{xx(ptr_left - offset), 0} else .{-1, -1};
return true;
}
init :: (using ui_line_input : *UI_Line_Input, max_length := 100) {
buffer = NewArray(max_length, Char_Type);
ptr_left, ptr_right = 0, max_length - 1;
}
add_char :: (using ui_line_input : *UI_Line_Input, c : Char_Type) -> bool {
if ptr_left > ptr_right return false;
buffer[ptr_left] = c;
ptr_left += 1;
return true;
}
remove_char_left :: (using ui_line_input : *UI_Line_Input) -> bool {
if ptr_left == 0 return false;
ptr_left -= 1;
return true;
}
move_ptr :: (using ui_line_input : *UI_Line_Input, key : Key) -> bool {
if key == {
case .LEFT;
if ptr_left > 0 {
ptr_left -= 1;
buffer[ptr_right] = buffer[ptr_left];
ptr_right -= 1;
return true;
}
case .RIGHT;
if ptr_right < buffer.count-1 {
ptr_right += 1;
buffer[ptr_left] = buffer[ptr_right];
ptr_left += 1;
return true;
}
case;
assert(false);
}
return false;
}
deinit :: (using ui_line_input : *UI_Line_Input) {
array_free(buffer);
}
is_printable :: (key : Key) -> bool {
code := cast(u64) key;
return (code >= #char" " && code <= #char"~");
}
get_string :: (using ui_line_input : *UI_Line_Input, allocator := context.allocator) -> string {
result : string;
size := ptr_left + (buffer.count - ptr_right - 1);
result.count = size;
result.data = alloc(size, allocator);
memcpy(result.data, buffer.data, ptr_left);
memcpy(result.data + ptr_left, buffer.data + ptr_right + 1, buffer.count - ptr_right - 1);
return result;
}
reset :: (using ui_line_input : *UI_Line_Input) {
ptr_left = 0;
ptr_right = buffer.count - 1;
}
|