From 0d1dadcae29c850b013f94fe549d241bba5a8fad Mon Sep 17 00:00:00 2001 From: =?utf8?q?Luk=C3=A1=C5=A1=20Ji=C5=99i=C5=A1t=C4=9B?= Date: Sat, 9 Mar 2024 00:17:29 +0100 Subject: [PATCH] Implement the basis of the loop mode Implement basic non-canonical handling. Needs some tuning. --- Libft | 2 +- Makefile | 1 + inc/palboss.h | 47 +++++++++++++++++ src/loop.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 27 ++-------- 5 files changed, 190 insertions(+), 25 deletions(-) create mode 100644 inc/palboss.h create mode 100644 src/loop.c diff --git a/Libft b/Libft index db179cd..45282f8 160000 --- a/Libft +++ b/Libft @@ -1 +1 @@ -Subproject commit db179cd200163de7d1cd25cc02b868edd0766cb2 +Subproject commit 45282f85cbe6209f2476953fef3146b4b65e4eb7 diff --git a/Makefile b/Makefile index f9be1eb..ac3323d 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ INCLUDE := $(addprefix -I, $(INCDIR)) SRCDIR := src SOURCES := main.c \ + loop.c \ SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES)) diff --git a/inc/palboss.h b/inc/palboss.h new file mode 100644 index 0000000..62b75be --- /dev/null +++ b/inc/palboss.h @@ -0,0 +1,47 @@ +#ifndef PALBOSS_H +# define PALBOSS_H + +# include "libft.h" +# include +# include +# include + +typedef struct s_database_entry +{ + int level; + time_t kill_time; + char *name; + char *biome; +} t_entry; + +typedef enum e_basic_command +{ + basic_kill, + basic_add, + basic_list, + basic_loop, + basic_remove, + basic_help, +} t_basic; + +typedef struct s_command +{ + t_basic basic; + t_entry entry; +} t_command; + +// This could be more structured but is quite simple as it is +typedef struct s_term +{ + size_t x; + size_t y; + size_t height; + size_t width; + size_t top_row; + struct termios termios; +} t_term; + +void loop(t_vec *database); +void kill_entry(t_vec *database, size_t ind); +void print_entry(t_entry *entry); +#endif //PALBOSS_H diff --git a/src/loop.c b/src/loop.c new file mode 100644 index 0000000..0cbd3bf --- /dev/null +++ b/src/loop.c @@ -0,0 +1,138 @@ +#include "palboss.h" +#include "libft.h" +#include +#include + +static const char *term_setup = "" + "\033[?1049h" // Set alternate screen on + "\033[0;0H" // Set cursor to the start + ; + +void init_term(t_term *term) +{ + struct termios new; + + tcgetattr(STDIN_FILENO, &term->termios); + tcgetattr(STDIN_FILENO, &new); + new.c_lflag &= ~(ICANON | ECHO); + new.c_cc[VMIN] = 0; + new.c_cc[VTIME] = 10; + tcsetattr(STDIN_FILENO, TCSANOW, &new); + ft_putstr_fd(term_setup, STDOUT_FILENO); + return ; +} + +void reset_term(t_term *term) +{ + tcsetattr(STDIN_FILENO, TCSANOW, &term->termios); + ft_putstr_fd("\033[?1049l", STDOUT_FILENO); + return ; +} + +void print_header(void) +{ + ft_putstr_fd("\033[7m", STDOUT_FILENO); + ft_printf(" %-20s%-5s %-20s%-5s\n", "name", "level", "location", "time"); + ft_putstr_fd("\033[0m", STDOUT_FILENO); +} + +#define TERMSIZE_BUFFER_SIZE 12 + +static const char *term_size_str = "" + "\033[s" // Save cursor position + "\033[9999;9999H" // Move cursor as far to the right bottom as possible + "\033[6n" // Report cursor position + ; + +static const char *restore_cursor = "\033[u"; + +void get_terminal_size(t_term *term) +{ + char buffer[TERMSIZE_BUFFER_SIZE]; + size_t i; + + ft_putstr_fd(term_size_str, STDOUT_FILENO); + if (read(STDIN_FILENO, buffer, TERMSIZE_BUFFER_SIZE) < 0) + term->height = ft_atoi(&buffer[2]); + i = 0; + while (buffer[i] != ';') + ++i; + ++i; + term->width = ft_atoi(&buffer[i]); + ft_putstr_fd(restore_cursor, STDOUT_FILENO); + return ; +} + +static const char *print_init_str = "" + "\033[s" + "\033[1;0H" + ; + +void print_noncanon(t_vec *database, t_term *term) +{ + size_t i; + + i = term->top_row; + ft_putstr_fd(print_init_str, STDOUT_FILENO); + while (i < database->size && i - term->top_row < term->height) + { + print_entry(ft_vec_access(database, i++)); + } + ft_putstr_fd(restore_cursor, STDOUT_FILENO); + return ; +} + +int handle_buffer(const char *buffer, t_vec *database, t_term *term) +{ + if (!ft_strcmp(buffer, "\033[A")) + { + if (term->y > 1) + { + --term->y; + ft_putstr_fd(buffer, STDOUT_FILENO); + } + else if (term->top_row > 0) + --term->top_row; + } + else if (!ft_strcmp(buffer, "\033[B")) + { + if (term->y < term->height) + { + ++term->y; + ft_putstr_fd(buffer, STDOUT_FILENO); + } + else if (database->size - term->top_row > term->height) + ++term->top_row; + } + else if (!ft_strcmp(buffer, "k") && term->top_row + term->y < database->size) + kill_entry(database, term->top_row + term->y); + else if (!ft_strcmp(buffer, "q") || !ft_strcmp(buffer, "\033")) + return (1); + return (0); +} + +#define BUFFER_SIZE 10 + +void loop(t_vec *database) +{ + t_term term; + char buffer[BUFFER_SIZE + 1]; + int chars_read; + int quit; + + init_term(&term); + print_header(); + quit = 0; + while (!quit) + { + get_terminal_size(&term); + print_noncanon(database, &term); + chars_read = read(STDIN_FILENO, buffer, BUFFER_SIZE); + if (chars_read < 0) + return ; + buffer[chars_read] = '\0'; + quit = handle_buffer(buffer, database, &term); + buffer[0] = '\0'; + } + reset_term(&term); +} diff --git a/src/main.c b/src/main.c index b20b543..84b0ed6 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,4 @@ +#include "palboss.h" #include "libft.h" #include #include @@ -7,30 +8,6 @@ #include #include -typedef struct s_database_entry -{ - int level; - time_t kill_time; - char *name; - char *biome; -} t_entry; - -typedef enum e_basic_command -{ - basic_kill, - basic_add, - basic_list, - basic_loop, - basic_remove, - basic_help, -} t_basic; - -typedef struct s_command -{ - t_basic basic; - t_entry entry; -} t_command; - // I know this is not an efficient database, the bad things about it are: // the whole database is loaded into memory // the whole database is rewritten with every call to this program @@ -310,6 +287,8 @@ void carry_out_command(t_command *com, t_vec *database) } else if (com->basic == basic_help) print_help(); + else if (com->basic == basic_loop) + loop(database); return ; } -- 2.30.2