feat: make dialogs a shared library
This commit is contained in:
+11
-11
@@ -148,16 +148,16 @@ imageviewer: libc libjpeg
|
|||||||
fontpreview:
|
fontpreview:
|
||||||
$(MAKE) -C src/fontpreview
|
$(MAKE) -C src/fontpreview
|
||||||
|
|
||||||
# Build spreadsheet standalone GUI client (depends on libc).
|
# Build spreadsheet standalone GUI client (depends on libc and libdialogs).
|
||||||
spreadsheet: libc
|
spreadsheet: libc libloader dialogs
|
||||||
$(MAKE) -C src/spreadsheet
|
$(MAKE) -C src/spreadsheet
|
||||||
|
|
||||||
# Build word processor standalone GUI client (depends on libc).
|
# Build word processor standalone GUI client (depends on libc and libdialogs).
|
||||||
wordprocessor: libc
|
wordprocessor: libc libloader dialogs
|
||||||
$(MAKE) -C src/wordprocessor
|
$(MAKE) -C src/wordprocessor
|
||||||
|
|
||||||
# Build PDF viewer standalone GUI client (depends on libc).
|
# Build PDF viewer standalone GUI client (depends on libc and libdialogs).
|
||||||
pdfviewer: libc
|
pdfviewer: libc libloader dialogs
|
||||||
$(MAKE) -C src/pdfviewer
|
$(MAKE) -C src/pdfviewer
|
||||||
|
|
||||||
# Build disks standalone GUI tool (depends on libc).
|
# Build disks standalone GUI tool (depends on libc).
|
||||||
@@ -232,8 +232,8 @@ fonts:
|
|||||||
paint: libc
|
paint: libc
|
||||||
$(MAKE) -C src/paint
|
$(MAKE) -C src/paint
|
||||||
|
|
||||||
# Build text editor standalone GUI app (depends on libc).
|
# Build text editor standalone GUI app (depends on libc and libdialogs).
|
||||||
texteditor: libc
|
texteditor: libc libloader dialogs
|
||||||
$(MAKE) -C src/texteditor
|
$(MAKE) -C src/texteditor
|
||||||
|
|
||||||
# Build Mandelbrot standalone GUI app (depends on libc).
|
# Build Mandelbrot standalone GUI app (depends on libc).
|
||||||
@@ -273,8 +273,8 @@ printd: bearssl libc tls libjpegwrite
|
|||||||
printctl: bearssl libc tls
|
printctl: bearssl libc tls
|
||||||
$(MAKE) -C src/printctl
|
$(MAKE) -C src/printctl
|
||||||
|
|
||||||
# Build shared dialogs app (depends on libc, bearssl, and tls through print helpers).
|
# Build libdialogs shared library.
|
||||||
dialogs: bearssl libc tls
|
dialogs:
|
||||||
$(MAKE) -C src/dialogs
|
$(MAKE) -C src/dialogs
|
||||||
|
|
||||||
# Build crashpad (crash reporter popup, depends on libc).
|
# Build crashpad (crash reporter popup, depends on libc).
|
||||||
@@ -286,7 +286,7 @@ test_dl: libloader libs libhello
|
|||||||
$(MAKE) -C src/test_dl
|
$(MAKE) -C src/test_dl
|
||||||
|
|
||||||
# Install app bundles (manifests, icons, data files) into bin/apps/<name>/.
|
# Install app bundles (manifests, icons, data files) into bin/apps/<name>/.
|
||||||
install-apps: doom rpgdemo paint spreadsheet wordprocessor weather wikipedia imageviewer fontpreview pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator screenshot texteditor mandelbrot printers dialogs crashpad
|
install-apps: doom rpgdemo paint spreadsheet wordprocessor weather wikipedia imageviewer fontpreview pdfviewer disks devexplorer installer volume music video bluetooth terminal klog procmgr calculator screenshot texteditor mandelbrot printers crashpad
|
||||||
../scripts/install_apps.sh
|
../scripts/install_apps.sh
|
||||||
|
|
||||||
# Copy man pages into bin/man/ so mkramdisk.sh picks them up.
|
# Copy man pages into bin/man/ so mkramdisk.sh picks them up.
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* dialogs.hpp
|
* dialogs.hpp
|
||||||
* Shared modal dialog protocol and client helpers
|
* Shared dialog request/result structures and client helpers
|
||||||
* Copyright (c) 2026 Daniel Hammer
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdio.h>
|
|
||||||
#include <montauk/syscall.h>
|
|
||||||
#include <montauk/string.h>
|
#include <montauk/string.h>
|
||||||
#include <Api/Syscall.hpp>
|
|
||||||
|
#ifndef GUI_DIALOGS_LIBRARY_BUILD
|
||||||
|
#include <libloader/libloader.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace gui::dialogs {
|
namespace gui::dialogs {
|
||||||
|
|
||||||
inline constexpr const char* APP_BINARY = "0:/apps/dialogs/dialogs.elf";
|
inline constexpr const char* LIBRARY_PATH = "0:/os/libdialogs.lib";
|
||||||
inline constexpr const char* STORAGE_DIR = "0:/tmp/dialogs";
|
inline constexpr const char* RUN_REQUEST_SYMBOL = "dialogs_run_request";
|
||||||
|
|
||||||
enum RequestKind : uint8_t {
|
enum RequestKind : uint8_t {
|
||||||
REQUEST_KIND_FILE = 1,
|
REQUEST_KIND_FILE = 1,
|
||||||
@@ -42,7 +43,6 @@ struct Request {
|
|||||||
char job_name[128];
|
char job_name[128];
|
||||||
char printer_uri[256];
|
char printer_uri[256];
|
||||||
uint32_t copies;
|
uint32_t copies;
|
||||||
char result_path[256];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Result {
|
struct Result {
|
||||||
@@ -72,227 +72,57 @@ inline void reset_result(Result* res) {
|
|||||||
montauk::memset(res, 0, sizeof(Result));
|
montauk::memset(res, 0, sizeof(Result));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ensure_storage_dirs() {
|
#ifndef GUI_DIALOGS_LIBRARY_BUILD
|
||||||
montauk::fmkdir("0:/tmp");
|
|
||||||
montauk::fmkdir(STORAGE_DIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool write_text_file(const char* path, const char* text) {
|
using RunRequestFn = bool (*)(const Request*, Result*);
|
||||||
if (!path || !path[0] || !text) return false;
|
|
||||||
int fd = montauk::fcreate(path);
|
|
||||||
if (fd < 0) return false;
|
|
||||||
int len = montauk::slen(text);
|
|
||||||
bool ok = montauk::fwrite(fd, (const uint8_t*)text, 0, (uint64_t)len) >= 0;
|
|
||||||
montauk::close(fd);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool read_text_file(const char* path, char* out, int out_len) {
|
struct Runtime {
|
||||||
if (!out || out_len <= 0) return false;
|
LibHandle* handle;
|
||||||
out[0] = '\0';
|
RunRequestFn run_request;
|
||||||
if (!path || !path[0]) return false;
|
};
|
||||||
int fd = montauk::open(path);
|
|
||||||
if (fd < 0) return false;
|
|
||||||
uint64_t size = montauk::getsize(fd);
|
|
||||||
if ((int)size >= out_len) size = (uint64_t)(out_len - 1);
|
|
||||||
int got = montauk::read(fd, (uint8_t*)out, 0, size);
|
|
||||||
montauk::close(fd);
|
|
||||||
if (got < 0) return false;
|
|
||||||
out[got] = '\0';
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool line_value(const char* text, const char* key, char* out, int out_len) {
|
inline Runtime g_runtime = {};
|
||||||
if (!text || !key || !out || out_len <= 0) return false;
|
|
||||||
|
|
||||||
int key_len = montauk::slen(key);
|
inline RunRequestFn resolve_run_request(char* out_message, int out_message_len) {
|
||||||
const char* p = text;
|
if (g_runtime.run_request) return g_runtime.run_request;
|
||||||
while (*p) {
|
|
||||||
const char* line = p;
|
|
||||||
while (*p && *p != '\n') p++;
|
|
||||||
int line_len = (int)(p - line);
|
|
||||||
if (*p == '\n') p++;
|
|
||||||
|
|
||||||
if (line_len <= key_len || line[key_len] != '=') continue;
|
if (!g_runtime.handle) {
|
||||||
|
g_runtime.handle = libloader::dlopen(LIBRARY_PATH);
|
||||||
bool match = true;
|
if (!g_runtime.handle) {
|
||||||
for (int i = 0; i < key_len; i++) {
|
if (out_message && out_message_len > 0)
|
||||||
if (line[i] != key[i]) {
|
safe_copy(out_message, out_message_len, "failed to load dialog library");
|
||||||
match = false;
|
return nullptr;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!match) continue;
|
|
||||||
|
|
||||||
const char* value = line + key_len + 1;
|
|
||||||
int value_len = line_len - key_len - 1;
|
|
||||||
while (value_len > 0 && (value[value_len - 1] == '\r' || value[value_len - 1] == '\n'))
|
|
||||||
value_len--;
|
|
||||||
if (value_len >= out_len) value_len = out_len - 1;
|
|
||||||
montauk::memcpy(out, value, (uint64_t)value_len);
|
|
||||||
out[value_len] = '\0';
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
g_runtime.run_request = (RunRequestFn)libloader::dlsym(g_runtime.handle, RUN_REQUEST_SYMBOL);
|
||||||
}
|
if (!g_runtime.run_request && out_message && out_message_len > 0)
|
||||||
|
safe_copy(out_message, out_message_len, "failed to resolve dialog entry point");
|
||||||
inline uint32_t parse_u32(const char* text) {
|
return g_runtime.run_request;
|
||||||
if (!text) return 0;
|
|
||||||
uint32_t value = 0;
|
|
||||||
for (int i = 0; text[i] >= '0' && text[i] <= '9'; i++) {
|
|
||||||
value = value * 10u + (uint32_t)(text[i] - '0');
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool write_request_file(const char* path, const Request* req) {
|
|
||||||
if (!path || !req) return false;
|
|
||||||
char text[1536];
|
|
||||||
int n = snprintf(text, sizeof(text),
|
|
||||||
"kind=%u\n"
|
|
||||||
"mode=%u\n"
|
|
||||||
"title=%s\n"
|
|
||||||
"initial_path=%s\n"
|
|
||||||
"suggested_name=%s\n"
|
|
||||||
"source_path=%s\n"
|
|
||||||
"job_name=%s\n"
|
|
||||||
"printer_uri=%s\n"
|
|
||||||
"copies=%u\n"
|
|
||||||
"result_path=%s\n",
|
|
||||||
(unsigned)req->kind,
|
|
||||||
(unsigned)req->mode,
|
|
||||||
req->title,
|
|
||||||
req->initial_path,
|
|
||||||
req->suggested_name,
|
|
||||||
req->source_path,
|
|
||||||
req->job_name,
|
|
||||||
req->printer_uri,
|
|
||||||
(unsigned)req->copies,
|
|
||||||
req->result_path);
|
|
||||||
if (n <= 0 || n >= (int)sizeof(text)) return false;
|
|
||||||
return write_text_file(path, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool read_request_file(const char* path, Request* req) {
|
|
||||||
if (!path || !req) return false;
|
|
||||||
char text[1536];
|
|
||||||
if (!read_text_file(path, text, sizeof(text))) return false;
|
|
||||||
|
|
||||||
reset_request(req);
|
|
||||||
char value[256];
|
|
||||||
if (line_value(text, "kind", value, sizeof(value))) req->kind = (uint8_t)parse_u32(value);
|
|
||||||
if (line_value(text, "mode", value, sizeof(value))) req->mode = (uint8_t)parse_u32(value);
|
|
||||||
line_value(text, "title", req->title, sizeof(req->title));
|
|
||||||
line_value(text, "initial_path", req->initial_path, sizeof(req->initial_path));
|
|
||||||
line_value(text, "suggested_name", req->suggested_name, sizeof(req->suggested_name));
|
|
||||||
line_value(text, "source_path", req->source_path, sizeof(req->source_path));
|
|
||||||
line_value(text, "job_name", req->job_name, sizeof(req->job_name));
|
|
||||||
line_value(text, "printer_uri", req->printer_uri, sizeof(req->printer_uri));
|
|
||||||
if (line_value(text, "copies", value, sizeof(value))) req->copies = parse_u32(value);
|
|
||||||
line_value(text, "result_path", req->result_path, sizeof(req->result_path));
|
|
||||||
return req->kind != 0 && req->result_path[0] != '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool write_result_file(const char* path, const Result* res) {
|
|
||||||
if (!path || !res) return false;
|
|
||||||
char text[1024];
|
|
||||||
int n = snprintf(text, sizeof(text),
|
|
||||||
"status=%s\n"
|
|
||||||
"path=%s\n"
|
|
||||||
"job_id=%s\n"
|
|
||||||
"printer_uri=%s\n"
|
|
||||||
"printer_name=%s\n"
|
|
||||||
"copies=%u\n"
|
|
||||||
"message=%s\n",
|
|
||||||
res->status,
|
|
||||||
res->path,
|
|
||||||
res->job_id,
|
|
||||||
res->printer_uri,
|
|
||||||
res->printer_name,
|
|
||||||
(unsigned)res->copies,
|
|
||||||
res->message);
|
|
||||||
if (n <= 0 || n >= (int)sizeof(text)) return false;
|
|
||||||
return write_text_file(path, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool read_result_file(const char* path, Result* res) {
|
|
||||||
if (!path || !res) return false;
|
|
||||||
char text[1024];
|
|
||||||
if (!read_text_file(path, text, sizeof(text))) return false;
|
|
||||||
|
|
||||||
reset_result(res);
|
|
||||||
char value[256];
|
|
||||||
line_value(text, "status", res->status, sizeof(res->status));
|
|
||||||
line_value(text, "path", res->path, sizeof(res->path));
|
|
||||||
line_value(text, "job_id", res->job_id, sizeof(res->job_id));
|
|
||||||
line_value(text, "printer_uri", res->printer_uri, sizeof(res->printer_uri));
|
|
||||||
line_value(text, "printer_name", res->printer_name, sizeof(res->printer_name));
|
|
||||||
if (line_value(text, "copies", value, sizeof(value))) res->copies = parse_u32(value);
|
|
||||||
line_value(text, "message", res->message, sizeof(res->message));
|
|
||||||
return res->status[0] != '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void make_unique_paths(char* request_path, int request_path_len,
|
|
||||||
char* result_path, int result_path_len) {
|
|
||||||
static uint32_t seq = 0;
|
|
||||||
ensure_storage_dirs();
|
|
||||||
uint64_t now = montauk::get_milliseconds();
|
|
||||||
int pid = montauk::getpid();
|
|
||||||
uint32_t cur = ++seq;
|
|
||||||
snprintf(request_path, request_path_len, "%s/%d-%llu-%u.req",
|
|
||||||
STORAGE_DIR, pid, (unsigned long long)now, (unsigned)cur);
|
|
||||||
snprintf(result_path, result_path_len, "%s/%d-%llu-%u.res",
|
|
||||||
STORAGE_DIR, pid, (unsigned long long)now, (unsigned)cur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool run_request(const Request* req, Result* out_res, char* out_message, int out_message_len) {
|
inline bool run_request(const Request* req, Result* out_res, char* out_message, int out_message_len) {
|
||||||
if (out_message && out_message_len > 0) out_message[0] = '\0';
|
if (out_message && out_message_len > 0) out_message[0] = '\0';
|
||||||
if (!req) {
|
if (!req) {
|
||||||
if (out_message && out_message_len > 0) safe_copy(out_message, out_message_len, "invalid dialog request");
|
if (out_message && out_message_len > 0)
|
||||||
|
safe_copy(out_message, out_message_len, "invalid dialog request");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char request_path[256];
|
|
||||||
char result_path[256];
|
|
||||||
make_unique_paths(request_path, sizeof(request_path), result_path, sizeof(result_path));
|
|
||||||
|
|
||||||
Request req_copy = *req;
|
|
||||||
safe_copy(req_copy.result_path, sizeof(req_copy.result_path), result_path);
|
|
||||||
|
|
||||||
if (!write_request_file(request_path, &req_copy)) {
|
|
||||||
if (out_message && out_message_len > 0) safe_copy(out_message, out_message_len, "failed to write dialog request");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pid = montauk::spawn(APP_BINARY, request_path);
|
|
||||||
if (pid < 0) {
|
|
||||||
montauk::fdelete(request_path);
|
|
||||||
if (out_message && out_message_len > 0) safe_copy(out_message, out_message_len, "failed to start dialog");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int proc = montauk::proc_open(pid);
|
|
||||||
if (proc >= 0) {
|
|
||||||
montauk::wait_handle(proc, Montauk::IPC_SIGNAL_EXITED);
|
|
||||||
montauk::close(proc);
|
|
||||||
} else {
|
|
||||||
montauk::waitpid(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result local_res = {};
|
Result local_res = {};
|
||||||
bool ok = read_result_file(result_path, &local_res);
|
reset_result(&local_res);
|
||||||
|
|
||||||
montauk::fdelete(request_path);
|
RunRequestFn run_fn = resolve_run_request(out_message, out_message_len);
|
||||||
montauk::fdelete(result_path);
|
if (!run_fn) return false;
|
||||||
|
if (!run_fn(req, &local_res)) {
|
||||||
if (!ok) {
|
if (out_message && out_message_len > 0 && !out_message[0])
|
||||||
if (out_message && out_message_len > 0) safe_copy(out_message, out_message_len, "dialog did not return a result");
|
safe_copy(out_message, out_message_len, "dialog library invocation failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_res) *out_res = local_res;
|
if (out_res) *out_res = local_res;
|
||||||
if (out_message && out_message_len > 0) safe_copy(out_message, out_message_len, local_res.message);
|
if (out_message && out_message_len > 0)
|
||||||
|
safe_copy(out_message, out_message_len, local_res.message);
|
||||||
return montauk::streq(local_res.status, "ok");
|
return montauk::streq(local_res.status, "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,4 +202,6 @@ inline bool configure_print(const char* title,
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace gui::dialogs
|
} // namespace gui::dialogs
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Makefile for shared dialogs (standalone Window Server app) on MontaukOS
|
# Makefile for libdialogs shared library on MontaukOS
|
||||||
# Copyright (c) 2026 Daniel Hammer
|
# Copyright (c) 2026 Daniel Hammer
|
||||||
|
|
||||||
MAKEFLAGS += -rR
|
MAKEFLAGS += -rR
|
||||||
@@ -6,16 +6,23 @@ MAKEFLAGS += -rR
|
|||||||
|
|
||||||
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||||
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
||||||
|
CC := $(TOOLCHAIN_PREFIX)gcc
|
||||||
CXX := $(TOOLCHAIN_PREFIX)g++
|
CXX := $(TOOLCHAIN_PREFIX)g++
|
||||||
|
LD := $(TOOLCHAIN_PREFIX)ld
|
||||||
|
STRIP := $(TOOLCHAIN_PREFIX)strip
|
||||||
else
|
else
|
||||||
|
CC := gcc
|
||||||
CXX := g++
|
CXX := g++
|
||||||
|
LD := ld
|
||||||
|
STRIP := strip
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PROG_INC := ../../include
|
PROG_INC := ../../include
|
||||||
LINK_LD := ../../link.ld
|
LIBOUTDIR := ../../bin/os
|
||||||
BINDIR := ../../bin
|
OBJDIR := obj
|
||||||
OBJDIR := obj
|
LEGACY_APPDIR := ../../bin/apps/dialogs
|
||||||
LIBDIR := ../../lib
|
LIBC_SRC := ../../lib/libc/libc.c
|
||||||
|
GCC_INCLUDE := $(shell $(CC) -print-file-name=include)
|
||||||
|
|
||||||
CXXFLAGS := \
|
CXXFLAGS := \
|
||||||
-std=gnu++20 \
|
-std=gnu++20 \
|
||||||
@@ -28,7 +35,7 @@ CXXFLAGS := \
|
|||||||
-ffreestanding \
|
-ffreestanding \
|
||||||
-fno-stack-protector \
|
-fno-stack-protector \
|
||||||
-fno-stack-check \
|
-fno-stack-check \
|
||||||
-fno-PIC \
|
-fPIC \
|
||||||
-fno-rtti \
|
-fno-rtti \
|
||||||
-fno-exceptions \
|
-fno-exceptions \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
@@ -40,6 +47,7 @@ CXXFLAGS := \
|
|||||||
-mno-red-zone \
|
-mno-red-zone \
|
||||||
-mcmodel=small \
|
-mcmodel=small \
|
||||||
-MMD -MP \
|
-MMD -MP \
|
||||||
|
-DGUI_DIALOGS_LIBRARY_BUILD \
|
||||||
-I $(PROG_INC) \
|
-I $(PROG_INC) \
|
||||||
-isystem $(PROG_INC)/libc \
|
-isystem $(PROG_INC)/libc \
|
||||||
-I ../../lib/bearssl/inc \
|
-I ../../lib/bearssl/inc \
|
||||||
@@ -47,33 +55,60 @@ CXXFLAGS := \
|
|||||||
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||||
|
|
||||||
LDFLAGS := \
|
LDFLAGS := \
|
||||||
-nostdlib \
|
-shared \
|
||||||
-static \
|
--build-id=none \
|
||||||
-Wl,--build-id=none \
|
--gc-sections \
|
||||||
-Wl,--gc-sections \
|
--hash-style=sysv \
|
||||||
-Wl,-m,elf_x86_64 \
|
-u dialogs_run_request \
|
||||||
-z max-page-size=0x1000 \
|
-m elf_x86_64 \
|
||||||
-T $(LINK_LD)
|
-z max-page-size=0x1000
|
||||||
|
|
||||||
|
LIBC_CFLAGS := \
|
||||||
|
-std=gnu11 \
|
||||||
|
-g -O2 -pipe \
|
||||||
|
-Wall \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
-nostdinc \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fPIC \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-m64 \
|
||||||
|
-march=x86-64 \
|
||||||
|
-msse \
|
||||||
|
-msse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mcmodel=small \
|
||||||
|
-isystem $(PROG_INC)/libc \
|
||||||
|
-isystem $(GCC_INCLUDE)
|
||||||
|
|
||||||
SRCS := main.cpp filedialog.cpp printdialog.cpp stb_truetype_impl.cpp font_data.cpp
|
SRCS := main.cpp filedialog.cpp printdialog.cpp stb_truetype_impl.cpp font_data.cpp
|
||||||
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||||
|
LIBC_PIC_OBJ := $(OBJDIR)/libc_pic.o
|
||||||
|
|
||||||
TARGET := $(BINDIR)/apps/dialogs/dialogs.elf
|
TARGET := $(LIBOUTDIR)/libdialogs.lib
|
||||||
LIBS := $(LIBDIR)/tls/libtls.a $(LIBDIR)/bearssl/libbearssl.a $(LIBDIR)/libc/liblibc.a
|
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LIBS)
|
$(TARGET): $(OBJS) $(LIBC_PIC_OBJ) Makefile
|
||||||
mkdir -p $(BINDIR)/apps/dialogs
|
mkdir -p $(LIBOUTDIR)
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
rm -rf $(LEGACY_APPDIR)
|
||||||
|
$(LD) $(LDFLAGS) $(OBJS) $(LIBC_PIC_OBJ) -o $@
|
||||||
|
$(STRIP) --strip-debug $@
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp Makefile
|
$(OBJDIR)/%.o: %.cpp Makefile
|
||||||
mkdir -p $(OBJDIR)
|
mkdir -p $(OBJDIR)
|
||||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(LIBC_PIC_OBJ): $(LIBC_SRC) Makefile
|
||||||
|
mkdir -p $(OBJDIR)
|
||||||
|
$(CC) $(LIBC_CFLAGS) -c $(LIBC_SRC) -o $@
|
||||||
|
|
||||||
-include $(OBJS:.o=.d)
|
-include $(OBJS:.o=.d)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJDIR) $(TARGET)
|
rm -rf $(OBJDIR) $(TARGET) $(LEGACY_APPDIR)
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
#include <gui/canvas.hpp>
|
#include <gui/canvas.hpp>
|
||||||
#include <montauk/user.h>
|
#include <montauk/user.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <stdio.h>
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <montauk/syscall.h>
|
||||||
#include <gui/gui.hpp>
|
#include <gui/gui.hpp>
|
||||||
#include <gui/dialogs.hpp>
|
#include <gui/dialogs.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* main.cpp
|
* main.cpp
|
||||||
* Shared modal dialogs for MontaukOS desktop apps
|
* libdialogs entry point for shared modal dialogs
|
||||||
* Copyright (c) 2026 Daniel Hammer
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -16,14 +16,11 @@
|
|||||||
#include "filedialog.hpp"
|
#include "filedialog.hpp"
|
||||||
#include "printdialog.hpp"
|
#include "printdialog.hpp"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <stdio.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
namespace dlg = gui::dialogs;
|
namespace dlg = gui::dialogs;
|
||||||
|
|
||||||
AppState g_app = {};
|
AppState g_app = {};
|
||||||
|
static bool g_fonts_ready = false;
|
||||||
|
|
||||||
void dialog_finish(const char* status, const char* path, const char* job_id, const char* message,
|
void dialog_finish(const char* status, const char* path, const char* job_id, const char* message,
|
||||||
const char* printer_uri, const char* printer_name, uint32_t copies) {
|
const char* printer_uri, const char* printer_name, uint32_t copies) {
|
||||||
@@ -34,7 +31,6 @@ void dialog_finish(const char* status, const char* path, const char* job_id, con
|
|||||||
gui::dialogs::safe_copy(g_app.result.printer_name, sizeof(g_app.result.printer_name), printer_name);
|
gui::dialogs::safe_copy(g_app.result.printer_name, sizeof(g_app.result.printer_name), printer_name);
|
||||||
g_app.result.copies = copies;
|
g_app.result.copies = copies;
|
||||||
gui::dialogs::safe_copy(g_app.result.message, sizeof(g_app.result.message), message);
|
gui::dialogs::safe_copy(g_app.result.message, sizeof(g_app.result.message), message);
|
||||||
gui::dialogs::write_result_file(g_app.request.result_path, &g_app.result);
|
|
||||||
g_app.running = false;
|
g_app.running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,17 +47,37 @@ void cleanup() {
|
|||||||
g_app.win.destroy();
|
g_app.win.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void _start() {
|
static void set_error_result(dlg::Result* result, const char* message) {
|
||||||
if (!fonts::init()) montauk::exit(1);
|
if (!result) return;
|
||||||
|
dlg::reset_result(result);
|
||||||
|
dlg::safe_copy(result->status, sizeof(result->status), "error");
|
||||||
|
dlg::safe_copy(result->message, sizeof(result->message), message);
|
||||||
|
}
|
||||||
|
|
||||||
char argbuf[256] = {};
|
extern "C" bool dialogs_run_request(const dlg::Request* request, dlg::Result* out_result) {
|
||||||
if (montauk::getargs(argbuf, sizeof(argbuf)) <= 0 || !argbuf[0]) montauk::exit(1);
|
if (!request || !out_result) return false;
|
||||||
if (!gui::dialogs::read_request_file(argbuf, &g_app.request)) montauk::exit(1);
|
|
||||||
|
|
||||||
|
set_error_result(out_result, "dialog failed");
|
||||||
|
|
||||||
|
if (!g_fonts_ready) {
|
||||||
|
if (!fonts::init()) {
|
||||||
|
set_error_result(out_result, "failed to initialize dialog fonts");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
g_fonts_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->kind != dlg::REQUEST_KIND_FILE && request->kind != dlg::REQUEST_KIND_PRINT) {
|
||||||
|
set_error_result(out_result, "unsupported dialog request");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_app = AppState {};
|
||||||
|
g_app.request = *request;
|
||||||
g_app.running = true;
|
g_app.running = true;
|
||||||
gui::dialogs::reset_result(&g_app.result);
|
dlg::reset_result(&g_app.result);
|
||||||
|
|
||||||
g_app.is_print = g_app.request.kind == gui::dialogs::REQUEST_KIND_PRINT;
|
g_app.is_print = g_app.request.kind == dlg::REQUEST_KIND_PRINT;
|
||||||
const int init_w = g_app.is_print ? printdialog::PRINT_INIT_W : filedialog::FILE_INIT_W;
|
const int init_w = g_app.is_print ? printdialog::PRINT_INIT_W : filedialog::FILE_INIT_W;
|
||||||
const int init_h = g_app.is_print ? printdialog::PRINT_INIT_H : filedialog::FILE_INIT_H;
|
const int init_h = g_app.is_print ? printdialog::PRINT_INIT_H : filedialog::FILE_INIT_H;
|
||||||
const char* title = g_app.request.title[0] ? g_app.request.title : (g_app.is_print ? "Print" : "Open");
|
const char* title = g_app.request.title[0] ? g_app.request.title : (g_app.is_print ? "Print" : "Open");
|
||||||
@@ -69,7 +85,11 @@ extern "C" void _start() {
|
|||||||
if (g_app.is_print) printdialog::init(g_app.request);
|
if (g_app.is_print) printdialog::init(g_app.request);
|
||||||
else filedialog::init(g_app.request);
|
else filedialog::init(g_app.request);
|
||||||
|
|
||||||
if (!g_app.win.create(title, init_w, init_h)) montauk::exit(1);
|
if (!g_app.win.create(title, init_w, init_h)) {
|
||||||
|
cleanup();
|
||||||
|
set_error_result(out_result, "failed to create dialog window");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_app.is_print) printdialog::draw();
|
if (g_app.is_print) printdialog::draw();
|
||||||
else filedialog::draw();
|
else filedialog::draw();
|
||||||
@@ -113,5 +133,6 @@ extern "C" void _start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
montauk::exit(0);
|
*out_result = g_app.result;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[app]
|
|
||||||
name = "Dialogs"
|
|
||||||
binary = "dialogs.elf"
|
|
||||||
icon = "system-file-manager.svg"
|
|
||||||
|
|
||||||
[menu]
|
|
||||||
category = "System"
|
|
||||||
visible = false
|
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <montauk/syscall.h>
|
||||||
#include <gui/gui.hpp>
|
#include <gui/gui.hpp>
|
||||||
#include <gui/dialogs.hpp>
|
#include <gui/dialogs.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ static constexpr uint32_t SHT_SYMTAB = 2;
|
|||||||
static constexpr uint32_t SHT_STRTAB = 3;
|
static constexpr uint32_t SHT_STRTAB = 3;
|
||||||
static constexpr uint32_t SHT_DYNSYM = 11;
|
static constexpr uint32_t SHT_DYNSYM = 11;
|
||||||
static constexpr uint16_t SHN_UNDEF = 0;
|
static constexpr uint16_t SHN_UNDEF = 0;
|
||||||
|
static constexpr uint64_t kMaxSymbolLookupFileSize = 8ull * 1024ull * 1024ull;
|
||||||
|
|
||||||
static bool readFile(const char* path, uint8_t** outBuf, uint64_t* outSize) {
|
static bool readFile(const char* path, uint8_t** outBuf, uint64_t* outSize) {
|
||||||
*outBuf = nullptr;
|
*outBuf = nullptr;
|
||||||
@@ -71,7 +72,7 @@ static bool readFile(const char* path, uint8_t** outBuf, uint64_t* outSize) {
|
|||||||
if (fd < 0) return false;
|
if (fd < 0) return false;
|
||||||
|
|
||||||
uint64_t size = montauk::getsize(fd);
|
uint64_t size = montauk::getsize(fd);
|
||||||
if (size < sizeof(Elf64Header) || size > (1 << 20)) {
|
if (size < sizeof(Elf64Header) || size > kMaxSymbolLookupFileSize) {
|
||||||
montauk::close(fd);
|
montauk::close(fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,14 +69,15 @@ OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
|||||||
# ---- Target ----
|
# ---- Target ----
|
||||||
|
|
||||||
TARGET := $(BINDIR)/apps/pdfviewer/pdfviewer.elf
|
TARGET := $(BINDIR)/apps/pdfviewer/pdfviewer.elf
|
||||||
|
LOADER_LIB := $(BINDIR)/liblibloader.a
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB)
|
||||||
mkdir -p $(BINDIR)/apps/pdfviewer
|
mkdir -p $(BINDIR)/apps/pdfviewer
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
HEADERS := pdfviewer.h
|
HEADERS := pdfviewer.h
|
||||||
|
|
||||||
|
|||||||
@@ -69,14 +69,15 @@ OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
|||||||
# ---- Target ----
|
# ---- Target ----
|
||||||
|
|
||||||
TARGET := $(BINDIR)/apps/spreadsheet/spreadsheet.elf
|
TARGET := $(BINDIR)/apps/spreadsheet/spreadsheet.elf
|
||||||
|
LOADER_LIB := $(BINDIR)/liblibloader.a
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB)
|
||||||
mkdir -p $(BINDIR)/apps/spreadsheet
|
mkdir -p $(BINDIR)/apps/spreadsheet
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp Makefile
|
$(OBJDIR)/%.o: %.cpp Makefile
|
||||||
mkdir -p $(OBJDIR)
|
mkdir -p $(OBJDIR)
|
||||||
|
|||||||
@@ -69,14 +69,15 @@ OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
|||||||
# ---- Target ----
|
# ---- Target ----
|
||||||
|
|
||||||
TARGET := $(BINDIR)/apps/texteditor/texteditor.elf
|
TARGET := $(BINDIR)/apps/texteditor/texteditor.elf
|
||||||
|
LOADER_LIB := $(BINDIR)/liblibloader.a
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile $(LOADER_LIB)
|
||||||
mkdir -p $(BINDIR)/apps/texteditor
|
mkdir -p $(BINDIR)/apps/texteditor
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LOADER_LIB) $(LIBDIR)/libc/liblibc.a -o $@
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp Makefile
|
$(OBJDIR)/%.o: %.cpp Makefile
|
||||||
mkdir -p $(OBJDIR)
|
mkdir -p $(OBJDIR)
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ LDFLAGS := \
|
|||||||
|
|
||||||
SRCS := main.cpp document.cpp render.cpp input.cpp print_export.cpp stb_truetype_impl.cpp
|
SRCS := main.cpp document.cpp render.cpp input.cpp print_export.cpp stb_truetype_impl.cpp
|
||||||
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||||
LIBS := $(LIBDIR)/tls/libtls.a $(LIBDIR)/bearssl/libbearssl.a $(LIBDIR)/libjpegwrite/libjpegwrite.a $(LIBDIR)/libc/liblibc.a
|
LOADER_LIB := $(BINDIR)/liblibloader.a
|
||||||
|
LIBS := $(LOADER_LIB) $(LIBDIR)/tls/libtls.a $(LIBDIR)/bearssl/libbearssl.a $(LIBDIR)/libjpegwrite/libjpegwrite.a $(LIBDIR)/libc/liblibc.a
|
||||||
|
|
||||||
TARGET := $(BINDIR)/apps/wordprocessor/wordprocessor.elf
|
TARGET := $(BINDIR)/apps/wordprocessor/wordprocessor.elf
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ APPS=(
|
|||||||
"procmgr|apps/scalable/system-monitor.svg"
|
"procmgr|apps/scalable/system-monitor.svg"
|
||||||
"calculator|apps/scalable/accessories-calculator.svg"
|
"calculator|apps/scalable/accessories-calculator.svg"
|
||||||
"printers|devices/scalable/preferences-devices-printer.svg"
|
"printers|devices/scalable/preferences-devices-printer.svg"
|
||||||
"dialogs|apps/scalable/system-file-manager.svg"
|
|
||||||
"rpgdemo|apps/scalable/utilities-terminal.svg"
|
"rpgdemo|apps/scalable/utilities-terminal.svg"
|
||||||
"paint|apps/scalable/kolourpaint.svg"
|
"paint|apps/scalable/kolourpaint.svg"
|
||||||
"screenshot|apps/scalable/gnome-screenshot.svg"
|
"screenshot|apps/scalable/gnome-screenshot.svg"
|
||||||
@@ -74,6 +73,8 @@ for entry in "${APPS[@]}"; do
|
|||||||
installed=$((installed + 1))
|
installed=$((installed + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
|
rm -rf "$BIN/apps/dialogs"
|
||||||
|
|
||||||
# Special case: copy doom1.wad alongside doom binary
|
# Special case: copy doom1.wad alongside doom binary
|
||||||
if [ -f "$PROJECT_ROOT/programs/data/games/doom1.wad" ]; then
|
if [ -f "$PROJECT_ROOT/programs/data/games/doom1.wad" ]; then
|
||||||
cp "$PROJECT_ROOT/programs/data/games/doom1.wad" "$BIN/apps/doom/doom1.wad"
|
cp "$PROJECT_ROOT/programs/data/games/doom1.wad" "$BIN/apps/doom/doom1.wad"
|
||||||
|
|||||||
Reference in New Issue
Block a user