/* * clipboard.hpp * Simple plain-text clipboard helpers for MontaukOS GUI apps * Copyright (c) 2026 Daniel Hammer */ #pragma once #include #include #include #include namespace gui { // The clipboard carries UTF-8. Text that is not well-formed (legacy // Windows-1252 bytes) is converted on the way in and on the way out, so // every reader can assume valid UTF-8. inline char* clipboard_utf8_copy(const char* text, int len, int* out_len) { int cap = len * 3 + 1; // each stray byte grows to at most 3 char* out = (char*)montauk::malloc(cap); if (!out) return nullptr; *out_len = montauk::utf8::normalize(text, len, out, cap); return out; } inline bool clipboard_set_text(const char* text, int len) { if (len < 0) return false; if (len > 0 && text == nullptr) return false; if (len > 0 && !montauk::utf8::valid(text, len)) { int fixed_len = 0; char* fixed = clipboard_utf8_copy(text, len, &fixed_len); if (!fixed) return false; bool ok = montauk::clipboard_set_text(fixed, (uint32_t)fixed_len) == 0; montauk::mfree(fixed); return ok; } return montauk::clipboard_set_text(text, (uint32_t)len) == 0; } inline bool clipboard_set_text(const char* text) { return clipboard_set_text(text, text ? montauk::slen(text) : 0); } inline bool clipboard_get_info(montauk::abi::ClipboardInfo* out) { if (out == nullptr) return false; return montauk::clipboard_get_info(out) == 0; } inline bool clipboard_has_text() { montauk::abi::ClipboardInfo info = {}; return clipboard_get_info(&info) && info.textBytes > 0; } inline char* clipboard_get_text_alloc(int* out_len = nullptr, uint64_t* out_serial = nullptr) { if (out_len) *out_len = 0; if (out_serial) *out_serial = 0; montauk::abi::ClipboardInfo info = {}; if (!clipboard_get_info(&info) || info.textBytes == 0) return nullptr; uint32_t cap = info.textBytes + 1; char* text = (char*)montauk::malloc(cap); if (text == nullptr) return nullptr; uint32_t actual_len = 0; uint64_t serial = 0; if (montauk::clipboard_get_text(text, info.textBytes, &actual_len, &serial) != 0 || actual_len > info.textBytes) { montauk::mfree(text); return nullptr; } text[actual_len] = '\0'; if (!montauk::utf8::valid(text, (int)actual_len)) { int fixed_len = 0; char* fixed = clipboard_utf8_copy(text, (int)actual_len, &fixed_len); montauk::mfree(text); if (!fixed) return nullptr; text = fixed; actual_len = (uint32_t)fixed_len; } if (out_len) *out_len = (int)actual_len; if (out_serial) *out_serial = serial; return text; } inline bool clipboard_clear() { return montauk::clipboard_clear() == 0; } }