Change white color, support enter and backspace and refactor
This commit is contained in:
parent
5df8a3fb5f
commit
4854d4bcee
6 changed files with 196 additions and 91 deletions
|
@ -2,5 +2,7 @@
|
|||
#define EDITOR_H_
|
||||
|
||||
void insert_char(int c);
|
||||
void insert_new_line();
|
||||
void del_char();
|
||||
|
||||
#endif
|
||||
|
|
14
include/row.h
Normal file
14
include/row.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef ROW_H_
|
||||
#define ROW_H_
|
||||
|
||||
int row_cx_to_rx(row *row, int cx);
|
||||
void update_row(row *row);
|
||||
void insert_row(int at, char *s, size_t len);
|
||||
void free_row(row *row);
|
||||
void del_row(int at);
|
||||
void row_insert_char(row *row, int at, int c);
|
||||
void row_append_str(row *row, char *s, size_t len);
|
||||
void row_del_char(row *row, int at);
|
||||
char *rows_to_str(int *buflen);
|
||||
|
||||
#endif
|
|
@ -7,6 +7,8 @@
|
|||
/* CONFIG */
|
||||
#define TAB_SIZE 4
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
/* number of times of warning before quitting when there is modified text */
|
||||
#define QUIT_CONFIRM 2
|
||||
|
||||
|
@ -15,12 +17,15 @@
|
|||
#define SURFACE_1_BG "\x1b[38;2;49;50;68m"
|
||||
#define BLACK_BG "\x1b[38;2;0;0;0m"
|
||||
#define BLACK_FG "\x1b[48;2;0;0;0m"
|
||||
#define WHITE_FG "\x1b[48;2;255;255;255m"
|
||||
#define WHITE_FG "\x1b[48;2;205;214;244m"
|
||||
#define BLUE_FG "\x1b[48;2;137;180;250m"
|
||||
#define BLUE_BG "\x1b[38;2;137;180;250m"
|
||||
#define GREEN_FG "\x1b[48;2;166;227;161m"
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
#define NORMAL 0
|
||||
#define INSERT 1
|
||||
#define VISUAL 2
|
||||
|
||||
typedef struct row {
|
||||
int size;
|
||||
|
@ -38,6 +43,7 @@ typedef struct editor {
|
|||
int rows;
|
||||
row *row;
|
||||
int dirty;
|
||||
int mode;
|
||||
char *filename;
|
||||
char statusmsg[80];
|
||||
time_t statusmsg_time;
|
||||
|
@ -55,6 +61,7 @@ void abAppend(struct abuf *ab, const char *s, int len);
|
|||
|
||||
void append_row(char *s, size_t len);
|
||||
void row_insert_char(row *row, int at, int c);
|
||||
void row_del_char(row *row, int at);
|
||||
|
||||
extern editor vip;
|
||||
|
||||
|
|
36
src/editor.c
36
src/editor.c
|
@ -1,12 +1,46 @@
|
|||
#include "vip.h"
|
||||
#include "row.h"
|
||||
|
||||
extern editor vip;
|
||||
|
||||
void insert_char(int c)
|
||||
{
|
||||
if (vip.cy == vip.rows) {
|
||||
append_row("", 0);
|
||||
insert_row(vip.rows, "", 0);
|
||||
}
|
||||
row_insert_char(&vip.row[vip.cy], vip.cx, c);
|
||||
vip.cx++;
|
||||
}
|
||||
|
||||
void insert_new_line()
|
||||
{
|
||||
if (vip.cx == 0) {
|
||||
insert_row(vip.cy, "", 0);
|
||||
} else {
|
||||
row *row = &vip.row[vip.cy];
|
||||
insert_row(vip.cy + 1, &row->chars[vip.cx], row->size - vip.cx);
|
||||
row = &vip.row[vip.cy];
|
||||
row->size = vip.cx;
|
||||
row->chars[row->size] = '\0';
|
||||
update_row(row);
|
||||
}
|
||||
vip.cy++;
|
||||
vip.cx = 0;
|
||||
}
|
||||
|
||||
void del_char()
|
||||
{
|
||||
if (vip.cy == vip.rows) return;
|
||||
if (vip.cx == 0 && vip.cy == 0) return;
|
||||
|
||||
row *row = &vip.row[vip.cy];
|
||||
if (vip.cx > 0) {
|
||||
row_del_char(row, vip.cx - 1);
|
||||
vip.cx--;
|
||||
} else {
|
||||
vip.cx = vip.row[vip.cy - 1].size;
|
||||
row_append_str(&vip.row[vip.cy - 1], row->chars, row->size);
|
||||
del_row(vip.cy);
|
||||
vip.cy--;
|
||||
}
|
||||
}
|
||||
|
|
127
src/row.c
Normal file
127
src/row.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vip.h"
|
||||
|
||||
extern editor vip;
|
||||
|
||||
int row_cx_to_rx(row *row, int cx)
|
||||
{
|
||||
int rx = 0;
|
||||
for (int j = 0; j < cx; j++) {
|
||||
if (row->chars[j] == '\t') {
|
||||
rx += (TAB_SIZE - 1) - (rx % TAB_SIZE);
|
||||
}
|
||||
rx++;
|
||||
}
|
||||
return rx;
|
||||
}
|
||||
|
||||
void update_row(row *row)
|
||||
{
|
||||
int tabs = 0;
|
||||
for (int j = 0; j < row->size; j++)
|
||||
if (row->chars[j] == '\t') tabs++;
|
||||
free(row->render);
|
||||
row->render = malloc(row->size + tabs * (TAB_SIZE - 1) + 1);
|
||||
int idx = 0;
|
||||
for (int j = 0; j < row->size; j++) {
|
||||
if (row->chars[j] == '\t') {
|
||||
row->render[idx++] = ' ';
|
||||
while (idx % TAB_SIZE != 0) {
|
||||
row->render[idx++] = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
row->render[idx++] = row->chars[j];
|
||||
}
|
||||
}
|
||||
row->render[idx] = '\0';
|
||||
row->render_size = idx;
|
||||
}
|
||||
|
||||
void insert_row(int at, char *s, size_t len)
|
||||
{
|
||||
if (at < 0 || at > vip.rows) return;
|
||||
|
||||
vip.row = realloc(vip.row, sizeof(row) * (vip.rows + 1));
|
||||
memmove(&vip.row[at + 1], &vip.row[at], sizeof(row) * (vip.rows - at));
|
||||
|
||||
vip.row[at].size = len;
|
||||
vip.row[at].chars = malloc(len + 1);
|
||||
memcpy(vip.row[at].chars, s, len);
|
||||
vip.row[at].chars[len] = '\0';
|
||||
|
||||
vip.row[at].render_size = 0;
|
||||
vip.row[at].render = NULL;
|
||||
update_row(&vip.row[at]);
|
||||
|
||||
vip.rows++;
|
||||
vip.dirty++;
|
||||
}
|
||||
|
||||
void free_row(row *row)
|
||||
{
|
||||
free(row->render);
|
||||
free(row->chars);
|
||||
}
|
||||
|
||||
void del_row(int at)
|
||||
{
|
||||
if (at < 0 || at >= vip.rows) return;
|
||||
free_row(&vip.row[at]);
|
||||
memmove(&vip.row[at], &vip.row[at + 1], sizeof(row) * (vip.rows - at - 1));
|
||||
vip.rows--;
|
||||
vip.dirty++;
|
||||
}
|
||||
|
||||
void row_insert_char(row *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;
|
||||
update_row(row);
|
||||
vip.dirty++;
|
||||
}
|
||||
|
||||
void row_append_str(row *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';
|
||||
update_row(row);
|
||||
vip.dirty++;
|
||||
}
|
||||
|
||||
void row_del_char(row *row, int at)
|
||||
{
|
||||
if (at < 0 || at >= row->size) return;
|
||||
memmove(&row->chars[at], &row->chars[at + 1], row->size - at);
|
||||
row->size--;
|
||||
update_row(row);
|
||||
vip.dirty++;
|
||||
}
|
||||
|
||||
char *rows_to_str(int *buflen)
|
||||
{
|
||||
int total_len = 0;
|
||||
for (int j = 0; j < vip.rows; j++) {
|
||||
total_len += vip.row[j].size + 1;
|
||||
}
|
||||
*buflen = total_len;
|
||||
char *buf = malloc(total_len);
|
||||
char *p = buf;
|
||||
for (int j = 0; j < vip.rows; j++) {
|
||||
memcpy(p, vip.row[j].chars, vip.row[j].size);
|
||||
p += vip.row[j].size;
|
||||
*p = '\n';
|
||||
p++;
|
||||
}
|
||||
return buf;
|
||||
}
|
97
src/vip.c
97
src/vip.c
|
@ -13,6 +13,7 @@
|
|||
#include "term.h"
|
||||
#include "bar.h"
|
||||
#include "editor.h"
|
||||
#include "row.h"
|
||||
|
||||
#define CTRL_KEY(k) ((k) & 0x1f)
|
||||
|
||||
|
@ -90,90 +91,6 @@ int read_key()
|
|||
}
|
||||
}
|
||||
|
||||
int row_cx_to_rx(row *row, int cx)
|
||||
{
|
||||
int rx = 0;
|
||||
for (int j = 0; j < cx; j++) {
|
||||
if (row->chars[j] == '\t') {
|
||||
rx += (TAB_SIZE - 1) - (rx % TAB_SIZE);
|
||||
}
|
||||
rx++;
|
||||
}
|
||||
return rx;
|
||||
}
|
||||
|
||||
void update_row(row *row)
|
||||
{
|
||||
int tabs = 0;
|
||||
for (int j = 0; j < row->size; j++)
|
||||
if (row->chars[j] == '\t') tabs++;
|
||||
free(row->render);
|
||||
row->render = malloc(row->size + tabs * (TAB_SIZE - 1) + 1);
|
||||
int idx = 0;
|
||||
for (int j = 0; j < row->size; j++) {
|
||||
if (row->chars[j] == '\t') {
|
||||
row->render[idx++] = ' ';
|
||||
while (idx % TAB_SIZE != 0) {
|
||||
row->render[idx++] = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
row->render[idx++] = row->chars[j];
|
||||
}
|
||||
}
|
||||
row->render[idx] = '\0';
|
||||
row->render_size = idx;
|
||||
}
|
||||
|
||||
void append_row(char *s, size_t len)
|
||||
{
|
||||
vip.row = realloc(vip.row, sizeof(row) * (vip.rows + 1));
|
||||
|
||||
int at = vip.rows;
|
||||
vip.row[at].size = len;
|
||||
vip.row[at].chars = malloc(len + 1);
|
||||
memcpy(vip.row[at].chars, s, len);
|
||||
vip.row[at].chars[len] = '\0';
|
||||
|
||||
vip.row[at].render_size = 0;
|
||||
vip.row[at].render = NULL;
|
||||
update_row(&vip.row[at]);
|
||||
|
||||
vip.rows++;
|
||||
vip.dirty++;
|
||||
}
|
||||
|
||||
void row_insert_char(row *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;
|
||||
update_row(row);
|
||||
vip.dirty++;
|
||||
}
|
||||
|
||||
char *rows_to_str(int *buflen)
|
||||
{
|
||||
int total_len = 0;
|
||||
for (int j = 0; j < vip.rows; j++) {
|
||||
total_len += vip.row[j].size + 1;
|
||||
}
|
||||
*buflen = total_len;
|
||||
char *buf = malloc(total_len);
|
||||
char *p = buf;
|
||||
for (int j = 0; j < vip.rows; j++) {
|
||||
memcpy(p, vip.row[j].chars, vip.row[j].size);
|
||||
p += vip.row[j].size;
|
||||
*p = '\n';
|
||||
p++;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void open_editor(char *filename)
|
||||
{
|
||||
free(vip.filename);
|
||||
|
@ -190,7 +107,7 @@ void open_editor(char *filename)
|
|||
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
|
||||
len--;
|
||||
}
|
||||
append_row(line, len);
|
||||
insert_row(vip.rows, line, len);
|
||||
}
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
@ -345,11 +262,12 @@ void move_cursor(int key)
|
|||
|
||||
void process_key()
|
||||
{
|
||||
static int quit_times = QUIT_CONFIRM
|
||||
static int quit_times = QUIT_CONFIRM;
|
||||
|
||||
int c = read_key();
|
||||
switch (c) {
|
||||
case '\r':
|
||||
/* TBC */
|
||||
insert_new_line();
|
||||
break;
|
||||
|
||||
case CTRL_KEY('q'):
|
||||
|
@ -380,7 +298,9 @@ void process_key()
|
|||
case BACKSPACE:
|
||||
case CTRL_KEY('h'):
|
||||
case DEL_KEY:
|
||||
/* TBC */
|
||||
if (c == DEL_KEY)
|
||||
move_cursor(ARROW_RIGHT);
|
||||
del_char();
|
||||
break;
|
||||
|
||||
case PAGE_UP:
|
||||
|
@ -426,6 +346,7 @@ void init_editor()
|
|||
vip.rows = 0;
|
||||
vip.row = NULL;
|
||||
vip.dirty = 0;
|
||||
vip.mode = NORMAL;
|
||||
vip.filename = NULL;
|
||||
vip.statusmsg[0] = '\0';
|
||||
vip.statusmsg_time = 0;
|
||||
|
|
Loading…
Reference in a new issue