commit a554e40db6f29fea69199f66dfa5fd2ed7e94b4e
parent 8a7cc7b412399d329790f80d496921b933bb4edc
Author: ssnf <ssnf@ssnf.xyz>
Date: Sun, 15 Aug 2021 15:49:29 +0000
implemented frame functionality
Diffstat:
M | sim.c | | | 206 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
1 file changed, 191 insertions(+), 15 deletions(-)
diff --git a/sim.c b/sim.c
@@ -5,16 +5,32 @@
#include "sim.h"
-void die(char*, ...);
-void* emalloc(ulong);
-void* erealloc(void*, ulong);
-void move(int);
-void quit(int);
+typedef struct {
+ Address* a;
+ ushort dot;
+ ushort n;
+ ushort size;
+} Frame;
-File file[FILECOUNT];
-File* f;
-Window w;
-uchar refresh;
+void die(char*, ...);
+void* emalloc(ulong);
+void* erealloc(void*, ulong);
+static void blind_reader(Frame* fr, Posn p0);
+static void blind_writer(ushort line, ushort offset, ushort top, ushort bot);
+static void fr_add(Frame* fr, Posn p0, Posn p1);
+static void fr_close(Frame* fr);
+static void fr_init(Frame* fr);
+static void fr_insert(Frame* p, Frame* q, ushort n);
+static void fr_insure(Frame* fr, ushort n);
+static void fr_update();
+static void fr_zero(Frame*);
+static void move(int);
+static void quit(int);
+
+static Frame frame;
+static File* f;
+static File file[FILECOUNT];
+static Window w;
#include "config.h"
@@ -63,23 +79,181 @@ erealloc(void* p, ulong n)
return p;
}
+static void
+blind_reader(Frame* fr, Posn p0)
+{
+ Posn p1;
+ uint wx;
+
+ p1 = p0;
+ do {
+ for (wx = 0; wx < w.wx && p1 < f->s->n - 1;) {
+ switch (f->s->s[p1]) {
+ case '\t':
+ wx += 4 - (wx % 4);
+ break;
+ case '\n':
+ goto endloop;
+ default:
+ ++wx;
+ }
+ if (wx < w.wx)
+ ++p1;
+ if (wx >= w.wx) {
+ if (f->s->s[p1] == '\t')
+ ++p1;
+ if (f->s->s[p1 + 1] == '\n')
+ ++p1;
+ }
+ }
+ endloop:
+ fr_add(fr, p0, p1);
+ p0 = ++p1;
+ } while (p1 < f->s->n - 1 && f->s->s[p1 - 1] != '\n');
+}
+
+static void
+blind_writer(ushort line, ushort offset, ushort top, ushort bot)
+{
+ ushort i, o;
+
+ o = frame.n - 1;
+ i = 0;
+ if (offset >= top)
+ i = offset - top + 1;
+ if (frame.n - offset > bot)
+ o = offset + bot - 1;
+ printf(CSI "%uH", line - offset);
+ fwrite(&f->s->s[frame.a[i].p0], frame.a[o].p1 - frame.a[i].p0, 1, stdout);
+}
+
+static void
+fr_add(Frame* fr, Posn p0, Posn p1)
+{
+ fr_insure(fr, fr->n + 1);
+ fr->a[fr->n].p0 = p0;
+ fr->a[fr->n].p1 = p1;
+ ++fr->n;
+}
+
+static void
+fr_close(Frame* fr)
+{
+ free(fr->a);
+}
+
+static void
+fr_init(Frame* fr)
+{
+ fr->a = emalloc(32 * sizeof(*fr->a));
+ fr->dot = 0;
+ fr->n = 0;
+ fr->size = 32;
+}
+
+static void
+fr_insert(Frame* p, Frame* q, ushort n)
+{
+ fr_insure(p, p->n + q->n);
+ memmove(p->a + n + q->n, p->a + n, (p->n - n) * sizeof(*p->a));
+ memmove(p->a + n, q->a, q->n * sizeof(*p->a));
+ p->n += q->n;
+}
+
+static void
+fr_insure(Frame* fr, ushort n)
+{
+ if (n > fr->size) {
+ fr->size += n + (32 - (n % 32));
+ fr->a = erealloc(fr->a, fr->size * sizeof(*fr->a));
+ }
+}
+
+static void
+fr_update()
+{
+ Frame fr;
+ Posn p0, p1;
+ ushort half;
+
+ half = w.wy >> 1;
+ if (!f->s->n) {
+ printf(ED);
+ goto status;
+ }
+ if (!frame.n || f->dot.p1 > frame.a[frame.n - 1].p1 || f->dot.p1 < frame.a[0].p0 || frame.n - frame.dot < half || frame.dot < half) {
+ fr_zero(&frame);
+ for (p0 = f->dot.p1; p0; --p0)
+ if (f->s->s[p0 - 1] == '\n')
+ break;
+ if ((p1 = p0)) {
+ fr_init(&fr);
+ for (--p1; p1 && frame.n < w.wy;) {
+ for (;p1 && f->s->s[p1 - 1] != '\n'; --p1);
+ blind_reader(&fr, p1);
+ if ((p1 = fr.a[0].p0))
+ --p1;
+ fr_insert(&frame, &fr, 0);
+ fr_zero(&fr);
+ }
+ fr_close(&fr);
+ }
+ for (p1 = p0; p1 < f->s->n - 1 && frame.n < 2 * w.wy;) {
+ blind_reader(&frame, p1);
+ p1 = frame.a[frame.n - 1].p1 + 1;
+ }
+ for (;f->dot.p1 > frame.a[frame.dot].p1; ++frame.dot);
+ goto full_update;
+ }
+ if (f->dot.p1 > frame.a[frame.dot].p1 || f->dot.p1 < frame.a[frame.dot].p0) {
+ for (;f->dot.p1 > frame.a[frame.dot].p1; ++frame.dot);
+ for (;f->dot.p1 < frame.a[frame.dot].p0; --frame.dot);
+ goto full_update;
+ }
+ status:
+ printf(CSI "%uH" "%lu 0x%02x", w.wy, f->dot.p1, f->s->s[f->dot.p1]);
+ for (p0 = frame.a[frame.dot].p0, p1 = 1; p0 < f->dot.p1; ++p0) {
+ if (f->s->s[p0] == '\t')
+ p1 += 5 - (p1 % 4);
+ else
+ ++p1;
+ }
+ printf(CSI "%u;%luH", half, p1);
+ return;
+ full_update:
+ printf(ED);
+ blind_writer(half, frame.dot, half, half + (w.wy % 2));
+ goto status;
+}
+
+static void
+fr_zero(Frame* fr)
+{
+ fr->n = 0;
+ fr->dot = 0;
+}
+
void
move(int arg)
{
switch (arg) {
case Left:
- if (f->dot.p0)
- f->dot.p1 = --f->dot.p0;
+ if (f->dot.p1)
+ f->dot.p0 = --f->dot.p1;
break;
case Right:
- if (f->dot.p0 < f->s->n)
- f->dot.p1 = ++f->dot.p0;
+ if (f->dot.p1 + 1 < f->s->n)
+ f->dot.p0 = ++f->dot.p1;
break;
case Up:
- for (;f->dot.p0 && f->s->s[f->dot.p0 - 1] != '\n'; f->dot.p1 = --f->dot.p0);
+ if (f->dot.p1)
+ for (;--f->dot.p1, f->dot.p1 && f->s->s[f->dot.p1] != '\n';);
+ f->dot.p0 = f->dot.p1;
break;
case Down:
- for (;f->dot.p0 < f->s->n && f->s->s[f->dot.p0] != '\n'; f->dot.p1 = ++f->dot.p0);
+ if (f->dot.p1 + 1 < f->s->n)
+ for (;++f->dot.p1, f->dot.p1 + 1 < f->s->n && f->s->s[f->dot.p1 - 1] != '\n';);
+ f->dot.p0 = f->dot.p1;
break;
};
}
@@ -98,6 +272,7 @@ main(int argc, char* argv[])
uchar c;
win_init();
+ fr_init(&frame);
for (i = 0; i < FILECOUNT; ++i)
file_init(&file[i]);
f = &file[0];
@@ -107,6 +282,7 @@ main(int argc, char* argv[])
}
for (;;) {
win_query(&w);
+ fr_update();
c = fgetc(stdin);
for (i = 0; i < LENGTH(keys); ++i) {
if (keys[i].key == c) {