Implement the basis of the loop mode
authorLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Fri, 8 Mar 2024 23:17:29 +0000 (00:17 +0100)
committerLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Fri, 8 Mar 2024 23:17:29 +0000 (00:17 +0100)
Implement basic non-canonical handling.
Needs some tuning.

Libft
Makefile
inc/palboss.h [new file with mode: 0644]
src/loop.c [new file with mode: 0644]
src/main.c

diff --git a/Libft b/Libft
index db179cd200163de7d1cd25cc02b868edd0766cb2..45282f85cbe6209f2476953fef3146b4b65e4eb7 160000 (submodule)
--- a/Libft
+++ b/Libft
@@ -1 +1 @@
-Subproject commit db179cd200163de7d1cd25cc02b868edd0766cb2
+Subproject commit 45282f85cbe6209f2476953fef3146b4b65e4eb7
index f9be1ebee38826503ed513ed083e445a0172d61e..ac3323dc62435b6b866de19f1ef7b3ce781fea48 100644 (file)
--- 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 (file)
index 0000000..62b75be
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef PALBOSS_H
+# define PALBOSS_H
+
+# include "libft.h"
+# include <stddef.h>
+# include <termios.h>
+# include <time.h>
+
+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 (file)
index 0000000..0cbd3bf
--- /dev/null
@@ -0,0 +1,138 @@
+#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);
+}
index b20b5433a23d55d7aa38a004dc0b14ab2a698675..84b0ed6ca4b0a4de09c2811efb7cc8cb85f4ddf9 100644 (file)
@@ -1,3 +1,4 @@
+#include "palboss.h"
 #include "libft.h"
 #include <sys/time.h>
 #include <sys/stat.h>
@@ -7,30 +8,6 @@
 #include <stddef.h>
 #include <limits.h>
 
-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 ;
 }