Vinicius Teshima 1 рік тому
батько
коміт
0b36ccc9e5
5 змінених файлів з 398 додано та 57 видалено
  1. 252 20
      src/buffer.h
  2. 22 3
      src/config.h
  3. 34 5
      src/file.h
  4. 80 18
      src/keybind.h
  5. 10 11
      src/main.c

+ 252 - 20
src/buffer.h

@@ -1,15 +1,47 @@
 #ifndef BUFFER_H
 #define BUFFER_H
 
+
+
 struct buffer {
 	DA_DEF_STRUCT_ITEM(char, data);
 	size_t cur;
 };
 
+enum buffer_err {
+	BUFFER_ERR_OK = 0,
+	BUFFER_ERR_EMPTY,
+	BUFFER_ERR_NOT_FOUND,
+	BUFFER_ERR_INVALID_CUR_POS,
+	BUFFER_ERR_FAIL_READ_FILE,
+	BUFFER_ERR_START_GT_END,
+	BUFFER_ERR_INVALID_END_SIZE,
+};
+
+struct ret_buffer_err {
+	struct buffer f1;
+	enum buffer_err f2;
+};
+
+struct ret_size_t_err {
+	size_t f1;
+	enum buffer_err f2;
+};
+
+struct ret_buffer_size_t_err {
+	struct buffer f1;
+	size_t f2;
+	enum buffer_err f3;
+};
+
 struct buffer buffer_create(void);
 void buffer_destroy(struct buffer buf);
 
-struct buffer buffer_mv_cur_letf(struct buffer buf);
+struct ret_buffer_err buffer_load_from_file(struct buffer buf,
+					    const char *filepath);
+enum buffer_err buffer_save_to_file(struct buffer buf, const char *filepath);
+
+struct buffer buffer_mv_cur_left(struct buffer buf);
 struct buffer buffer_mv_cur_right(struct buffer buf);
 struct buffer buffer_mv_cur_up(struct buffer buf);
 struct buffer buffer_mv_cur_down(struct buffer buf);
@@ -17,14 +49,22 @@ struct buffer buffer_mv_cur_down(struct buffer buf);
 struct buffer buffer_insert_char(struct buffer buf, size_t index, char c);
 struct buffer buffer_remove_char_mv_cur(struct buffer buf, size_t index);
 struct buffer buffer_remove_char(struct buffer buf, size_t index);
-struct buffer buffer_remove_between(struct buffer buf,
-				    size_t start, size_t end);
+struct ret_buffer_size_t_err buffer_remove_between(struct buffer buf,
+						   size_t start, size_t end);
 
-size_t buffer_index_bw_word(struct buffer buf);
+struct ret_size_t_err buffer_index_bw_word(struct buffer buf);
+struct ret_size_t_err buffer_index_fw_word(struct buffer buf);
+
+struct ret_size_t_err buffer_index_bw_char(struct buffer buf, char c);
+struct ret_size_t_err buffer_index_fw_char(struct buffer buf, char c);
 
 #if defined(BUFFER_IMP) || defined(IMP)
 
+#include <ctype.h>
+
+#include "file.h"
 #include "da.h"
+#include "unwrap.h"
 
 struct buffer
 buffer_create(void)
@@ -41,9 +81,47 @@ buffer_destroy(struct buffer buf)
 	free(buf.data.items);
 }
 
+struct ret_buffer_err
+buffer_load_from_file(struct buffer buf, const char *filepath)
+{
+
+	void *ptr;
+	size_t file_size;
+	enum file_err err;
+	RET_UNWRAP3(ptr, file_size, err,
+		    struct ret_void_p_err, file_read_all(filepath));
+
+	if ( err != FILE_ERR_OK ) {
+		return (struct ret_buffer_err) {
+			.f1 = buf,
+			.f2 = BUFFER_ERR_FAIL_READ_FILE
+		};
+	}
+
+	buffer_destroy(buf);
+
+	buf.data.items = ptr;
+	buf.data.size = file_size - 1;
+	buf.data.cap = file_size;
+
+	return (struct ret_buffer_err) {
+		.f1 = buf,
+		.f2 = BUFFER_ERR_OK
+	};
+}
+
+enum buffer_err
+buffer_save_to_file(struct buffer buf, const char *filepath)
+{
+	(void) buf;
+	(void) filepath;
+
+	return BUFFER_ERR_OK;
+}
+
 
 struct buffer
