Checkpoint file split.
This commit is contained in:
@@ -21,12 +21,13 @@ include(GNUInstallDirs)
|
|||||||
|
|
||||||
# Add executable
|
# Add executable
|
||||||
add_executable(ke
|
add_executable(ke
|
||||||
main.c
|
|
||||||
abuf.c
|
abuf.c
|
||||||
term.c
|
term.c
|
||||||
buffer.c
|
buffer.c
|
||||||
|
editor.c
|
||||||
core.c
|
core.c
|
||||||
core.h
|
core.h
|
||||||
|
main.c
|
||||||
)
|
)
|
||||||
target_compile_definitions(ke PRIVATE KE_VERSION="ke version ${KE_VERSION}")
|
target_compile_definitions(ke PRIVATE KE_VERSION="ke version ${KE_VERSION}")
|
||||||
install(TARGETS ke RUNTIME DESTINATION bin)
|
install(TARGETS ke RUNTIME DESTINATION bin)
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -11,7 +11,8 @@ LDFLAGS := -fsanitize=address
|
|||||||
|
|
||||||
all: $(TARGET) test.txt
|
all: $(TARGET) test.txt
|
||||||
|
|
||||||
SRCS := main.c abuf.c term.c buffer.c
|
SRCS := main.c abuf.c term.c buffer.c editor.c core.c
|
||||||
|
HDRS := abuf.h term.h buffer.h editor.h core.h
|
||||||
|
|
||||||
$(TARGET): $(SRCS)
|
$(TARGET): $(SRCS)
|
||||||
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LDFLAGS)
|
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LDFLAGS)
|
||||||
@@ -33,3 +34,7 @@ test.txt:
|
|||||||
gdb:
|
gdb:
|
||||||
@test -f $(TARGET).pid || (echo "error: $(TARGET).pid not found" >&2; exit 1)
|
@test -f $(TARGET).pid || (echo "error: $(TARGET).pid not found" >&2; exit 1)
|
||||||
@gdb -p $$(cat $(TARGET).pid | tr -d ' \t\n\r') ./$(TARGET)
|
@gdb -p $$(cat $(TARGET).pid | tr -d ' \t\n\r') ./$(TARGET)
|
||||||
|
|
||||||
|
.PHONY: cloc
|
||||||
|
cloc:
|
||||||
|
cloc $(SRCS) $(HDRS)
|
||||||
|
|||||||
22
abuf.c
22
abuf.c
@@ -3,10 +3,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "abuf.h"
|
#include "abuf.h"
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
abuf_init(abuf *buf)
|
ab_init(abuf *buf)
|
||||||
{
|
{
|
||||||
assert(buf != NULL);
|
assert(buf != NULL);
|
||||||
|
|
||||||
@@ -15,6 +16,25 @@ abuf_init(abuf *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ab_init_cap(abuf *buf, const size_t cap)
|
||||||
|
{
|
||||||
|
buf->b = calloc(cap, 1);
|
||||||
|
buf->size = 0;
|
||||||
|
buf->cap = cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ab_resize(abuf *buf, size_t cap)
|
||||||
|
{
|
||||||
|
cap = cap_growth(buf->cap, cap);
|
||||||
|
buf->b = realloc(buf->b, cap);
|
||||||
|
assert(buf->b != NULL);
|
||||||
|
buf->cap = cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ab_appendch(abuf *buf, char c)
|
ab_appendch(abuf *buf, char c)
|
||||||
{
|
{
|
||||||
|
|||||||
3
abuf.h
3
abuf.h
@@ -13,10 +13,13 @@ typedef struct abuf {
|
|||||||
size_t cap;
|
size_t cap;
|
||||||
} abuf;
|
} abuf;
|
||||||
|
|
||||||
|
|
||||||
#define ABUF_INIT {NULL, 0, 0}
|
#define ABUF_INIT {NULL, 0, 0}
|
||||||
|
|
||||||
|
|
||||||
void ab_init(abuf *buf);
|
void ab_init(abuf *buf);
|
||||||
|
void ab_init_cap(abuf *buf, size_t cap);
|
||||||
|
void ab_resize(abuf *buf, size_t cap);
|
||||||
void ab_appendch(abuf *buf, char c);
|
void ab_appendch(abuf *buf, char c);
|
||||||
void ab_append(abuf *buf, const char *s, size_t len);
|
void ab_append(abuf *buf, const char *s, size_t len);
|
||||||
void ab_prependch(abuf *buf, const char c);
|
void ab_prependch(abuf *buf, const char c);
|
||||||
|
|||||||
123
buffer.c
123
buffer.c
@@ -1,4 +1,4 @@
|
|||||||
/* buffer.c - buffer management implementation */
|
/* buffer.c - multiple file buffers */
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -8,13 +8,15 @@
|
|||||||
|
|
||||||
#include "abuf.h"
|
#include "abuf.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "core.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
|
|
||||||
#define NO_NAME "[No Name]"
|
#define NO_NAME "[No Name]"
|
||||||
|
|
||||||
|
|
||||||
/* externs from other modules */
|
/* externs from other modules */
|
||||||
char *editor_prompt(char *, void (*cb)(char *, int16_t));
|
char *editor_prompt(const char *, void (*cb)(char *, int16_t));
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
@@ -28,6 +30,7 @@ buf_basename(const char *path)
|
|||||||
return (slash != NULL) ? (slash + 1) : path;
|
return (slash != NULL) ? (slash + 1) : path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
buffer_find_exact_by_name(const char *name)
|
buffer_find_exact_by_name(const char *name)
|
||||||
{
|
{
|
||||||
@@ -38,7 +41,7 @@ buffer_find_exact_by_name(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < editor.bufcount; i++) {
|
for (int i = 0; i < editor.bufcount; i++) {
|
||||||
b = editor.buffers[i];
|
b = editor.buffers[i];
|
||||||
const char *full = b->filename;
|
const char *full = b->filename;
|
||||||
const char *base = buf_basename(full);
|
const char *base = buf_basename(full);
|
||||||
|
|
||||||
@@ -62,13 +65,13 @@ buffer_find_exact_by_name(const char *name)
|
|||||||
static int
|
static int
|
||||||
buffer_collect_prefix_matches(const char *prefix, int *out_idx, const int max_out)
|
buffer_collect_prefix_matches(const char *prefix, int *out_idx, const int max_out)
|
||||||
{
|
{
|
||||||
buffer *b = NULL;
|
buffer *b = NULL;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int matched = 0;
|
int matched = 0;
|
||||||
size_t plen = (prefix ? strlen(prefix) : 0);
|
size_t plen = (prefix ? strlen(prefix) : 0);
|
||||||
|
|
||||||
for (int i = 0; i < editor.bufcount; i++) {
|
for (int i = 0; i < editor.bufcount; i++) {
|
||||||
b = editor.buffers[i];
|
b = editor.buffers[i];
|
||||||
|
|
||||||
const char *cand1 = b->filename;
|
const char *cand1 = b->filename;
|
||||||
const char *cand2 = buf_basename(cand1);
|
const char *cand2 = buf_basename(cand1);
|
||||||
@@ -100,13 +103,13 @@ buffer_collect_prefix_matches(const char *prefix, int *out_idx, const int max_ou
|
|||||||
static void
|
static void
|
||||||
longest_common_prefix(char *buf, const size_t bufsz, const int *idxs, const int n)
|
longest_common_prefix(char *buf, const size_t bufsz, const int *idxs, const int n)
|
||||||
{
|
{
|
||||||
const char *first = NULL;
|
const char *first = NULL;
|
||||||
const char *cand = NULL;
|
const char *cand = NULL;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
size_t cur = 0;
|
size_t cur = 0;
|
||||||
size_t lcp = 0;
|
size_t lcp = 0;
|
||||||
size_t to_copy = 0;
|
size_t to_copy = 0;
|
||||||
|
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
return;
|
return;
|
||||||
@@ -150,19 +153,18 @@ longest_common_prefix(char *buf, const size_t bufsz, const int *idxs, const int
|
|||||||
static void
|
static void
|
||||||
buffer_switch_prompt_cb(char *buf, const int16_t key)
|
buffer_switch_prompt_cb(char *buf, const int16_t key)
|
||||||
{
|
{
|
||||||
char msg[80] = {0};
|
char msg[80] = {0};
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
const char *nm = NULL;
|
const char *nm = NULL;
|
||||||
int idxs[64] = {0};
|
int idxs[64] = {0};
|
||||||
int n = 0;
|
int n = 0;
|
||||||
size_t need = 0;
|
size_t need = 0;
|
||||||
size_t used = 0;
|
size_t used = 0;
|
||||||
|
|
||||||
if (key != 9) { /* TODO(kyle): extract TAB_KEY */
|
if (key != TAB_KEY) {
|
||||||
return; /* TAB key */
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
n = buffer_collect_prefix_matches(buf, idxs, 64);
|
n = buffer_collect_prefix_matches(buf, idxs, 64);
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
editor_set_status("No matches");
|
editor_set_status("No matches");
|
||||||
@@ -187,7 +189,7 @@ buffer_switch_prompt_cb(char *buf, const int16_t key)
|
|||||||
|
|
||||||
longest_common_prefix(buf, 128, idxs, n);
|
longest_common_prefix(buf, 128, idxs, n);
|
||||||
msg[0] = '\0';
|
msg[0] = '\0';
|
||||||
used = 0;
|
used = 0;
|
||||||
used += snprintf(msg + used, sizeof(msg) - used, "%d matches: ", n);
|
used += snprintf(msg + used, sizeof(msg) - used, "%d matches: ", n);
|
||||||
for (int i = 0; i < n && used < sizeof(msg) - 1; i++) {
|
for (int i = 0; i < n && used < sizeof(msg) - 1; i++) {
|
||||||
nm = buf_basename(editor.buffers[idxs[i]]->filename);
|
nm = buf_basename(editor.buffers[idxs[i]]->filename);
|
||||||
@@ -204,7 +206,7 @@ buffer_switch_prompt_cb(char *buf, const int16_t key)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
buffer_bind_to_editor(buffer *b)
|
buffer_bind_to_editor(const buffer *b)
|
||||||
{
|
{
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
return;
|
return;
|
||||||
@@ -225,7 +227,8 @@ buffer_bind_to_editor(buffer *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void buffer_extract_from_editor(buffer *b)
|
static void
|
||||||
|
buffer_extract_from_editor(buffer *b)
|
||||||
{
|
{
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
return;
|
return;
|
||||||
@@ -273,9 +276,9 @@ buffers_init(void)
|
|||||||
int
|
int
|
||||||
buffer_add_empty(void)
|
buffer_add_empty(void)
|
||||||
{
|
{
|
||||||
buffer *buf = NULL;
|
buffer *buf = NULL;
|
||||||
buffer **newlist = realloc(editor.buffers, sizeof(buffer *) * (editor.bufcount + 1));
|
buffer **newlist = realloc(editor.buffers, sizeof(buffer *) * (editor.bufcount + 1));
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
assert(newlist != NULL);
|
assert(newlist != NULL);
|
||||||
editor.buffers = newlist;
|
editor.buffers = newlist;
|
||||||
@@ -306,7 +309,7 @@ buffer_add_empty(void)
|
|||||||
void
|
void
|
||||||
buffer_save_current(void)
|
buffer_save_current(void)
|
||||||
{
|
{
|
||||||
buffer *b = NULL;
|
buffer *b = NULL;
|
||||||
|
|
||||||
if (editor.curbuf < 0 || editor.curbuf >= editor.bufcount) {
|
if (editor.curbuf < 0 || editor.curbuf >= editor.bufcount) {
|
||||||
return;
|
return;
|
||||||
@@ -317,6 +320,43 @@ buffer_save_current(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
buffer *
|
||||||
|
buffer_current(void)
|
||||||
|
{
|
||||||
|
if (editor.curbuf < 0 || editor.curbuf >= editor.bufcount) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return editor.buffers[editor.curbuf];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
buffer_is_unnamed_and_empty(const buffer *b)
|
||||||
|
{
|
||||||
|
if (b == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->filename != NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->dirty) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->nrows != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->row != NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
buffer_switch(const int idx)
|
buffer_switch(const int idx)
|
||||||
{
|
{
|
||||||
@@ -345,7 +385,7 @@ buffer_switch(const int idx)
|
|||||||
void
|
void
|
||||||
buffer_next(void)
|
buffer_next(void)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
if (editor.bufcount <= 1) {
|
if (editor.bufcount <= 1) {
|
||||||
return;
|
return;
|
||||||
@@ -355,7 +395,9 @@ buffer_next(void)
|
|||||||
buffer_switch(idx);
|
buffer_switch(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_prev(void)
|
|
||||||
|
void
|
||||||
|
buffer_prev(void)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
@@ -371,10 +413,10 @@ void buffer_prev(void)
|
|||||||
void
|
void
|
||||||
buffer_close_current(void)
|
buffer_close_current(void)
|
||||||
{
|
{
|
||||||
buffer *b = NULL;
|
buffer *b = NULL;
|
||||||
int closing = 0;
|
int closing = 0;
|
||||||
int target = 0;
|
int target = 0;
|
||||||
int nb = 0;
|
int nb = 0;
|
||||||
|
|
||||||
if (editor.curbuf < 0 || editor.curbuf >= editor.bufcount) {
|
if (editor.curbuf < 0 || editor.curbuf >= editor.bufcount) {
|
||||||
editor_set_status("No buffer to close.");
|
editor_set_status("No buffer to close.");
|
||||||
@@ -429,10 +471,15 @@ void
|
|||||||
buffer_switch_by_name(void)
|
buffer_switch_by_name(void)
|
||||||
{
|
{
|
||||||
int idxs[64] = {0};
|
int idxs[64] = {0};
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
|
if (editor.bufcount <= 1) {
|
||||||
|
editor_set_status("No other buffers.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
name = editor_prompt("Switch buffer (name, TAB to complete): %s", buffer_switch_prompt_cb);
|
name = editor_prompt("Switch buffer (name, TAB to complete): %s", buffer_switch_prompt_cb);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
19
buffer.h
19
buffer.h
@@ -16,6 +16,23 @@ typedef struct buffer {
|
|||||||
int mark_curx, mark_cury;
|
int mark_curx, mark_cury;
|
||||||
} buffer;
|
} buffer;
|
||||||
|
|
||||||
|
/* Access current buffer and convenient aliases for file-specific fields */
|
||||||
|
buffer *buffer_current(void);
|
||||||
|
|
||||||
|
#define CURBUF (buffer_current())
|
||||||
|
#define EROW (CURBUF->row)
|
||||||
|
#define ENROWS (CURBUF->nrows)
|
||||||
|
#define ECURX (CURBUF->curx)
|
||||||
|
#define ECURY (CURBUF->cury)
|
||||||
|
#define ERX (CURBUF->rx)
|
||||||
|
#define EROWOFFS (CURBUF->rowoffs)
|
||||||
|
#define ECOLOFFS (CURBUF->coloffs)
|
||||||
|
#define EFILENAME (CURBUF->filename)
|
||||||
|
#define EDIRTY (CURBUF->dirty)
|
||||||
|
#define EMARK_SET (CURBUF->mark_set)
|
||||||
|
#define EMARK_CURX (CURBUF->mark_curx)
|
||||||
|
#define EMARK_CURY (CURBUF->mark_cury)
|
||||||
|
|
||||||
|
|
||||||
void buffers_init(void);
|
void buffers_init(void);
|
||||||
int buffer_add_empty(void);
|
int buffer_add_empty(void);
|
||||||
@@ -26,6 +43,8 @@ void buffer_prev(void);
|
|||||||
void buffer_switch_by_name(void);
|
void buffer_switch_by_name(void);
|
||||||
void buffer_close_current(void);
|
void buffer_close_current(void);
|
||||||
const char *buffer_name(buffer *b);
|
const char *buffer_name(buffer *b);
|
||||||
|
/* Helpers */
|
||||||
|
int buffer_is_unnamed_and_empty(const buffer *b);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
64
core.c
64
core.c
@@ -35,6 +35,70 @@ strnstr(const char *s, const char *find, size_t slen)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
char
|
||||||
|
nibble_to_hex(char c)
|
||||||
|
{
|
||||||
|
c &= 0xf;
|
||||||
|
if (c < 10) {
|
||||||
|
return (char)('0' + c);
|
||||||
|
}
|
||||||
|
return (char)('A' + (c - 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
swap_int(int *first, int *second)
|
||||||
|
{
|
||||||
|
*first ^= *second;
|
||||||
|
*second ^= *first;
|
||||||
|
*first ^= *second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
next_power_of_2(int n)
|
||||||
|
{
|
||||||
|
if (n < 2) {
|
||||||
|
n = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
n--;
|
||||||
|
n |= n >> 1;
|
||||||
|
n |= n >> 2;
|
||||||
|
n |= n >> 4;
|
||||||
|
n |= n >> 8;
|
||||||
|
n |= n >> 16;
|
||||||
|
|
||||||
|
return n + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
cap_growth(int cap, int sz)
|
||||||
|
{
|
||||||
|
if (cap == 0) {
|
||||||
|
cap = INITIAL_CAPACITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cap <= sz) {
|
||||||
|
cap = next_power_of_2(cap + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
kstrnlen(const char *buf, const size_t max)
|
||||||
|
{
|
||||||
|
if (buf == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strnlen(buf, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
kwrite(const int fd, const char* buf, const int len)
|
kwrite(const int fd, const char* buf, const int len)
|
||||||
{
|
{
|
||||||
|
|||||||
17
core.h
17
core.h
@@ -1,11 +1,13 @@
|
|||||||
#ifndef KE_CORE_H
|
#ifndef KE_CORE_H
|
||||||
#define KE_CORE_H
|
#define KE_CORE_H
|
||||||
|
|
||||||
|
|
||||||
#define calloc1(sz) calloc(1, sz)
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define calloc1(sz) calloc(1, sz)
|
||||||
|
#define INITIAL_CAPACITY 8
|
||||||
|
|
||||||
|
|
||||||
typedef enum key_press {
|
typedef enum key_press {
|
||||||
TAB_KEY = 9,
|
TAB_KEY = 9,
|
||||||
ESC_KEY = 27,
|
ESC_KEY = 27,
|
||||||
@@ -21,14 +23,19 @@ typedef enum key_press {
|
|||||||
PG_DN = 1008,
|
PG_DN = 1008,
|
||||||
} key_press;
|
} key_press;
|
||||||
|
|
||||||
|
|
||||||
#ifndef strnstr
|
#ifndef strnstr
|
||||||
char *strnstr(const char *s, const char *find, size_t slen);
|
char *strnstr(const char *s, const char *find, size_t slen);
|
||||||
#define INCLUDE_STRNSTR
|
#define INCLUDE_STRNSTR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char nibble_to_hex(char c);
|
||||||
void kwrite(int fd, const char *buf, int len);
|
void swap_int(int *first, int *second);
|
||||||
void die(const char *s);
|
int next_power_of_2(int n);
|
||||||
|
int cap_growth(int cap, int sz);
|
||||||
|
size_t kstrnlen(const char *buf, size_t max);
|
||||||
|
void kwrite(int fd, const char *buf, int len);
|
||||||
|
void die(const char *s);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
124
editor.c
Normal file
124
editor.c
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/* editor.c - editor-wide state and functions */
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "abuf.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "core.h"
|
||||||
|
#include "editor.h"
|
||||||
|
#include "term.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global editor instance
|
||||||
|
*/
|
||||||
|
struct editor editor = {
|
||||||
|
.cols = 0,
|
||||||
|
.rows = 0,
|
||||||
|
.curx = 0,
|
||||||
|
.cury = 0,
|
||||||
|
.rx = 0,
|
||||||
|
.mode = 0,
|
||||||
|
.nrows = 0,
|
||||||
|
.rowoffs = 0,
|
||||||
|
.coloffs = 0,
|
||||||
|
.row = NULL,
|
||||||
|
.killring = NULL,
|
||||||
|
.kill = 0,
|
||||||
|
.no_kill = 0,
|
||||||
|
.filename = NULL,
|
||||||
|
.dirty = 0,
|
||||||
|
.dirtyex = 0,
|
||||||
|
.mark_set = 0,
|
||||||
|
.mark_curx = 0,
|
||||||
|
.mark_cury = 0,
|
||||||
|
.uarg = 0,
|
||||||
|
.ucount = 0,
|
||||||
|
.msgtm = 0,
|
||||||
|
.buffers = NULL,
|
||||||
|
.bufcount = 0,
|
||||||
|
.curbuf = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
editor_set_status(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(editor.msg, sizeof(editor.msg), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
editor.msgtm = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
init_editor(void)
|
||||||
|
{
|
||||||
|
editor.cols = 0;
|
||||||
|
editor.rows = 0;
|
||||||
|
|
||||||
|
if (get_winsz(&editor.rows, &editor.cols) == -1) {
|
||||||
|
die("can't get window size");
|
||||||
|
}
|
||||||
|
editor.rows--; /* status bar */
|
||||||
|
editor.rows--; /* message line */
|
||||||
|
|
||||||
|
editor.curx = editor.cury = 0;
|
||||||
|
editor.rx = 0;
|
||||||
|
|
||||||
|
editor.nrows = 0;
|
||||||
|
editor.rowoffs = editor.coloffs = 0;
|
||||||
|
editor.row = NULL;
|
||||||
|
|
||||||
|
/* don't clear out the kill ring:
|
||||||
|
* killing / yanking across files is helpful, and killring
|
||||||
|
* is initialized to NULL at program start.
|
||||||
|
*/
|
||||||
|
editor.kill = 0;
|
||||||
|
editor.no_kill = 0;
|
||||||
|
|
||||||
|
editor.msg[0] = '\0';
|
||||||
|
editor.msgtm = 0;
|
||||||
|
|
||||||
|
editor.dirty = 0;
|
||||||
|
editor.mark_set = 0;
|
||||||
|
editor.mark_cury = editor.mark_curx = 0;
|
||||||
|
|
||||||
|
/* initialize buffer system on first init */
|
||||||
|
if (editor.buffers == NULL && editor.bufcount == 0) {
|
||||||
|
buffers_init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
reset_editor(void)
|
||||||
|
{
|
||||||
|
/* Clear current working set. Notably, does not reset terminal
|
||||||
|
* or buffers list. */
|
||||||
|
for (int i = 0; i < editor.nrows; i++) {
|
||||||
|
ab_free(&editor.row[i]);
|
||||||
|
}
|
||||||
|
free(editor.row);
|
||||||
|
|
||||||
|
editor.row = NULL;
|
||||||
|
editor.nrows = 0;
|
||||||
|
editor.rowoffs = editor.coloffs = 0;
|
||||||
|
editor.curx = editor.cury = 0;
|
||||||
|
editor.rx = 0;
|
||||||
|
|
||||||
|
if (editor.filename != NULL) {
|
||||||
|
free(editor.filename);
|
||||||
|
editor.filename = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.dirty = 0;
|
||||||
|
editor.mark_set = 0;
|
||||||
|
editor.mark_cury = editor.mark_curx = 0;
|
||||||
|
}
|
||||||
47
editor.h
Normal file
47
editor.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef EDITOR_H
|
||||||
|
#define EDITOR_H
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "abuf.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO(kyle): remove the "per-buffer" fields completely from the editor. */
|
||||||
|
|
||||||
|
struct editor {
|
||||||
|
int rows, cols;
|
||||||
|
int curx, cury; /* per-buffer */
|
||||||
|
int rx; /* per-buffer */
|
||||||
|
int mode;
|
||||||
|
int nrows; /* per-buffer */
|
||||||
|
int rowoffs, coloffs; /* per-buffer */
|
||||||
|
abuf *row; /* per-buffer */
|
||||||
|
abuf *killring;
|
||||||
|
int kill; /* KILL CHAIN (\m/) */
|
||||||
|
int no_kill; /* don't kill in delete_row */
|
||||||
|
char *filename; /* per-buffer */
|
||||||
|
int dirty; /* per-buffer */
|
||||||
|
int dirtyex;
|
||||||
|
char msg[80];
|
||||||
|
int mark_set; /* per-buffer */
|
||||||
|
int mark_curx, mark_cury; /* per-buffer */
|
||||||
|
int uarg, ucount; /* C-u support */
|
||||||
|
time_t msgtm;
|
||||||
|
|
||||||
|
/* Multi-buffer support */
|
||||||
|
struct buffer **buffers; /* array of buffers */
|
||||||
|
int bufcount; /* number of buffers */
|
||||||
|
int curbuf; /* current buffer index */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern struct editor editor;
|
||||||
|
void editor_set_status(const char *fmt, ...);
|
||||||
|
void init_editor(void);
|
||||||
|
void reset_editor(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* EDITOR_H */
|
||||||
Reference in New Issue
Block a user