From ad5cf0d4b7dc619bf567a795fc372fe672627d12 Mon Sep 17 00:00:00 2001 From: Braeden Sowinski Date: Tue, 6 Sep 2022 22:36:03 -0700 Subject: [PATCH] delete, enter key handling --- .gitignore | 3 + level.cpp | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 176 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 59c8aa1..4ab8bdc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ # Visual Studio Config .vs/* +# Test file +test.txt + # Output level \ No newline at end of file diff --git a/level.cpp b/level.cpp index f93c0ab..33ac50f 100644 --- a/level.cpp +++ b/level.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -22,10 +23,12 @@ #define LEVEL_VERSION "0.0.1" #define LEVEL_TAB_STOP 8 +#define LEVEL_QUIT_TIMES 3 #define CTRL_KEY(k) ((k) & 0x1f) enum editorKey { + BACKSPACE = 127, ARROW_LEFT = 1000, ARROW_RIGHT, ARROW_UP, @@ -56,6 +59,7 @@ struct editorConfig { int screencols; int numrows; erow *row; + int dirty; char *filename; char statusmsg[80]; time_t statusmsg_time; @@ -64,6 +68,10 @@ struct editorConfig { struct editorConfig E; +/*** prototypes ***/ + +void editorSetStatusMessage(const char* fmt, ...); + /*** terminal ***/ void die(const char *s) { @@ -219,10 +227,12 @@ void editorUpdateRow(erow *row) { row->rsize = idx; } -void editorAppendRow(char *s, size_t len) { +void editorInsertRow(int at, const char *s, size_t len) { + if (at < 0 || at > E.numrows) return; + E.row = (erow*)realloc(E.row, sizeof(erow) * (E.numrows + 1)); + memmove(&E.row[at + 1], &E.row[at], sizeof(erow) * (E.numrows - at)); - int at = E.numrows; E.row[at].size = len; E.row[at].chars = (char*)malloc(len + 1); memcpy(E.row[at].chars, s, len); @@ -233,10 +243,108 @@ void editorAppendRow(char *s, size_t len) { editorUpdateRow(&E.row[at]); E.numrows++; + E.dirty++; +} + +void editorFreeRow(erow* row) { + free(row->render); + free(row->chars); +} + +void editorDelRow(int at) { + if (at < 0 || at >= E.numrows) return; + editorFreeRow(&E.row[at]); + memmove(&E.row[at], &E.row[at + 1], sizeof(erow) * (E.numrows - at - 1)); + E.numrows--; + E.dirty++; +} + +void editorRowInsertChar(erow* row, int at, int c) { + if (at < 0 || at > row->size) at = row->size; + row->chars = (char*)realloc(row->chars, row->size + 2); + memmove(&row->chars[at + 1], &row->chars[at], row->size - at + 1); + row->size++; + row->chars[at] = c; + editorUpdateRow(row); + E.dirty++; +} + +void editorRowAppendString(erow* row, const char* s, size_t len) { + row->chars = (char*)realloc(row->chars, row->size + len + 1); + memcpy(&row->chars[row->size], s, len); + row->size += len; + row->chars[row->size] = '\0'; + 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 ***/ + +void editorInsertChar(int c) { + if (E.cy == E.numrows) editorInsertRow(E.numrows, "", 0); + editorRowInsertChar(&E.row[E.cy], E.cx, c); + E.cx++; +} + +void editorInsertNewLine() { + if (E.cx == 0) { + editorInsertRow(E.cy, "", 0); + } else { + erow *row = &E.row[E.cy]; + editorInsertRow(E.cy + 1, &row->chars[E.cx], row->size - E.cx); + row = &E.row[E.cy]; + row->size = E.cx; + row->chars[row->size] = '\0'; + editorUpdateRow(row); + } + E.cy++; + E.cx = 0; +} + +void editorDelChar() { + if (E.cy == E.numrows) return; + if (E.cx == 0 && E.cy == 0) return; + + erow* row = &E.row[E.cy]; + if (E.cx > 0) { + editorRowDelChar(row, E.cx - 1); + E.cx--; + } else { + E.cx = E.row[E.cy - 1].size; + editorRowAppendString(&E.row[E.cy - 1], row->chars, row->size); + editorDelRow(E.cy); + E.cy--; + } } /*** file i/o ***/ +char* editorRowsToString(int* buflen) { + int total_len = 0; + for (int j = 0; j < E.numrows; j++) + total_len += E.row[j].size + 1; + *buflen = total_len; + + char *buf = (char*)malloc(total_len); + char *p = buf; + for (int 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); E.filename = strdup(filename); @@ -251,11 +359,35 @@ E.filename = strdup(filename); while (linelen > 0 && (line[linelen - 1] == '\n' || line[linelen - 1] == '\r')) linelen--; - editorAppendRow(line, linelen); + editorInsertRow(E.numrows, line, linelen); } 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("Successfully Saved"); + return; + } + } + close(fd); + } + + free(buf); + editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno)); } /*** append buffer ***/ @@ -326,8 +458,9 @@ void editorDrawRows(struct abuf *ab) { 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); if (len > E.screencols) len = E.screencols; @@ -409,16 +542,32 @@ void editorMoveCursor(int key) { } void editorProcessKeypress() { + static int quit_times = LEVEL_QUIT_TIMES; + int c = editorReadKey(); switch (c) { + case '\r': + editorInsertNewLine(); + break; + case CTRL_KEY('q'): + if (E.dirty && quit_times > 0) { + editorSetStatusMessage("WARNING! File has unsaved Changed. " + "Press Ctrl-Q %d more times 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; @@ -427,6 +576,13 @@ void editorProcessKeypress() { if (E.cy < E.numrows) E.cx = E.row[E.cy].size; break; + case BACKSPACE: + case CTRL_KEY('h'): + case DEL_KEY: + if (c == DEL_KEY) editorMoveCursor(ARROW_RIGHT); + editorDelChar(); + break; + case PAGE_UP: case PAGE_DOWN: { @@ -448,7 +604,17 @@ void editorProcessKeypress() { case ARROW_RIGHT: editorMoveCursor(c); break; + + case CTRL_KEY('l'): + case '\x1b': + break; + + default: + editorInsertChar(c); + break; } + + quit_times = LEVEL_QUIT_TIMES; } /*** init ***/ @@ -461,6 +627,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; @@ -474,7 +641,7 @@ int main(int argc, char *argv[]) { initEditor(); if (argc >= 2) editorOpen(argv[1]); - editorSetStatusMessage("HELP: Ctrl-Q = quit"); + editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = quit"); while (1) { editorRefreshScreen();