-buffer_mv_cur_letf(struct buffer buf)
+buffer_mv_cur_left(struct buffer buf)
 {
 	if ( buf.cur == 0 ) {
 		return buf;
@@ -134,19 +212,26 @@ buffer_remove_char(struct buffer buf, size_t index)
 	return buf;
 }
 
-struct buffer
+struct ret_buffer_size_t_err
 buffer_remove_between(struct buffer buf, size_t start, size_t end)
 {
+	enum buffer_err err = BUFFER_ERR_OK;
 	if ( buf.data.size == 0 ) {
-		return buf;
+		err = BUFFER_ERR_EMPTY;
+		goto err;
 	}
 
 	if ( start == end ) {
-		return buffer_remove_char(buf, start);
+		return (struct ret_buffer_size_t_err) {
+			.f1 = buffer_remove_char(buf, start),
+			.f2 = 1,
+			.f3 = BUFFER_ERR_OK,
+		};
 	}
 
 	if ( start > end ) {
-		return buf;
+		err = BUFFER_ERR_START_GT_END;
+		goto err;
 	}
 
 	DA_DEF_STRUCT_ITEM(char, da);
@@ -155,35 +240,99 @@ buffer_remove_between(struct buffer buf, size_t start, size_t end)
 	/* There is no need to check start > buf.data.size, because */
 	/* we know that start < end */
 	if ( end > da.size ) {
-		return buf;
+		err = BUFFER_ERR_INVALID_END_SIZE;
+		goto err;
 	}
 
 	size_t nrm = end - start;
-	printf("%ld\n", nrm);
 	memmove(da.items+start, da.items+end, da.size - nrm);
 	da.size -= nrm;
-	buf.cur -= nrm;
 
-	return buf;
+	return (struct ret_buffer_size_t_err) {
+		.f1 = buf,
+		.f2 = nrm,
+		.f3 = BUFFER_ERR_OK,
+	};
+
+err: ;
+	return (struct ret_buffer_size_t_err) {
+		.f1 = buf,
+		.f2 = 0,
+		.f3 = err
+	};
 }
 
-#include <ctype.h>
 
-size_t
+struct ret_size_t_err
 buffer_index_bw_word(struct buffer buf)
 {
+	enum buffer_err err = BUFFER_ERR_OK;
 	if ( buf.data.size == 0 ) {
-		return 0;
+		err = BUFFER_ERR_EMPTY;
+		goto err;
+	}
+
+	if ( buf.cur > buf.data.size ) {
+		err = BUFFER_ERR_INVALID_CUR_POS;
+		goto err;
 	}
 
 	bool found_letter = false;
-	size_t i = buf.cur;
+	size_t i = buf.cur - 1;
 	for ( ; i > 0; --i) {
 		char c = buf.data.items[i];
 		if ( isalpha(c) ) {
 			found_letter = true;
 		} else if ( found_letter ) {
-			return i+1;
+			++i;
+			goto exit;
+		}
+	}
+	if ( i == 0 ) {
+		char c = buf.data.items[i];
+		if ( isalpha(c) ) {
+			found_letter = true;
+		} else if ( found_letter ) {
+			++i;
+			goto exit;
+		}
+	}
+
+exit: ;
+	return (struct ret_size_t_err) {
+		.f1 = i,
+		.f2 = BUFFER_ERR_OK,
+	};
+
+err: ;
+	return (struct ret_size_t_err) {
+		.f1 = 0,
+		.f2 = err,
+	};
+}
+
+struct ret_size_t_err
+buffer_index_fw_word(struct buffer buf)
+{
+		enum buffer_err err = BUFFER_ERR_OK;
+	if ( buf.data.size == 0 ) {
+		err = BUFFER_ERR_EMPTY;
+		goto err;
+	}
+
+	if ( buf.cur > buf.data.size ) {
+		err = BUFFER_ERR_INVALID_CUR_POS;
+		goto err;
+	}
+
+	bool found_letter = false;
+	size_t i = buf.cur;
+	for ( ; i < buf.data.size; ++i) {
+		char c = buf.data.items[i];
+		if ( isalpha(c) ) {
+			found_letter = true;
+		} else if ( found_letter ) {
+			goto exit;
 		}
 	}
 	if ( i == 0 ) {
@@ -191,11 +340,94 @@ buffer_index_bw_word(struct buffer buf)
 		if ( isalpha(c) ) {
 			found_letter = true;
 		} else if ( found_letter ) {
-			return i+1;
+			goto exit;
+		}
+	}
+
+exit: ;
+	return (struct ret_size_t_err) {
+		.f1 = i,
+		.f2 = BUFFER_ERR_OK,
+	};
+
+err: ;
+	return (struct ret_size_t_err) {
+		.f1 = 0,
+		.f2 = err,
+	};
+}
+
+struct ret_size_t_err
+buffer_index_bw_char(struct buffer buf, char c)
+{
+	enum buffer_err err;
+	if ( buf.data.size == 0 ) {
+		err = BUFFER_ERR_EMPTY;
+		goto err;
+	}
+
+	if ( buf.cur > buf.data.size ) {
+		err = BUFFER_ERR_INVALID_CUR_POS;
+		goto err;
+	}
+
+	const char *str = buf.data.items;
+
+	bool cond = false;
+	/* TODO: Find a way to not use ssize_t buf size_t */
+	ssize_t closest = -1;
+	for ( ssize_t i = 0; i < (ssize_t) buf.cur; ++i ) {
+		cond = str[i] == c;
+		closest = ( cond ) * i + ( ! cond ) * closest;
+	}
+	if ( closest == -1 ) {
+		err = BUFFER_ERR_NOT_FOUND;
+		goto err;
+	}
+
+	return (struct ret_size_t_err) {
+		.f1 = (size_t) closest,
+		.f2 = BUFFER_ERR_OK,
+	};
+
+err: ;
+	return (struct ret_size_t_err) {
+		.f1 = 0,
+		.f2 = err,
+	};
+}
+
+struct ret_size_t_err
+buffer_index_fw_char(struct buffer buf, char c)
+{
+	enum buffer_err err;
+	if ( buf.data.size == 0 ) {
+		err = BUFFER_ERR_EMPTY;
+		goto err;
+	}
+
+	if ( buf.cur > buf.data.size ) {
+		err = BUFFER_ERR_INVALID_CUR_POS;
+		goto err;
+	}
+
+	const char *str = buf.data.items;
+
+	for ( size_t i = buf.cur; i < buf.data.size; ++i ) {
+		if ( str[i] == c ) {
+			return (struct ret_size_t_err) {
+				.f1 = i,
+				.f2 = BUFFER_ERR_OK,
+			};
 		}
 	}
+	err = BUFFER_ERR_NOT_FOUND;
 
-	return i;
+err: ;
+	return (struct ret_size_t_err) {
+		.f1 = 0,
+		.f2 = err,
+	};
 }
 
 #endif /* defined(BUFFER_IMP) || defined(IMP) */

+ 22 - 3
src/config.h

@@ -9,13 +9,13 @@ static struct keybinds keybinds[KMS] = {
 	[SDLK_LEFT % KMS] = {
 		.size = 1,
 		.binds = {
-			{KMOD_NONE, keybind_left, {.ptr = NULL}}
+			{KMOD_NONE, keybind_mv_cur_char, {.dir = DIR_BACKWARD}}
 		}
 	},
 	[SDLK_RIGHT % KMS] = {
 		.size = 1,
 		.binds = {
-			{KMOD_NONE, keybind_right, {.ptr = NULL}}
+			{KMOD_NONE, keybind_mv_cur_char, {.dir = DIR_FORWARD}}
 		}
 	},
 	[SDLK_DELETE % KMS] = {
@@ -36,9 +36,28 @@ static struct keybinds keybinds[KMS] = {
 			{KMOD_NONE, keybind_delete_char, {.dir = DIR_BACKWARD}},
 			{KMOD_CTRL, keybind_delete_word, {.dir = DIR_BACKWARD}}
 		}
+	},
+	[SDLK_f % KMS] = {
+		.size = 1,
+		.binds = {
+			{KMOD_ALT, keybind_mv_cur_word, {.dir = DIR_FORWARD}}
+		}
+	},
+	[SDLK_b % KMS] = {
+		.size = 1,
+		.binds = {
+			{KMOD_ALT, keybind_mv_cur_word, {.dir = DIR_BACKWARD}}
+		}
+	},
+	[SDLK_d % KMS] = {
+		.size = 1,
+		.binds = {
+			{KMOD_ALT, keybind_delete_word, {.dir = DIR_FORWARD}}
+		}
 	}
-
 };
+
+
 #undef KMS
 
 #endif

+ 34 - 5
src/file.h

@@ -10,12 +10,14 @@
 
 enum file_err {
 	FILE_ERR_OK,
-	FILE_ERR_FAIL_OPEN_FILEPATH,
+	FILE_ERR_FAIL_OPEN,
 	FILE_ERR_FAIL_SEEK,
 	FILE_ERR_FAIL_READ,
+	FILE_ERR_FAIL_WRITE,
 	FILE_ERR_FAIL_CALLOC,
-	FILE_ERR_FAIL_CLOSE_FD,
+	FILE_ERR_FAIL_CLOSE,
 	FILE_ERR_FILE_EMPTY,
+	FILE_ERR_FAIL_WROTE_MORE,
 };
 
 struct ret_void_p_err {
@@ -25,6 +27,7 @@ struct ret_void_p_err {
 };
 
 struct ret_void_p_err file_read_all(const char *filepath);
+enum file_err file_save(const char *filepath, const char *str, size_t str_size);
 
 #if defined(BMP_IMP) || defined(IMP)
 
@@ -38,7 +41,7 @@ file_read_all(const char *filepath)
 
 	int32_t fd = open(filepath, O_RDONLY);
 	if ( fd < 0 ) {
-		err = FILE_ERR_FAIL_OPEN_FILEPATH;
+		err = FILE_ERR_FAIL_OPEN;
 		goto err;
 	}
 
@@ -73,7 +76,7 @@ file_read_all(const char *filepath)
 
 	if ( close(fd) != 0 ) {
 		/* It should be possible to handle EIO */
-		err = FILE_ERR_FAIL_CLOSE_FD;
+		err = FILE_ERR_FAIL_CLOSE;
 		goto err;
 	}
 
@@ -86,7 +89,7 @@ file_read_all(const char *filepath)
 err_close: ;
 	if ( close(fd) != 0 ) {
 		/* It should be possible to handle EIO */
-		err = FILE_ERR_FAIL_CLOSE_FD;
+		err = FILE_ERR_FAIL_CLOSE;
 		goto err;
 	}
 
@@ -98,5 +101,31 @@ err: ;
 	};
 }
 
