all repos — xyw @ 5455787cc2c749e4372e695aa2db153035289c64

A minimal virtual machine and assembler for terminals.

Fixed fenster initialization warnings.
h3rald h3rald@h3rald.com
Mon, 15 Dec 2025 08:35:01 +0100
commit

5455787cc2c749e4372e695aa2db153035289c64

parent

c7dfaf0efb5ee4bfe2acdb8e509387c4384505d4

1 files changed, 98 insertions(+), 49 deletions(-)

jump to
M fenster.hfenster.h

@@ -18,7 +18,8 @@

#include <stdint.h> #include <stdlib.h> -struct fenster { +struct fenster +{ const char *title; const int width; const int height;

@@ -52,22 +53,23 @@ #define fenster_pixel(f, x, y) ((f)->buf[((y) * (f)->width) + (x)])

#ifndef FENSTER_HEADER #if defined(__APPLE__) -#define msg(r, o, s) ((r(*)(id, SEL))objc_msgSend)(o, sel_getUid(s)) -#define msg1(r, o, s, A, a) \ - ((r(*)(id, SEL, A))objc_msgSend)(o, sel_getUid(s), a) -#define msg2(r, o, s, A, a, B, b) \ - ((r(*)(id, SEL, A, B))objc_msgSend)(o, sel_getUid(s), a, b) -#define msg3(r, o, s, A, a, B, b, C, c) \ - ((r(*)(id, SEL, A, B, C))objc_msgSend)(o, sel_getUid(s), a, b, c) -#define msg4(r, o, s, A, a, B, b, C, c, D, d) \ - ((r(*)(id, SEL, A, B, C, D))objc_msgSend)(o, sel_getUid(s), a, b, c, d) +#define msg(r, o, s) ((r (*)(id, SEL))objc_msgSend)(o, sel_getUid(s)) +#define msg1(r, o, s, A, a) \ + ((r (*)(id, SEL, A))objc_msgSend)(o, sel_getUid(s), a) +#define msg2(r, o, s, A, a, B, b) \ + ((r (*)(id, SEL, A, B))objc_msgSend)(o, sel_getUid(s), a, b) +#define msg3(r, o, s, A, a, B, b, C, c) \ + ((r (*)(id, SEL, A, B, C))objc_msgSend)(o, sel_getUid(s), a, b, c) +#define msg4(r, o, s, A, a, B, b, C, c, D, d) \ + ((r (*)(id, SEL, A, B, C, D))objc_msgSend)(o, sel_getUid(s), a, b, c, d) #define cls(x) ((id)objc_getClass(x)) extern id const NSDefaultRunLoopMode; extern id const NSApp; -static void fenster_draw_rect(id v, SEL s, CGRect r) { +static void fenster_draw_rect(id v, SEL s, CGRect r) +{ (void)r, (void)s; struct fenster *f = (struct fenster *)objc_getAssociatedObject(v, "fenster"); CGContextRef context =

@@ -86,13 +88,15 @@ CGContextDrawImage(context, CGRectMake(0, 0, f->width, f->height), img);

