commit ab1f1760a39941a79bfc650f0141409272036c46
parent 72c781bf356dddf0dffc5363a4ba46920a481dfe
Author: ssnf <ssnf@ssnf.xyz>
Date: Sun, 22 Aug 2021 03:15:31 +0000
added undo/redo functionality
Diffstat:
M | config.def.h | | | 4 | ++++ |
M | sim.c | | | 123 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
2 files changed, 105 insertions(+), 22 deletions(-)
diff --git a/config.def.h b/config.def.h
@@ -24,13 +24,17 @@ Key keys[] = {
{ 'x', delete , 'x' },
{ 'c', change },
{ 'C', change , 'c' },
+ { 'r', change, 'x' },
{ 'E', file_open },
{ 'q', file_close, -1 },
{ 'S', file_save, -1 },
{ 'Q', quit },
{ '/', search, '/' },
+ { '?', search, '?' },
{ 'n', search, 'n' },
{ 'N', search, 'N' },
+ { 'u', undo },
+ { Ctrl + 'r', redo },
{ Esc, escape }
};
diff --git a/sim.c b/sim.c
@@ -26,6 +26,9 @@ enum {
Word,
EndWord,
PrevWord,
+ Insert,
+ Delete,
+ Change,
Ctrl = -0x60,
Esc = 0x1b,
Del = 0x7f
@@ -33,7 +36,7 @@ enum {
typedef struct {
Posn p0, p1;
-} Address ;
+} Address;
typedef struct {
char* s;
@@ -42,9 +45,17 @@ typedef struct {
} String;
typedef struct {
+ String s[2048];
+ int c[2048];
+ Posn p0[2048];
+ ushort n;
+} Buffer; /*yes, it is very big. absolutely no compromises*/
+
+typedef struct {
String* s;
String* name;
Address dot;
+ ushort i; /*buffer index*/
uchar dirty;
} File;
@@ -66,8 +77,10 @@ void* emalloc(ulong);
void* erealloc(void*, ulong);
static void blind_reader(Frame* fr, String* s, Posn p0);
static void blind_writer(String* s, Frame* fr, ushort line, ushort offset, ushort top, ushort bot);
+static void buf_add(Buffer* b, String* s, int c, Posn p0);
static void change(int arg);
static void delete(int arg);
+static void redo(int arg);
static void escape(int c);
static void init();
static void input(String* s, ushort line, char* msg);
@@ -91,17 +104,19 @@ static void str_close(String* p);
static void str_zero(String* p);
static void str_insure(String* p, ulong n);
static void str_addc(String* p, int c);
-static void str_adds(String* p, char* s);
+static void str_adds(String* p, char* s, ulong n);
static void str_delc(String* p);
static void str_insert(String* p, String* q, Posn p0);
static void str_delete(String* p, Posn p0, Posn p1);
+static void undo(int arg);
static void move(int);
static void quit(int);
-static Frame* fr, frame[FILECOUNT];
-static File* f, file[FILECOUNT];
-static String srch;
-static Window w;
+static Frame* fr, frame[FILECOUNT];
+static File* f, file[FILECOUNT];
+static Buffer* buf, buffer[FILECOUNT];
+static String srch;
+static Window w;
#include "config.h"
@@ -122,7 +137,7 @@ die(char* fmt, ...)
for (i = 0; i < FILECOUNT; ++i) {
if (!file[i].s->n)
continue;
- str_adds(file[i].name, ".swap");
+ str_adds(file[i].name, ".swap", 5);
file_save(i);
fprintf(stderr, "file saved to %s\n", file[i].name->s);
}
@@ -200,6 +215,18 @@ blind_writer(String* s, Frame* fr, ushort line, ushort offset, ushort top, ushor
}
static void
+buf_add(Buffer* b, String* s, int c, Posn p0)
+{
+ b->n = ++f->i;
+ if (s != NULL) {
+ str_zero(&b->s[b->n]);
+ str_insert(&b->s[b->n], s, 0);
+ }
+ b->c[b->n] = c;
+ b->p0[b->n] = p0;
+}
+
+static void
change(int arg)
{
if (!arg)
@@ -211,10 +238,12 @@ change(int arg)
case 'c':
delete('d');
insert(Up);
+ buf_add(buf, NULL, Change, 0);
return;
case 'G':
delete('G');
insert(Down);
+ buf_add(buf, NULL, Change, 0);
return;
case 'g':
delete('g');
@@ -229,11 +258,15 @@ change(int arg)
return;
}
insert(0);
+ if (buf->c[f->i] == Insert)
+ arg = -1;
+ buf_add(buf, NULL, Change, arg);
}
static void
delete(int arg)
{
+ String s;
Posn m, n;
if (!f->s->n)
@@ -275,7 +308,7 @@ delete(int arg)
arg = fgetc(stdin);
if (arg == Esc)
return;
- for (;f->dot.p1 < f->s->n && f->s->s[f->dot.p1] != arg; ++f->dot.p1);
+ for (;++f->dot.p1, f->dot.p1 < f->s->n && f->s->s[f->dot.p1] != arg;);
m = f->dot.p0;
n = f->dot.p1;
f->dot.p0 = f->dot.p1 = m;
@@ -283,12 +316,33 @@ delete(int arg)
default:
return;
}
+ str_init(&s);
+ str_adds(&s, f->s->s + m, n - m);
+ buf_add(buf, &s, Delete, m);
+ str_close(&s);
str_delete(f->s, m, n);
f->dirty = '*';
fr_update(1);
}
static void
+redo(int arg)
+{
+ if (f->i == buf->n)
+ return;
+ ++f->i;
+ if (buf->c[f->i] == Insert)
+ str_insert(f->s, &buf->s[f->i], buf->p0[f->i]);
+ else if (buf->c[f->i] == Delete)
+ str_delete(f->s, buf->p0[f->i], buf->s[f->i].n);
+ else if (buf->c[f->i] == Change) {
+ str_delete(f->s, buf->p0[f->i], buf->s[f->i].n);
+ str_insert(f->s, &buf->s[f->i], buf->p0[f->i]);
+ }
+ fr_update(1);
+}
+
+static void
escape(int c)
{
c = fgetc(stdin) - 0x30;
@@ -296,7 +350,10 @@ escape(int c)
--c;
f = &file[c];
fr = &frame[c];
+ buf = &buffer[c];
+ return;
}
+ ungetc(c + 0x30, stdin);
}
static void
@@ -359,15 +416,14 @@ insert(int arg)
case Down:
move(EndLine);
str_addc(&s, '\n');
- str_insert(f->s, &s, ++f->dot.p0);
- str_zero(&s);
- f->dot.p1 = f->dot.p0;
+ str_insert(f->s, &s, f->dot.p0);
+ ++f->dot.p1;
break;
case Up:
move(StartLine);
str_addc(&s, '\n');
str_insert(f->s, &s, f->dot.p0);
- str_zero(&s);
+ ++f->dot.p1;
break;
}
for (;;) {
@@ -391,10 +447,16 @@ insert(int arg)
f->dot.p1 = f->dot.p0 + s.n;
}
endloop:
- str_insert(f->s, &s, f->dot.p0);
+ if (s.n) {
+ if (arg == Up)
+ str_addc(&s, '\n');
+ buf_add(buf, &s, Insert, f->dot.p0);
+ str_insert(f->s, &s, f->dot.p0);
+ fr_update(0);
+ f->dirty = '*';
+ }
str_close(&s);
f->dot.p0 = f->dot.p1;
- f->dirty = '*';
}
static void
@@ -409,6 +471,7 @@ init()
}
f = &file[0];
fr = &frame[0];
+ buf = &buffer[0];
str_init(&srch);
}
@@ -435,7 +498,7 @@ file_init(File* f)
f->name = emalloc(sizeof(String));
str_init(f->s);
str_init(f->name);
- f->dirty = f->dot.p0 = f->dot.p1 = 0;
+ f->i = f->dirty = f->dot.p0 = f->dot.p1 = 0;
}
static void
@@ -451,7 +514,7 @@ file_load(File* f)
rewind(disk);
fread(f->s->s, f->s->n, 1, disk);
fclose(disk);
- f->dot.p0 = f->dot.p1 = 0;
+ f->i = f->dot.p0 = f->dot.p1 = 0;
}
static void
@@ -680,7 +743,7 @@ search(int arg)
Posn pos;
uchar* p;
- if (arg == '/') {
+ if (arg == '/' || arg == '?') {
str_zero(&srch);
input(&srch, w.wy, "/");
for (pos = 0; pos < srch.n; ++pos)
@@ -756,11 +819,8 @@ str_addc(String* p, int c)
}
static void
-str_adds(String* p, char* s)
+str_adds(String* p, char* s, ulong n)
{
- ulong n;
-
- n = strlen(s);
str_insure(p, p->n + n);
memmove(p->s + p->n, s, n);
p->n += n;
@@ -793,6 +853,25 @@ str_delete(String* p, Posn p0, Posn p1)
p->n -= p1 - p0;
}
+static void
+undo(int arg)
+{
+ if (!f->i)
+ return;
+ if (buf->c[f->i] == Insert)
+ str_delete(f->s, buf->p0[f->i], buf->p0[f->i] + buf->s[f->i].n);
+ else if (buf->c[f->i] == Delete)
+ str_insert(f->s, &buf->s[f->i], buf->p0[f->i]);
+ else if (buf->c[f->i] == Change) {
+ if (buf->p0[f->i] == -1)
+ --f->i, str_delete(f->s, buf->p0[f->i], buf->p0[f->i] + buf->s[f->i].n);
+ --f->i, str_insert(f->s, &buf->s[f->i], buf->p0[f->i]);
+ }
+ f->dot.p0 = f->dot.p1 = buf->p0[f->i];
+ --f->i;
+ fr_update(1);
+}
+
int
main(int argc, char* argv[])
{
@@ -801,7 +880,7 @@ main(int argc, char* argv[])
init();
if (argv[1]) {
- str_adds(f->name, argv[1]);
+ str_adds(f->name, argv[1], strlen(argv[1]));
file_load(f);
}
for (;;) {