+enum file_err
+file_save(const char *filepath, const char *str, size_t str_size)
+{
+	int32_t fd = open(filepath, O_WRONLY);
+	if ( fd < 0 ) {
+		return FILE_ERR_FAIL_OPEN;
+	}
+
+	ssize_t wrote = write(fd, str, str_size);
+	if ( wrote == -1 ) {
+		return FILE_ERR_FAIL_WRITE;
+	}
+
+	if ( ((size_t) wrote) != str_size ) {
+		return FILE_ERR_FAIL_WROTE_MORE;
+	}
+
+	if ( close(fd) != 0 ) {
+		/* It should be possible to handle EIO */
+		return FILE_ERR_FAIL_CLOSE;
+	}
+
+	return FILE_ERR_OK;
+}
+
+
 #endif
 #endif

+ 80 - 18
src/keybind.h

@@ -23,58 +23,120 @@ struct bind {
 	union keybind_args args;
 };
 
-#define BINDS_SIZE 5
+#define BINDS_SIZE 10
 struct keybinds {
 	uint8_t size;
 	const struct bind binds[BINDS_SIZE];
 };
 
-struct app keybind_left(struct app app, union keybind_args args);
-struct app keybind_right(struct app app, union keybind_args args);
+struct app keybind_mv_cur_char(struct app app, union keybind_args args);
+struct app keybind_forward_char(struct app app, union keybind_args args);
 struct app keybind_delete_char(struct app app, union keybind_args args);
