From e14432eae4ee28abb56fe530039f7fa10d0d99a2 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Tue, 20 Aug 2019 10:24:00 -0400 Subject: [PATCH] Saving and backspacing --- kilo.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 6 deletions(-) diff --git a/kilo.c b/kilo.c index 1c0ec8b..e77bb73 100644 --- a/kilo.c +++ b/kilo.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -19,7 +20,8 @@ /*** defines ***/ #define KILO_VERSION "0.0.1" -#define KILO_TAB_STOP 8 +#define KILO_TAB_STOP 4 +#define KILO_QUIT_TIMES 3 #define CTRL_KEY(k) ((k) & 0x1f) @@ -54,6 +56,7 @@ struct editorConfig { int screencols; int numrows; erow *row; + int dirty; char *filename; char statusmsg[80]; time_t statusmsg_time; @@ -62,6 +65,10 @@ struct editorConfig { struct editorConfig E; +/*** prototypes ***/ + +void editorSetStatusMessage(const char *fmt, ...); + /*** terminal ***/ void die(const char *s) @@ -311,6 +318,7 @@ void editorAppendRow(char *s, size_t len) editorUpdateRow(&E.row[at]); E.numrows++; + E.dirty++; } void editorRowInsertChar(erow *row, int at, int c) @@ -325,6 +333,20 @@ void editorRowInsertChar(erow *row, int at, int c) row->size++; row->chars[at] = c; editorUpdateRow(row); + E.dirty++; +} + +void editorRowDelChar(erow *row, int at) +{ + if (at < 0 || at >= row->size) + { + return; + } + + memmove(&row->chars[at], &row->chars[at + 1], row->size - at); + row->size--; + editorUpdateRow(row); + E.dirty++; } /*** editor operations ***/ @@ -339,7 +361,46 @@ void editorInsertChar(int c) E.cx++; } +void editorDelChar() +{ + if (E.cy == E.numrows) + { + return; + } + + erow *row = &E.row[E.cy]; + if (E.cx > 0) + { + editorRowDelChar(row, E.cx - 1); + E.cx--; + } +} + /*** file i/o ***/ + +char *editorRowsToString(int *buflen) +{ + int totlen = 0; + int j; + for (j = 0; j < E.numrows; j++) + { + totlen += E.row[j].size + 1; + } + *buflen = totlen; + + char *buf = malloc(totlen); + char *p = buf; + for (j = 0; j < E.numrows; j++) + { + memcpy(p, E.row[j].chars, E.row[j].size); + p += E.row[j].size; + *p = '\n'; + p++; + } + + return buf; +} + void editorOpen(char *filename) { free(E.filename); @@ -367,6 +428,37 @@ void editorOpen(char *filename) free(line); fclose(fp); + E.dirty = 0; +} + +void editorSave() +{ + if (E.filename == NULL) + { + return; + } + + int len; + char *buf = editorRowsToString(&len); + + int fd = open(E.filename, O_RDWR | O_CREAT, 0644); + if (fd != -1) + { + if (ftruncate(fd, len) != -1) + { + if (write(fd, buf, len) == len) + { + close(fd); + free(buf); + E.dirty = 0; + editorSetStatusMessage("%d bytes written to disk", len); + return; + } + } + close(fd); + } + free(buf); + editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno)); } /*** append buffer ***/ @@ -491,8 +583,9 @@ void editorDrawStatusBar(struct abuf *ab) { abAppend(ab, "\x1b[7m", 4); char status[80], rstatus[80]; - int len = snprintf(status, sizeof(status), "%.20s - %d lines", - E.filename ? E.filename : "[No Name]", E.numrows); + int len = snprintf(status, sizeof(status), "%.20s - %d lines %s", + E.filename ? E.filename : "[No Name]", E.numrows, + E.dirty ? "(modified)" : ""); int rlen = snprintf(rstatus, sizeof(rstatus), "%d/%d", E.cy + 1, E.numrows); @@ -626,6 +719,8 @@ void editorMoveCursor(int key) void editorProcessKeypress() { + static int quit_times = KILO_QUIT_TIMES; + int c = editorReadKey(); switch (c) @@ -635,11 +730,22 @@ void editorProcessKeypress() break; case CTRL_KEY('q'): + if (E.dirty && quit_times > 0) + { + editorSetStatusMessage("WARNING!!! File has unsaved changes ." + "Press Ctrl-Q %d more time(s) to quit.", quit_times); + quit_times--; + return; + } write(STDOUT_FILENO, "\x1b[2J", 4); write(STDOUT_FILENO, "\x1b[H", 3); exit(0); break; + case CTRL_KEY('s'): + editorSave(); + break; + case HOME_KEY: E.cx = 0; break; @@ -654,11 +760,16 @@ void editorProcessKeypress() case BACKSPACE: case CTRL_KEY('h'): case DEL_KEY: - /* TODO */ + if (c == DEL_KEY) + { + editorMoveCursor(ARROW_RIGHT); + } + editorDelChar(); break; case PAGE_UP: - case PAGE_DOWN: { + case PAGE_DOWN: + { if (c == PAGE_UP) { E.cy = E.rowoff; @@ -695,6 +806,8 @@ void editorProcessKeypress() editorInsertChar(c); break; } + + quit_times = KILO_QUIT_TIMES; } /*** init ***/ @@ -708,6 +821,7 @@ void initEditor() E.coloff = 0; E.numrows = 0; E.row = NULL; + E.dirty = 0; E.filename = NULL; E.statusmsg[0] = '\0'; E.statusmsg_time = 0; @@ -729,7 +843,7 @@ int main(int argc, char *argv[]) editorOpen(argv[1]); } - editorSetStatusMessage("HELP: Ctrl-Q = quit"); + editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = quit"); while (1) {