summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-08-11 13:19:05 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-08-11 13:19:05 +0200
commita97e134450f47ba0e90541e6791f72cbf1f65e27 (patch)
tree68c811ead50aa8e293038f0354ac6721433a7d68 /examples
parent10b7903cd144b1d6eb5a1b006edbfaebdb48e689 (diff)
downloadreduced_system_layer-a97e134450f47ba0e90541e6791f72cbf1f65e27.zip
UTF-8
Diffstat (limited to 'examples')
-rwxr-xr-xexamples/ui.c163
1 files changed, 108 insertions, 55 deletions
diff --git a/examples/ui.c b/examples/ui.c
index d51ad99..d853c4b 100755
--- a/examples/ui.c
+++ b/examples/ui.c
@@ -66,6 +66,7 @@ typedef unsigned short u16;
typedef unsigned u32;
typedef unsigned long long u64;
typedef char c8;
+typedef int c32;
typedef signed char b8;
typedef float f32;
typedef double f64;
@@ -117,29 +118,34 @@ enum {
MOD_CAPS,
MOD_NUM,
MOD_SCROLL,
- KEY_KP_,
- KEY_F_ = KEY_KP_ + 64,
+ KEY_F_,
+ KEY_KP_ = KEY_F_ + 64,
};
typedef struct {
- c8 *title;
- i32 frame_width;
- i32 frame_height;
- u32 *pixels;
- i64 input_size;
- i16 *input;
- i64 clipboard_size;
- c8 *clipboard; // TODO
- b8 done;
- b8 has_focus;
- b8 has_cursor;
- i32 cursor_x;
- i32 cursor_y;
- i32 cursor_dx;
- i32 cursor_dy;
- i64 wheel_dy;
- b8 key_down[512];
- b8 key_pressed[512];
+ u32 key;
+ c32 c;
+} Input_Key;
+
+typedef struct {
+ c8 * title;
+ i32 frame_width;
+ i32 frame_height;
+ u32 * pixels;
+ i64 input_size;
+ Input_Key *input;
+ i64 clipboard_size;
+ c8 * clipboard; // TODO
+ b8 done;
+ b8 has_focus;
+ b8 has_cursor;
+ i32 cursor_x;
+ i32 cursor_y;
+ i32 cursor_dx;
+ i32 cursor_dy;
+ i64 wheel_dy;
+ b8 key_down[512];
+ b8 key_pressed[512];
} Platform;
typedef struct {
@@ -196,7 +202,7 @@ u64 bitfont[] = {
#define BITFONT_LEN ((i64) (sizeof bitfont / sizeof *bitfont))
-i64 char_column_offset(c8 c, i64 column_index) {
+i64 char_column_offset(c32 c, i64 column_index) {
if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
return -1;
return (c - 32) * CHAR_NUM_BITS + column_index * CHAR_NUM_BITS_Y;
@@ -214,7 +220,7 @@ b8 char_bit(i64 column_offset, i64 row_index) {
return !!(bitfont[qword_index] & mask);
}
-u64 char_column_convolved(c8 c, i64 column_index) {
+u64 char_column_convolved(c32 c, i64 column_index) {
if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
return 0;
@@ -235,7 +241,7 @@ u64 char_column_convolved(c8 c, i64 column_index) {
return column;
}
-b8 char_column_empty(c8 c, i64 column_index) {
+b8 char_column_empty(c32 c, i64 column_index) {
if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
return 1;
@@ -248,7 +254,7 @@ b8 char_column_empty(c8 c, i64 column_index) {
return 1;
}
-i64 char_width(c8 c) {
+i64 char_width(c32 c) {
if (c < 32)
return 0;
if (c == ' ')
@@ -263,7 +269,7 @@ i64 char_width(c8 c) {
return width;
}
-i64 char_spacing(i64 num_chars, c8 *text, i64 index) {
+i64 char_spacing(i64 num_chars, c32 *text, i64 index) {
assert(text != NULL);
if (index < 0 || index + 1 >= num_chars)
@@ -278,7 +284,7 @@ i64 char_spacing(i64 num_chars, c8 *text, i64 index) {
return 0;
}
-i64 text_cursor(i64 num_chars, c8 *text) {
+i64 text_cursor(i64 num_chars, c32 *text) {
assert(text != NULL);
i64 cursor = 0;
@@ -301,7 +307,7 @@ i64 text_cursor(i64 num_chars, c8 *text) {
return cursor;
}
-i64 enum_text_columns(i64 num_chars, c8 *text) {
+i64 enum_text_columns(i64 num_chars, c32 *text) {
assert(text != NULL);
i64 cols = 0;
@@ -334,7 +340,7 @@ i64 enum_text_columns(i64 num_chars, c8 *text) {
return cols;
}
-i64 enum_text_rows(i64 num_chars, c8 *text) {
+i64 enum_text_rows(i64 num_chars, c32 *text) {
assert(text != NULL);
i64 rows = 0;
@@ -349,7 +355,7 @@ i64 enum_text_rows(i64 num_chars, c8 *text) {
return rows;
}
-void print_text(u32 color, f64 x0, f64 y0, f64 scale_x, f64 scale_y, i64 num_chars, c8 *text) {
+void print_text(u32 color, f64 x0, f64 y0, f64 scale_x, f64 scale_y, i64 num_chars, c32 *text) {
assert(text != NULL);
f64 x = x0;
@@ -422,7 +428,7 @@ void draw_panel(u32 op, u32 color, f64 x0, f64 y0, f64 width, f64 height) {
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) {
+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, c32 *text) {
assert(max_scale_x > 1e-6);
assert(max_scale_y > 1e-6);
@@ -443,7 +449,7 @@ void draw_text_area(u32 color, f64 x0, f64 y0, f64 width, f64 height, f64 max_sc
print_text(color, x0, y0, kx, ky, num_chars, text);
}
-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 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, c32 *text) {
assert(max_scale_x > 1e-6);
assert(max_scale_y > 1e-6);
@@ -523,8 +529,8 @@ i32 main(i32 argc, c8 **argv) {
b8 button_1_down = 0;
b8 button_1_checked = 0;
- i64 text_len = 0;
- static c8 text[512] = "";
+ i64 text_len = 0;
+ static c32 text[512] = {0};
i64 cursor = 0;
i64 selection = 0;
@@ -577,7 +583,7 @@ i32 main(i32 argc, c8 **argv) {
color = 0xffffff;
for (i64 i = 0; i < platform.input_size; ++i)
- switch (platform.input[i]) {
+ switch (platform.input[i].key) {
case KEY_LEFT:
if (platform.key_down[MOD_SHIFT]) {
if (cursor > 0)
@@ -635,8 +641,14 @@ i32 main(i32 argc, c8 **argv) {
}
break;
+ case '\n':
+ case '\r':
+ case '\t':
+ platform.input[i].c = platform.input[i].key;
+ // fallthrough
+
default:
- if (platform.input[i] > 0 && platform.input[i] < 128) {
+ if (platform.input[i].c) {
if (selection != 0) {
i64 i0 = selection < 0 ? cursor + selection : cursor;
i64 i1 = selection < 0 ? cursor : cursor + selection;
@@ -650,7 +662,7 @@ i32 main(i32 argc, c8 **argv) {
if (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[cursor++] = platform.input[i].c;
++text_len;
}
}
@@ -728,14 +740,16 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data) {
#include <sched.h>
#include <time.h>
-static i16 _key_table[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;
+static i16 _key_table[512] = {0};
+static u32 _buffer[MAX_NUM_PIXELS] = {0};
+static Input_Key _input[MAX_INPUT_SIZE] = {0};
+static XImage _image = {0};
+static Display * _display = NULL;
+static GC _gc = NULL;
+static XIM _im = NULL;
+static XIC _ic = NULL;
+static Window _window = 0;
+static Atom _wm_delete_window = 0;
void p_init(void) {
_display = XOpenDisplay(NULL);
@@ -846,6 +860,7 @@ void p_init(void) {
Visual *visual = DefaultVisual(_display, screen);
_gc = DefaultGC(_display, screen);
+ assert(_gc != NULL);
XSetGraphicsExposures(_display, _gc, False);
@@ -857,6 +872,14 @@ 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, });
+ _im = XOpenIM(_display, NULL, NULL, NULL);
+ assert(_im != NULL);
+
+ _ic = XCreateIC(_im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, _window, NULL);
+ assert(_ic != NULL);
+
+ XSetICFocus(_ic);
+
platform.pixels = _buffer;
platform.input = _input;
@@ -894,8 +917,36 @@ void p_cleanup(void) {
XCloseDisplay (_display);
}
+c32 c32_from_utf8(i64 len, c8 *s) {
+ if (len <= 1 &&
+ (s[0] & 0x80) == 0)
+ return s[0];
+ if (len <= 2 &&
+ (s[0] & 0xe0) == 0xc0 &&
+ (s[1] & 0xc0) == 0x80)
+ return (s[1] & 0x3f)
+ | ((s[0] & 0x1f) << 6);
+ if (len <= 3 &&
+ (s[0] & 0xf0) == 0xe0 &&
+ (s[1] & 0xc0) == 0x80 &&
+ (s[2] & 0xc0) == 0x80)
+ return (s[2] & 0x3f)
+ | ((s[1] & 0x3f) << 6)
+ | ((s[0] & 0x0f) << 12);
+ if (len <= 4 &&
+ (s[0] & 0xf8) == 0xf0 &&
+ (s[1] & 0xc0) == 0x80 &&
+ (s[2] & 0xc0) == 0x80 &&
+ (s[3] & 0xc0) == 0x80)
+ return (s[3] & 0x3f)
+ | ((s[2] & 0x3f) << 6)
+ | ((s[1] & 0x3f) << 12)
+ | ((s[0] & 0x07) << 18);
+ return 0;
+}
+
i32 p_handle_events(void) {
- i32 num_events = XEventsQueued(_display, QueuedAlready);
+ i32 num_events = 0;
memset(platform.key_pressed, 0, sizeof platform.key_pressed);
@@ -906,8 +957,11 @@ i32 p_handle_events(void) {
XEvent ev;
- for (i32 i = 0; i < num_events; ++i) {
+ while (XEventsQueued(_display, QueuedAlready) > 0) {
+ ++num_events;
+
XNextEvent(_display, &ev);
+ XFilterEvent(&ev, _window);
switch (ev.type) {
case DestroyNotify:
@@ -968,17 +1022,12 @@ i32 p_handle_events(void) {
platform.key_down[MOD_SCROLL] = !!(ev.xkey.state & Mod3Mask);
if (platform.input_size < MAX_INPUT_SIZE) {
if (k < 32 || k >= 128)
- platform.input[platform.input_size++] = k;
+ platform.input[platform.input_size++] = (Input_Key) { .key = k, .c = 0, };
else {
c8 buf[16];
- i32 len = XLookupString(&ev.xkey, buf, sizeof buf - 1, NULL, NULL);
- buf[len] = '\0';
- printf("key:");
- for (i32 i = 0; i < len; ++i)
- printf("%02x", buf[i]);
- printf("\n");
- for (i32 i = 0; i < len && platform.input_size < MAX_INPUT_SIZE; ++i, ++platform.input_size)
- platform.input[platform.input_size] = buf[i];
+ i32 len = Xutf8LookupString(_ic, &ev.xkey, buf, sizeof buf - 1, NULL, NULL);
+ if (len > 0)
+ platform.input[platform.input_size++] = (Input_Key) { .key = k, .c = c32_from_utf8(len, buf), };
}
}
} break;
@@ -1002,6 +1051,10 @@ i32 p_handle_events(void) {
case FocusIn: platform.has_focus = 1; break;
case FocusOut: platform.has_focus = 0; break;
+ case MappingNotify:
+ XRefreshKeyboardMapping(&ev.xmapping);
+ break;
+
case ClientMessage:
if ((Atom) ev.xclient.data.l[0] == _wm_delete_window)
platform.done = 1;