-struct app keybind_insert_newline(struct app app, union keybind_args args);
+
+struct app keybind_mv_cur_word(struct app app, union keybind_args args);
 struct app keybind_delete_word(struct app app, union keybind_args args);
 
+struct app keybind_insert_newline(struct app app, union keybind_args args);
+
 
 #if defined(KEYBIND_IMP) || defined(IMP)
 
 struct app
-keybind_left(struct app app, union keybind_args args)
+keybind_mv_cur_char(struct app app, union keybind_args args)
 {
-	(void) args;
-	app.buf = buffer_mv_cur_letf(app.buf);
+	if ( args.dir == DIR_FORWARD ) {
+		app.buf = buffer_mv_cur_right(app.buf);
+	}
+	if ( args.dir == DIR_BACKWARD ) {
+		app.buf = buffer_mv_cur_left(app.buf);
+	}
 	return app;
 }
 
-
 struct app
-keybind_right(struct app app, union keybind_args args)
+keybind_delete_char(struct app app, union keybind_args args)
 {
-	(void) args;
-	app.buf = buffer_mv_cur_right(app.buf);
+	if ( args.dir == DIR_FORWARD ) {
+		app.buf = buffer_remove_char(app.buf, app.buf.cur);
+	}
+	if ( args.dir == DIR_BACKWARD ) {
+		app.buf = buffer_remove_char(app.buf, --app.buf.cur);
+	}
 	return app;
 }
 
 struct app
