diff --git a/csedit b/csedit index 6f9a362..122ef1e 100755 Binary files a/csedit and b/csedit differ diff --git a/csedit.c b/csedit.c index b56e89c..770dbd7 100644 --- a/csedit.c +++ b/csedit.c @@ -1,12 +1,17 @@ // // includes // -------- +#define _DEFAULT_SOURCE +#define _BSD_SOURCE +#define _GNU_SOURCE + #include #include #include #include #include #include +#include #include #include @@ -34,16 +39,25 @@ enum editorKey { // data // ---- +typedef struct erow { + int size; + char *chars; +} erow; + struct editorConfig { - struct termios orig_termios; enum editorMode mode; + int rowoff; int cx, cy; int screenRows; int screenCols; + int numRows; + erow *row; + struct termios orig_termios; }; struct editorConfig E; + // // terminal // -------- @@ -159,6 +173,42 @@ int getWindowSize(int *rows, int *cols) { return 0; } +// +// row ops +// ------- + +void editorAppendRow(char *s, size_t len) { + E.row = realloc(E.row, sizeof(erow) * (E.numRows + 1)); + + int at = E.numRows; + E.row[at].size = len; + E.row[at].chars = malloc(len + 1); + memcpy(E.row[at].chars, s, len); + E.row[at].chars[len] = '\0'; + E.numRows++; +} + +// +// file io +// ------- + +void editorOpen(char *filename) { + FILE *fp = fopen(filename, "r"); + if (!fp) die("Open file"); + + char *line = NULL; + size_t linecap = 0; + ssize_t linelen; + while ((linelen = getline(&line, &linecap, fp)) != -1) { + while (linelen > 0 && (line[linelen - 1] == '\n' || line[linelen - 1] == '\r')) + linelen--; + editorAppendRow(line, linelen); + + } + free(line); + fclose(fp); +} + // // append buffer // ------------- @@ -185,22 +235,38 @@ void abFree(struct abuf *ab) { // // output // ------ +void editorScroll() { + if (E.cy < E.rowoff) { + E.rowoff = E.cy; + } + if (E.cy >= E.rowoff + E.screenRows) { + E.rowoff = E.cy - E.screenRows + 1; + } +} + void editorDrawRows(struct abuf *ab) { int y; for (y = 0; y < E.screenRows; y++) { - if (y == E.screenRows / 3) { - char welcome[80]; - int welcomelen = snprintf(welcome, sizeof(welcome), "[ cs edit ] - version %s", CSEDIT_VERSION); - if (welcomelen > E.screenCols) welcomelen = E.screenCols; - int padding = (E.screenCols - welcomelen) / 2; - if (padding) { + int filerow = y + E.rowoff; + if (filerow >= E.numRows) { + if (E.numRows == 0 && y == E.screenRows / 3) { + char welcome[80]; + int welcomelen = snprintf(welcome, sizeof(welcome), "[ cs edit ] - version %s", CSEDIT_VERSION); + if (welcomelen > E.screenCols) welcomelen = E.screenCols; + int padding = (E.screenCols - welcomelen) / 2; + if (padding) { + abAppend(ab, "~", 1); + padding--; + } + while (padding--) abAppend(ab, " ", 1); + abAppend(ab, welcome, welcomelen); + } else { abAppend(ab, "~", 1); - padding--; } - while (padding--) abAppend(ab, " ", 1); - abAppend(ab, welcome, welcomelen); } else { - abAppend(ab, "~", 1); + int len = E.row[filerow].size; + if (len > E.screenCols) len = E.screenCols; + abAppend(ab, E.row[filerow].chars, len); } abAppend(ab, "\033[K", 3); @@ -212,6 +278,8 @@ void editorDrawRows(struct abuf *ab) { } void editorRefreshScreen() { + editorScroll(); + struct abuf ab = ABUF_INIT; abAppend(&ab, "\033[?25l", 6); @@ -219,7 +287,7 @@ void editorRefreshScreen() { editorDrawRows(&ab); char buf[32]; - snprintf(buf, sizeof(buf), "\033[%d;%dH", E.cy + 1, E.cx + 1); + snprintf(buf, sizeof(buf), "\033[%d;%dH", (E.cy - E.rowoff) + 1, E.cx + 1); abAppend(&ab, buf, strlen(buf)); abAppend(&ab, "\033[?25h", 6); @@ -235,7 +303,7 @@ void editorMoveCursor(int key) { switch (key) { case 'j': case ARROW_DOWN: - if (E.cy != E.screenRows - 1) { + if (E.cy < E.numRows) { E.cy++; } break; @@ -285,6 +353,13 @@ void editorCommandKp(int c) { case 'l': editorMoveCursor(c); break; + case 'g': + E.cy = 0; + break; + case 'G': + E.cy = E.numRows - E.screenRows - 1; + editorPageCursor(PAGE_DOWN); + break; case 'i': E.mode = InputMode; break; @@ -345,14 +420,20 @@ void editorProcessKeypress() { // ---- void initEditor() { E.mode = CommandMode; + E.rowoff = 0; + E.numRows = 0; + E.row = NULL; E.cx = 0; E.cy = 0; if (getWindowSize(&E.screenRows, &E.screenCols) == -1) die("getWindowSize"); } -int main() { +int main(int argc, char *argv[]) { enableRawMode(); initEditor(); + if (argc >= 2) { + editorOpen(argv[1]); + } while (1) { editorRefreshScreen();