/* * main.cpp * libdialogs entry point for shared modal dialogs * Copyright (c) 2026 Daniel Hammer */ #include #include #include #include #include #include #include #include "main.hpp" #include "filedialog.hpp" #include "printdialog.hpp" #include "messagebox.hpp" using namespace gui; namespace dlg = gui::dialogs; 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, const char* printer_uri, const char* printer_name, uint32_t copies) { gui::dialogs::safe_copy(g_app.result.status, sizeof(g_app.result.status), status); gui::dialogs::safe_copy(g_app.result.path, sizeof(g_app.result.path), path); gui::dialogs::safe_copy(g_app.result.job_id, sizeof(g_app.result.job_id), job_id); gui::dialogs::safe_copy(g_app.result.printer_uri, sizeof(g_app.result.printer_uri), printer_uri); gui::dialogs::safe_copy(g_app.result.printer_name, sizeof(g_app.result.printer_name), printer_name); g_app.result.copies = copies; gui::dialogs::safe_copy(g_app.result.message, sizeof(g_app.result.message), message); g_app.running = false; } void dialog_cancel(const char* message) { dialog_finish("cancel", "", "", message, "", "", 0); } void cleanup() { if (g_app.is_print) { printdialog::cleanup(); } else if (g_app.is_message) { messagebox::cleanup(); } else { filedialog::cleanup(); } g_app.win.destroy(); } static void set_error_result(dlg::Result* result, const char* message) { 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); } static bool ensure_fonts(dlg::Result* result) { if (g_fonts_ready) return true; if (!fonts::init()) { if (result) set_error_result(result, "failed to initialize dialog fonts"); return false; } g_fonts_ready = true; return true; } extern "C" bool dialogs_run_request(const dlg::Request* request, dlg::Result* out_result) { if (!request || !out_result) return false; set_error_result(out_result, "dialog failed"); if (!ensure_fonts(out_result)) return 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; dlg::reset_result(&g_app.result); g_app.is_print = g_app.request.kind == dlg::REQUEST_KIND_PRINT; int init_w = filedialog::FILE_INIT_W; int init_h = filedialog::FILE_INIT_H; if (g_app.is_print) { init_w = printdialog::PRINT_INIT_W; init_h = printdialog::PRINT_INIT_H; } const char* default_title = g_app.is_print ? "Print" : "Open"; const char* title = g_app.request.title[0] ? g_app.request.title : default_title; if (g_app.is_print) printdialog::init(g_app.request); else filedialog::init(g_app.request); 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(); else filedialog::draw(); g_app.win.present(); while (g_app.running) { if (g_app.is_print) printdialog::draw(); else filedialog::draw(); g_app.win.present(); Montauk::WinEvent ev; int rc = g_app.win.poll(&ev); if (rc < 0) { dialog_cancel(""); break; } if (rc == 0) { montauk::sleep_ms(16); continue; } if (ev.type == 3) { dialog_cancel(""); break; } if (ev.type == 2 || ev.type == 4) { continue; } if (ev.type == 1) { if (g_app.is_print) printdialog::handle_mouse(ev); else filedialog::handle_mouse(ev); continue; } if (ev.type == 0) { if (g_app.is_print) printdialog::handle_key(ev.key); else filedialog::handle_key(ev.key); } } cleanup(); *out_result = g_app.result; return true; } extern "C" uint8_t dialogs_message_box(const char* title, const char* message, uint8_t buttons) { if (!ensure_fonts(nullptr)) return dlg::MESSAGE_BOX_RESULT_NONE; g_app = AppState {}; g_app.running = true; g_app.is_message = true; const char* window_title = title && title[0] ? title : "Message"; messagebox::init(message ? message : "", buttons); int init_w = 0; int init_h = 0; messagebox::preferred_size(window_title, &init_w, &init_h); if (!g_app.win.create(window_title, init_w, init_h)) { cleanup(); return dlg::MESSAGE_BOX_RESULT_NONE; } messagebox::draw(); g_app.win.present(); while (g_app.running) { messagebox::draw(); g_app.win.present(); Montauk::WinEvent ev; int rc = g_app.win.poll(&ev); if (rc < 0) { messagebox::dismiss(); break; } if (rc == 0) { montauk::sleep_ms(16); continue; } if (ev.type == 3) { messagebox::dismiss(); break; } if (ev.type == 2 || ev.type == 4) { continue; } if (ev.type == 1) { messagebox::handle_mouse(ev); continue; } if (ev.type == 0) { messagebox::handle_key(ev.key); } } uint8_t choice = messagebox::selected_choice(); cleanup(); return choice ? choice : (uint8_t)dlg::MESSAGE_BOX_RESULT_NONE; }