-keybind_delete_char(struct app app, union keybind_args args)
+keybind_mv_cur_word(struct app app, union keybind_args args)
 {
-	(void) args;
-
+	size_t index;
+	enum buffer_err err;
 	if ( args.dir == DIR_FORWARD ) {
-		app.buf = buffer_remove_char(app.buf, app.buf.cur);
+		RET_UNWRAP2(index, err,
+			    struct ret_size_t_err,
+			    buffer_index_fw_word(app.buf));
+		if ( err != BUFFER_ERR_OK ) {
+			if ( err == BUFFER_ERR_INVALID_CUR_POS ) {
+				app.buf.cur = app.buf.data.size;
+			}
+			return app;
+		}
+		app.buf.cur = index;
 	}
 	if ( args.dir == DIR_BACKWARD ) {
-		app.buf = buffer_remove_char(app.buf, --app.buf.cur);
+		RET_UNWRAP2(index, err,
+			    struct ret_size_t_err,
+			    buffer_index_bw_word(app.buf));
+		if ( err != BUFFER_ERR_OK ) {
+			if ( err == BUFFER_ERR_INVALID_CUR_POS ) {
+				app.buf.cur = app.buf.data.size;
+			}
+			return app;
+		}
+		app.buf.cur = index;
 	}
 	return app;
 }
 
+
 struct app
 keybind_delete_word(struct app app, union keybind_args args)
 {
+	size_t index, n_rm;
+	enum buffer_err err;
 	if ( args.dir == DIR_BACKWARD ) {
-		size_t index = buffer_index_bw_word(app.buf);
-		app.buf = buffer_remove_between(app.buf, index, app.buf.cur);;
+		RET_UNWRAP2(index, err,
+			    struct ret_size_t_err,
+			    buffer_index_bw_word(app.buf));
+		if ( err != BUFFER_ERR_OK ) {
+			if ( err == BUFFER_ERR_INVALID_CUR_POS ) {
+				app.buf.cur = app.buf.data.size;
+			}
+			return app;
+		}
+		RET_UNWRAP3(app.buf, n_rm, err,
+			    struct ret_buffer_size_t_err,
+			    buffer_remove_between(app.buf, index, app.buf.cur));
+		if ( err != BUFFER_ERR_OK ) {
+			return app;
+		}
+		app.buf.cur -= n_rm;
+	}
+	if ( args.dir == DIR_FORWARD ) {
+		RET_UNWRAP2(index, err,
+			    struct ret_size_t_err,
+			    buffer_index_fw_word(app.buf));
+		if ( err != BUFFER_ERR_OK ) {
+			if ( err == BUFFER_ERR_INVALID_CUR_POS ) {
+				app.buf.cur = app.buf.data.size;
+			}
+			return app;
+		}
+		RET_UNWRAP3(app.buf, n_rm, err,
+			    struct ret_buffer_size_t_err,
+			    buffer_remove_between(app.buf, app.buf.cur, index));
+		if ( err != BUFFER_ERR_OK ) {
+			return app;
+		}
 	}
 	return app;
 }

+ 10 - 11
src/main.c

@@ -36,24 +36,18 @@ main(int32_t argc, char **argv)
 	SCE(SDL_Init(SDL_INIT_VIDEO));
 
 	const char *font_path = "./charmap-oldschool_white.png";
-	const char *file_path = "./src/main.c";
 
 	struct app app = app_create("ged");
 
 	app.font = font_create(app.rdr, font_path, 7, 18);
 	app.font.scale = 2.0;
 
-	free(app.buf.data.items);
-
-	void *ptr = NULL;
-	size_t file_size = 0;
-	enum file_err err;
-	RET_UNWRAP3(ptr, file_size, err,
-		    struct ret_void_p_err, file_read_all(file_path));
+	const char *filepath = "./src/main.c";
+	enum buffer_err err;
+	RET_UNWRAP2(app.buf, err,
+		    struct ret_buffer_err,
+		    buffer_load_from_file(app.buf, filepath));
 	(void) err;
-	app.buf.data.items = ptr;
-	app.buf.data.size = file_size-1;
-	app.buf.data.cap = file_size;
 
 	uint64_t i = 0;
 	while ( app.running == true ) {
@@ -84,6 +78,7 @@ struct app
 handle_events(struct app app)
 {
 	SDL_Event e = {0};
+	bool done = false;
 	while ( SDL_PollEvent(&e) ) {
 		switch ( e.type ) {
 		case SDL_QUIT: {
@@ -104,9 +99,13 @@ handle_events(struct app app)
 					continue;
 				}
 				app = b.func(app, b.args);
+				done = true;
 			}
 		} break;
 		case SDL_TEXTINPUT: {
+			if ( done == true ) {
+				break;
+			}
 			char *t = e.text.text;
 			while( *t != '\0' ) {
 				app.buf = buffer_insert_char(