sim

the sim text editor
git clone git://ssnf.xyz/sim
Log | Files | Refs | README

commit ab1f1760a39941a79bfc650f0141409272036c46
parent 72c781bf356dddf0dffc5363a4ba46920a481dfe
Author: ssnf <ssnf@ssnf.xyz>
Date:   Sun, 22 Aug 2021 03:15:31 +0000

added undo/redo functionality

Diffstat:
Mconfig.def.h | 4++++
Msim.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 (;;) {