summaryrefslogtreecommitdiff
path: root/src/user/settings/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/settings/main.cpp')
-rw-r--r--src/user/settings/main.cpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/user/settings/main.cpp b/src/user/settings/main.cpp
new file mode 100644
index 0000000..2045137
--- /dev/null
+++ b/src/user/settings/main.cpp
@@ -0,0 +1,191 @@
+#include <raleigh/d/saving_window.h>
+#include <raleigh/w/padding.h>
+#include <raleigh/w/button.h>
+#include <raleigh/w/label.h>
+#include <raleigh/w/vbox.h>
+#include <structs/map.h>
+#include <knob/format.h>
+#include <knob/file.h>
+#include <stdint.h>
+
+#include "color_editor.h"
+#include "str_editor.h"
+#include "model.h"
+
+struct file_header {
+ uint32_t main_offset;
+ uint32_t main_entries;
+ uint32_t names_offset;
+ uint32_t data_offset;
+} __attribute__ ((packed));
+
+struct main_entry {
+ uint32_t name_offset;
+ uint8_t name_len;
+ enum : uint8_t {
+ STRING = 0,
+ COLOR
+ } kind;
+ uint16_t pad;
+ union {
+ struct {
+ uint32_t data_offset;
+ uint32_t data_len;
+ } as_string;
+ _pixel_t as_color;
+ };
+} __attribute__ ((packed));
+
+#define SETTINGS_FILE "sys/settings.pls"
+
+using namespace raleigh;
+
+bool save(save_tag_t) {
+ struct file *f = open_file(SETTINGS_FILE);
+ struct file_header fh;
+ fh.main_offset = sizeof(struct file_header);
+ fh.main_entries = settings.n_entries;
+ fh.names_offset = fh.main_offset + sizeof(struct main_entry) * settings.n_entries;
+
+ uint32_t name_i = 0;
+ uint32_t data_i = 0;
+ seek_file_to(f, sizeof(struct file_header));
+ struct main_entry me;
+
+ for (struct setting *i = settings.buf; i < settings.buf + settings.n_entries; ++i) {
+ me.name_offset = name_i;
+ me.name_len = strlen(i->name);
+ name_i += me.name_len;
+
+ switch (i->kind) {
+ case setting::STRING:
+ me.kind = main_entry::STRING;
+ me.as_string.data_offset = data_i;
+ me.as_string.data_len = strlen(i->data.string);
+ data_i += me.as_string.data_len;
+ break;
+ case setting::COLOR:
+ me.kind = main_entry::COLOR;
+ me.as_color = i->data.color;
+ break;
+ }
+
+ write_to_file(f, sizeof(struct main_entry), &me);
+ }
+
+ seek_file_to(f, fh.names_offset);
+ for (struct setting *i = settings.buf; i < settings.buf + settings.n_entries; ++i)
+ write_to_file(f, strlen(i->name), (void *)i->name);
+
+ fh.data_offset = get_file_pos(f);
+ for (struct setting *i = settings.buf; i < settings.buf + settings.n_entries; ++i)
+ switch (i->kind) {
+ case setting::STRING:
+ write_to_file(f, strlen(i->data.string), (void *)i->data.string);
+ break;
+ default:
+ break;
+ }
+
+ trunc_file(f);
+ seek_file_to(f, 0);
+ write_to_file(f, sizeof(struct file_header), &fh);
+ close_file(f);
+
+ main_w->is_saved = true;
+ return true;
+}
+
+void on_button_click(button_tag_t n) {
+ struct setting *const s = settings.buf + (uint32_t)n;
+ editor *e;
+ switch (s->kind) {
+ case setting::STRING:
+ e = new str_editor(s, s->name);
+ break;
+ case setting::COLOR:
+ e = new color_editor(s, s->name);
+ break;
+ default:
+ show_error_and_quitf("Internal model corrupted: setting %s had type 0x%2x.", s->name, s->kind);
+ }
+ e->show();
+}
+
+button *make_button(uint32_t i) {
+ label *l = new label(settings.buf[i].name);
+ padding *p = new padding(*l, 2);
+ return new button(*p, &on_button_click, (button_tag_t)i);
+}
+
+void main() {
+ struct file *f = open_file(SETTINGS_FILE);
+
+ struct file_header file_head;
+ read_from_file(f, sizeof(struct file_header), &file_head);
+
+ settings = alist<struct setting>(file_head.main_entries + 10);
+
+ dllist<widget &> for_vbox;
+
+ label l("Click a setting name below to edit its value.");
+ label l2("A restart is required for changes to take effect.");
+
+ dllist<widget &> for_subbox;
+ for_subbox.add_back(l);
+ for_subbox.add_back(l2);
+ vbox subbox(for_subbox);
+
+ padding p_subbox(subbox, 2);
+ for_vbox.add_back(p_subbox);
+
+ for (uint32_t i = 0; i < file_head.main_entries; ++i) {
+ struct main_entry entry;
+ seek_file_to(f, file_head.main_offset + i * sizeof(struct main_entry));
+ read_from_file(f, sizeof(struct main_entry), &entry);
+
+ char *const sname = new char[entry.name_len + 1];
+ seek_file_to(f, file_head.names_offset + entry.name_offset);
+ read_from_file(f, entry.name_len, sname);
+ sname[entry.name_len] = '\0';
+
+ switch (entry.kind) {
+ char *sz;
+ struct setting s;
+ case main_entry::STRING:
+ sz = new char[entry.as_string.data_len + 1];
+ seek_file_to(f, file_head.data_offset + entry.as_string.data_offset);
+ read_from_file(f, entry.as_string.data_len, sz);
+ sz[entry.as_string.data_len] = '\0';
+
+ s.kind = setting::STRING;
+ s.data.string = sz;
+ s.name = sname;
+ settings.add_back(s);
+ break;
+
+ case main_entry::COLOR:
+ s.kind = setting::COLOR;
+ s.data.color = entry.as_color;
+ s.name = sname;
+ settings.add_back(s);
+ break;
+ default:
+ show_error_and_quitf("Refusing to open " SETTINGS_FILE ":\n\"%s\" has unrecognized type id 0x%2x.\nHighest known is 0x01.", sname, entry.kind);
+ }
+
+ button *const b = make_button(settings.n_entries - 1);
+
+ padding *p = new padding(*b, 2);
+ for_vbox.add_back(*p);
+ }
+
+ close_file(f);
+
+ vbox box(for_vbox);
+ padding pbox(box, 2);
+
+ main_w = new saving_window(&save, 0, pbox);
+ main_w->show();
+ start_runtime();
+} \ No newline at end of file