Vinicius Teshima 1 рік тому
батько
коміт
5421e71265
6 змінених файлів з 266 додано та 23 видалено
  1. 81 11
      src/app.h
  2. 118 1
      src/buffer.h
  3. 5 4
      src/config.h
  4. 10 0
      src/keybind.h
  5. 44 6
      src/main.c
  6. 8 1
      src/window.h

+ 81 - 11
src/app.h

@@ -17,9 +17,11 @@ struct app {
 	struct font font;
 	struct buffer buf;
 	bool running;
+	uint64_t target_fps;
 	struct {
 		uint8_t tab_size;
 	} cfg;
+	bool show_fps;
 };
 
 struct app app_create(const char *win_title);
@@ -32,9 +34,13 @@ void app_render_cursor(struct app app, uint32_t color);
 void app_render_char(struct app app, const char c, struct vec2 pos,
 		     double scale);
 
+void app_render_buffer(struct app app, struct vec2 pos,
+		       uint32_t color, double scale);
 void app_render_text(struct app app, const char *text, size_t text_size,
 		     struct vec2 pos, uint32_t color, double scale);
 
+struct vec2 app_calc_cur_pos(struct app app);
+
 #if defined(APP_IMP) || defined(IMP)
 
 #define UNHEX_COLOR(hex)			\
@@ -54,8 +60,9 @@ app_create(const char *win_title)
 		.running = true,
 		.buf = buffer_create(),
 		.cfg = {
-			.tab_size = 4
-		}
+			.tab_size = 8
+		},
+		.target_fps = 120,
 	};
 
 	app.rdr = SDL_CreateRenderer(app.win.ptr, -1, SDL_RENDERER_ACCELERATED);
