Status bar / editing / saving file
This commit is contained in:
@@ -16,7 +16,7 @@ build: main.c src/*
|
|||||||
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/*
|
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/*
|
||||||
doxygen
|
doxygen
|
||||||
|
|
||||||
DEBUG_FLAGS=-Wall -Wextra -pedantic -Werror -fsanitize=address,undefined -g
|
DEBUG_FLAGS=-Wall -Wextra -pedantic -Werror -fsanitize=address -g
|
||||||
|
|
||||||
debug: main.c src/*
|
debug: main.c src/*
|
||||||
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
||||||
|
|||||||
+30
-11
@@ -2,10 +2,19 @@
|
|||||||
#define DATA_H_
|
#define DATA_H_
|
||||||
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct erow
|
||||||
|
* \brief Store one editor row
|
||||||
|
* \param
|
||||||
|
* */
|
||||||
|
|
||||||
typedef struct erow {
|
typedef struct erow {
|
||||||
int size;
|
int size; /**< Size of the line */
|
||||||
char *chars;
|
int rsize; /**< Size of the render line */
|
||||||
|
char *chars; /**< Characters of the line */
|
||||||
|
char *render; /**< The actual line we will print */
|
||||||
} erow;
|
} erow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,18 +22,28 @@ typedef struct erow {
|
|||||||
* \brief Containing our editor state.
|
* \brief Containing our editor state.
|
||||||
*/
|
*/
|
||||||
struct editorConfig {
|
struct editorConfig {
|
||||||
int cursor_x, cursor_y;
|
int cursor_x, cursor_y; /**< Cursor position */
|
||||||
int row_offset;
|
int rx; /**< Position in the render*/
|
||||||
int screenrows;
|
int row_offset; /**< Position scroll of lines */
|
||||||
int screencols;
|
int col_offset; /**< Position scroll of colomns*/
|
||||||
int numrows;
|
int screenrows; /**< Terminal height*/
|
||||||
erow *row;
|
int screencols; /**< Terminal width*/
|
||||||
struct termios orig_termios;
|
int numrows; /**< Number of rows contained */
|
||||||
|
erow *row; /**< Store all the rows printed */
|
||||||
|
char *filename;
|
||||||
|
char status_msg[80];
|
||||||
|
time_t status_msg_time;
|
||||||
|
struct termios orig_termios; /**< Terminal communication interface */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct abuf
|
||||||
|
* \brief Contains text to add before writing to screen.
|
||||||
|
* */
|
||||||
|
|
||||||
struct abuf {
|
struct abuf {
|
||||||
char *b;
|
char *b; /**< Text that will be printed */
|
||||||
int len;
|
int len; /**< Length of the text */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#define ERASE_END_LINE "\x1b[K"
|
#define ERASE_END_LINE "\x1b[K"
|
||||||
|
|
||||||
enum editorKey {
|
enum editorKey {
|
||||||
|
BACKSPACE = 127,
|
||||||
CURSOR_LEFT = 1000,
|
CURSOR_LEFT = 1000,
|
||||||
CURSOR_RIGHT,
|
CURSOR_RIGHT,
|
||||||
CURSOR_UP,
|
CURSOR_UP,
|
||||||
@@ -23,5 +24,6 @@ enum editorKey {
|
|||||||
#define ABUF_INIT {NULL, 0}
|
#define ABUF_INIT {NULL, 0}
|
||||||
|
|
||||||
#define BELUGA_VERSION "0.1"
|
#define BELUGA_VERSION "0.1"
|
||||||
|
#define TAB_LENGTH 8
|
||||||
|
|
||||||
#endif // DEFINE_H_
|
#endif // DEFINE_H_
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef EDITOR_OP_H_
|
||||||
|
#define EDITOR_OP_H_
|
||||||
|
|
||||||
|
#include "data.h"
|
||||||
|
void editorInsertChar(struct editorConfig *E, int c);
|
||||||
|
|
||||||
|
#endif // EDITOR_OP_H_
|
||||||
@@ -8,6 +8,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
char *editorRowsToString(struct editorConfig *E, int *buffer_len);
|
||||||
|
|
||||||
void editorOpen(struct editorConfig *E, char *filename);
|
void editorOpen(struct editorConfig *E, char *filename);
|
||||||
|
|
||||||
|
void editorSave(struct editorConfig *E);
|
||||||
|
|
||||||
#endif // FILE_IO_H_
|
#endif // FILE_IO_H_
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "append_buffer.h"
|
#include "append_buffer.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "define.h"
|
#include "define.h"
|
||||||
|
#include "row_op.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@@ -16,4 +17,12 @@ void editorDrawRows(struct editorConfig *E, struct abuf *ab);
|
|||||||
|
|
||||||
void editorRefreshScreen(struct editorConfig *E);
|
void editorRefreshScreen(struct editorConfig *E);
|
||||||
|
|
||||||
|
void editorScroll(struct editorConfig *E);
|
||||||
|
|
||||||
|
void editorDrawStatusBar(struct editorConfig *E, struct abuf *ab);
|
||||||
|
|
||||||
|
void editorDrawMessageBar(struct editorConfig *E, struct abuf *ab);
|
||||||
|
|
||||||
|
void editorSetStatusMessage(struct editorConfig *E, const char *fmt, ...);
|
||||||
|
|
||||||
#endif // OUTPUT_H_
|
#endif // OUTPUT_H_
|
||||||
|
|||||||
@@ -2,10 +2,17 @@
|
|||||||
#define ROW_OP_H_
|
#define ROW_OP_H_
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "define.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int editorRowCxToRx(erow *row, int cursor_x);
|
||||||
|
|
||||||
|
void editorUpdateRow(erow *row);
|
||||||
|
|
||||||
void editorAppendRow(struct editorConfig *E, char *s, size_t len);
|
void editorAppendRow(struct editorConfig *E, char *s, size_t len);
|
||||||
|
|
||||||
|
void editorRowInsertChar(erow *row, int at, int c);
|
||||||
|
|
||||||
#endif // ROW_OP_H_
|
#endif // ROW_OP_H_
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ int main(int argc, char *argv[]) {
|
|||||||
editorOpen(&E, argv[1]);
|
editorOpen(&E, argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editorSetStatusMessage(&E, "HELP: Ctrl-Q = quit");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
editorRefreshScreen(&E);
|
editorRefreshScreen(&E);
|
||||||
editorProcessKeypress(&E);
|
editorProcessKeypress(&E);
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "../include/editor_op.h"
|
||||||
|
#include "../include/row_op.h"
|
||||||
|
|
||||||
|
void editorInsertChar(struct editorConfig *E, int c) {
|
||||||
|
if (E->cursor_y == E->numrows) {
|
||||||
|
editorAppendRow(E, "", 0);
|
||||||
|
}
|
||||||
|
editorRowInsertChar(&E->row[E->cursor_y], E->cursor_x, c);
|
||||||
|
E->cursor_x++;
|
||||||
|
}
|
||||||
+49
-1
@@ -1,7 +1,40 @@
|
|||||||
#include "../include/file_io.h"
|
#include "../include/file_io.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
char *editorRowsToString(struct editorConfig *E, int *buffer_len) {
|
||||||
|
int tot_len = 0;
|
||||||
|
int j;
|
||||||
|
char *buf;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for (j = 0; j < E->numrows; ++j) {
|
||||||
|
tot_len += E->row[j].size + 1;
|
||||||
|
}
|
||||||
|
*buffer_len = tot_len;
|
||||||
|
buf = malloc(tot_len);
|
||||||
|
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(struct editorConfig *E, char *filename) {
|
void editorOpen(struct editorConfig *E, char *filename) {
|
||||||
FILE *fp = fopen(filename, "r");
|
FILE *fp;
|
||||||
|
|
||||||
|
free(E->filename);
|
||||||
|
E->filename = strdup(filename);
|
||||||
|
|
||||||
|
fp = fopen(filename, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
die("fopen");
|
die("fopen");
|
||||||
|
|
||||||
@@ -19,3 +52,18 @@ void editorOpen(struct editorConfig *E, char *filename) {
|
|||||||
free(line);
|
free(line);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void editorSave(struct editorConfig *E) {
|
||||||
|
int len;
|
||||||
|
char *buf;
|
||||||
|
int fd;
|
||||||
|
if (E->filename == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buf = editorRowsToString(E, &len);
|
||||||
|
fd = open(E->filename, O_RDWR | O_CREAT, 0644);
|
||||||
|
ftruncate(fd, len);
|
||||||
|
write(fd, buf, len);
|
||||||
|
close(fd);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,10 +3,16 @@
|
|||||||
void initEditor(struct editorConfig *E) {
|
void initEditor(struct editorConfig *E) {
|
||||||
E->cursor_x = 0;
|
E->cursor_x = 0;
|
||||||
E->cursor_y = 0;
|
E->cursor_y = 0;
|
||||||
|
E->rx = 0;
|
||||||
E->row_offset = 0;
|
E->row_offset = 0;
|
||||||
|
E->col_offset = 0;
|
||||||
E->numrows = 0;
|
E->numrows = 0;
|
||||||
E->row = NULL;
|
E->row = NULL;
|
||||||
|
E->filename = NULL;
|
||||||
|
E->status_msg[0] = '\0';
|
||||||
|
E->status_msg_time = 0;
|
||||||
if (getWindowSize(&E->screenrows, &E->screencols) == -1) {
|
if (getWindowSize(&E->screenrows, &E->screencols) == -1) {
|
||||||
die("getWindowSize");
|
die("getWindowSize");
|
||||||
}
|
}
|
||||||
|
E->screenrows -= 2;
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-6
@@ -1,14 +1,22 @@
|
|||||||
#include "../include/input.h"
|
#include "../include/input.h"
|
||||||
|
#include "../include/editor_op.h"
|
||||||
|
#include "../include/file_io.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void editorMoveCursor(struct editorConfig *E, int key) {
|
void editorMoveCursor(struct editorConfig *E, int key) {
|
||||||
|
erow *row = (E->cursor_y >= E->numrows) ? NULL : &E->row[E->cursor_y];
|
||||||
|
int row_len;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case CURSOR_RIGHT:
|
case CURSOR_RIGHT:
|
||||||
if (E->cursor_x != 0) {
|
if (row && E->cursor_x < row->size) {
|
||||||
--E->cursor_x;
|
++E->cursor_x;
|
||||||
|
} else if (row && E->cursor_x == row->size) {
|
||||||
|
E->cursor_y++;
|
||||||
|
E->cursor_x = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CURSOR_DOWN:
|
case CURSOR_DOWN:
|
||||||
if (E->cursor_y != E->screenrows - 1) {
|
if (E->cursor_y < E->numrows) {
|
||||||
++E->cursor_y;
|
++E->cursor_y;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -18,11 +26,20 @@ void editorMoveCursor(struct editorConfig *E, int key) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CURSOR_LEFT:
|
case CURSOR_LEFT:
|
||||||
if (E->cursor_x != E->screencols - 1) {
|
if (E->cursor_x != 0) {
|
||||||
++E->cursor_x;
|
--E->cursor_x;
|
||||||
|
} else if (E->cursor_y > 0) {
|
||||||
|
--E->cursor_y;
|
||||||
|
E->cursor_x = E->row[E->cursor_y].size;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
row = (E->cursor_y >= E->numrows) ? NULL : &E->row[E->cursor_y];
|
||||||
|
row_len = row ? row->size : 0;
|
||||||
|
if (E->cursor_x > row_len) {
|
||||||
|
E->cursor_x = row_len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void editorProcessKeypress(struct editorConfig *E) {
|
void editorProcessKeypress(struct editorConfig *E) {
|
||||||
@@ -30,6 +47,9 @@ void editorProcessKeypress(struct editorConfig *E) {
|
|||||||
int times;
|
int times;
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case '\r':
|
||||||
|
/* TODO */
|
||||||
|
break;
|
||||||
case CTRL_KEY('q'):
|
case CTRL_KEY('q'):
|
||||||
write(STDOUT_FILENO, "\x1b[2J", 4);
|
write(STDOUT_FILENO, "\x1b[2J", 4);
|
||||||
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
||||||
@@ -37,16 +57,36 @@ void editorProcessKeypress(struct editorConfig *E) {
|
|||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CTRL_KEY('s'):
|
||||||
|
editorSave(E);
|
||||||
|
break;
|
||||||
|
|
||||||
case BEG_LINE:
|
case BEG_LINE:
|
||||||
E->cursor_x = 0;
|
E->cursor_x = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case END_LINE:
|
case END_LINE:
|
||||||
E->cursor_x = E->screencols - 1;
|
if (E->cursor_y < E->numrows) {
|
||||||
|
E->cursor_x = E->row[E->cursor_y].size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BACKSPACE:
|
||||||
|
case CTRL_KEY('h'):
|
||||||
|
// case DEL_KEY:
|
||||||
|
/* TODO */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAGE_UP:
|
case PAGE_UP:
|
||||||
case PAGE_DOWN: {
|
case PAGE_DOWN: {
|
||||||
|
if (c == PAGE_UP) {
|
||||||
|
E->cursor_y = E->row_offset;
|
||||||
|
} else if (c == PAGE_DOWN) {
|
||||||
|
E->cursor_y = E->row_offset + E->screenrows - 1;
|
||||||
|
if (E->cursor_y > E->numrows) {
|
||||||
|
E->cursor_y = E->numrows;
|
||||||
|
}
|
||||||
|
}
|
||||||
times = E->screenrows;
|
times = E->screenrows;
|
||||||
while (--times) {
|
while (--times) {
|
||||||
editorMoveCursor(E, c == PAGE_UP ? CURSOR_UP : CURSOR_DOWN);
|
editorMoveCursor(E, c == PAGE_UP ? CURSOR_UP : CURSOR_DOWN);
|
||||||
@@ -59,5 +99,12 @@ void editorProcessKeypress(struct editorConfig *E) {
|
|||||||
case CURSOR_RIGHT:
|
case CURSOR_RIGHT:
|
||||||
editorMoveCursor(E, c);
|
editorMoveCursor(E, c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CTRL_KEY('l'):
|
||||||
|
case '\x1b':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
editorInsertChar(E, c);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+80
-6
@@ -1,4 +1,8 @@
|
|||||||
#include "../include/output.h"
|
#include "../include/output.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
void editorDrawRows(struct editorConfig *E, struct abuf *ab) {
|
void editorDrawRows(struct editorConfig *E, struct abuf *ab) {
|
||||||
int y;
|
int y;
|
||||||
@@ -30,18 +34,77 @@ void editorDrawRows(struct editorConfig *E, struct abuf *ab) {
|
|||||||
abAppend(ab, "~", 1);
|
abAppend(ab, "~", 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
len = E->row[file_row].size > E->screencols ? E->screencols
|
len = E->row[file_row].rsize - E->col_offset;
|
||||||
: E->row[y].size;
|
if (len < 0)
|
||||||
abAppend(ab, E->row[file_row].chars, len);
|
len = 0;
|
||||||
|
if (len > E->screencols)
|
||||||
|
len = E->screencols;
|
||||||
|
abAppend(ab, &E->row[file_row].render[E->col_offset], len);
|
||||||
}
|
}
|
||||||
abAppend(ab, ERASE_END_LINE, 3);
|
abAppend(ab, ERASE_END_LINE, 3);
|
||||||
if (y < E->screenrows - 1) {
|
abAppend(ab, "\r\n", 2);
|
||||||
abAppend(ab, "\r\n", 2);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorScroll(struct editorConfig *E) {
|
||||||
|
E->rx = E->cursor_x;
|
||||||
|
if (E->cursor_y < E->numrows) {
|
||||||
|
E->rx = editorRowCxToRx(&E->row[E->cursor_y], E->cursor_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E->cursor_y < E->row_offset) {
|
||||||
|
E->row_offset = E->cursor_y;
|
||||||
|
}
|
||||||
|
if (E->cursor_y >= E->row_offset + E->screenrows) {
|
||||||
|
E->row_offset = E->cursor_y - E->screenrows + 1;
|
||||||
|
}
|
||||||
|
if (E->rx < E->col_offset) {
|
||||||
|
E->col_offset = E->rx;
|
||||||
|
}
|
||||||
|
if (E->rx >= E->col_offset + E->screencols) {
|
||||||
|
E->col_offset = E->rx - E->screencols + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorDrawStatusBar(struct editorConfig *E, struct abuf *ab) {
|
||||||
|
int len, render_len;
|
||||||
|
char status[80], render_status[80];
|
||||||
|
|
||||||
|
abAppend(ab, "\x1b[7m", 4); // inverting colors
|
||||||
|
len = snprintf(status, sizeof(status), "%.20s - %d lines",
|
||||||
|
E->filename ? E->filename : "[No Name]", E->numrows);
|
||||||
|
render_len = snprintf(render_status, sizeof(render_status), "%d/%d",
|
||||||
|
E->cursor_y + 1, E->numrows);
|
||||||
|
if (len > E->screencols) {
|
||||||
|
len = E->screencols;
|
||||||
|
}
|
||||||
|
abAppend(ab, status, len);
|
||||||
|
while (len < E->screencols) {
|
||||||
|
if (E->screencols - len == render_len) {
|
||||||
|
abAppend(ab, render_status, render_len);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
abAppend(ab, " ", 1);
|
||||||
|
++len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
abAppend(ab, "\x1b[m", 3); // normal text mode
|
||||||
|
abAppend(ab, "\r\n", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorDrawMessageBar(struct editorConfig *E, struct abuf *ab) {
|
||||||
|
int msg_len = strlen(E->status_msg);
|
||||||
|
abAppend(ab, ERASE_END_LINE, 3);
|
||||||
|
if (msg_len > E->screencols) {
|
||||||
|
msg_len = E->screencols;
|
||||||
|
}
|
||||||
|
if (msg_len && time(NULL) - E->status_msg_time < 5) {
|
||||||
|
abAppend(ab, E->status_msg, msg_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void editorRefreshScreen(struct editorConfig *E) {
|
void editorRefreshScreen(struct editorConfig *E) {
|
||||||
|
editorScroll(E);
|
||||||
struct abuf ab = ABUF_INIT;
|
struct abuf ab = ABUF_INIT;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
@@ -49,8 +112,11 @@ void editorRefreshScreen(struct editorConfig *E) {
|
|||||||
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
||||||
|
|
||||||
editorDrawRows(E, &ab);
|
editorDrawRows(E, &ab);
|
||||||
|
editorDrawStatusBar(E, &ab);
|
||||||
|
editorDrawMessageBar(E, &ab);
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "\x1b[%d;%dH", E->cursor_y + 1, E->cursor_x + 1);
|
snprintf(buf, sizeof(buf), "\x1b[%d;%dH", (E->cursor_y - E->row_offset) + 1,
|
||||||
|
(E->rx - E->col_offset) + 1);
|
||||||
abAppend(&ab, buf, strlen(buf));
|
abAppend(&ab, buf, strlen(buf));
|
||||||
|
|
||||||
abAppend(&ab, SHOW_CURSOR, 6);
|
abAppend(&ab, SHOW_CURSOR, 6);
|
||||||
@@ -58,3 +124,11 @@ void editorRefreshScreen(struct editorConfig *E) {
|
|||||||
write(STDOUT_FILENO, ab.b, ab.len);
|
write(STDOUT_FILENO, ab.b, ab.len);
|
||||||
abFree(&ab);
|
abFree(&ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void editorSetStatusMessage(struct editorConfig *E, const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(E->status_msg, sizeof(E->status_msg), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
E->status_msg_time = time(NULL);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,56 @@
|
|||||||
#include "../include/row_op.h"
|
#include "../include/row_op.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int editorRowCxToRx(erow *row, int cursor_x) {
|
||||||
|
int render_x = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < cursor_x; ++i) {
|
||||||
|
if (row->chars[i] == '\t') {
|
||||||
|
render_x += (TAB_LENGTH - 1) - (render_x % TAB_LENGTH);
|
||||||
|
}
|
||||||
|
render_x++;
|
||||||
|
}
|
||||||
|
return render_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn editorUpdateRow(erow *row)
|
||||||
|
* \brief Copy content of \p row in \p row->render.
|
||||||
|
* */
|
||||||
|
|
||||||
|
void editorUpdateRow(erow *row) {
|
||||||
|
int i, i_render;
|
||||||
|
int tabs = 0;
|
||||||
|
|
||||||
|
// counting number of tabs
|
||||||
|
|
||||||
|
for (i = 0; i < row->size; ++i) {
|
||||||
|
tabs +=
|
||||||
|
(row->chars[i] == '\t'); /**< increment tabs of 1 if chars[i] is one. */
|
||||||
|
}
|
||||||
|
|
||||||
|
free(row->render);
|
||||||
|
row->render = malloc(row->size + tabs * (TAB_LENGTH - 1) +
|
||||||
|
1); /**< Tabs needs TAB_LENGTH chars so TAB_LENGTH - 1
|
||||||
|
more than the first already counted. */
|
||||||
|
|
||||||
|
// end of counting
|
||||||
|
i_render = 0;
|
||||||
|
for (i = 0; i < row->size; ++i) {
|
||||||
|
if (row->chars[i] == '\t') {
|
||||||
|
row->render[i_render++] = ' ';
|
||||||
|
while (i_render % TAB_LENGTH) {
|
||||||
|
row->render[i_render++] =
|
||||||
|
' '; /**< Addind the right amount of spaces for tabs */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row->render[i_render++] = row->chars[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row->render[i_render] = '\0'; // Don't forget the end of string character.
|
||||||
|
row->rsize = i_render;
|
||||||
|
}
|
||||||
|
|
||||||
void editorAppendRow(struct editorConfig *E, char *s, size_t len) {
|
void editorAppendRow(struct editorConfig *E, char *s, size_t len) {
|
||||||
int at;
|
int at;
|
||||||
@@ -9,5 +61,25 @@ void editorAppendRow(struct editorConfig *E, char *s, size_t len) {
|
|||||||
E->row[at].chars = malloc(len + 1);
|
E->row[at].chars = malloc(len + 1);
|
||||||
memcpy(E->row[at].chars, s, len);
|
memcpy(E->row[at].chars, s, len);
|
||||||
E->row[at].chars[len] = '\0';
|
E->row[at].chars[len] = '\0';
|
||||||
|
|
||||||
|
E->row[at].rsize = 0;
|
||||||
|
E->row[at].render = NULL;
|
||||||
|
editorUpdateRow(&E->row[at]);
|
||||||
|
|
||||||
++E->numrows;
|
++E->numrows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn editorRowInsertChar(erow *row, int at, int c)
|
||||||
|
* \param at Index of where we want to insert the char */
|
||||||
|
|
||||||
|
void editorRowInsertChar(erow *row, int at, int c) {
|
||||||
|
if (at < 0 || at > row->size) {
|
||||||
|
at = row->size;
|
||||||
|
}
|
||||||
|
row->chars = 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);
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -77,9 +77,9 @@ int editorReadKey() {
|
|||||||
case 'B':
|
case 'B':
|
||||||
return CURSOR_DOWN;
|
return CURSOR_DOWN;
|
||||||
case 'C':
|
case 'C':
|
||||||
return CURSOR_LEFT;
|
|
||||||
case 'D':
|
|
||||||
return CURSOR_RIGHT;
|
return CURSOR_RIGHT;
|
||||||
|
case 'D':
|
||||||
|
return CURSOR_LEFT;
|
||||||
case 'H':
|
case 'H':
|
||||||
return BEG_LINE;
|
return BEG_LINE;
|
||||||
case 'F':
|
case 'F':
|
||||||
|
|||||||
Reference in New Issue
Block a user