94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
/*
|
|
* clipboard.hpp
|
|
* Simple plain-text clipboard helpers for MontaukOS GUI apps
|
|
* Copyright (c) 2026 Daniel Hammer
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <montauk/syscall.h>
|
|
#include <montauk/string.h>
|
|
#include <montauk/heap.h>
|
|
#include <montauk/utf8.h>
|
|
|
|
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;
|
|
}
|
|
|
|
}
|