summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-08-10 21:30:49 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-08-10 21:30:49 +0200
commit2b7970daa07c41614d046c1e2bfd941f711d49d7 (patch)
tree6ad17f37fa37fe0bea8db2ac6ec45c52d1d2f523
parent03633cde2a8e16f813f08e8cdd85ddded51f87ae (diff)
downloadreduced_system_layer-2b7970daa07c41614d046c1e2bfd941f711d49d7.zip
Text input
-rwxr-xr-xexamples/ui.c139
1 files changed, 118 insertions, 21 deletions
diff --git a/examples/ui.c b/examples/ui.c
index 9f31550..c4e4719 100755
--- a/examples/ui.c
+++ b/examples/ui.c
@@ -78,6 +78,7 @@ typedef double f64;
enum {
MAX_NUM_PIXELS = 4 * 1024 * 1024,
+ MAX_INPUT_SIZE = 256,
MAX_CLIPBOARD_SIZE = 0,
MAX_NUM_AUDIO_SAMPLES = 0,
MAX_NUM_SOCKETS = 0,
@@ -88,7 +89,7 @@ enum {
IPv4 = 1,
IPv6 = 2,
- KEY_LEFT,
+ KEY_LEFT = 128,
KEY_RIGHT,
KEY_UP,
KEY_DOWN,
@@ -107,11 +108,17 @@ enum {
KEY_END,
KEY_PAGEUP,
KEY_PAGEDOWN,
- KEY_KP_ = 128,
- KEY_F_ = 256,
- BUTTON_LEFT = KEY_F_ + 64,
+ BUTTON_LEFT,
BUTTON_MIDDLE,
BUTTON_RIGHT,
+ MOD_CTRL,
+ MOD_SHIFT,
+ MOD_ALT,
+ MOD_CAPS,
+ MOD_NUM,
+ MOD_SCROLL,
+ KEY_KP_,
+ KEY_F_ = KEY_KP_ + 64,
};
typedef struct {
@@ -119,6 +126,8 @@ typedef struct {
i32 frame_width;
i32 frame_height;
u32 *pixels;
+ i64 input_size;
+ i16 *input;
i64 clipboard_size;
c8 *clipboard; // TODO
b8 done;
@@ -356,14 +365,22 @@ void print_text(u32 color, f64 x0, f64 y0, f64 scale_x, f64 scale_y, i64 num_cha
}
}
-void draw_text_area(u32 color, f64 x0, f64 y0, f64 width, f64 height, i64 num_chars, c8 *text) {
+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);
+
i64 num_columns = enum_text_columns(num_chars, text);
i64 num_rows = enum_text_rows(num_chars, text);
f64 scale_x = width / num_columns;
f64 scale_y = height / num_rows;
- print_text(color, x0, y0, scale_x, scale_y, num_chars, text);
+ f64 kx = scale_x / max_scale_x;
+ f64 ky = scale_y / max_scale_y;
+
+ f64 k = kx < ky ? kx : ky;
+
+ print_text(color, x0, y0, k * max_scale_x, k * max_scale_y, num_chars, text);
}
void draw_panel(u32 color, f64 x0, f64 y0, f64 width, f64 height) {
@@ -398,6 +415,9 @@ i32 main(i32 argc, c8 **argv) {
b8 button_1_down = 0;
b8 button_1_checked = 0;
+ i32 text_len = 0;
+ static c8 text[512] = "";
+
while (!platform.done) {
p_wait_events();
@@ -445,7 +465,19 @@ i32 main(i32 argc, c8 **argv) {
platform.cursor_y >= y0 && platform.cursor_y < y0 + h)
color = 0xffffff;
- draw_text_area(color, x0, y0, w, h, 27, "Hello, Sailor!\nUI edit text");
+ for (i64 i = 0; i < platform.input_size; ++i)
+ switch (platform.input[i]) {
+ case '\b':
+ if (text_len > 0)
+ --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];
+ }
+
+ draw_text_area(color, x0, y0, w, h, 10., 10., text_len, text);
p_render_frame();
}
@@ -514,18 +546,66 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data) {
#include <sched.h>
#include <time.h>
-static i16 _key_table[512];
-static u32 _buffer[MAX_NUM_PIXELS];
-static XImage _image;
-static Display *_display;
-static GC _gc;
-static Window _window;
-static Atom _wm_delete_window;
+static i16 _key_table[512] = {0};
+static i16 _upper[512] = {0};
+static u32 _buffer[MAX_NUM_PIXELS] = {0};
+static i16 _input[MAX_INPUT_SIZE] = {0};
+static XImage _image = {0};
+static Display *_display = NULL;
+static GC _gc = NULL;
+static Window _window = 0;
+static Atom _wm_delete_window = 0;
void p_init(void) {
_display = XOpenDisplay(NULL);
assert(_display != NULL);
+ _upper['0'] = ')';
+ _upper['1'] = '!';
+ _upper['2'] = '@';
+ _upper['3'] = '#';
+ _upper['4'] = '$';
+ _upper['5'] = '%';
+ _upper['6'] = '^';
+ _upper['7'] = '&';
+ _upper['8'] = '*';
+ _upper['9'] = '(';
+ _upper['a'] = 'A';
+ _upper['b'] = 'B';
+ _upper['c'] = 'C';
+ _upper['d'] = 'D';
+ _upper['e'] = 'E';
+ _upper['f'] = 'F';
+ _upper['g'] = 'G';
+ _upper['h'] = 'H';
+ _upper['i'] = 'I';
+ _upper['j'] = 'J';
+ _upper['k'] = 'K';
+ _upper['l'] = 'L';
+ _upper['m'] = 'M';
+ _upper['n'] = 'N';
+ _upper['o'] = 'O';
+ _upper['p'] = 'P';
+ _upper['q'] = 'Q';
+ _upper['r'] = 'R';
+ _upper['s'] = 'S';
+ _upper['t'] = 'T';
+ _upper['u'] = 'U';
+ _upper['v'] = 'V';
+ _upper['w'] = 'W';
+ _upper['x'] = 'X';
+ _upper['y'] = 'Y';
+ _upper['z'] = 'Z';
+ _upper['['] = '{';
+ _upper[']'] = '}';
+ _upper[';'] = ':';
+ _upper['\''] = '"';
+ _upper['`'] = '~';
+ _upper['\\'] = '|';
+ _upper[','] = '<';
+ _upper['.'] = '>';
+ _upper['/'] = '?';
+
_key_table[XKeysymToKeycode(_display, XK_Left)] = KEY_LEFT;
_key_table[XKeysymToKeycode(_display, XK_Right)] = KEY_RIGHT;
_key_table[XKeysymToKeycode(_display, XK_Up)] = KEY_UP;
@@ -641,6 +721,7 @@ void p_init(void) {
_window = XCreateWindow(_display, XDefaultRootWindow(_display), x, y, platform.frame_width, platform.frame_height, 0, depth, InputOutput, visual, CWEventMask, &(XSetWindowAttributes) { .event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | SubstructureNotifyMask, });
platform.pixels = _buffer;
+ platform.input = _input;
_image = (XImage) {
.width = platform.frame_width,
@@ -681,9 +762,10 @@ i32 p_handle_events(void) {
memset(platform.key_pressed, 0, sizeof platform.key_pressed);
- platform.cursor_dx = 0;
- platform.cursor_dy = 0;
- platform.wheel_dy = 0;
+ platform.input_size = 0;
+ platform.cursor_dx = 0;
+ platform.cursor_dy = 0;
+ platform.wheel_dy = 0;
XEvent ev;
@@ -735,18 +817,33 @@ i32 p_handle_events(void) {
}
break;
- case KeyPress:
+ case KeyPress: {
+ 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]] = 1;
- platform.key_pressed[_key_table[ev.xkey.keycode]]++;
- break;
+ platform.key_down [k] = 1;
+ 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);
+ if (platform.input_size < MAX_INPUT_SIZE)
+ platform.input[platform.input_size++] = ((platform.key_down[MOD_SHIFT] ^ platform.key_down[MOD_CAPS])) && _upper[k] != 0 ? _upper[k] : k;
+ } break;
case KeyRelease:
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[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;
case EnterNotify: platform.has_cursor = 1; break;