summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-08-11 06:18:29 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-08-11 06:18:29 +0200
commitf4114edbbd2cddbf25ed6c2083d0e81d5626cd1e (patch)
treef3b4eac2978f201921a8b27d5b6d8301a27ad051
parent7b0bb2262d49636988daa24c17d2807bd7cf0706 (diff)
downloadreduced_system_layer-f4114edbbd2cddbf25ed6c2083d0e81d5626cd1e.zip
Update text input
-rwxr-xr-xexamples/ui.c145
1 files changed, 115 insertions, 30 deletions
diff --git a/examples/ui.c b/examples/ui.c
index f713417..13f0f68 100755
--- a/examples/ui.c
+++ b/examples/ui.c
@@ -185,6 +185,11 @@ Platform platform = {0};
#define CHAR_NUM_BITS_Y 7
#define CHAR_NUM_BITS (CHAR_NUM_BITS_X * CHAR_NUM_BITS_Y)
+enum {
+ OP_SET,
+ OP_XOR,
+};
+
u64 bitfont[] = {
0xbc0000000000, 0xc00300000, 0x5fd5040093f24fc9, 0xa00a2c2a1a280105, 0xc000415e6f, 0x400000020be0000, 0x1c38a8400000007d, 0x40002043e1020215, 0x408102000000010, 0x9800000000020002, 0xf913e00000033, 0x53200000207c8800, 0x3654880000099, 0x54b800000f840e00, 0xe953c000001a, 0x953e000000674080, 0x1e54b800000f, 0x490000000000240, 0x88a08000000, 0x20a220050a142850, 0x6520800000, 0x912f801eab260be, 0x800034952bf0001f, 0xc850bf0000921427, 0xf00010a54afc0003, 0xd29427800002142b, 0x840007e1023f0000, 0x7d09100000217e, 0x3f000188a08fc000, 0xc30c0cfc00000810, 0x27803f101013f00f, 0xc244bf0000f214, 0x4bf0002f21427800, 0xc254a480006c24, 0x407c00102fc08100, 0xf208080f0000fa0, 0x531007d81c607c0, 0xc208288c031141, 0x83fc00046954b10, 0x180e03000000, 0x41040000000ff04, 0x8102040810000404, 0x2a54600000000101, 0x309123e0000e, 0xc912180000a22447, 0x8000062a54700007, 0xe52a4300000029f0, 0xa0000602043e0001, 0x1d48000002074, 0x1f000003610f8000, 0x13e04f800000010, 0x470000780813e00f, 0x184893e0000e224, 0x23e0001f12243000, 0x82a54100000008, 0x40780000009f0200, 0xe208080e0001f20, 0xa22007981860780, 0x82082888022282, 0x16c200004ca95320, 0x7f000004, 0x408200000086d04, 0x8204,
};
@@ -225,7 +230,6 @@ u64 char_column_convolved(c8 c, i64 column_index) {
// colvolution
if (mask != 1) column |= mask >> 1;
- if (mask != 1ull << 63) column |= mask << 1;
}
return column;
@@ -274,6 +278,29 @@ i64 char_spacing(i64 num_chars, c8 *text, i64 index) {
return 0;
}
+i64 text_cursor(i64 num_chars, c8 *text) {
+ assert(text != NULL);
+
+ i64 cursor = 0;
+
+ for (i64 i = 0; i < num_chars; ++i) {
+ if (text[i] <= ' ') {
+ if (text[i] == '\n')
+ cursor = 0;
+ else if (text[i] == '\b' && i > 0)
+ cursor -= char_width(text[i - 1]) + char_spacing(num_chars, text, i - 1);
+ else if (text[i] == '\r')
+ cursor = 0;
+ else
+ cursor += char_width(' ') + char_spacing(num_chars, text, i);
+ continue;
+ }
+ cursor += char_width(text[i]) + char_spacing(num_chars, text, i);
+ }
+
+ return cursor;
+}
+
i64 enum_text_columns(i64 num_chars, c8 *text) {
assert(text != NULL);
@@ -376,6 +403,25 @@ void print_text(u32 color, f64 x0, f64 y0, f64 scale_x, f64 scale_y, i64 num_cha
}
}
+void draw_panel(u32 op, u32 color, f64 x0, f64 y0, f64 width, f64 height) {
+ i64 i0 = (i64) floor(x0 + .5);
+ i64 j0 = (i64) floor(y0 + .5);
+ i64 i1 = (i64) floor(x0 + width + .5);
+ i64 j1 = (i64) floor(y0 + height + .5);
+
+ if (i0 < 0) i0 = 0;
+ if (j0 < 0) j0 = 0;
+ if (i1 >= platform.frame_width) i1 = platform.frame_width - 1;
+ if (j1 >= platform.frame_height) j1 = platform.frame_height - 1;
+
+ for (i64 j = j0; j < j1; ++j)
+ for (i64 i = i0; i < i1; ++i)
+ if (op == OP_XOR)
+ platform.pixels[j * platform.frame_width + i] ^= color;
+ else
+ platform.pixels[j * platform.frame_width + i] = color;
+}
+
void draw_text_area(u32 color, f64 x0, f64 y0, f64 width, f64 height, f64 max_scale_x, f64 max_scale_y, i64 num_chars, c8 *text) {
assert(max_scale_x > 1e-6);
assert(max_scale_y > 1e-6);
@@ -391,23 +437,35 @@ void draw_text_area(u32 color, f64 x0, f64 y0, f64 width, f64 height, f64 max_sc
f64 k = kx < ky ? kx : ky;
- print_text(color, x0, y0, k * max_scale_x, k * max_scale_y, num_chars, text);
+ kx = k * max_scale_x;
+ ky = k * max_scale_y;
+
+ print_text(color, x0, y0, kx, ky, num_chars, text);
}
-void draw_panel(u32 color, f64 x0, f64 y0, f64 width, f64 height) {
- i64 i0 = (i64) floor(x0 + .5);
- i64 j0 = (i64) floor(y0 + .5);
- i64 i1 = (i64) floor(x0 + width + .5);
- i64 j1 = (i64) floor(y0 + height + .5);
+void draw_text_cursor(u32 color, f64 x0, f64 y0, f64 width, f64 height, f64 max_scale_x, f64 max_scale_y, i64 cursor, i64 selection, i64 num_chars, c8 *text) {
+ (void) selection;
- if (i0 < 0) i0 = 0;
- if (j0 < 0) j0 = 0;
- if (i1 >= platform.frame_width) i1 = platform.frame_width - 1;
- if (j1 >= platform.frame_height) j1 = platform.frame_height - 1;
+ assert(max_scale_x > 1e-6);
+ assert(max_scale_y > 1e-6);
- for (i64 j = j0; j < j1; ++j)
- for (i64 i = i0; i < i1; ++i)
- platform.pixels[j * platform.frame_width + i] = color;
+ i64 num_columns = enum_text_columns(num_chars, text);
+ i64 num_rows = enum_text_rows(num_chars, text);
+ i64 cursor_x = text_cursor(cursor, text);
+ i64 cursor_y = enum_text_rows(cursor, text);
+
+ f64 scale_x = width / num_columns;
+ f64 scale_y = height / num_rows;
+
+ f64 kx = scale_x / max_scale_x;
+ f64 ky = scale_y / max_scale_y;
+
+ f64 k = kx < ky ? kx : ky;
+
+ kx = k * max_scale_x;
+ ky = k * max_scale_y;
+
+ draw_panel(OP_XOR, color, x0 + kx * cursor_x, y0 + ky * cursor_y - ky * CHAR_NUM_BITS_Y, kx * .5, ky * (CHAR_NUM_BITS_Y - 1));
}
i32 main(i32 argc, c8 **argv) {
@@ -426,9 +484,12 @@ i32 main(i32 argc, c8 **argv) {
b8 button_1_down = 0;
b8 button_1_checked = 0;
- i32 text_len = 0;
+ i64 text_len = 0;
static c8 text[512] = "";
+ i64 cursor = 0;
+ i64 selection = 0;
+
while (!platform.done) {
p_wait_events();
@@ -439,12 +500,12 @@ i32 main(i32 argc, c8 **argv) {
if (platform.cursor_x >= 40 && platform.cursor_x < 100 && platform.cursor_y >= 40 && platform.cursor_y < 100) {
button_0_down = platform.key_down[BUTTON_LEFT];
if (button_0_down)
- draw_panel(0xffffff, 40, 40, 60, 60);
+ draw_panel(OP_SET, 0xffffff, 40, 40, 60, 60);
else
- draw_panel(0x00ff00, 40, 40, 60, 60);
+ draw_panel(OP_SET, 0x00ff00, 40, 40, 60, 60);
} else {
button_0_down = 0;
- draw_panel(0x208020, 40, 40, 60, 60);
+ draw_panel(OP_SET, 0x208020, 40, 40, 60, 60);
}
if (platform.cursor_x >= 40 && platform.cursor_x < 100 && platform.cursor_y >= 120 && platform.cursor_y < 180) {
@@ -452,17 +513,17 @@ i32 main(i32 argc, c8 **argv) {
if (platform.key_pressed[BUTTON_LEFT])
button_1_checked = !button_1_checked;
if (button_1_down)
- draw_panel(0xffffff, 40, 120, 60, 60);
+ draw_panel(OP_SET, 0xffffff, 40, 120, 60, 60);
else if (button_1_checked)
- draw_panel(0xff8080, 40, 120, 60, 60);
+ draw_panel(OP_SET, 0xff8080, 40, 120, 60, 60);
else
- draw_panel(0x80ff80, 40, 120, 60, 60);
+ draw_panel(OP_SET, 0x80ff80, 40, 120, 60, 60);
} else {
button_1_down = 0;
if (button_1_checked)
- draw_panel(0xff0000, 40, 120, 60, 60);
+ draw_panel(OP_SET, 0xff0000, 40, 120, 60, 60);
else
- draw_panel(0x00ff00, 40, 120, 60, 60);
+ draw_panel(OP_SET, 0x00ff00, 40, 120, 60, 60);
}
i64 w = platform.frame_width / 2;
@@ -478,17 +539,37 @@ i32 main(i32 argc, c8 **argv) {
for (i64 i = 0; i < platform.input_size; ++i)
switch (platform.input[i]) {
+ case KEY_LEFT:
+ if (cursor > 0)
+ --cursor;
+ break;
+
+ case KEY_RIGHT:
+ if (cursor < text_len)
+ ++cursor;
+ break;
+
case '\b':
- if (text_len > 0)
+ if (cursor > 0 && text_len > 0) {
+ for (i64 i = cursor; i < text_len; ++i)
+ text[i - 1] = text[i];
+ --cursor;
--text_len;
+ }
break;
default:
- if (platform.input[i] > 0 && platform.input[i] < 128 && text_len < (i64) sizeof text)
- text[text_len++] = (c8) platform.input[i];
+ if (platform.input[i] > 0 && platform.input[i] < 128 && text_len < (i64) sizeof text) {
+ for (i64 i = text_len; i > cursor; --i)
+ text[i] = text[i - 1];
+ text[cursor++] = (c8) platform.input[i];
+ ++text_len;
+ }
}
+ draw_text_area(0, x0 + 8, y0 - 8, w, h, 10., 10., text_len, text);
draw_text_area(color, x0, y0, w, h, 10., 10., text_len, text);
+ draw_text_cursor(0xffffff, x0, y0, w, h, 10., 10., cursor, selection, text_len, text);
p_render_frame();
}
@@ -848,18 +929,19 @@ i32 p_handle_events(void) {
platform.input[platform.input_size++] = ((platform.key_down[MOD_SHIFT] ^ platform.key_down[MOD_CAPS])) && _upper[k] != 0 ? _upper[k] : k;
} break;
- case KeyRelease:
+ case KeyRelease: {
+ i16 k = _key_table[ev.xkey.keycode];
platform.cursor_x = ev.xkey.x;
platform.cursor_y = ev.xkey.y;
- platform.key_down [_key_table[ev.xkey.keycode]] = 0;
- platform.key_pressed[_key_table[ev.xkey.keycode]]--;
+ platform.key_down [k] = 0;
+ platform.key_pressed[k]--;
platform.key_down[MOD_CTRL] = !!(ev.xkey.state & ControlMask);
platform.key_down[MOD_SHIFT] = !!(ev.xkey.state & ShiftMask);
platform.key_down[MOD_ALT] = !!(ev.xkey.state & Mod1Mask);
platform.key_down[MOD_CAPS] = !!(ev.xkey.state & LockMask);
platform.key_down[MOD_NUM] = !!(ev.xkey.state & Mod2Mask);
platform.key_down[MOD_SCROLL] = !!(ev.xkey.state & Mod3Mask);
- break;
+ } break;
case EnterNotify: platform.has_cursor = 1; break;
case LeaveNotify: platform.has_cursor = 0; break;
@@ -875,6 +957,9 @@ i32 p_handle_events(void) {
}
}
+ for (i64 k = 0; k < (i64) (sizeof platform.key_pressed / sizeof *platform.key_pressed); ++k)
+ platform.key_pressed[k] = platform.key_pressed[k] > 0 ? 1 : 0;
+
XWindowAttributes attrs;
XGetWindowAttributes(_display, _window, &attrs);