Fully fonctional editing
This commit is contained in:
@@ -6,15 +6,11 @@
|
|||||||
|
|
||||||
BELUGA_OUTPUT=bin
|
BELUGA_OUTPUT=bin
|
||||||
|
|
||||||
BUILD_DIR=build
|
|
||||||
|
|
||||||
BUILD_FLAGS=-Wall -Wextra -pedantic
|
BUILD_FLAGS=-Wall -Wextra -pedantic
|
||||||
|
|
||||||
build: main.c src/*
|
build: main.c src/*
|
||||||
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
||||||
if [ ! -d doc/ ]; then mkdir doc; fi
|
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/* $(BUILD_FLAGS)
|
||||||
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/*
|
|
||||||
doxygen
|
|
||||||
|
|
||||||
DEBUG_FLAGS=-Wall -Wextra -pedantic -Werror -fsanitize=address -g
|
DEBUG_FLAGS=-Wall -Wextra -pedantic -Werror -fsanitize=address -g
|
||||||
|
|
||||||
@@ -22,8 +18,15 @@ debug: main.c src/*
|
|||||||
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
||||||
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/* $(DEBUG_FLAGS)
|
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/* $(DEBUG_FLAGS)
|
||||||
|
|
||||||
|
doc:
|
||||||
|
if [ ! -d doc/ ]; then mkdir doc; fi
|
||||||
|
doxygen
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -r $(BELUGA_OUTPUT)/*
|
rm -r $(BELUGA_OUTPUT)
|
||||||
rm -rf doc/
|
rm -rf doc/
|
||||||
|
rm -rf tmp/
|
||||||
|
|
||||||
|
all: build doc
|
||||||
|
|
||||||
# end
|
# end
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
# Beluga
|
# Beluga
|
||||||
|
|
||||||
Beluga is a project of CLI text editor that will fit perfectly with your azerty keyboard.
|
Beluga is a project of CLI text editor that will fit perfectly with your azerty keyboard.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
You will only need **make** or **gcc** to compile the editor.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Here is the installation line :
|
||||||
|
```git clone https://github.com/le-cocotier/beluga.git ~/.beluga && cd ~/.beluga && make build```
|
||||||
|
|
||||||
|
The executable file will be in `bin/beluga`. Feel free to add it to your path.
|
||||||
|
|
||||||
|
You can either run `make all` if you're interested by the doxygen documentation.
|
||||||
|
|
||||||
|
## Getting start
|
||||||
|
|
||||||
|
To open an existing file just type :
|
||||||
|
```beluga path_to_my_file```
|
||||||
|
|
||||||
|
The only keybinds that you will need will be :
|
||||||
|
- Ctrl-Q : leave the editor
|
||||||
|
- Ctrl-S : Save a file
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ struct editorConfig {
|
|||||||
int screencols; /**< Terminal width*/
|
int screencols; /**< Terminal width*/
|
||||||
int numrows; /**< Number of rows contained */
|
int numrows; /**< Number of rows contained */
|
||||||
erow *row; /**< Store all the rows printed */
|
erow *row; /**< Store all the rows printed */
|
||||||
|
int dirty;
|
||||||
char *filename;
|
char *filename;
|
||||||
char status_msg[80];
|
char status_msg[80];
|
||||||
time_t status_msg_time;
|
time_t status_msg_time;
|
||||||
|
|||||||
+9
-7
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#define CTRL_KEY(k) ((k) & 0x1f)
|
#define CTRL_KEY(k) ((k) & 0x1f)
|
||||||
|
|
||||||
|
#define ESCAPE '\x1b'
|
||||||
#define CURSOR_TOP_LEFT "\x1b[H"
|
#define CURSOR_TOP_LEFT "\x1b[H"
|
||||||
#define HIDE_CURSOR "\x1b[?25l"
|
#define HIDE_CURSOR "\x1b[?25l"
|
||||||
#define SHOW_CURSOR "\x1b[?25h"
|
#define SHOW_CURSOR "\x1b[?25h"
|
||||||
@@ -10,12 +11,12 @@
|
|||||||
|
|
||||||
enum editorKey {
|
enum editorKey {
|
||||||
BACKSPACE = 127,
|
BACKSPACE = 127,
|
||||||
CURSOR_LEFT = 1000,
|
ARROW_LEFT = 1000,
|
||||||
CURSOR_RIGHT,
|
ARROW_RIGHT,
|
||||||
CURSOR_UP,
|
ARROW_UP,
|
||||||
CURSOR_DOWN,
|
ARROW_DOWN,
|
||||||
|
DEL_KEY,
|
||||||
BEG_LINE,
|
BEG_LINE,
|
||||||
DELETE,
|
|
||||||
END_LINE,
|
END_LINE,
|
||||||
PAGE_UP,
|
PAGE_UP,
|
||||||
PAGE_DOWN,
|
PAGE_DOWN,
|
||||||
@@ -23,7 +24,8 @@ enum editorKey {
|
|||||||
|
|
||||||
#define ABUF_INIT {NULL, 0}
|
#define ABUF_INIT {NULL, 0}
|
||||||
|
|
||||||
#define BELUGA_VERSION "0.1"
|
#define BELUGA_VERSION "1.0"
|
||||||
#define TAB_LENGTH 8
|
#define TAB_LENGTH 4
|
||||||
|
#define QUIT_TIMES 1
|
||||||
|
|
||||||
#endif // DEFINE_H_
|
#endif // DEFINE_H_
|
||||||
|
|||||||
@@ -4,4 +4,8 @@
|
|||||||
#include "data.h"
|
#include "data.h"
|
||||||
void editorInsertChar(struct editorConfig *E, int c);
|
void editorInsertChar(struct editorConfig *E, int c);
|
||||||
|
|
||||||
|
void editorInsertNewLine(struct editorConfig *E);
|
||||||
|
|
||||||
|
void editorDelChar(struct editorConfig *E);
|
||||||
|
|
||||||
#endif // EDITOR_OP_H_
|
#endif // EDITOR_OP_H_
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "define.h"
|
#include "define.h"
|
||||||
|
#include "output.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@@ -18,6 +19,8 @@
|
|||||||
// END \x1b[4~ || <esc>[8~ || <esc>[F || <esc>OF
|
// END \x1b[4~ || <esc>[8~ || <esc>[F || <esc>OF
|
||||||
// DELETE \x1b[3~
|
// DELETE \x1b[3~
|
||||||
|
|
||||||
|
char *editorPrompt(struct editorConfig *E, char *prompt);
|
||||||
|
|
||||||
void editorMoveCursor(struct editorConfig *E, int key);
|
void editorMoveCursor(struct editorConfig *E, int key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+12
-2
@@ -5,14 +5,24 @@
|
|||||||
#include "define.h"
|
#include "define.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int editorRowCxToRx(erow *row, int cursor_x);
|
int editorRowCxToRx(erow *row, int cursor_x);
|
||||||
|
|
||||||
void editorUpdateRow(erow *row);
|
void editorUpdateRow(erow *row);
|
||||||
|
|
||||||
void editorAppendRow(struct editorConfig *E, char *s, size_t len);
|
void editorInsertRow(struct editorConfig *E, int at, char *s, size_t len);
|
||||||
|
|
||||||
void editorRowInsertChar(erow *row, int at, int c);
|
void editorFreeRow(erow *row);
|
||||||
|
|
||||||
|
void editorDelRow(struct editorConfig *E, int at);
|
||||||
|
|
||||||
|
void editorRowInsertChar(struct editorConfig *E, erow *row, int at, int c);
|
||||||
|
|
||||||
|
void editorRowAppendString(struct editorConfig *E, erow *row, char *s,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
void editorRowDelchar(struct editorConfig *E, erow *row, int at);
|
||||||
|
|
||||||
#endif // ROW_OP_H_
|
#endif // ROW_OP_H_
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ int main(int argc, char *argv[]) {
|
|||||||
editorOpen(&E, argv[1]);
|
editorOpen(&E, argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
editorSetStatusMessage(&E, "HELP: Ctrl-Q = quit");
|
editorSetStatusMessage(&E, "HELP: Ctrl-S = save | Ctrl-Q = quit");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
editorRefreshScreen(&E);
|
editorRefreshScreen(&E);
|
||||||
|
|||||||
+36
-2
@@ -3,8 +3,42 @@
|
|||||||
|
|
||||||
void editorInsertChar(struct editorConfig *E, int c) {
|
void editorInsertChar(struct editorConfig *E, int c) {
|
||||||
if (E->cursor_y == E->numrows) {
|
if (E->cursor_y == E->numrows) {
|
||||||
editorAppendRow(E, "", 0);
|
editorInsertRow(E, E->numrows, "", 0);
|
||||||
}
|
}
|
||||||
editorRowInsertChar(&E->row[E->cursor_y], E->cursor_x, c);
|
editorRowInsertChar(E, &E->row[E->cursor_y], E->cursor_x, c);
|
||||||
E->cursor_x++;
|
E->cursor_x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void editorInsertNewLine(struct editorConfig *E) {
|
||||||
|
erow *row;
|
||||||
|
if (!E->cursor_x) {
|
||||||
|
editorInsertRow(E, E->cursor_y, "", 0);
|
||||||
|
} else {
|
||||||
|
row = &E->row[E->cursor_y];
|
||||||
|
editorInsertRow(E, E->cursor_y + 1, &row->chars[E->cursor_x],
|
||||||
|
row->size - E->cursor_x);
|
||||||
|
row = &E->row[E->cursor_y];
|
||||||
|
row->size = E->cursor_x;
|
||||||
|
row->chars[row->size] = '\0';
|
||||||
|
editorUpdateRow(row);
|
||||||
|
}
|
||||||
|
++E->cursor_y;
|
||||||
|
E->cursor_x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorDelChar(struct editorConfig *E) {
|
||||||
|
erow *row;
|
||||||
|
if (E->cursor_y == E->numrows || !(E->cursor_x || E->cursor_y)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
row = &E->row[E->cursor_y];
|
||||||
|
if (E->cursor_x > 0) {
|
||||||
|
editorRowDelchar(E, row, E->cursor_x - 1);
|
||||||
|
--E->cursor_x;
|
||||||
|
} else {
|
||||||
|
E->cursor_x = E->row[E->cursor_y - 1].size;
|
||||||
|
editorRowAppendString(E, &E->row[E->cursor_y - 1], row->chars, row->size);
|
||||||
|
editorDelRow(E, E->cursor_y);
|
||||||
|
--E->cursor_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+22
-5
@@ -1,4 +1,6 @@
|
|||||||
#include "../include/file_io.h"
|
#include "../include/file_io.h"
|
||||||
|
#include "../include/input.h"
|
||||||
|
#include "../include/output.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -47,10 +49,11 @@ void editorOpen(struct editorConfig *E, char *filename) {
|
|||||||
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) {
|
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) {
|
||||||
--line_len;
|
--line_len;
|
||||||
}
|
}
|
||||||
editorAppendRow(E, line, line_len);
|
editorInsertRow(E, E->numrows, line, line_len);
|
||||||
}
|
}
|
||||||
free(line);
|
free(line);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
E->dirty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void editorSave(struct editorConfig *E) {
|
void editorSave(struct editorConfig *E) {
|
||||||
@@ -58,12 +61,26 @@ void editorSave(struct editorConfig *E) {
|
|||||||
char *buf;
|
char *buf;
|
||||||
int fd;
|
int fd;
|
||||||
if (E->filename == NULL) {
|
if (E->filename == NULL) {
|
||||||
return;
|
E->filename = editorPrompt(E, "Save as: %s (ESC to cancel)");
|
||||||
|
if (E->filename == NULL) {
|
||||||
|
editorSetStatusMessage(E, "Save aborted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf = editorRowsToString(E, &len);
|
buf = editorRowsToString(E, &len);
|
||||||
fd = open(E->filename, O_RDWR | O_CREAT, 0644);
|
fd = open(E->filename, O_RDWR | O_CREAT, 0644);
|
||||||
ftruncate(fd, len);
|
if (fd != -1) {
|
||||||
write(fd, buf, len);
|
if (ftruncate(fd, len) != -1) {
|
||||||
close(fd);
|
if (write(fd, buf, len) == len) {
|
||||||
|
close(fd);
|
||||||
|
free(buf);
|
||||||
|
E->dirty = 0;
|
||||||
|
editorSetStatusMessage(E, "%d bytes written to disk", len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
|
editorSetStatusMessage(E, "Can't save! I/O error: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ void initEditor(struct editorConfig *E) {
|
|||||||
E->col_offset = 0;
|
E->col_offset = 0;
|
||||||
E->numrows = 0;
|
E->numrows = 0;
|
||||||
E->row = NULL;
|
E->row = NULL;
|
||||||
|
E->dirty = 0;
|
||||||
E->filename = NULL;
|
E->filename = NULL;
|
||||||
E->status_msg[0] = '\0';
|
E->status_msg[0] = '\0';
|
||||||
E->status_msg_time = 0;
|
E->status_msg_time = 0;
|
||||||
|
|||||||
+70
-12
@@ -1,13 +1,58 @@
|
|||||||
#include "../include/input.h"
|
#include "../include/input.h"
|
||||||
#include "../include/editor_op.h"
|
#include "../include/editor_op.h"
|
||||||
#include "../include/file_io.h"
|
#include "../include/file_io.h"
|
||||||
|
#include "../include/output.h"
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn char * editorPrompt(struct editorConfig *E, char *prompt)
|
||||||
|
* \brief Return user input in a prompt when enter is hit. */
|
||||||
|
|
||||||
|
char *editorPrompt(struct editorConfig *E, char *prompt) {
|
||||||
|
size_t buf_size = 128;
|
||||||
|
char *buf = malloc(buf_size);
|
||||||
|
size_t buf_len = 0;
|
||||||
|
int c = 0;
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
editorSetStatusMessage(E, prompt, buf);
|
||||||
|
editorRefreshScreen(E);
|
||||||
|
c = editorReadKey();
|
||||||
|
if (c == DEL_KEY || c == CTRL_KEY('h') || c == BACKSPACE) {
|
||||||
|
if (buf_len != 0) {
|
||||||
|
buf[--buf_len] = '\0';
|
||||||
|
}
|
||||||
|
} else if (c == ESCAPE) {
|
||||||
|
fprintf(stderr, "escape");
|
||||||
|
editorSetStatusMessage(E, "");
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
} else if (c == '\r') {
|
||||||
|
if (buf_len != 0) {
|
||||||
|
editorSetStatusMessage(E, "");
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
} else if (!iscntrl(c) && c < 128) {
|
||||||
|
if (buf_len == buf_size - 1) {
|
||||||
|
buf_size *= 2;
|
||||||
|
buf = realloc(buf, buf_size);
|
||||||
|
}
|
||||||
|
buf[buf_len++] = c;
|
||||||
|
buf[buf_len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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];
|
erow *row = (E->cursor_y >= E->numrows) ? NULL : &E->row[E->cursor_y];
|
||||||
int row_len;
|
int row_len;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case CURSOR_RIGHT:
|
case ARROW_RIGHT:
|
||||||
if (row && E->cursor_x < row->size) {
|
if (row && E->cursor_x < row->size) {
|
||||||
++E->cursor_x;
|
++E->cursor_x;
|
||||||
} else if (row && E->cursor_x == row->size) {
|
} else if (row && E->cursor_x == row->size) {
|
||||||
@@ -15,17 +60,17 @@ void editorMoveCursor(struct editorConfig *E, int key) {
|
|||||||
E->cursor_x = 0;
|
E->cursor_x = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CURSOR_DOWN:
|
case ARROW_DOWN:
|
||||||
if (E->cursor_y < E->numrows) {
|
if (E->cursor_y < E->numrows) {
|
||||||
++E->cursor_y;
|
++E->cursor_y;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CURSOR_UP:
|
case ARROW_UP:
|
||||||
if (E->cursor_y != 0) {
|
if (E->cursor_y != 0) {
|
||||||
--E->cursor_y;
|
--E->cursor_y;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CURSOR_LEFT:
|
case ARROW_LEFT:
|
||||||
if (E->cursor_x != 0) {
|
if (E->cursor_x != 0) {
|
||||||
--E->cursor_x;
|
--E->cursor_x;
|
||||||
} else if (E->cursor_y > 0) {
|
} else if (E->cursor_y > 0) {
|
||||||
@@ -43,14 +88,23 @@ void editorMoveCursor(struct editorConfig *E, int key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void editorProcessKeypress(struct editorConfig *E) {
|
void editorProcessKeypress(struct editorConfig *E) {
|
||||||
|
static int quit_times = QUIT_TIMES;
|
||||||
int c = editorReadKey();
|
int c = editorReadKey();
|
||||||
int times;
|
int times;
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|
||||||
case '\r':
|
case '\r':
|
||||||
/* TODO */
|
editorInsertNewLine(E);
|
||||||
break;
|
break;
|
||||||
case CTRL_KEY('q'):
|
case CTRL_KEY('q'):
|
||||||
|
if (E->dirty && quit_times > 0) {
|
||||||
|
editorSetStatusMessage(E,
|
||||||
|
"WARNING! Changes hasn't been saved. Press Ctrl-Q "
|
||||||
|
"another time to quit.");
|
||||||
|
--quit_times;
|
||||||
|
return;
|
||||||
|
}
|
||||||
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);
|
||||||
disableRawMode(E);
|
disableRawMode(E);
|
||||||
@@ -73,8 +127,11 @@ void editorProcessKeypress(struct editorConfig *E) {
|
|||||||
|
|
||||||
case BACKSPACE:
|
case BACKSPACE:
|
||||||
case CTRL_KEY('h'):
|
case CTRL_KEY('h'):
|
||||||
// case DEL_KEY:
|
case DEL_KEY:
|
||||||
/* TODO */
|
if (c == DEL_KEY) {
|
||||||
|
editorMoveCursor(E, ARROW_RIGHT);
|
||||||
|
}
|
||||||
|
editorDelChar(E);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAGE_UP:
|
case PAGE_UP:
|
||||||
@@ -89,14 +146,14 @@ void editorProcessKeypress(struct editorConfig *E) {
|
|||||||
}
|
}
|
||||||
times = E->screenrows;
|
times = E->screenrows;
|
||||||
while (--times) {
|
while (--times) {
|
||||||
editorMoveCursor(E, c == PAGE_UP ? CURSOR_UP : CURSOR_DOWN);
|
editorMoveCursor(E, c == PAGE_UP ? ARROW_UP : ARROW_DOWN);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case CURSOR_UP:
|
case ARROW_UP:
|
||||||
case CURSOR_DOWN:
|
case ARROW_DOWN:
|
||||||
case CURSOR_LEFT:
|
case ARROW_LEFT:
|
||||||
case CURSOR_RIGHT:
|
case ARROW_RIGHT:
|
||||||
editorMoveCursor(E, c);
|
editorMoveCursor(E, c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -107,4 +164,5 @@ void editorProcessKeypress(struct editorConfig *E) {
|
|||||||
editorInsertChar(E, c);
|
editorInsertChar(E, c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
quit_times = QUIT_TIMES;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -71,8 +71,9 @@ void editorDrawStatusBar(struct editorConfig *E, struct abuf *ab) {
|
|||||||
char status[80], render_status[80];
|
char status[80], render_status[80];
|
||||||
|
|
||||||
abAppend(ab, "\x1b[7m", 4); // inverting colors
|
abAppend(ab, "\x1b[7m", 4); // inverting colors
|
||||||
len = snprintf(status, sizeof(status), "%.20s - %d lines",
|
len = snprintf(status, sizeof(status), "%.20s - %d lines%s",
|
||||||
E->filename ? E->filename : "[No Name]", E->numrows);
|
E->filename ? E->filename : "[No Name]", E->numrows,
|
||||||
|
E->dirty ? "*" : "");
|
||||||
render_len = snprintf(render_status, sizeof(render_status), "%d/%d",
|
render_len = snprintf(render_status, sizeof(render_status), "%d/%d",
|
||||||
E->cursor_y + 1, E->numrows);
|
E->cursor_y + 1, E->numrows);
|
||||||
if (len > E->screencols) {
|
if (len > E->screencols) {
|
||||||
|
|||||||
+51
-5
@@ -1,6 +1,7 @@
|
|||||||
#include "../include/row_op.h"
|
#include "../include/row_op.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
int editorRowCxToRx(erow *row, int cursor_x) {
|
int editorRowCxToRx(erow *row, int cursor_x) {
|
||||||
int render_x = 0;
|
int render_x = 0;
|
||||||
@@ -52,11 +53,14 @@ void editorUpdateRow(erow *row) {
|
|||||||
row->rsize = i_render;
|
row->rsize = i_render;
|
||||||
}
|
}
|
||||||
|
|
||||||
void editorAppendRow(struct editorConfig *E, char *s, size_t len) {
|
void editorInsertRow(struct editorConfig *E, int at, char *s, size_t len) {
|
||||||
int at;
|
if (at < 0 || at > E->numrows) {
|
||||||
E->row = realloc(E->row, sizeof(erow) * (E->numrows + 1));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
E->row = realloc(E->row, sizeof(erow) * (E->numrows + 1));
|
||||||
|
memmove(&E->row[at + 1], &E->row[at], sizeof(erow) * (E->numrows - at));
|
||||||
|
|
||||||
at = E->numrows;
|
|
||||||
E->row[at].size = len;
|
E->row[at].size = 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);
|
||||||
@@ -67,13 +71,29 @@ void editorAppendRow(struct editorConfig *E, char *s, size_t len) {
|
|||||||
editorUpdateRow(&E->row[at]);
|
editorUpdateRow(&E->row[at]);
|
||||||
|
|
||||||
++E->numrows;
|
++E->numrows;
|
||||||
|
++E->dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorFreeRow(erow *row) {
|
||||||
|
free(row->render);
|
||||||
|
free(row->chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorDelRow(struct editorConfig *E, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \fn editorRowInsertChar(erow *row, int at, int c)
|
* \fn editorRowInsertChar(erow *row, int at, int c)
|
||||||
* \param at Index of where we want to insert the char */
|
* \param at Index of where we want to insert the char */
|
||||||
|
|
||||||
void editorRowInsertChar(erow *row, int at, int c) {
|
void editorRowInsertChar(struct editorConfig *E, erow *row, int at, int c) {
|
||||||
if (at < 0 || at > row->size) {
|
if (at < 0 || at > row->size) {
|
||||||
at = row->size;
|
at = row->size;
|
||||||
}
|
}
|
||||||
@@ -82,4 +102,30 @@ void editorRowInsertChar(erow *row, int at, int c) {
|
|||||||
++row->size;
|
++row->size;
|
||||||
row->chars[at] = c;
|
row->chars[at] = c;
|
||||||
editorUpdateRow(row);
|
editorUpdateRow(row);
|
||||||
|
++E->dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorRowAppendString(struct editorConfig *E, erow *row, char *s,
|
||||||
|
size_t len) {
|
||||||
|
row->chars = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn editorRowDelChar(struct editorConfig *E, erow *erow, int at)
|
||||||
|
* \brief Delete the a char at the chosen position on the given row
|
||||||
|
* \param at Index of the char to delete
|
||||||
|
* \param row Row on operation is made */
|
||||||
|
void editorRowDelchar(struct editorConfig *E, 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;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -56,7 +56,7 @@ int editorReadKey() {
|
|||||||
case '1':
|
case '1':
|
||||||
return BEG_LINE;
|
return BEG_LINE;
|
||||||
case '3':
|
case '3':
|
||||||
return DELETE;
|
return DEL_KEY;
|
||||||
case '4':
|
case '4':
|
||||||
return END_LINE;
|
return END_LINE;
|
||||||
case '5':
|
case '5':
|
||||||
@@ -73,13 +73,13 @@ int editorReadKey() {
|
|||||||
|
|
||||||
switch (seq[1]) {
|
switch (seq[1]) {
|
||||||
case 'A':
|
case 'A':
|
||||||
return CURSOR_UP;
|
return ARROW_UP;
|
||||||
case 'B':
|
case 'B':
|
||||||
return CURSOR_DOWN;
|
return ARROW_DOWN;
|
||||||
case 'C':
|
case 'C':
|
||||||
return CURSOR_RIGHT;
|
return ARROW_RIGHT;
|
||||||
case 'D':
|
case 'D':
|
||||||
return CURSOR_LEFT;
|
return ARROW_LEFT;
|
||||||
case 'H':
|
case 'H':
|
||||||
return BEG_LINE;
|
return BEG_LINE;
|
||||||
case 'F':
|
case 'F':
|
||||||
|
|||||||
Reference in New Issue
Block a user