Implement vertical scrolling (so far)
This commit is contained in:
parent
af9379057f
commit
6664dd67e9
1 changed files with 67 additions and 34 deletions
99
kilo.c
99
kilo.c
|
@ -1,6 +1,5 @@
|
||||||
#define _BSD_SOURCE
|
|
||||||
#define _DEFAULT_SOURCE
|
#define _DEFAULT_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define KILO_VERSION "0.0.1"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -16,6 +15,9 @@
|
||||||
|
|
||||||
#define CTRL_KEY(key) ((key) & 0x1f)
|
#define CTRL_KEY(key) ((key) & 0x1f)
|
||||||
|
|
||||||
|
#define MAX(a, b) (((a)>(b))?(a):(b))
|
||||||
|
#define MIN(a, b) (((a)<(b))?(a):(b))
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
struct screen_buf;
|
struct screen_buf;
|
||||||
|
@ -29,11 +31,14 @@ struct erow {
|
||||||
struct {
|
struct {
|
||||||
int cx, cy;
|
int cx, cy;
|
||||||
int screenrows, screencols;
|
int screenrows, screencols;
|
||||||
int display_rows;
|
int row_off, col_off;
|
||||||
bool running;
|
|
||||||
struct erow row;
|
struct erow *rows;
|
||||||
|
int n_rows;
|
||||||
|
|
||||||
struct termios orig_termios;
|
struct termios orig_termios;
|
||||||
struct input_buf *ib;
|
struct input_buf *ib;
|
||||||
|
bool running;
|
||||||
} E;
|
} E;
|
||||||
|
|
||||||
enum KEYS {
|
enum KEYS {
|
||||||
|
@ -54,15 +59,15 @@ typedef uint16_t KEY;
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void editor_init();
|
void editor_init();
|
||||||
void editor_open();
|
void editor_open(char *);
|
||||||
|
void editor_append_row(const char *, int);
|
||||||
void editor_redraw_screen();
|
void editor_redraw_screen();
|
||||||
void editor_draw_rows(struct screen_buf *);
|
void editor_draw_rows(struct screen_buf *);
|
||||||
void editor_process_key();
|
void editor_process_key();
|
||||||
void editor_free();
|
void editor_free();
|
||||||
|
|
||||||
struct screen_buf *sb_init();
|
struct screen_buf *sb_init();
|
||||||
void sb_append(struct screen_buf *, const char *);
|
void sb_append(struct screen_buf *, const char *, int);
|
||||||
void sb_append_max(struct screen_buf *, const char *, int);
|
|
||||||
void sb_write(struct screen_buf *);
|
void sb_write(struct screen_buf *);
|
||||||
void sb_free(struct screen_buf *);
|
void sb_free(struct screen_buf *);
|
||||||
|
|
||||||
|
@ -86,9 +91,11 @@ void die(const char *);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
int main() {
|
int main(int argc, char **argv) {
|
||||||
editor_init();
|
editor_init();
|
||||||
editor_open();
|
|
||||||
|
if (argc >= 2)
|
||||||
|
editor_open(argv[1]);
|
||||||
|
|
||||||
while (E.running) {
|
while (E.running) {
|
||||||
editor_redraw_screen();
|
editor_redraw_screen();
|
||||||
|
@ -112,18 +119,40 @@ void editor_init() {
|
||||||
|
|
||||||
E.cx = E.cy = 0;
|
E.cx = E.cy = 0;
|
||||||
if (term_get_win_size(&E.screenrows, &E.screencols) == -1) die("term_get_win_size");
|
if (term_get_win_size(&E.screenrows, &E.screencols) == -1) die("term_get_win_size");
|
||||||
E.display_rows = 0;
|
E.row_off = E.col_off = 0;
|
||||||
|
|
||||||
|
E.n_rows = 0;
|
||||||
E.running = true;
|
E.running = true;
|
||||||
E.ib = ib_init(128);
|
E.ib = ib_init(128);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_open() {
|
void editor_open(char *filename) {
|
||||||
char *line = "hello world";
|
FILE *file = fopen(filename, "r");
|
||||||
int line_len = (int) strlen(line);
|
if (!file) die("fopen");
|
||||||
|
|
||||||
E.row.s = line;
|
char *line = NULL;
|
||||||
E.row.size = line_len;
|
size_t linecap = 0;
|
||||||
E.display_rows = 1;
|
int linelen = -1;
|
||||||
|
|
||||||
|
while ((linelen = getline(&line, &linecap, file)) != -1) {
|
||||||
|
while (linelen > 0 && (line[linelen-1] == '\n' || line[linelen-1] == '\r'))
|
||||||
|
linelen--;
|
||||||
|
|
||||||
|
editor_append_row(line, linelen);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void editor_append_row(const char *s, int len) {
|
||||||
|
E.rows = realloc(E.rows, sizeof(struct erow) * (E.n_rows + 1));
|
||||||
|
|
||||||
|
E.rows[E.n_rows].s = malloc(len);
|
||||||
|
memcpy(E.rows[E.n_rows].s, s, len);
|
||||||
|
|
||||||
|
E.rows[E.n_rows++].size = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_redraw_screen() {
|
void editor_redraw_screen() {
|
||||||
|
@ -134,7 +163,7 @@ void editor_redraw_screen() {
|
||||||
sb_write(sb);
|
sb_write(sb);
|
||||||
sb_free(sb);
|
sb_free(sb);
|
||||||
|
|
||||||
if (term_set_cursor_pos(E.cy + 1, E.cx + 1) == -1) die("term_set_cursor_pos");
|
if (term_set_cursor_pos(E.cy - E.row_off + 1, E.cx + 1) == -1) die("term_set_cursor_pos");
|
||||||
if (term_cursor_hidden(false) == -1) die("term_cursor_hidden");
|
if (term_cursor_hidden(false) == -1) die("term_cursor_hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,12 +171,22 @@ void editor_draw_rows(struct screen_buf *sb) {
|
||||||
term_set_cursor_pos(1, 1);
|
term_set_cursor_pos(1, 1);
|
||||||
|
|
||||||
for (int y = 0; y < E.screenrows; y++) {
|
for (int y = 0; y < E.screenrows; y++) {
|
||||||
if (y < E.display_rows) {
|
if (y < E.screenrows && y+E.row_off < E.n_rows) {
|
||||||
sb_append_max(sb, E.row.s, E.screencols);
|
sb_append(sb, E.rows[y+E.row_off].s, MIN(E.rows[y+E.row_off].size, E.screencols));
|
||||||
} else sb_append(sb, "~");
|
} else if (E.n_rows == 0 && y == E.screenrows / 2) {
|
||||||
|
char welcome[64];
|
||||||
|
int len = snprintf(welcome, sizeof(welcome), "Welcome to kilo! -- v%s", KILO_VERSION);
|
||||||
|
|
||||||
sb_append(sb, "\x1b[K"); // Clear rest of the line
|
int padding = (E.screencols - len) / 2;
|
||||||
if (y < E.screenrows - 1) sb_append(sb, "\r\n");
|
if (padding--)
|
||||||
|
sb_append(sb, "~", 1);
|
||||||
|
while (padding-- > 0) sb_append(sb, " ", 1);
|
||||||
|
|
||||||
|
sb_append(sb, welcome, len);
|
||||||
|
} else sb_append(sb, "~", 1);
|
||||||
|
|
||||||
|
sb_append(sb, "\x1b[K", 3); // Clear rest of the line
|
||||||
|
if (y < E.screenrows - 1) sb_append(sb, "\r\n", 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,10 +199,12 @@ void editor_process_key() {
|
||||||
if (E.cx > 0) E.cx--;
|
if (E.cx > 0) E.cx--;
|
||||||
break;
|
break;
|
||||||
case ARROW_DOWN:
|
case ARROW_DOWN:
|
||||||
if (E.cy < E.screenrows - 1) E.cy++;
|
if (E.cy < E.n_rows - 1) E.cy++;
|
||||||
|
if (E.cy > E.row_off + E.screenrows - 1) E.row_off = E.cy - E.screenrows + 1;
|
||||||
break;
|
break;
|
||||||
case ARROW_UP:
|
case ARROW_UP:
|
||||||
if (E.cy > 0) E.cy--;
|
if (E.cy > 0) E.cy--;
|
||||||
|
if (E.row_off > E.cy) E.row_off = E.cy;
|
||||||
break;
|
break;
|
||||||
case ARROW_RIGHT:
|
case ARROW_RIGHT:
|
||||||
if (E.cx < E.screencols - 1) E.cx++;
|
if (E.cx < E.screencols - 1) E.cx++;
|
||||||
|
@ -209,14 +250,7 @@ struct screen_buf *sb_init() {
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sb_append(struct screen_buf *sb, const char *s) {
|
void sb_append(struct screen_buf *sb, const char *s, int size) {
|
||||||
sb_append_max(sb, s, INT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sb_append_max(struct screen_buf *sb, const char *s, int max_size) {
|
|
||||||
int size = strlen(s);
|
|
||||||
size = (size > max_size ? max_size : size);
|
|
||||||
|
|
||||||
sb->s = realloc(sb->s, sb->size + size);
|
sb->s = realloc(sb->s, sb->size + size);
|
||||||
memcpy(sb->s + sb->size, s, size);
|
memcpy(sb->s + sb->size, s, size);
|
||||||
|
|
||||||
|
@ -363,7 +397,6 @@ KEY term_read_key() {
|
||||||
if (c == '\x1b') {
|
if (c == '\x1b') {
|
||||||
char buf[8] = { '\0' };
|
char buf[8] = { '\0' };
|
||||||
|
|
||||||
// Inefficient but I like the way it looks
|
|
||||||
for (int i = 0; i < (int) sizeof(buf); i++) {
|
for (int i = 0; i < (int) sizeof(buf); i++) {
|
||||||
if (read(STDIN_FILENO, buf+i, 1) == 0) break;
|
if (read(STDIN_FILENO, buf+i, 1) == 0) break;
|
||||||
|
|
||||||
|
|
Reference in a new issue