Files
MontaukOS/programs/src/spreadsheet/spreadsheet.h
T

299 lines
9.4 KiB
C++

/*
* spreadsheet.h
* Shared header for the MontaukOS spreadsheet app
* Copyright (c) 2026 Daniel Hammer
*/
#pragma once
#include <montauk/syscall.h>
#include <montauk/string.h>
#include <montauk/heap.h>
#include <gui/gui.hpp>
#include <gui/truetype.hpp>
#include <gui/stb_math.h>
#include <gui/svg.hpp>
extern "C" {
#include <string.h>
#include <stdio.h>
}
using namespace gui;
// ============================================================================
// Constants
// ============================================================================
static constexpr int INIT_W = 900;
static constexpr int INIT_H = 600;
static constexpr int TOOLBAR_H = 36;
static constexpr int FORMULA_BAR_H = 36;
static constexpr int COL_HEADER_H = 28;
static constexpr int ROW_HEADER_W = 48;
static constexpr int STATUS_BAR_H = 24;
static constexpr int SCROLL_STEP = 50;
static constexpr int TB_BTN_SIZE = 24;
static constexpr int TB_BTN_Y = 6;
static constexpr int TB_BTN_RAD = 3;
static constexpr int MAX_COLS = 26; // A-Z
static constexpr int MAX_ROWS = 100;
static constexpr int DEF_COL_W = 100;
static constexpr int MIN_COL_W = 30;
static constexpr int ROW_H = 26;
static constexpr int COL_RESIZE_GRAB = 5; // pixels from border edge for grab zone
static constexpr int FILL_HANDLE_SIZE = 6;
static constexpr int AC_MAX_MATCHES = 8;
static constexpr int DBLCLICK_MS = 400;
static constexpr int CELL_TEXT_MAX = 128;
static constexpr int FONT_SIZE = 18;
static constexpr int HEADER_FONT = 16;
static constexpr Color BG_COLOR = Color::from_rgb(0xFF, 0xFF, 0xFF);
static constexpr Color GRID_COLOR = Color::from_rgb(0xD0, 0xD0, 0xD0);
static constexpr Color HEADER_BG = Color::from_rgb(0xF0, 0xF0, 0xF0);
static constexpr Color HEADER_TEXT = Color::from_rgb(0x55, 0x55, 0x55);
static constexpr Color CELL_TEXT = Color::from_rgb(0x22, 0x22, 0x22);
static constexpr Color SELECT_BORDER = Color::from_rgb(0x36, 0x7B, 0xF0);
static constexpr Color SELECT_FILL = Color::from_rgb(0xD8, 0xE8, 0xFD);
static constexpr Color FORMULA_BG = Color::from_rgb(0xFF, 0xFF, 0xFF);
static constexpr Color FORMULA_BORDER = Color::from_rgb(0xCC, 0xCC, 0xCC);
static constexpr Color STATUS_BG = Color::from_rgb(0x2B, 0x3E, 0x50);
static constexpr Color STATUS_TEXT = Color::from_rgb(0xFF, 0xFF, 0xFF);
static constexpr Color NUM_COLOR = Color::from_rgb(0x10, 0x50, 0x90);
static constexpr Color ERR_COLOR = Color::from_rgb(0xCC, 0x22, 0x22);
static constexpr Color TOOLBAR_BG = Color::from_rgb(0xF5, 0xF5, 0xF5);
static constexpr Color TB_BTN_BG = Color::from_rgb(0xE8, 0xE8, 0xE8);
static constexpr Color TB_BTN_ACTIVE = Color::from_rgb(0xC0, 0xD0, 0xE8);
static constexpr Color TB_SEP_COLOR = Color::from_rgb(0xCC, 0xCC, 0xCC);
// ============================================================================
// Types
// ============================================================================
enum CellAlign : uint8_t { ALIGN_AUTO = 0, ALIGN_LEFT = 1, ALIGN_CENTER = 2, ALIGN_RIGHT = 3 };
enum NumFormat : uint8_t { FMT_AUTO = 0, FMT_DECIMAL = 1, FMT_CURRENCY = 2, FMT_PERCENT = 3 };
enum CellType : uint8_t {
CT_EMPTY = 0,
CT_TEXT = 1,
CT_NUMBER = 2,
CT_FORMULA = 3,
CT_ERROR = 4,
};
struct Cell {
char input[CELL_TEXT_MAX]; // raw user input
char display[CELL_TEXT_MAX]; // computed display string
double value; // numeric value (for formulas/numbers)
CellType type;
CellAlign align;
NumFormat fmt;
bool bold;
};
static constexpr int CLIP_MAX_CELLS = 256;
struct ClipCell {
char text[CELL_TEXT_MAX];
int rel_col;
int rel_row;
CellAlign align;
NumFormat fmt;
bool bold;
};
static constexpr int UNDO_MAX = 6;
struct UndoCellData {
char input[CELL_TEXT_MAX];
CellAlign align;
NumFormat fmt;
bool bold;
};
struct UndoEntry {
UndoCellData cells[MAX_ROWS][MAX_COLS];
};
static constexpr int PATHBAR_H = 32;
// ============================================================================
// Toolbar button IDs (must match handle_toolbar_click and render order)
// ============================================================================
enum ToolBtnId {
TB_OPEN,
TB_SAVE,
TB_CUT,
TB_COPY,
TB_PASTE,
TB_BOLD,
TB_AL,
TB_AC,
TB_AR,
TB_FMT,
TB_UNDO,
TB_REDO,
TB_COUNT
};
int tb_btn_x0(ToolBtnId id);
int tb_btn_x1(ToolBtnId id);
// ============================================================================
// Global state (extern — defined in main.cpp)
// ============================================================================
extern int g_win_w, g_win_h;
extern Cell g_cells[MAX_ROWS][MAX_COLS];
extern int g_sel_col, g_sel_row;
extern int g_scroll_x, g_scroll_y;
extern int g_col_widths[MAX_COLS];
extern bool g_editing;
extern char g_edit_buf[CELL_TEXT_MAX];
extern int g_edit_len;
extern int g_edit_cursor;
extern bool g_has_selection;
extern int g_anchor_col, g_anchor_row;
extern ClipCell g_clipboard[CLIP_MAX_CELLS];
extern int g_clip_count;
extern int g_clip_cols, g_clip_rows;
extern char g_filepath[256];
extern bool g_modified;
extern bool g_pathbar_open;
extern bool g_pathbar_save;
extern char g_pathbar_text[256];
extern int g_pathbar_len;
extern int g_pathbar_cursor;
extern TrueTypeFont* g_font;
extern TrueTypeFont* g_font_bold;
extern bool g_fmt_dropdown_open;
extern bool g_col_resizing;
extern int g_col_resize_idx;
extern int g_col_resize_start_x;
extern int g_col_resize_start_w;
extern UndoEntry* g_undo[UNDO_MAX + 1];
extern int g_undo_count;
extern int g_undo_pos;
// Formula autocomplete
extern bool g_ac_open;
extern int g_ac_sel;
extern int g_ac_count;
extern char g_ac_matches[AC_MAX_MATCHES][16];
extern char g_ac_hints[AC_MAX_MATCHES][32];
// Fill handle
extern bool g_fill_dragging;
extern int g_fill_target_row;
// Mouse drag selection
extern bool g_mouse_selecting;
// Double-click detection
extern uint64_t g_last_click_ms;
extern int g_last_click_col;
extern int g_last_click_row;
// ============================================================================
// Function declarations — helpers.cpp
// ============================================================================
void px_fill(uint32_t* px, int bw, int bh, int x, int y, int w, int h, Color c);
void px_hline(uint32_t* px, int bw, int bh, int x, int y, int w, Color c);
void px_vline(uint32_t* px, int bw, int bh, int x, int y, int h, Color c);
void px_rect(uint32_t* px, int bw, int bh, int x, int y, int w, int h, Color c);
void px_fill_rounded(uint32_t* px, int bw, int bh, int x, int y, int w, int h, int r, Color c);
int str_len(const char* s);
void str_cpy(char* dst, const char* src, int max);
bool is_digit(char c);
bool is_alpha(char c);
char to_upper(char c);
double str_to_double(const char* s, bool* ok);
void double_to_str(char* buf, int max, double v);
bool str_is_int(const char* s);
int str_to_int(const char* s);
void int_to_str(char* dst, int max, int v);
// ============================================================================
// Function declarations — formula.cpp
// ============================================================================
void eval_cell(int col, int row);
void eval_all_cells();
int col_x(int col);
int content_width();
int content_height();
void cell_name(char* buf, int col, int row);
void format_value(char* buf, int max, double val, NumFormat fmt);
void update_autocomplete();
void accept_autocomplete();
void adjust_formula_refs(const char* src, char* dst, int max, int dcol, int drow);
// ============================================================================
// Function declarations — fileio.cpp
// ============================================================================
void save_file();
void load_file(const char* path);
// ============================================================================
// Function declarations — edit.cpp
// ============================================================================
void undo_push();
void undo_do();
void redo_do();
void start_editing();
void commit_edit();
void cancel_edit();
void sel_range(int* c0, int* r0, int* c1, int* r1);
void clear_selection();
void copy_selection();
void cut_selection();
void paste_at_cursor();
void apply_bold_toggle();
void apply_align(CellAlign a);
void apply_format(NumFormat f);
void clamp_scroll();
void ensure_sel_visible();
void fill_down(int src_r0, int src_c0, int src_r1, int src_c1, int dst_r1);
void auto_fit_column(int col);
// ============================================================================
// Function declarations — render.cpp
// ============================================================================
void render(uint32_t* pixels);
// ============================================================================
// Icons
// ============================================================================
extern SvgIcon g_icon_folder;
extern SvgIcon g_icon_save;
extern SvgIcon g_icon_cut;
extern SvgIcon g_icon_copy;
extern SvgIcon g_icon_paste;
void ss_load_icons();
void ss_unload_icons();
// ============================================================================
// Function declarations — main.cpp
// ============================================================================
bool hit_cell(int mx, int my, int* out_col, int* out_row);
bool hit_fill_handle(int mx, int my);
bool handle_toolbar_click(int mx, int my);
bool handle_fmt_dropdown_click(int mx, int my);