ref: 02c13a3ce3bcf6e19dcf794c4efa57d4056b2d4c
parent: 31ef221de8dcd5baca4e48520af6c84d97a8ec8b
author: glenda <glenda@krsna>
date: Wed Aug 20 16:42:20 EDT 2025
soa-refactor
--- a/da.c
+++ b/da.c
@@ -5,9 +5,9 @@
#include <keyboard.h>
#include <bio.h>
-#define CONFIG_FILE "/tmp/da.conf"
-#define DEFAULT_CTL_FILE "/tmp/da.ctl"
-#define DEFAULT_SAVE_PATH "/tmp/canvas.da"
+#define CONFIG_FILE "/usr/glenda/da/da.conf"
+#define DEFAULT_CTL_FILE "/usr/glenda/da/da.ctl"
+#define DEFAULT_SAVE_PATH "/usr/glenda/da/canvas.da"
#define DEFAULT_CTL_CHECK_INTERVAL 200
#define DEFAULT_REDRAW_INTERVAL 30
#define DEFAULT_BANNER_HEIGHT 25
@@ -23,7 +23,7 @@
#define DEFAULT_GRIDSNAP 1
#define DEFAULT_EMOJI 1
/* const */
-#define MAXBOXES 2000
+#define MAXBOXES 9000
enum {
@@ -74,23 +74,24 @@
typedef struct Box Box;
struct Box {
- Point pos;
- Rectangle r;
- int type;
- int selected;
- int color_idx;
+ Rectangle r[MAXBOXES];
+ int color_idx[MAXBOXES];
+ Point pos[MAXBOXES];
+ int type[MAXBOXES];
+ int selected[MAXBOXES];
+
};
typedef struct BoxType BoxType;
struct BoxType {
char *name;
- void (*draw)(Box*, Image*);
+ void (*draw)(int idx, Image*);
int default_color;
};
typedef struct Canvas Canvas;
struct Canvas {
- Box boxes[MAXBOXES];
+ Box boxes;
int nboxes;
int selected;
int fnkey;
@@ -163,8 +164,7 @@
void handlekey(int key);
void handlemouse(Mouse m);
void cleanup(void);
-void draw_box(Box*, Image*);
-void draw_bigbox(Box*, Image*);
+void draw_box(int idx, Image *dst);
void draw_nol(void);
void draw_fnol(void);
void draw_bg(void);
@@ -193,6 +193,9 @@
void initcolors(void);
void validate_config(void);
void apply_config(void);
+int addbox(Point p);
+void delbox(int i);
+int boxat(Point p);
static ulong palette[] = {
0x2ECC71FF, 0x34495EFF, 0x95A5A6FF, 0xE67E22FF,
@@ -243,7 +246,7 @@
file_key,
fn_mouse,
draw_fnol,
- "Tab:/tmp/ Enter:confirm Esc:cancel"
+ "Tab:/usr/glenda/da/ Enter:confirm Esc:cancel"
},
};
@@ -656,107 +659,142 @@
"~v~v~"
};
-void
+void
save_da(char *file)
{
- int fd;
- Biobuf *b;
- int i;
- Box *box;
-
- fd = create(file, OWRITE, 0644);
- if(fd < 0){
- fprint(2, "cannot create %s: %r\n", file);
- return;
- }
-
- b = Bfdopen(fd, OWRITE);
-
- for(i = 0; i < canvas.nboxes; i++){
- box = &canvas.boxes[i];
- Bprint(b, "box %d\n", i);
- Bprint(b, " pos %d %d\n", box->pos.x, box->pos.y);
- Bprint(b, " type %d\n", box->type);
- Bprint(b, " color %08lux\n", palette[box->color_idx]);
- }
-
- Bterm(b);
- close(fd);
+ int fd, i;
+ Biobuf *b;
+
+ fd = create(file, OWRITE, 0644);
+ if(fd < 0){
+ fprint(2, "cannot create %s: %r\n", file);
+ return;
+ }
+
+ b = Bfdopen(fd, OWRITE);
+
+ // New format - write arrays in bulk
+ Bprint(b, "count %d\n", canvas.nboxes);
+
+ // Write all data in array chunks - much more efficient!
+
+ // Positions array
+ Bprint(b, "positions\n");
+ for(i = 0; i < canvas.nboxes; i++){
+ Bprint(b, "%d %d\n",
+ canvas.boxes.pos[i].x,
+ canvas.boxes.pos[i].y);
+ }
+
+ // Types array
+ Bprint(b, "types\n");
+ for(i = 0; i < canvas.nboxes; i++){
+ Bprint(b, "%d\n", canvas.boxes.type[i]);
+ }
+
+ // Colors array
+ Bprint(b, "colors\n");
+ for(i = 0; i < canvas.nboxes; i++){
+ Bprint(b, "%d\n", canvas.boxes.color_idx[i]);
+ }
+
+ Bterm(b);
+ close(fd);
}
-void
+void
load_da(char *file)
{
- Biobuf *b;
- char *line;
- char *fields[10];
- int nf;
-
- b = Bopen(file, OREAD);
- if(b == nil){
- fprint(2, "cannot open %s: %r\n", file);
- return;
- }
-
- memset(&canvas, 0, sizeof(canvas));
- canvas.selected = -1;
- canvas.fnkey = 0;
- canvas.current_mode = 0;
- canvas.current_color = 8;
- canvas.gridsize = config.gridsize;
- canvas.gridsnap = config.gridsnap;
- init_emoji();
-
- while((line = Brdline(b, '\n')) != nil){
- line[Blinelen(b)-1] = '\0';
-
- if(line[0] == '#' || line[0] == '\0')
- continue;
-
- nf = tokenize(line, fields, nelem(fields));
-
- if(nf >= 2 && strcmp(fields[0], "box") == 0){
- if(canvas.nboxes < MAXBOXES){
- Box *box = &canvas.boxes[canvas.nboxes];
- memset(box, 0, sizeof(Box));
- box->r = Rect(0, 0, config.box_width, config.box_height);
- canvas.nboxes++;
- }
- } else if(nf >= 3 && strcmp(fields[0], "pos") == 0){
- Box *box = &canvas.boxes[canvas.nboxes-1];
- box->pos.x = atoi(fields[1]);
- box->pos.y = atoi(fields[2]);
- box->r = Rect(box->pos.x, box->pos.y,
- box->pos.x + config.box_width, box->pos.y + config.box_height);
-
- } else if(nf >= 2 && strcmp(fields[0], "type") == 0){
- int type = atoi(fields[1]);
- if (type >= 0 && type < MAXBOXTYPES) {
- Box *box = &canvas.boxes[canvas.nboxes-1];
- box->type = type;
-
- if(type == T_BIGBOX){
- box->r = Rect(box->pos.x, box->pos.y,
- box->pos.x + config.bigbox_width,
- box->pos.y + config.bigbox_height);
- }
- }
- } else if(nf >= 2 && strcmp(fields[0], "color") == 0){
- ulong loaded_color = strtoul(fields[1], nil, 16);
- int color_idx = 0;
- for(int i = 0; i < 16; i++) {
- if (palette[i] == loaded_color) {
- color_idx = i;
- break;
- }
- }
- canvas.boxes[canvas.nboxes-1].color_idx = color_idx;
- }
- }
-
- Bterm(b);
- redraw();
-}
+ Biobuf *b;
+ char *line;
+ char *fields[10];
+ int nf, i;
+ enum { NONE, POSITIONS, TYPES, COLORS } section = NONE;
+ int idx = 0;
+ int count = 0;
+
+ b = Bopen(file, OREAD);
+ if(b == nil){
+ fprint(2, "cannot open %s: %r\n", file);
+ return;
+ }
+
+ // Clear canvas
+ memset(&canvas.boxes, 0, sizeof(canvas.boxes));
+ canvas.nboxes = 0;
+ canvas.selected = -1;
+ canvas.current_color = 8;
+ init_emoji();
+
+ while((line = Brdline(b, '\n')) != nil){
+ line[Blinelen(b)-1] = '\0';
+
+ if(line[0] == '#' || line[0] == '\0')
+ continue;
+
+ nf = tokenize(line, fields, nelem(fields));
+ if(nf == 0) continue;
+
+ // Check for section headers
+ if(strcmp(fields[0], "count") == 0 && nf >= 2){
+ count = atoi(fields[1]);
+ if(count > MAXBOXES) count = MAXBOXES;
+ } else if(strcmp(fields[0], "positions") == 0){
+ section = POSITIONS;
+ idx = 0;
+ } else if(strcmp(fields[0], "types") == 0){
+ section = TYPES;
+ idx = 0;
+ } else if(strcmp(fields[0], "colors") == 0){
+ section = COLORS;
+ idx = 0;
+ } else {
+ // Parse data based on current section
+ switch(section){
+ case POSITIONS:
+ if(nf >= 2 && idx < count){
+ canvas.boxes.pos[idx] = Pt(atoi(fields[0]), atoi(fields[1]));
+ idx++;
+ }
+ break;
+
+ case TYPES:
+ if(nf >= 1 && idx < count){
+ canvas.boxes.type[idx] = atoi(fields[0]);
+ idx++;
+ }
+ break;
+
+ case COLORS:
+ if(nf >= 1 && idx < count){
+ canvas.boxes.color_idx[idx] = atoi(fields[0]);
+ idx++;
+ }
+ break;
+ }
+ }
+ }
+
+ canvas.nboxes = count;
+
+ // Reconstruct rectangles from positions and types
+ for(i = 0; i < canvas.nboxes; i++){
+ Point p = canvas.boxes.pos[i];
+ if(canvas.boxes.type[i] == T_BIGBOX){
+ canvas.boxes.r[i] = Rect(p.x, p.y,
+ p.x + config.bigbox_width,
+ p.y + config.bigbox_height);
+ } else {
+ canvas.boxes.r[i] = Rect(p.x, p.y,
+ p.x + config.box_width,
+ p.y + config.box_height);
+ }
+ canvas.boxes.selected[i] = 0; // Clear selection on load
+ }
+
+ Bterm(b);
+ redraw();
+}
void
save_config(char *path)
@@ -996,15 +1034,14 @@
void
cmd_set_color(int idx)
{
- if(idx >= 0 && idx < 16) {
- canvas.current_color = idx;
- if(canvas.selected >= 0 && canvas.selected < canvas.nboxes) {
- canvas.boxes[canvas.selected].color_idx = idx;
- }
- canvas.needredraw = 1;
- }
+ if(idx >= 0 && idx < 16) {
+ canvas.current_color = idx;
+ if(canvas.selected >= 0 && canvas.selected < canvas.nboxes) {
+ canvas.boxes.color_idx[canvas.selected] = idx;
+ }
+ canvas.needredraw = 1;
+ }
}
-
void
cmd_toggle_boxtype(void)
{
@@ -1012,73 +1049,78 @@
canvas.needredraw = 1;
}
-int
+int
boxat(Point p)
{
- int i;
- Box *b;
-
- for(i = canvas.nboxes - 1; i >= 0; i--){
- b = &canvas.boxes[i];
- if(ptinrect(p, b->r))
- return i;
- }
- return -1;
+ int i;
+ for(i = canvas.nboxes - 1; i >= 0; i--){
+ if(ptinrect(p, canvas.boxes.r[i]))
+ return i;
+ }
+ return -1;
}
-int
+int
addbox(Point p)
{
- Box *b;
+ int idx;
if(canvas.nboxes >= MAXBOXES)
return -1;
-
- b = &canvas.boxes[canvas.nboxes];
- memset(b, 0, sizeof(Box));
-
- if(canvas.gridsnap){
+
+ idx = canvas.nboxes;
+
+ if(canvas.gridsnap) {
p.x = (p.x / canvas.gridsize) * canvas.gridsize;
p.y = (p.y / canvas.gridsize) * canvas.gridsize;
}
-
- b->pos = p;
- b->type = canvas.next_box_type;
- b->color_idx = canvas.current_color;
-
- if(b->type == T_BIGBOX) {
- b->r = Rect(p.x, p.y,
- p.x + config.bigbox_width,
- p.y + config.bigbox_height);
+
+ canvas.boxes.pos[idx] = p;
+ canvas.boxes.type[idx] = canvas.next_box_type;
+ canvas.boxes.color_idx[idx] = canvas.current_color;
+ canvas.boxes.selected[idx] = 0;
+
+ if(canvas.boxes.type[idx] == T_BIGBOX) {
+ canvas.boxes.r[idx] = Rect(p.x, p.y,
+ p.x + config.bigbox_width,
+ p.y + config.bigbox_height);
} else {
- b->r = Rect(p.x, p.y,
- p.x + config.box_width,
- p.y + config.box_height);
+ canvas.boxes.r[idx] = Rect(p.x, p.y,
+ p.x + config.box_width,
+ p.y + config.box_height);
}
return canvas.nboxes++;
}
-void
+void
delbox(int i)
{
- if(i < 0 || i >= canvas.nboxes)
- return;
-
- memmove(&canvas.boxes[i], &canvas.boxes[i+1],
- (canvas.nboxes - i - 1) * sizeof(Box));
- canvas.nboxes--;
-
+ int last;
+ if(i < 0 || i >= canvas.nboxes)
+ return;
+
+ last = canvas.nboxes - 1;
+
+ if(i != last) {
+ canvas.boxes.pos[i] = canvas.boxes.pos[last];
+ canvas.boxes.r[i] = canvas.boxes.r[last];
+ canvas.boxes.type[i] = canvas.boxes.type[last];
+ canvas.boxes.selected[i] = canvas.boxes.selected[last];
+ canvas.boxes.color_idx[i] = canvas.boxes.color_idx[last];
+ }
+
+ canvas.nboxes--;
}
void
-draw_box(Box *b, Image *dst)
+draw_box(int idx, Image *dst)
{
- Image *bg = colors[b->color_idx];
+ Image *bg = colors[canvas.boxes.color_idx[idx]];
- if(b->selected)
+ if(canvas.boxes.selected[idx])
bg = boxselected;
- draw(dst, b->r, bg, nil, ZP);
+ draw(dst, canvas.boxes.r[idx], bg, nil, ZP);
}
void
@@ -1143,21 +1185,33 @@
drawgrid(screen);
}
-void
+void
draw_all(void)
{
- int i;
- for(i = 0; i < canvas.nboxes; i++) {
- Box *b = &canvas.boxes[i];
- if (b->type >= 0 && b->type < MAXBOXTYPES) {
- BoxType *bt = &boxtypes[b->type];
- if (bt->draw) {
- bt->draw(b, screen);
- }
- }
- }
+ int i;
+ // First pass: Draw all regular boxes
+ for(i = 0; i < canvas.nboxes; i++) {
+ if(canvas.boxes.type[i] == T_BOX) {
+ Image *color = colors[canvas.boxes.color_idx[i]];
+ draw(screen, canvas.boxes.r[i], color, nil, ZP);
+ }
+ }
+
+ // Second pass: Draw all big boxes
+ for(i = 0; i < canvas.nboxes; i++) {
+ if(canvas.boxes.type[i] == T_BIGBOX) {
+ Image *color = colors[canvas.boxes.color_idx[i]];
+ draw(screen, canvas.boxes.r[i], color, nil, ZP);
+ }
+ }
+
+ // Third pass: Draw selection highlights
+ for(i = 0; i < canvas.nboxes; i++) {
+ if(canvas.boxes.selected[i]) {
+ border(screen, canvas.boxes.r[i], 2, boxselected, ZP);
+ }
+ }
}
-
void
draw_status(void)
{
@@ -1538,24 +1592,23 @@
void
norm_key(int key)
{
- Command *cmd;
-
+ Command *cmd;
if(key >= '0' && key <= '9') {
- cmd_set_color(key - '0');
- return;
- }
-
- if(key >= 'a' && key <= 'f') {
- cmd_set_color(10 + (key - 'a'));
- return;
- }
+ cmd_set_color(key - '0'); // Pass the index
+ return;
+ }
+
+ if(key >= 'a' && key <= 'f') {
+ cmd_set_color(10 + (key - 'a')); // Pass the index
+ return;
+ }
- for(cmd = commands; cmd->action; cmd++) {
- if(cmd->key == key) {
- cmd->action();
- return;
- }
- }
+ for(cmd = commands; cmd->action; cmd++) {
+ if(cmd->key == key) {
+ cmd->action();
+ return;
+ }
+ }
}
void
@@ -1580,8 +1633,8 @@
canvas.current_mode = 0;
canvas.needredraw = 1;
} else if(key == '\t') {
- if(!strstr(canvas.fnbuf, "/tmp/")) {
- strcat(canvas.fnbuf, "/tmp/");
+ if(!strstr(canvas.fnbuf, "/usr/glenda/da/")) {
+ strcat(canvas.fnbuf, "/usr/glenda/da/");
canvas.fnpos = strlen(canvas.fnbuf);
canvas.needredraw = 1;
}
@@ -1615,26 +1668,29 @@
}
}
- if(m.buttons & 2){
+ if(m.buttons & 2){
i = boxat(m.xy);
if(i >= 0){
canvas.selected = i;
- Box *box = &canvas.boxes[i];
- int width = (box->type == T_BIGBOX) ? config.bigbox_width : config.box_width;
- int height = (box->type == T_BIGBOX) ? config.bigbox_height : config.box_height;
- box->selected = 1;
+ // Access arrays directly, not through pointer
+ int type = canvas.boxes.type[i];
+ int width = (type == T_BIGBOX) ? config.bigbox_width : config.box_width;
+ int height = (type == T_BIGBOX) ? config.bigbox_height : config.box_height;
+ canvas.boxes.selected[i] = 1;
+
while(m.buttons & 2){
- box->pos = subpt(m.xy, Pt(width/2, height/2));
+ Point new_pos = subpt(m.xy, Pt(width/2, height/2));
if(canvas.gridsnap){
- box->pos.x = (box->pos.x / canvas.gridsize) * canvas.gridsize;
- box->pos.y = (box->pos.y / canvas.gridsize) * canvas.gridsize;
+ new_pos.x = (new_pos.x / canvas.gridsize) * canvas.gridsize;
+ new_pos.y = (new_pos.y / canvas.gridsize) * canvas.gridsize;
}
- box->r = Rect(box->pos.x, box->pos.y,
- box->pos.x + width, box->pos.y + height);
+ canvas.boxes.pos[i] = new_pos;
+ canvas.boxes.r[i] = Rect(new_pos.x, new_pos.y,
+ new_pos.x + width, new_pos.y + height);
redraw();
m = emouse();
}
- box->selected = 0;
+ canvas.boxes.selected[i] = 0;
canvas.needredraw = 1;
}
}
@@ -1655,14 +1711,13 @@
{
USED(m);
}
-
void
ctl_addbox(char **args, int nargs)
{
- Point p = Pt(atoi(args[0]), atoi(args[1]));
- int idx = addbox(p);
-
- canvas.needredraw = 1;
+ USED(nargs); // Add this
+ Point p = Pt(atoi(args[0]), atoi(args[1]));
+ addbox(p); // Don't need to capture idx if not using it
+ canvas.needredraw = 1;
}
void
--
⑨