@@ -114,20 +121,24 @@ app_get_text_color(struct app app) {
 	(((cond)) * (when_true) + (!(cond)) * (when_false))
 
 void
-app_render_text(struct app app, const char *text, size_t text_size,
-		struct vec2 pos, uint32_t color, double scale)
+app_render_buffer(struct app app, struct vec2 pos,
+		  uint32_t color, double scale)
 {
 	app_set_text_color(app, color);
 
+	struct buffer buf = app.buf;
+	DA_DEF_STRUCT_ITEM(char, da);
+	DA_ASSIGN(da, buf.data);
+
 	struct vec2 pen = pos;
-	size_t i = 0;
+	size_t i = buf.render_start;
 	char c;
-	for ( ; i < text_size; ++i ) {
-		c = text[i];
-		bool cond = (pen.x > app.win.w);
-		pen.x = BRANCHLESS_IF(cond, pos.x, pen.x);
-		pen.y += BRANCHLESS_IF(cond,
-				       (double) (app.font.ch_h * scale), 0);
+	for ( ; i < da.size; ++i ) {
+		c = da.items[i];
+		/* bool cond = (pen.x > app.win.w); */
+		/* pen.x = BRANCHLESS_IF(cond, pos.x, pen.x); */
+		/* pen.y += BRANCHLESS_IF(cond, */
+		/* 		       (double) (app.font.ch_h * scale), 0); */
 		switch ( c ) {
 		case '\n': {
 			if ( i == app.buf.cur ) {
@@ -155,7 +166,34 @@ app_render_text(struct app app, const char *text, size_t text_size,
 	if ( i == app.buf.cur ) {
 		app_render_cursor_in_pos(app, pen, 0xFF00FFFF);
 	}
+}
 
+void
+app_render_text(struct app app, const char *text, size_t text_size,
+		struct vec2 pos, uint32_t color, double scale)
+{
+	app_set_text_color(app, color);
+
+	struct vec2 pen = pos;
+	size_t i = 0;
+	char c;
+	for ( ; i < text_size; ++i ) {
+		c = text[i];
+		switch ( c ) {
+		case '\n': {
+			pen.x = pos.x;
+			pen.y += (double) (app.font.ch_h * scale);
+			continue;
+		} break;
+		case '\t': {
+			pen.x += (double) ((app.font.ch_w * scale)
+					   * app.cfg.tab_size);
+			continue;
+		} break;
+		}
+		app_render_char(app, c, pen, scale);
+		pen.x += (double) (app.font.ch_w * scale);
+	}
 }
 
 void
@@ -193,6 +231,38 @@ app_render_cursor(struct app app, uint32_t color)
 	app_render_cursor_in_pos(app, pos, color);
 }
 
+struct vec2
+app_calc_cur_pos(struct app app)
+{
+	size_t col = 0;
+	size_t row = buffer_calc_cur_row(app.buf);
+	enum buffer_err err;
+	/* RET_UNWRAP2(col, row, */
+	/* 	    struct ret_size_t_size_t, */
+	/* 	    buffer_calc_cur_pos(app.buf)); */
+	size_t start_line;
+	RET_UNWRAP2(start_line, err, struct ret_size_t_err,
+		    buffer_index_bw_char(app.buf, app.buf.cur, '\n'));
+	col = (app.buf.cur - start_line) - 1;
+	if ( err == BUFFER_ERR_NOT_FOUND ) {
+		col = app.buf.cur;
+	}
+
+	size_t tabs_n = 0;
+	RET_UNWRAP2(tabs_n, err,
+		    struct ret_size_t_err,
+		    buffer_count_char_between(app.buf, '\t',
+					      start_line, app.buf.cur));
+	col += ( tabs_n > 0 ) * ((tabs_n * app.cfg.tab_size) - tabs_n);
+
+	double row_px = (((double)row)
+			  * (app.font.ch_h * app.font.scale));
+	double col_px = (((double) col) *
+			 (app.font.ch_w * app.font.scale));
+
+	return vec2(col_px, row_px);
+}
+
 
 #endif /* defined(APP_IMP) || defined(IMP) */
 

+ 118 - 1
src/buffer.h

@@ -5,8 +5,13 @@
 
 struct buffer {
 	DA_DEF_STRUCT_ITEM(char, data);
+	size_t render_start;
 	size_t cur;
 	const char *filepath;
+	struct {
+		struct vec2 pos;
+		struct vec2 vel;
+	} cam;
 };
 
 enum buffer_err {
@@ -19,6 +24,7 @@ enum buffer_err {
 	BUFFER_ERR_INVALID_END_SIZE,
 	BUFFER_ERR_FAIL_GET_REALPATH,
 	BUFFER_ERR_FAIL_SAVE,
+	BUFFER_ERR_START_EQ_END,
 };
 
 struct ret_buffer_err {
@@ -37,6 +43,11 @@ struct ret_buffer_size_t_err {
 	enum buffer_err f3;
 };
 
+struct ret_size_t_size_t {
+	size_t f1;
+	size_t f2;
+};
+
 struct buffer buffer_create(void);
 void buffer_destroy(struct buffer buf);
 
@@ -64,10 +75,18 @@ struct ret_size_t_err buffer_index_bw_char(struct buffer buf,
 struct ret_size_t_err buffer_index_fw_char(struct buffer buf,
 					   size_t start, char c);
 
+struct ret_size_t_err buffer_count_char_between(struct buffer buf, char c,
+						size_t start, size_t end);
+
+size_t buffer_calc_cur_col(struct buffer buf);
+size_t buffer_calc_cur_row(struct buffer buf);
+struct ret_size_t_size_t buffer_calc_cur_pos(struct buffer buf);
+
 #if defined(BUFFER_IMP) || defined(IMP)
 
 #include <ctype.h>
 
+#include "vec2.h"
 #include "file.h"
 #include "da.h"
 #include "unwrap.h"
@@ -409,7 +428,7 @@ buffer_index_bw_char(struct buffer buf, size_t start, char c)
 	/* TODO: Find a way to not use ssize_t buf size_t */
 	ssize_t closest = -1;
 	for ( ssize_t i = 0; i < (ssize_t) start; ++i ) {
-		cond = str[i] == c;
+		cond = (str[i] == c);
 		closest = ( cond ) * i + ( ! cond ) * closest;
 	}
 	if ( closest == -1 ) {
@@ -462,6 +481,104 @@ err: ;
 	};
 }
 
+struct ret_size_t_err
+buffer_count_char_between(struct buffer buf, char c, size_t start, size_t end)
+{
+	enum buffer_err err = BUFFER_ERR_OK;
+	if ( buf.data.size == 0 ) {
+		err = BUFFER_ERR_EMPTY;
+		goto err;
+	}
+
+	if ( start == end ) {
+		err = BUFFER_ERR_START_EQ_END;
+		goto err;
+	}
+
+	if ( start > end ) {
+		err = BUFFER_ERR_START_GT_END;
+		goto err;
+	}
+
+	DA_DEF_STRUCT_ITEM(char, da);
+	DA_ASSIGN(da, buf.data);
+
+	/* There is no need to check start > buf.data.size, because */
+	/* we know that start < end */
+	if ( end > da.size ) {
+		err = BUFFER_ERR_INVALID_END_SIZE;
+		goto err;
+	}
+
+	size_t count = 0;
+
+	for ( size_t i = start; i < end; ++i ) {
+		count += ( da.items[i] == c );
+	}
+
+	return (struct ret_size_t_err) {
+		.f1 = count,
+		.f2 = BUFFER_ERR_OK,
+	};
+
+err: ;
+	return (struct ret_size_t_err) {
+		.f1 = 0,
+		.f2 = err
+	};
+}
+
+size_t
+buffer_calc_cur_col(struct buffer buf)
+{
+	/* DA_DEF_STRUCT_ITEM(char, da); */
+	/* DA_ASSIGN(da, buf.data); */
+
+	/* size_t start_line = 0; */
+	/* for ( size_t i = buf.cur; i > 0; --i ) { */
+	/* 	if ( da.items[i] == '\n' ) { */
+	/* 		start_line = i; */
+	/* 		break; */
+	/* 	} */
+	/* } */
+
+	size_t col;
+	enum buffer_err err;
+	RET_UNWRAP2(col, err, struct ret_size_t_err,
+		    buffer_index_bw_char(buf, buf.cur, '\n'));
+	col = (buf.cur - col) - 1;
+	if ( err == BUFFER_ERR_NOT_FOUND ) {
+		col = buf.cur;
+	}
+
+	return col;
+}
+
+size_t
+buffer_calc_cur_row(struct buffer buf)
+{
+	size_t row = 0;
+	enum buffer_err err;
+	RET_UNWRAP2(row, err,
+		    struct ret_size_t_err,
+		    buffer_count_char_between(buf, '\n', 0, buf.cur));
+	(void) err;
+
+	return row;
+}
+
+struct ret_size_t_size_t
+buffer_calc_cur_pos(struct buffer buf)
+{
+	size_t col = buffer_calc_cur_col(buf);
+	size_t row = buffer_calc_cur_row(buf);
+
+	return (struct ret_size_t_size_t) {
+		.f1 = col,
+		.f2 = row
+	};
+}
+
 #endif /* defined(BUFFER_IMP) || defined(IMP) */
 
 #endif

+ 5 - 4
src/config.h

@@ -3,7 +3,7 @@
 
 #include "keybind.h"
 
-#define KEYBINDS_MAX_SIZE 1024
+#define KEYBINDS_MAX_SIZE 1048
 #define KMS KEYBINDS_MAX_SIZE
 static struct keybinds keybinds[KMS] = {
 	[SDLK_LEFT % KMS] = {
@@ -38,9 +38,10 @@ static struct keybinds keybinds[KMS] = {
 		}
 	},
 	[SDLK_f % KMS] = {
-		.size = 1,
+		.size = 2,
 		.binds = {
-			{KMOD_ALT, keybind_mv_cur_word, {.dir = DIR_FORWARD}}
+			{KMOD_ALT, keybind_mv_cur_word, {.dir = DIR_FORWARD}},
+			{KMOD_CTRL, keybind_toggle_fps, {.ptr = NULL}}
 		}
 	},
 	[SDLK_b % KMS] = {
@@ -72,7 +73,7 @@ static struct keybinds keybinds[KMS] = {
 		.binds = {
 			{KMOD_CTRL, keybind_save_buffer, {.ptr = NULL}}
 		}
-	}
+	},
 };
 
 

+ 10 - 0
src/keybind.h

@@ -43,6 +43,8 @@ struct app keybind_mv_cur_end_line(struct app app, union keybind_args args);
 
 struct app keybind_insert_newline(struct app app, union keybind_args args);
 
+struct app keybind_toggle_fps(struct app app, union keybind_args args);
+
 
 #if defined(KEYBIND_IMP) || defined(IMP)
 
@@ -198,6 +200,14 @@ keybind_insert_newline(struct app app, union keybind_args args)
 	return app;
 }
 
+struct app
+keybind_toggle_fps(struct app app, union keybind_args args)
+{
+	(void) args;
+	app.show_fps = ! app.show_fps;
+	return app;
+}
+
 #endif /* defined(KEYBIND_IMP) || defined(IMP) */
 
 #endif

+ 44 - 6
src/main.c

@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <time.h>
 
 #include <SDL2/SDL.h>
 
@@ -31,6 +32,7 @@ struct app handle_events(struct app app);
 int32_t
 main(int32_t argc, char **argv)
 {
+	srand((uint32_t) time(NULL));
 	if ( argc != 2 ) {
 		fprintf(stderr, "MUST pass file to open\n");
 		exit(EXIT_FAILURE);
@@ -59,20 +61,56 @@ main(int32_t argc, char **argv)
 	(void) err;
 
 	uint64_t i = 0;
-	while ( app.running == true ) {
-		struct buffer *c_buf = &app.buf;
+	double dt = (1.0 / (double)app.target_fps) * 3;
+	uint32_t frame_target_dur = (uint32_t)(1000 / app.target_fps);
 
+	char *fps_text = calloc(1, 128);
+	size_t fps_text_size = 0;
 
+	uint32_t fr_end = 0;
+	uint32_t fr_start = 0;
+	uint32_t fr_dur = 1;
+	while ( app.running == true ) {
+		fr_start = SDL_GetTicks();
+		struct buffer *buf = &app.buf;
 		app = handle_events(app);
 
-		SCE(SDL_SetRenderDrawColor(app.rdr, i & 0xFF, 0, 0, 1));
+		SCE(SDL_SetRenderDrawColor(app.rdr, 0x0, 0, 0, 1));
 		SCE(SDL_RenderClear(app.rdr));
 
-		app_render_text(app, c_buf->data.items, c_buf->data.size,
-				vec2(0, 0), 0xFFFFFFFF, app.font.scale);
-		/* app_render_cursor(app, 0x00FF000F); */
+		if ( app.show_fps == true ) {
+			fps_text_size = (size_t) snprintf(fps_text, 128,
+							  "FPS: %.2f",
+							  1000.0 / fr_dur);
+			app_render_text(app, fps_text, fps_text_size,
+					vec2s(0), 0xFF00FFFF, 5);
+		}
+
+		{
+			struct vec2 cur_pos = app_calc_cur_pos(app);
+			cur_pos = vec2_sub(vec2(app.win.hw, app.win.hh),
+					   cur_pos);
+			struct vec2 cpos = buf->cam.pos;
+			struct vec2 cvel = buf->cam.vel;
+			cvel = vec2_sub(cur_pos, cpos);
+			cpos = vec2_add(cpos, vec2_mul(cvel, vec2s(dt)));
+			buf->cam.pos = cpos;
+			buf->cam.vel = cvel;
+		}
+
+		app_render_buffer(app, buf->cam.pos, (uint32_t)
+				  (0xFF << 24)
+				  | (0xFF << 16)
+				  | (0xFF << 8 )
+				  | 0xFF
+				  /* 0xFFFFFFFF */, app.font.scale);
 
 		SDL_RenderPresent(app.rdr);
+		fr_end = SDL_GetTicks();
+		fr_dur = (fr_end - fr_start);
+		if ( fr_dur < frame_target_dur ) {
+			SDL_Delay(frame_target_dur - fr_dur);
+		}
 		++i;
 	}
 

+ 8 - 1
src/window.h

@@ -7,9 +7,16 @@ struct window {
 	SDL_Window *ptr;
 	int32_t h;
 	int32_t w;
+	int32_t hw;
+	int32_t hh;
 };
 
-#define WINDOW_UP_SIZE(win) SDL_GetWindowSize(win.ptr, &win.w, &win.h)
+#define WINDOW_UP_SIZE(win) \
+	do {							\
+		SDL_GetWindowSize(win.ptr, &win.w, &win.h);	\
+		win.hw = win.w / 2;				\
+		win.hh = win.h / 2;				\
+	} while(0)
 
 struct window window_create(const char *win_title);