--- /dev/null
+#include "palboss.h"
+#include "libft.h"
+#include <termios.h>
+#include <unistd.h>
+
+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);
+}