aboutsummaryrefslogtreecommitdiffstats
path: root/src/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/screen.c')
-rw-r--r--src/screen.c229
1 files changed, 0 insertions, 229 deletions
diff --git a/src/screen.c b/src/screen.c
deleted file mode 100644
index fdecaf4..0000000
--- a/src/screen.c
+++ /dev/null
@@ -1,229 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-#include "vega.h"
-#include "module-text.h"
-#include <math.h>
-#include <string.h>
-#include <time.h>
-
-double vega_now(void) {
- struct timespec t;
- clock_gettime(CLOCK_REALTIME, &t);
- return floor((double)t.tv_sec * 1000 + (double)t.tv_nsec / 1e6);
-}
-
-void vega_timers_start(VegaTimers *timers, const PureModule *m, double now) {
- for (uint32_t i = 0; i < m->inputs; ++i)
- timers->next[i] = m->input[i].kind == PURE_KIND_TIMER ? now + m->input[i].period : 0;
-}
-
-long vega_timers_run(VegaTimers *timers, PureApp *app, double now, bool *ticked) {
- const PureModule *m = app->module;
- double soonest = -1;
- for (uint32_t i = 0; i < m->inputs; ++i) {
- if (m->input[i].kind != PURE_KIND_TIMER) continue;
- if (timers->next[i] <= now) {
- app->now = now;
- pure_app_tick(app, i); /* a failed tick changes nothing, as any failed event */
- *ticked = true;
- timers->next[i] = now + m->input[i].period;
- }
- if (soonest < 0 || timers->next[i] - now < soonest) soonest = timers->next[i] - now;
- }
- return soonest < 0 ? -1 : (long)ceil(soonest);
-}
-
-static unsigned long evaluations;
-
-unsigned long vega_evaluations(void) { return evaluations; }
-
-static int column(const PureModule *m, uint32_t table, const char *name, uint8_t type) {
- int view = pure_module_column(m, table, name);
- return view >= 0 && m->view_type[view] == type ? view : -1;
-}
-
-void vega_screen(VegaScreen *screen, const PureModule *m) {
- memset(screen, 0, sizeof(*screen));
- screen->module = m;
- screen->title = pure_module_view(m, "title");
- if (screen->title >= 0 && m->view_type[screen->title] != PURE_VIEW_TEXT) screen->title = -1;
- screen->prompt = -1;
- for (uint32_t i = 0; i < m->inputs && screen->prompt < 0; ++i)
- if (m->input[i].kind == PURE_KIND_TEXT) screen->prompt = (int)i;
- for (uint32_t h = 0; h < m->handlers; ++h) screen->ticks = screen->ticks || m->handler[h].event == 0;
- /* A <table>_focus view belongs to its table, not to the fields. */
- bool focus_view[PURE_MODULE_VIEWS] = {false};
- for (uint32_t i = 0; i < m->views; ++i) {
- if (m->view_type[i] != PURE_VIEW_TABLE) continue;
- char name[PURE_MODULE_NAME + 8];
- snprintf(name, sizeof(name), "%s_focus", m->view_names[i]);
- int focus = pure_module_view(m, name);
- if (focus >= 0 && m->view_type[focus] == PURE_VIEW_NUM) focus_view[focus] = true;
- }
- for (uint32_t i = 0; i < m->views && screen->count < VEGA_PARTS; ++i) {
- if (m->view_table[i] || (int)i == screen->title || focus_view[i]) continue;
- VegaPart *part = &screen->parts[screen->count++];
- *part = (VegaPart){.kind = VEGA_FIELD, .view = i, .focus = -1, .pointer = -1, .label = -1, .tone = -1, .detail = -1,
- .badge = -1};
- if (m->view_type[i] != PURE_VIEW_TABLE) continue;
- char name[PURE_MODULE_NAME + 8];
- snprintf(name, sizeof(name), "%s_focus", m->view_names[i]);
- part->focus = pure_module_view(m, name);
- if (part->focus >= 0 && !focus_view[part->focus]) part->focus = -1;
- part->pointer = part->focus >= 0 ? pure_module_position(m, (uint32_t)part->focus) : -1;
- part->label = column(m, i, "label", PURE_VIEW_TEXT);
- part->tone = column(m, i, "tone", PURE_VIEW_NUM);
- part->kind = part->label >= 0 ? VEGA_LIST : VEGA_TABLE;
- if (part->kind == VEGA_LIST) {
- part->detail = column(m, i, "detail", PURE_VIEW_TEXT);
- part->badge = column(m, i, "badge", PURE_VIEW_TEXT);
- }
- for (uint32_t k = 0; k < m->views; ++k)
- if (m->view_table[k] == i + 1 && (int)k != part->tone) part->columns[part->column_count++] = k;
- }
-}
-
-static bool is_view(const PureModule *m, int view, uint8_t type) {
- return view >= 0 && m->view_type[view] == type;
-}
-
-unsigned vega_check(const PureModule *m, void (*report)(void *, const char *name, const char *message), void *context) {
- unsigned found = 0;
- char name[2 * PURE_MODULE_NAME + 8], message[256];
-#define FIND(...) do { snprintf(message, sizeof(message), __VA_ARGS__); report(context, name, message); ++found; } while (0)
- int title = pure_module_view(m, "title");
- snprintf(name, sizeof(name), "title");
- if (title >= 0 && m->view_type[title] != PURE_VIEW_TEXT) FIND("a title is text; this one shows as a field");
- for (uint32_t i = 0; i < m->views; ++i) {
- if (m->view_table[i]) continue;
- const char *view = m->view_names[i];
- size_t length = strlen(view);
- snprintf(name, sizeof(name), "%s", view);
- if (length > 6 && !strcmp(view + length - 6, "_focus")) {
- char table[PURE_MODULE_NAME];
- snprintf(table, sizeof(table), "%.*s", (int)(length - 6), view);
- int owner = pure_module_view(m, table);
- if (!is_view(m, owner, PURE_VIEW_TABLE))
- FIND("names no list or table %s; it shows as a field", table);
- else if (m->view_type[i] != PURE_VIEW_NUM) FIND("the focused row is a number; %s shows no focus", table);
- }
- if (m->view_type[i] != PURE_VIEW_TABLE) continue;
- int label = pure_module_column(m, i, "label"), tone = pure_module_column(m, i, "tone");
- bool list = is_view(m, label, PURE_VIEW_TEXT);
- unsigned shown = 0;
- for (uint32_t k = 0; k < m->views; ++k) {
- if (m->view_table[k] != i + 1) continue;
- const char *column = m->view_names[k];
- bool text = m->view_type[k] == PURE_VIEW_TEXT;
- snprintf(name, sizeof(name), "%s.%s", view, column);
- if ((int)k == label && !text) FIND("a list's label is text; %s shows as a table", view);
- else if ((int)k == tone && text) FIND("a tone is a number (vega.normal ... vega.danger); %s", list ?
- "the list ignores it" : "it shows as a column");
- else if (list && (!strcmp(column, "badge") || !strcmp(column, "detail")) && !text)
- FIND("a list's %s is text; this one is not shown", column);
- else if (list && (int)k != label && (int)k != tone && strcmp(column, "badge") && strcmp(column, "detail"))
- FIND("a list shows label, badge, detail and tone; this column is not shown");
- shown += (int)k != tone || text;
- }
- snprintf(name, sizeof(name), "%s", view);
- if (!list && !shown) FIND("a table with no column to show");
- }
- int prompt = -1;
- for (uint32_t i = 0; i < m->inputs; ++i) {
- if (m->input[i].kind != PURE_KIND_TEXT) continue;
- snprintf(name, sizeof(name), "%s", m->input_names[i]);
- if (prompt >= 0) FIND("only the first text input (%s) has a place to type into", m->input_names[prompt]);
- else prompt = (int)i;
- }
-#undef FIND
- return found;
-}
-
-typedef struct { char *out; size_t used; } Collect;
-
-static bool collect(void *context, PureSpan span) {
- Collect *c = context;
- size_t room = VEGA_TEXT - 1 - c->used;
- size_t take = span.size < room ? span.size : room;
- /* Never cut a character: back off to a UTF-8 boundary. */
- if (take < span.size) while (take && (span.data[take] & 0xC0) == 0x80) --take;
- if (take) memcpy(c->out + c->used, span.data, take);
- c->used += take;
- return true;
-}
-
-bool vega_text(PureApp *app, uint32_t view, size_t row, char out[VEGA_TEXT], size_t *length) {
- const PureModule *m = app->module;
- bool column = m->view_table[view] != 0;
- ++evaluations;
- *length = 0;
- out[0] = 0;
- if (m->view_type[view] == PURE_VIEW_NUM) {
- double value;
- if (!(column ? pure_app_cell(app, view, row, &value) : pure_app_view(app, view, &value))) return false;
- *length = pure_format_number(value, out);
- out[*length] = 0;
- return true;
- }
- Collect c = {out, 0};
- PureResult result = column ? pure_app_cell_text(app, view, row, collect, &c) : pure_app_view_text(app, view, collect, &c);
- out[c.used] = 0;
- *length = c.used;
- return result == PURE_OK;
-}
-
-bool vega_number(PureApp *app, uint32_t view, size_t row, double *out) {
- ++evaluations;
- return app->module->view_table[view] ? pure_app_cell(app, view, row, out) : pure_app_view(app, view, out);
-}
-
-size_t vega_rows(PureApp *app, const VegaPart *part) {
- return part->kind == VEGA_FIELD ? 0 : pure_app_rows(app, part->view);
-}
-
-size_t vega_focus(PureApp *app, const VegaPart *part) {
- size_t rows = vega_rows(app, part), row;
- double focus;
- if (part->focus < 0 || !rows || !vega_number(app, (uint32_t)part->focus, 0, &focus) || !(focus >= 0)) return 0;
- bool filtered = app->module->view_code[part->view].length > 0;
- size_t item = focus < (double)SIZE_MAX ? (size_t)focus : SIZE_MAX;
- if (pure_app_item_row(app, part->view, item, &row)) return row;
- return filtered ? VEGA_NO_ROW : rows - 1;
-}
-
-size_t vega_scroll(size_t first, size_t focus, size_t visible, size_t rows) {
- if (focus < rows && focus < first) first = focus;
- if (focus < rows && visible && focus >= first + visible) first = focus - visible + 1;
- if (first + visible > rows) first = rows > visible ? rows - visible : 0;
- return first;
-}
-
-int vega_key_input(const PureModule *m, const char *key) {
- for (uint32_t i = 0; i < m->inputs; ++i)
- if (m->input[i].kind == PURE_KIND_KEY && !strcmp(m->input_keys[i], key)) return (int)i;
- return -1;
-}
-
-bool vega_press(PureApp *app, const char *key) {
- int input = vega_key_input(app->module, key);
- if (input < 0) return false;
- bool ok = pure_app_input(app, (uint32_t)input, PURE_EDGE_DOWN) == PURE_OK;
- pure_app_input(app, (uint32_t)input, PURE_EDGE_UP);
- return ok;
-}
-
-bool vega_commit(PureApp *app, const VegaScreen *screen, const char *text, size_t length) {
- return screen->prompt >= 0 &&
- pure_app_text(app, (uint32_t)screen->prompt, (PureSpan){(const unsigned char *)text, length}) == PURE_OK;
-}
-
-bool vega_point(PureApp *app, const VegaPart *part, size_t row) {
- size_t item; /* a filtered list's row shows some item of the list */
- return part->pointer >= 0 && pure_app_row_item(app, part->view, row, &item) &&
- pure_app_point(app, (uint32_t)part->pointer, item) == PURE_OK;
-}
-
-VegaTone vega_tone(PureApp *app, const VegaPart *part, size_t row) {
- double tone;
- if (part->tone < 0 || !vega_number(app, (uint32_t)part->tone, row, &tone)) return VEGA_NORMAL;
- return tone >= 0 && tone < VEGA_TONES && tone == floor(tone) ? (VegaTone)tone : VEGA_NORMAL;
-}