CGImageRelease(img); } -static BOOL fenster_should_close(id v, SEL s, id w) { +static BOOL fenster_should_close(id v, SEL s, id w) +{ (void)v, (void)s, (void)w; msg1(void, NSApp, "terminate:", id, NSApp); return YES; } -FENSTER_API int fenster_open(struct fenster *f) { +FENSTER_API int fenster_open(struct fenster *f) +{ msg(id, cls("NSApplication"), "sharedApplication"); msg1(void, NSApp, "setActivationPolicy:", NSInteger, 0); f->wnd = msg4(id, msg(id, cls("NSWindow"), "alloc"),

@@ -123,14 +127,16 @@ msg1(void, NSApp, "activateIgnoringOtherApps:", BOOL, YES);

return 0; } -FENSTER_API void fenster_close(struct fenster *f) { +FENSTER_API void fenster_close(struct fenster *f) +{ msg(void, f->wnd, "close"); } // clang-format off static const uint8_t FENSTER_KEYCODES[128] = {65,83,68,70,72,71,90,88,67,86,0,66,81,87,69,82,89,84,49,50,51,52,54,53,61,57,55,45,56,48,93,79,85,91,73,80,10,76,74,39,75,59,92,44,47,78,77,46,9,32,96,8,0,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,2,3,127,0,5,0,4,0,20,19,18,17,0}; // clang-format on -FENSTER_API int fenster_loop(struct fenster *f) { +FENSTER_API int fenster_loop(struct fenster *f) +{ msg1(void, msg(id, f->wnd, "contentView"), "setNeedsDisplay:", BOOL, YES); id ev = msg4(id, NSApp, "nextEventMatchingMask:untilDate:inMode:dequeue:", NSUInteger,

@@ -138,7 +144,8 @@ NSUIntegerMax, id, NULL, id, NSDefaultRunLoopMode, BOOL, YES);

if (!ev) return 0; NSUInteger evtype = msg(NSUInteger, ev, "type"); - switch (evtype) { + switch (evtype) + { case 1: /* NSEventTypeMouseDown */ f->mouse |= 1; break;

@@ -146,14 +153,16 @@ case 2: /* NSEventTypeMouseUp*/

f->mouse &= ~1; break; case 5: - case 6: { /* NSEventTypeMouseMoved */ + case 6: + { /* NSEventTypeMouseMoved */ CGPoint xy = msg(CGPoint, ev, "locationInWindow"); f->x = (int)xy.x; f->y = (int)(f->height - xy.y); return 0; } case 10: /*NSEventTypeKeyDown*/ - case 11: /*NSEventTypeKeyUp:*/ { + case 11: /*NSEventTypeKeyUp:*/ + { NSUInteger k = msg(NSUInteger, ev, "keyCode"); f->keys[k < 127 ? FENSTER_KEYCODES[k] : 0] = evtype == 10; NSUInteger mod = msg(NSUInteger, ev, "modifierFlags") >> 17;

@@ -168,21 +177,38 @@ #elif defined(_WIN32)

// clang-format off static const uint8_t FENSTER_KEYCODES[] = {0,27,49,50,51,52,53,54,55,56,57,48,45,61,8,9,81,87,69,82,84,89,85,73,79,80,91,93,10,0,65,83,68,70,71,72,74,75,76,59,39,96,0,92,90,88,67,86,66,78,77,44,46,47,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,17,3,0,20,0,19,0,5,18,4,26,127}; // clang-format on -typedef struct BINFO{ - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[3]; -}BINFO; +typedef struct BINFO +{ + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[3]; +} BINFO; static LRESULT CALLBACK fenster_wndproc(HWND hwnd, UINT msg, WPARAM wParam, - LPARAM lParam) { + LPARAM lParam) +{ struct fenster *f = (struct fenster *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - switch (msg) { - case WM_PAINT: { + switch (msg) + { + case WM_PAINT: + { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HDC memdc = CreateCompatibleDC(hdc); HBITMAP hbmp = CreateCompatibleBitmap(hdc, f->width, f->height); HBITMAP oldbmp = SelectObject(memdc, hbmp); - BINFO bi = {{sizeof(bi), f->width, -f->height, 1, 32, BI_BITFIELDS}}; + BINFO bi = { + .bmiHeader = { + .biSize = sizeof(BITMAPINFOHEADER), + .biWidth = f->width, + .biHeight = -f->height, + .biPlanes = 1, + .biBitCount = 32, + .biCompression = BI_BITFIELDS, + .biSizeImage = (DWORD)(f->width * f->height * 4), + .biXPelsPerMeter = 0, + .biYPelsPerMeter = 0, + .biClrUsed = 0, + .biClrImportant = 0}, + .bmiColors = {{0}}}; bi.bmiColors[0].rgbRed = 0xff; bi.bmiColors[1].rgbGreen = 0xff; bi.bmiColors[2].rgbBlue = 0xff;

@@ -193,7 +219,8 @@ SelectObject(memdc, oldbmp);

DeleteObject(hbmp); DeleteDC(memdc); EndPaint(hwnd, &ps); - } break; + } + break; case WM_CLOSE: DestroyWindow(hwnd); break;

@@ -205,13 +232,15 @@ case WM_MOUSEMOVE:

f->y = HIWORD(lParam), f->x = LOWORD(lParam); break; case WM_KEYDOWN: - case WM_KEYUP: { + case WM_KEYUP: + { f->mod = ((GetKeyState(VK_CONTROL) & 0x8000) >> 15) | ((GetKeyState(VK_SHIFT) & 0x8000) >> 14) | ((GetKeyState(VK_MENU) & 0x8000) >> 13) | (((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000) >> 12); f->keys[FENSTER_KEYCODES[HIWORD(lParam) & 0x1ff]] = !((lParam >> 31) & 1); - } break; + } + break; case WM_DESTROY: PostQuitMessage(0); break;

@@ -221,7 +250,8 @@ }

return 0; } -FENSTER_API int fenster_open(struct fenster *f) { +FENSTER_API int fenster_open(struct fenster *f) +{ HINSTANCE hInstance = GetModuleHandle(NULL); WNDCLASSEX wc = {0}; wc.cbSize = sizeof(WNDCLASSEX);

@@ -244,9 +274,11 @@ }

FENSTER_API void fenster_close(struct fenster *f) { (void)f; } -FENSTER_API int fenster_loop(struct fenster *f) { +FENSTER_API int fenster_loop(struct fenster *f) +{ MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { if (msg.message == WM_QUIT) return -1; TranslateMessage(&msg);

@@ -259,7 +291,8 @@ #else

// clang-format off static int FENSTER_KEYCODES[124] = {XK_BackSpace,8,XK_Delete,127,XK_Down,18,XK_End,5,XK_Escape,27,XK_Home,2,XK_Insert,26,XK_Left,20,XK_Page_Down,4,XK_Page_Up,3,XK_Return,10,XK_Right,19,XK_Tab,9,XK_Up,17,XK_apostrophe,39,XK_backslash,92,XK_bracketleft,91,XK_bracketright,93,XK_comma,44,XK_equal,61,XK_grave,96,XK_minus,45,XK_period,46,XK_semicolon,59,XK_slash,47,XK_space,32,XK_a,65,XK_b,66,XK_c,67,XK_d,68,XK_e,69,XK_f,70,XK_g,71,XK_h,72,XK_i,73,XK_j,74,XK_k,75,XK_l,76,XK_m,77,XK_n,78,XK_o,79,XK_p,80,XK_q,81,XK_r,82,XK_s,83,XK_t,84,XK_u,85,XK_v,86,XK_w,87,XK_x,88,XK_y,89,XK_z,90,XK_0,48,XK_1,49,XK_2,50,XK_3,51,XK_4,52,XK_5,53,XK_6,54,XK_7,55,XK_8,56,XK_9,57}; // clang-format on -FENSTER_API int fenster_open(struct fenster *f) { +FENSTER_API int fenster_open(struct fenster *f) +{ f->dpy = XOpenDisplay(NULL); int screen = DefaultScreen(f->dpy); f->w = XCreateSimpleWindow(f->dpy, RootWindow(f->dpy, screen), 0, 0, f->width,

@@ -277,13 +310,16 @@ (char *)f->buf, f->width, f->height, 32, 0);

return 0; } FENSTER_API void fenster_close(struct fenster *f) { XCloseDisplay(f->dpy); } -FENSTER_API int fenster_loop(struct fenster *f) { +FENSTER_API int fenster_loop(struct fenster *f) +{ XEvent ev; XPutImage(f->dpy, f->w, f->gc, f->img, 0, 0, 0, 0, f->width, f->height); XFlush(f->dpy); - while (XPending(f->dpy)) { + while (XPending(f->dpy)) + { XNextEvent(f->dpy, &ev); - switch (ev.type) { + switch (ev.type) + { case ButtonPress: case ButtonRelease: f->mouse = (ev.type == ButtonPress);

@@ -292,18 +328,22 @@ case MotionNotify:

f->x = ev.xmotion.x, f->y = ev.xmotion.y; break; case KeyPress: - case KeyRelease: { + case KeyRelease: + { int m = ev.xkey.state; int k = XkbKeycodeToKeysym(f->dpy, ev.xkey.keycode, 0, 0); - for (unsigned int i = 0; i < 124; i += 2) { - if (FENSTER_KEYCODES[i] == k) { + for (unsigned int i = 0; i < 124; i += 2) + { + if (FENSTER_KEYCODES[i] == k) + { f->keys[FENSTER_KEYCODES[i + 1]] = (ev.type == KeyPress); break; } } f->mod = (!!(m & ControlMask)) | (!!(m & ShiftMask) << 1) | (!!(m & Mod1Mask) << 2) | (!!(m & Mod4Mask) << 3); - } break; + } + break; } } return 0;

@@ -312,20 +352,23 @@ #endif

#ifdef _WIN32 FENSTER_API void fenster_sleep(int64_t ms) { Sleep(ms); } -FENSTER_API int64_t fenster_time() { +FENSTER_API int64_t fenster_time() +{ LARGE_INTEGER freq, count; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&count); return (int64_t)(count.QuadPart * 1000.0 / freq.QuadPart); } #else -FENSTER_API void fenster_sleep(int64_t ms) { +FENSTER_API void fenster_sleep(int64_t ms) +{ struct timespec ts; ts.tv_sec = ms / 1000; ts.tv_nsec = (ms % 1000) * 1000000; nanosleep(&ts, NULL); } -FENSTER_API int64_t fenster_time(void) { +FENSTER_API int64_t fenster_time(void) +{ struct timespec time; clock_gettime(CLOCK_REALTIME, &time); return time.tv_sec * 1000 + (time.tv_nsec / 1000000);

@@ -333,30 +376,36 @@ }

#endif #ifdef __cplusplus -class Fenster { +class Fenster +{ struct fenster f; int64_t now; public: Fenster(const int w, const int h, const char *title) - : f{.title = title, .width = w, .height = h} { + : f{.title = title, .width = w, .height = h} + { this->f.buf = new uint32_t[w * h]; this->now = fenster_time(); fenster_open(&this->f); } - ~Fenster() { + ~Fenster() + { fenster_close(&this->f); delete[] this->f.buf; } - bool loop(const int fps) { + bool loop(const int fps) + { int64_t t = fenster_time(); - if (t - this->now < 1000 / fps) { + if (t - this->now < 1000 / fps) + { fenster_sleep(t - now); } this->now = t; return fenster_loop(&this->f) == 0; } - inline uint32_t &px(const int x, const int y) { + inline uint32_t &px(const int x, const int y) + { return fenster_pixel(&this->f, x, y); } bool key(int c) { return c >= 0 && c < 128 ? this->f.keys[c] : false; }