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:
M | config.def.h | | | 24 | ++++++++++++++++-------- |
M | sim.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();
}
}