Introduction
Introduction Statistics Contact Development Disclaimer Help
tAdd basic file loading and writing functionality - ledit - Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log
Files
Refs
README
LICENSE
---
commit 86dd70c41a66c874b49092caa1986ecedd36f254
parent 36a12616e748e39265af475dbaee5e8356cc984a
Author: lumidify <[email protected]>
Date: Wed, 22 Sep 2021 20:17:12 +0200
Add basic file loading and writing functionality
Diffstat:
M buffer.c | 103 +++++++++++++++++++++++++++++…
M buffer.h | 8 ++++++--
M commands.c | 9 +++++++--
M ledit.c | 13 ++++++++++++-
4 files changed, 122 insertions(+), 11 deletions(-)
---
diff --git a/buffer.c b/buffer.c
t@@ -1,8 +1,10 @@
/* FIXME: shrink buffers when text length less than a fourth of the size */
/* FIXME: also cache PangoLayouts since keeping them around isn't really of mu…
+#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <limits.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
t@@ -44,6 +46,7 @@ ledit_create_buffer(ledit_common_state *state) {
ledit_buffer *buffer = ledit_malloc(sizeof(ledit_buffer));
buffer->state = state;
buffer->lines = NULL;
+ buffer->filename = NULL;
buffer->lines_num = 0;
buffer->lines_cap = 0;
buffer->cur_line = 0;
t@@ -62,6 +65,84 @@ ledit_create_buffer(ledit_common_state *state) {
return buffer;
}
+/* FIXME: don't generate extra blank line at end! */
+/* WARNING: errstr must be copied as soon as possible! */
+int
+ledit_load_file_into_buffer(ledit_buffer *buffer, char *filename, int line, ch…
+ long len;
+ int off = 0;
+ ledit_line *ll;
+ char *file_contents;
+ FILE *file;
+
+ file = fopen(filename, "r");
+ if (!file) goto error;
+ if (fseek(file, 0, SEEK_END)) goto errorclose;
+ len = ftell(file);
+ if (len < 0) goto errorclose;
+ if (fseek(file, 0, SEEK_SET)) goto errorclose;
+
+ ll = ledit_get_line(buffer, line);
+ file_contents = ledit_malloc(len + 2);
+ /* mimic nvi (or at least the openbsd version) - if the line
+ is empty, insert directly, otherwise insert after the line */
+ if (ll->len > 0) {
+ off = 1;
+ file_contents[0] = '\n';
+ }
+ clearerr(file);
+ fread(file_contents + off, 1, (size_t)len, file);
+ if (ferror(file)) goto errorclose;
+ file_contents[len + off] = '\0';
+ /* don't generate extra newline at end */
+ if (len + off > 1 && file_contents[len + off - 1 == '\n']) {
+ file_contents[len + off - 1] = '\0';
+ len--;
+ }
+ if (fclose(file)) goto error;
+
+ ledit_insert_text_with_newlines(
+ buffer, line, ll->len, file_contents, len + off, NULL, NULL
+ );
+ free(file_contents);
+ return 0;
+error:
+ if (*errstr)
+ *errstr = strerror(errno);
+ return 1;
+errorclose:
+ if (*errstr)
+ *errstr = strerror(errno);
+ fclose(file);
+ return 1;
+}
+
+/* FIXME: allow to write only certain lines */
+int
+ledit_write_buffer_to_file(ledit_buffer *buffer, char *filename, char **errstr…
+ FILE *file;
+ ledit_line *ll;
+ file = fopen(filename, "w");
+ if (!file) goto error;
+ clearerr(file);
+ for (int i = 0; i < buffer->lines_num; i++) {
+ ll = ledit_get_line(buffer, i);
+ ledit_normalize_line(ll);
+ if (fprintf(file, "%s\n", ll->text) < 0) goto errorclose;
+ }
+ if (fclose(file)) goto error;
+ return 0;
+error:
+ if (*errstr)
+ *errstr = strerror(errno);
+ return 1;
+errorclose:
+ if (*errstr)
+ *errstr = strerror(errno);
+ fclose(file);
+ return 1;
+}
+
void
ledit_destroy_buffer(ledit_buffer *buffer) {
ledit_line *l;
t@@ -71,6 +152,7 @@ ledit_destroy_buffer(ledit_buffer *buffer) {
free(l->text);
}
free(buffer->lines);
+ if (buffer->filename) free(buffer->filename);
free(buffer);
}
t@@ -84,6 +166,7 @@ ledit_normalize_line(ledit_line *line) {
);
line->gap = line->len;
}
+ /* FIXME: check if enough space, just to be sure */
line->text[line->len] = '\0';
}
t@@ -338,8 +421,8 @@ ledit_insert_text_final(ledit_buffer *buffer, int line_ind…
/* FIXME: this isn't optimized like the standard version, but whatever */
static char *
-strchr_len(char *text, char c, int len) {
- for (int i = 0; i < len; i++) {
+strchr_len(char *text, char c, long len) {
+ for (long i = 0; i < len; i++) {
if (text[i] == c)
return text + i;
}
t@@ -347,11 +430,18 @@ strchr_len(char *text, char c, int len) {
}
/* FIXME: make these functions that call recalc* also be final as described ab…
+/* FIXME: Sort out integer types.
+ -> len is long here mainly because that's what ftell(3) returns and it sort…
+ makes sense since a file can be very long (although ledit probably won't wo…
+ with such long files anyways). The individual lines have to use int anyways
+ because of pango.
+ Maybe len isn't needed anyways? It might be possible to enforce that text
+ just always has to be null-terminated. */
void
ledit_insert_text_with_newlines(
ledit_buffer *buffer,
int line_index, int index,
- char *text, int len,
+ char *text, long len,
int *end_line_ret, int *end_char_ret) {
int end;
ledit_insert_text_with_newlines_base(
t@@ -366,15 +456,16 @@ ledit_insert_text_with_newlines(
ledit_recalc_from_line(buffer, line_index);
}
+/* FIXME: Check for integer overflow when casting to int */
void
ledit_insert_text_with_newlines_base(
ledit_buffer *buffer,
int line_index, int index,
- char *text, int len,
+ char *text, long len,
int *end_line_ret, int *end_char_ret) {
if (len == -1)
len = strlen(text);
- int rem_len = len;
+ long rem_len = len;
char *cur, *last = text;
int cur_line = line_index;
int cur_index = index;
t@@ -384,8 +475,8 @@ ledit_insert_text_with_newlines_base(
ledit_insert_text_base(buffer, cur_line, cur_index, last, cur …
cur_index = 0;
cur_line++;
- last = cur + 1;
rem_len -= cur - last + 1;
+ last = cur + 1;
}
/* FIXME: check how legal this casting between pointers and ints is */
ledit_insert_text_base(buffer, cur_line, cur_index, last, text + len -…
diff --git a/buffer.h b/buffer.h
t@@ -25,9 +25,11 @@ typedef struct {
char h_dirty; /* whether height needs to be recalculated still */
} ledit_line;
+/* TODO: advisory lock on file? also check if modification date changed before…
struct ledit_buffer {
ledit_common_state *state; /* general state, e.g. display, window, etc…
ledit_line *lines; /* array of lines */
+ char *filename;
int lines_cap; /* number of lines allocated in array */
int lines_num; /* number of used lines */
int cur_line; /* current line */
t@@ -44,6 +46,8 @@ struct ledit_buffer {
};
ledit_buffer *ledit_create_buffer(ledit_common_state *state);
+int ledit_load_file_into_buffer(ledit_buffer *buffer, char *filename, int line…
+int ledit_write_buffer_to_file(ledit_buffer *buffer, char *filename, char **er…
void ledit_destroy_buffer(ledit_buffer *buffer);
void ledit_normalize_line(ledit_line *line);
void ledit_set_line_selection(ledit_buffer *buffer, int line, int start_byte, …
t@@ -80,7 +84,7 @@ void ledit_insert_text_base(ledit_buffer *buffer, int line_i…
void ledit_insert_text_with_newlines_base(
ledit_buffer *buffer,
int line_index, int index,
- char *text, int len,
+ char *text, long len,
int *end_line_ret, int *end_char_ret
);
void ledit_append_line_base(ledit_buffer *buffer, int line_index, int text_ind…
t@@ -105,7 +109,7 @@ void ledit_insert_text(ledit_buffer *buffer, int line_inde…
void ledit_insert_text_with_newlines(
ledit_buffer *buffer,
int line_index, int index,
- char *text, int len,
+ char *text, long len,
int *end_line_ret, int *end_char_ret
);
void ledit_append_line(ledit_buffer *buffer, int line_index, int text_index);
diff --git a/commands.c b/commands.c
t@@ -1,5 +1,6 @@
/* FIXME: Parse commands properly and allow combinations of commands */
#include <ctype.h>
+#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <pango/pangoxft.h>
t@@ -16,7 +17,10 @@ handle_write(ledit_buffer *buffer, char *cmd, int l1, int l…
(void)cmd;
(void)l1;
(void)l2;
- printf("write\n");
+ /* FIXME: Implement properly; handle error */
+ char *errstr;
+ if (buffer->filename)
+ ledit_write_buffer_to_file(buffer, buffer->filename, &errstr);
return 0;
}
t@@ -26,7 +30,8 @@ handle_quit(ledit_buffer *buffer, char *cmd, int l1, int l2)…
(void)cmd;
(void)l1;
(void)l2;
- printf("quit\n");
+ /* FIXME: Implement */
+ exit(1);
return 0;
}
diff --git a/ledit.c b/ledit.c
t@@ -37,6 +37,7 @@
#include "cache.h"
#include "util.h"
#include "undo.h"
+#include "commands.h"
enum key_type {
KEY_NONE = 0,
t@@ -1021,7 +1022,17 @@ setup(int argc, char *argv[]) {
buffer = ledit_create_buffer(&state);
/* FIXME: move this to create_buffer */
ledit_init_undo_stack(buffer);
- set_mode(INSERT);
+ /* FIXME: Support multiple buffers/files */
+ if (argc > 1) {
+ char *load_err;
+ if (ledit_load_file_into_buffer(buffer, argv[1], 0, &load_err)…
+ fprintf(stderr, "Error opening file '%s': %s\n", argv[…
+ exit(1);
+ }
+ buffer->filename = ledit_strdup(argv[1]);
+ }
+ set_mode(NORMAL);
+ ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_inde…
key_stack.len = key_stack.alloc = 0;
key_stack.stack = NULL;
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.