sim

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

commit 2c8be1d44378919c593eb8d5ef38c4ed0de5bef9
parent 20115b04d28f23f0c02b5ef23e7357ca59f9cbf7
Author: ssnf <ssnf@ssnf.xyz>
Date:   Sat, 21 Aug 2021 17:06:13 +0000

added insert and delete functions, improved file handling

Diffstat:
Mconfig.def.h | 24++++++++++++++++--------
Msim.c | 280++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
2 files changed, 215 insertions(+), 89 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -1,17 +1,25 @@ Key keys[] = { - { '$', move, EndLine }, - { '0', move, StartLine }, - { 'G', move, Top }, - { 'Q', quit }, - { 'g', move, Bottom }, { 'h', move, Left }, { 'j', move, Down }, { 'k', move, Up }, { 'l', move, Right }, - { 'o', file_open }, - { 'q', file_close , cur}, - { 's', file_save , cur}, { Ctrl + 'd', move, HalfDown }, { Ctrl + 'u', move, HalfUp }, + { '$', move, EndLine }, + { '0', move, StartLine }, + { 'G', move, Bottom }, + { 'g', move, Top }, + { 'i', insert }, + { 'I', insert , StartLine}, + { 'A', insert , EndLine }, + { 'a', insert , Right }, + { 'o', insert , Down }, + { 'O', insert , Up }, + { 'd', delete }, + { 'x', delete , 1 }, + { 'e', file_open }, + { 'q', file_close, -1 }, + { 's', file_save, -1 }, + { 'Q', quit }, { Esc, escape } }; diff --git a/sim.c b/sim.c @@ -13,7 +13,7 @@ typedef long Posn; enum { - Up, + Up = 1, Down, Left, Right, @@ -61,13 +61,16 @@ typedef struct { 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 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 delete(int arg); static void escape(int c); static void init(); +static void input(String* s, char* msg); +static void insert(int arg); static void file_close(int arg); static void file_init(File* f); -static void file_load(char* name); +static void file_load(File* f); static void file_open(int c); static void file_save(int arg); static void fr_add(Frame* fr, Posn p0, Posn p1); @@ -75,7 +78,7 @@ 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_update(int arg); static void fr_zero(Frame*); static void str_init(String* p); static void str_close(String* p); @@ -92,7 +95,6 @@ static void quit(int); static Frame* fr, frame[FILECOUNT]; static File* f, file[FILECOUNT]; static Window w; -uchar cur; #include "config.h" @@ -142,15 +144,15 @@ erealloc(void* p, ulong n) } static void -blind_reader(Frame* fr, Posn p0) +blind_reader(Frame* fr, String* s, 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]) { + for (wx = 0; wx < w.wx && p1 < s->n;) { + switch (s->s[p1]) { case '\t': wx += 4 - (wx % 4); break; @@ -162,31 +164,72 @@ blind_reader(Frame* fr, Posn p0) if (wx < w.wx) ++p1; if (wx >= w.wx) { - if (f->s->s[p1] == '\t') + if (s->s[p1] == '\t') ++p1; - if (f->s->s[p1 + 1] == '\n') + if (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'); + } while (p1 <= s->n && s->s[p1 - 1] != '\n'); } static void -blind_writer(ushort line, ushort offset, ushort top, ushort bot) +blind_writer(String* s, Frame* fr, ushort line, ushort offset, ushort top, ushort bot) { ushort i, o; - o = fr->n - 1; - i = 0; + i = o = 0; if (offset >= top) i = offset - top + 1; if (fr->n - offset > bot) o = offset + bot - 1; + else if (fr->n) + o = fr->n - 1; printf(CSI "%uH", line - offset); - fwrite(&f->s->s[fr->a[i].p0], fr->a[o].p1 - fr->a[i].p0, 1, stdout); + fwrite(&s->s[fr->a[i].p0], fr->a[o].p1 - fr->a[i].p0, 1, stdout); +} + +static void +delete(int arg) +{ + Posn m, n; + + if (!f->s->n) + return; + if (arg == 1) { + str_delete(f->s, f->dot.p0, f->dot.p1 + 1); + if (f->dot.p1 == f->s->n) + move(Left); + f->dirty = '*'; + fr_update(1); + return; + } + m = fr->a[fr->dot].p0; + switch (fgetc(stdin)) { + case 'd': + n = fr->a[fr->dot].p1 + 1; + move(StartLine); + if (fr->dot == fr->n - 1) + move(Up); + break; + case 'G': + n = f->s->n; + move(Up); + break; + case 'g': + m = 0; + n = fr->a[fr->dot].p1 + 1; + move(Top); + break; + default: + return; + } + str_delete(f->s, m, n); + f->dirty = '*'; + fr_update(1); } static void @@ -197,11 +240,95 @@ escape(int c) --c; f = &file[c]; fr = &frame[c]; - cur = c; } } static void +input(String* s, char* msg) +{ + uchar c; + + for (;;) { + printf(CSI "%uH" EL "%s%s", w.wy/2, msg, s->s); + switch (c = fgetc(stdin)) { + case Esc: + str_zero(s); + case '\n': + return; + case '\t': + continue; + case Del: + str_delc(s); + break; + default: + str_addc(s, c); + } + } +} + +static void +insert(int arg) +{ + String s; + uchar c; + + str_init(&s); + switch (arg) { + case StartLine: + move(StartLine); + break; + case EndLine: + move(EndLine); + break; + case Right: + move(Right); + if (f->dot.p0 >= f->s->n) + str_addc(f->s, '\n'); + break; + 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; + break; + case Up: + move(StartLine); + str_addc(&s, '\n'); + str_insert(f->s, &s, f->dot.p0); + str_zero(&s); + break; + default: + break; + } + for (;;) { + win_query(&w); + fr_update(0); + c = fgetc(stdin); + switch (c) { + case Esc: + if (f->dot.p1 != f->dot.p0) + str_delete(f->s, f->dot.p0, f->dot.p1); + goto endloop; + case Del: + str_delc(&s); + break; + default: + str_addc(&s, c); + } + if (f->dot.p1 != f->dot.p0) + str_delete(f->s, f->dot.p0, f->dot.p1); + str_insert(f->s, &s, f->dot.p0); + f->dot.p1 = f->dot.p0 + s.n; + } + endloop: + str_insert(f->s, &s, f->dot.p0); + str_close(&s); + f->dot.p0 = f->dot.p1; + f->dirty = '*'; +} + +static void init() { uint i; @@ -213,20 +340,24 @@ init() } f = &file[0]; fr = &frame[0]; - cur = 0; } static void file_close(int arg) { + if (arg == -1) + arg = f - file; if (file[arg].dirty) { printf(CSI "%uH" EL CSI "31mSave %s?" CSI "0m [y/n]", w.wy/2, file[arg].name->s); - if (fgetc(stdin) != 'n') + if (fgetc(stdin) == 'y') { + if (!file[arg].name->n) + input(file[arg].name, "File name: "); file_save(arg); + str_zero(f->s); + str_zero(f->name); + f->dot.p0 = f->dot.p1 = 0; + } } - str_zero(f->s); - str_zero(f->name); - f->dot.p0 = f->dot.p1 = 0; } static void @@ -240,13 +371,11 @@ file_init(File* f) } static void -file_load(char* name) +file_load(File* f) { FILE* disk; - str_zero(f->name); - str_adds(f->name, name); - if (!(disk = fopen(name, "r"))) + if (!(disk = fopen(f->name->s, "r"))) return; fseek(disk, 0, SEEK_END); f->s->n = ftell(disk); @@ -260,40 +389,27 @@ file_load(char* name) static void file_open(int c) { - String s; - - str_init(&s); - str_adds(&s, f->name->s); - printf(CSI "%uH" EL CSI "32m$" CSI "0m %s", w.wy/2, s.s); - for (;c = fgetc(stdin), c != '\n';) { - switch (c) { - case Esc: - str_close(&s); - return; - case '\t': - continue; - case Del: - str_delc(&s); - break; - default: - str_addc(&s, c); - } - printf(CSI "%uH" EL CSI "32m$" CSI "0m %s", w.wy/2, s.s); + if (f->dirty) { + printf(CSI "%uH" EL CSI "31mSave %s?" CSI "0m [y/n]", w.wy/2, f->name->s); + if (fgetc(stdin) == 'y') + file_save(f - file); } - file_load(s.s); - str_close(&s); + input(f->name, CSI "32m$ " CSI "m"); + file_load(f); } static void file_save(int arg) { - FILE* f; + FILE* disk; + if (arg == -1) + arg = f - file; if (!file[arg].name->n) return; - f = fopen(file[arg].name->s, "w"); - fwrite(file[arg].s->s, file[arg].s->n, 1, f); - fclose(f); + disk = fopen(file[arg].name->s, "w"); + fwrite(file[arg].s->s, file[arg].s->n, 1, disk); + fclose(disk); file[arg].dirty = 0; } @@ -340,7 +456,7 @@ fr_insure(Frame* fr, ushort n) } static void -fr_update() +fr_update(int arg) { Frame fr0; Posn p0, p1; @@ -348,10 +464,11 @@ fr_update() half = w.wy >> 1; if (!f->s->n) { + fr->a[0].p0 = fr->a[0].p1 = 0; printf(ED); goto status; } - if (!fr->n || f->dot.p1 > fr->a[fr->n - 1].p1 || f->dot.p1 < fr->a[0].p0 || fr->n - fr->dot < half || fr->dot < half) { + if (arg || !fr->n || f->dot.p0 != f->dot.p1 || f->dot.p1 > fr->a[fr->n - 1].p1 || f->dot.p1 < fr->a[0].p0 || fr->n - fr->dot <= w.wy || fr->dot <= half) { fr_zero(fr); for (p0 = f->dot.p1; p0; --p0) if (f->s->s[p0 - 1] == '\n') @@ -360,7 +477,7 @@ fr_update() fr_init(&fr0); for (--p1; p1 && fr->n < w.wy;) { for (;p1 && f->s->s[p1 - 1] != '\n'; --p1); - blind_reader(&fr0, p1); + blind_reader(&fr0, f->s, p1); if ((p1 = fr0.a[0].p0)) --p1; fr_insert(fr, &fr0, 0); @@ -368,8 +485,8 @@ fr_update() } fr_close(&fr0); } - for (p1 = p0; p1 < f->s->n - 1 && fr->n < 2 * w.wy;) { - blind_reader(fr, p1); + for (p1 = p0; p1 < f->s->n && fr->n < 3 * w.wy;) { + blind_reader(fr, f->s, p1); p1 = fr->a[fr->n - 1].p1 + 1; } for (;f->dot.p1 > fr->a[fr->dot].p1; ++fr->dot); @@ -381,7 +498,7 @@ fr_update() goto full_update; } status: - printf(CSI "%uH" "%lu 0x%02x -%u- %s", w.wy, f->dot.p1, f->s->s[f->dot.p1], cur, f->name->s); + printf(CSI "%uH" "%lu;%lu;%lu 0x%02x -%lu- %s%c", w.wy, f->s->n, f->dot.p0, f->dot.p1, f->s->s[f->dot.p1], f - file, f->name->s, f->dirty); for (p0 = fr->a[fr->dot].p0, p1 = 1; p0 < f->dot.p1; ++p0) { if (f->s->s[p0] == '\t' && p1 % 4) { p1 += 5 - (p1 % 4); @@ -391,7 +508,7 @@ fr_update() return; full_update: printf(ED); - blind_writer(half, fr->dot, half, half + (w.wy % 2)); + blind_writer(f->s, fr, half, fr->dot, half, half + (w.wy % 2)); goto status; } @@ -415,14 +532,16 @@ move(int arg) f->dot.p0 = ++f->dot.p1; break; case Up: - if (f->dot.p1) - for (;--f->dot.p1, f->dot.p1 && f->s->s[f->dot.p1] != '\n';); - f->dot.p0 = f->dot.p1; + if (fr->dot) + f->dot.p0 = f->dot.p1 = fr->a[fr->dot - 1].p0; + else + f->dot.p0 = f->dot.p1 = 0; break; case Down: - 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; + if (fr->dot < fr->n - 1) + f->dot.p0 = f->dot.p1 = fr->a[fr->dot + 1].p0; + else + f->dot.p0 = f->dot.p1 = fr->a[fr->dot].p1; break; case HalfUp: if (fr->dot < w.wy/2) @@ -449,14 +568,10 @@ move(int arg) f->dot.p0 = f->dot.p1 = f->s->n - 1; break; case StartLine: - if (f->dot.p1) - for (;f->dot.p1 && f->s->s[f->dot.p1 - 1] != '\n'; --f->dot.p1); - f->dot.p0 = f->dot.p1; + f->dot.p0 = f->dot.p1 = fr->a[fr->dot].p0; break; case EndLine: - if (f->dot.p1 + 1 < f->s->n) - for (;f->dot.p1 + 1 < f->s->n && f->s->s[f->dot.p1] != '\n'; ++f->dot.p1); - f->dot.p0 = f->dot.p1; + f->dot.p0 = f->dot.p1 = fr->a[fr->dot].p1; break; }; } @@ -464,6 +579,10 @@ move(int arg) static void quit(int arg) { + uint i; + + for (i = 0; i < FILECOUNT; ++i) + file_close(i); win_end(); exit(arg); } @@ -497,13 +616,7 @@ static void str_insure(String* p, ulong n) { if (p->size < n) { - n += MAXEMPTY; - p->s = erealloc(p->s, n * sizeof(*p->s)); - p->size = n; - return; - } - if (p->size - p->n > MAXEMPTY) { - p->size = p->n + MAXEMPTY; + p->size = n + MAXEMPTY; p->s = erealloc(p->s, p->size * sizeof(*p->s)); } } @@ -536,6 +649,8 @@ str_delc(String* p) static void str_insert(String* p, String* q, Posn p0) { + if (p0 > p->n) + p0 = p->n; str_insure(p, p->n + q->n); memmove(p->s + p0 + q->n, p->s + p0, p->n - p0); memmove(p->s + p0, q->s, q->n); @@ -545,6 +660,8 @@ str_insert(String* p, String* q, Posn p0) static void str_delete(String* p, Posn p0, Posn p1) { + if (p1 > p->n) + p1 = p->n; memmove(p->s + p0, p->s + p1, p->n - p1); p->n -= p1 - p0; } @@ -556,11 +673,13 @@ main(int argc, char* argv[]) uchar c; init(); - if (argv[1]) - file_load(argv[1]); + if (argv[1]) { + str_adds(f->name, argv[1]); + file_load(f); + } for (;;) { win_query(&w); - fr_update(); + fr_update(0); c = fgetc(stdin); for (i = 0; i < LENGTH(keys); ++i) { if (keys[i].key == c) { @@ -568,6 +687,5 @@ main(int argc, char* argv[]) break; } } - fr_update(); } }