#include <unistd.h>
#include <fcntl.h>
+#define BUFFER_SIZE 10
+
+void free_node(void *node)
+{
+ ft_vec_free(&((t_node *)node)->connected, NULL);
+ return ;
+}
+
+/*
void build_graph(const char *filename, t_vec *nodes, t_vec *mosfets)
{
int fd;
return ;
}
-void free_node(void *node)
-{
- ft_vec_free(&((t_node *)node)->connected, NULL);
- return ;
-}
-
void free_split(char **sp)
{
size_t i;
free_split(split_inp);
return (mode_command);
}
+*/
-int handle_escape_code(__attribute__((unused)) t_input *input, __attribute__((unused)) const char *code)
+t_window *process_input_command(__attribute__((unused)) const char *buffer, t_tui *tui, __attribute__((unused)) t_vec *nodes, __attribute__((unused)) t_vec *mosfets)
{
- return (1);
+ return (tui->active_win);
+}
+
+int init_win(t_window *win, t_mode type, t_pair pos, t_pair size)
+{
+ static t_symbol filler = {.sym = " "};
+ size_t i;
+
+ win->type = type;
+ win->pos = pos;
+ win->size = size;
+ win->pos_in_content = (t_pair){.x = 0, .y = 0};
+ ft_mat_init(&win->content, sizeof(t_symbol));
+ ft_vec_init(&win->situational, sizeof(char));
+ if (ft_mat_zeros(&win->content, size.y - 1, size.x) != success)
+ return (1);
+ ft_mat_fill(&win->content, &filler);
+ if (type == mode_schema)
+ {
+ win->cursor = (t_pair){.x = size.x / 2, .y = size.y / 2};
+ if (ft_vec_reserve(&win->situational, size.x) != success)
+ {
+ ft_mat_free(&win->content, NULL);
+ return (1);
+ }
+ i = 0;
+ while (i < size.x)
+ {
+ ft_vec_append(&win->situational, " ");
+ ++i;
+ }
+ }
+ else
+ win->cursor = (t_pair){.x = 0, .y = 0};
+ return (0);
+}
+
+void destroy_win(void *window)
+{
+ t_window *win;
+
+ win = window;
+ ft_mat_free(&win->content, NULL);
+ ft_vec_free(&win->situational, NULL);
+ return ;
}
-t_mode get_input(t_input *input, int fd)
+// Let's create a convention that the 0th window is the main command one
+// and that the 1st window is the main schema one
+// This is reflected in FET_sim.h as macro definitions
+// MAIN_COMMAND_W and MAIN_SCHEMA_W
+int init_tui(t_tui *tui)
{
- int res;
- static char *str_inp;
- char buff[10];
- size_t len;
+ t_window tmp;
+ t_pair term;
+ size_t command_height;
- while(1)
+ term = get_terminal_size();
+ tui->terminal_size = term;
+ ft_vec_init(&tui->windows, sizeof(t_window));
+ command_height = ft_mins(term.y, COMMAND_WINDOW_DEFAULT_HEIGHT);
+ if (init_win(&tmp, mode_command,
+ (t_pair){.x = 0, .y = term.y - command_height},
+ (t_pair){.x = term.x, .y = command_height}))
+ return (1);
+ if (ft_vec_append(&tui->windows, &tmp))
+ {
+ destroy_win(&tmp);
+ return (1);
+ }
+ if (init_win(&tmp, mode_schema,
+ (t_pair){.x = 0, .y = 0},
+ (t_pair){.x = term.x, .y = term.y - command_height}))
+ {
+ destroy_win(ft_vec_access(&tui->windows, 0));
+ return (1);
+ }
+ if (ft_vec_append(&tui->windows, &tmp))
+ {
+ destroy_win(ft_vec_access(&tui->windows, 0));
+ destroy_win(&tmp);
+ return (1);
+ }
+ tui->active_win = ft_vec_access(&tui->windows, 1);
+ return (0);
+}
+
+void move_cursor(t_window *win, int dx, int dy)
+{
+ static const t_symbol empty_sym = {.sym = " "};
+ t_vec empty_vec;
+
+ ft_vec_init(&empty_vec, sizeof(t_symbol));
+ ft_vec_append_range(&empty_vec, &empty_sym, win->content.rows);
+ if (!((dx < 0 && (size_t)-dx > win->cursor.x)
+ || dx + win->cursor.x >= win->size.x))
+ win->cursor.x += dx;
+ else if (dx < 0)
+ {
+ dx += (int)win->cursor.x;
+ win->cursor.x = 0;
+ if ((size_t)-dx <= win->pos_in_content.x)
+ win->pos_in_content.x += dx;
+ else
+ {
+ dx += (int)win->pos_in_content.x;
+ win->pos_in_content.x = 0;
+ while (dx != 0)
+ {
+ ft_mat_insert_col(&win->content, &empty_vec, 0);
+ ++dx;
+ }
+ }
+ }
+ else
{
- len = read(fd, buff, 10);
- buff[len] = '\0';
- if (buff[0] == '\033' && len == 1)
- return (mode_schema);
- else if (buff[0] == '\033')
+ dx -= win->size.x - win->cursor.x - 1;
+ win->cursor.x = win->size.x - 1;
+ if (win->pos_in_content.x + win->size.x - 1 + dx < win->content.cols)
+ win->pos_in_content.x += dx;
+ else
{
- if (handle_escape_code(input, buff))
- ft_printf("%s", buff);
+ dx -= win->content.cols - win->pos_in_content.x - win->size.x;
+ win->pos_in_content.x = win->content.cols - win->size.x;
+ while (dx != 0)
+ {
+ ft_mat_append_col(&win->content, &empty_vec);
+ ++win->pos_in_content.x;
+ --dx;
+ }
}
+ }
+ if (empty_vec.size > win->content.rows)
+ ft_vec_forget_range(&empty_vec, win->content.rows, empty_vec.size - win->content.rows);
+ else
+ ft_vec_append_range(&empty_vec, &empty_sym, win->content.rows - empty_vec.size);
+ if (!((dy < 0 && (size_t)-dy > win->cursor.y)
+ || dy + win->cursor.y >= win->size.y))
+ win->cursor.y += dy;
+ else if (dy < 0)
+ {
+ dy += (int)win->cursor.y;
+ win->cursor.y = 0;
+ if ((size_t)-dy <= win->pos_in_content.y)
+ win->pos_in_content.y += dy;
else
- ft_printf("%s", buff);
+ {
+ dy += (int)win->pos_in_content.y;
+ win->pos_in_content.y = 0;
+ while (dy != 0)
+ {
+ ft_mat_insert_row(&win->content, &empty_vec, 0);
+ ++dy;
+ }
+ }
+ }
+ else
+ {
+ dy -= win->size.y - win->cursor.y - 1;
+ win->cursor.y = win->size.y - 1;
+ if (win->pos_in_content.y + win->size.y - 1 + dy < win->content.cols)
+ win->pos_in_content.y += dy;
+ else
+ {
+ dy -= win->content.cols - win->pos_in_content.y - win->size.y;
+ win->pos_in_content.y = win->content.cols - win->size.y;
+ while (dy != 0)
+ {
+ ft_mat_append_row(&win->content, &empty_vec);
+ ++win->pos_in_content.y;
+ --dy;
+ }
+ }
+ }
+ ft_vec_free(&empty_vec, NULL);
+ ft_printf("\033[%i;%iH", 1 + win->pos.y + win->cursor.y, 1 + win->pos.x + win->cursor.x);
+ return ;
+}
+
+void handle_escape_seq(const char *seq, t_window *win)
+{
+ const size_t seq_size = ft_strlen(seq);
+ int arg1;
+
+ if (seq[0] == '\033')
+ {
+ if (seq_size >= 3 && seq[1] == '[')
+ {
+ arg1 = ft_atoi(seq + 2);
+ if (arg1 == 0)
+ arg1 = 1;
+ if (seq[seq_size - 1] == 'A')
+ move_cursor(win, 0, -arg1);
+ else if (seq[seq_size - 1] == 'B')
+ move_cursor(win, 0, arg1);
+ else if (seq[seq_size - 1] == 'C')
+ move_cursor(win, arg1, 0);
+ else if (seq[seq_size - 1] == 'D')
+ move_cursor(win, -arg1, 0);
+ }
+ }
+ return ;
+}
+
+t_symbol *str_to_sym(const char *str)
+{
+ t_symbol *res;
+ t_symbol *cur;
+ size_t i;
+
+ res = ft_calloc(sizeof(*res), ft_strlen(str) + 1);
+ if (!res)
+ return (NULL);
+ cur = res;
+ i = 0;
+ while(*str)
+ {
+ cur->sym[i] = *str;
+ ++i;
+ if (*str & 0x80)
+ {
+ ++cur;
+ i = 0;
+ }
+ ++str;
}
- if (!str_inp)
- return (mode_exit);
- process_input_string(input, str_inp);
- free(str_inp);
return (res);
}
-t_mode process_input(t_vec *nodes, t_vec *mosfets, int fd)
+void draw_window(t_window *win)
+{
+ char *mat_ptr;
+ size_t i;
+
+ ft_printf("\033[%u;%uH", 1 + (unsigned int)win->pos.y, 1 + (unsigned int)win->pos.x);
+ i = 0;
+ while (i < win->size.y)
+ {
+ mat_ptr = ft_mat_access(&win->content, win->pos.y + i, win->pos.x);
+ write(STDOUT_FILENO, mat_ptr, win->size.x * SYMBOL_SIZE);
+ ++i;
+ }
+ ft_printf("\033[%u;%uH", 1 + (unsigned int)(win->pos.y + win->cursor.y), 1 + (unsigned int)(win->pos.x + win->cursor.x));
+ return ;
+}
+
+void print_to_win(t_window *win, const char *str)
{
- t_mode res;
- int success;
- static t_input input = {.command = help, .argc = 0};
-
- ft_printf("FET_sim> ");
- res = get_input(&input, fd);
- if (res != mode_command)
- return (res);
- success = 1;
- if (input.command == next)
- success = c_next(input, nodes, mosfets);
- else if (input.command == draw)
- success = c_draw(input, mosfets);
- else if (input.command == setnode)
- success = c_setnode(input, nodes);
- else if (input.command == addnode)
- success = c_addnode(input, nodes);
- else if (input.command == addfet)
- success = c_addfet(input, mosfets);
- else if (input.command == bind)
- success = c_bind(input, nodes, mosfets);
- else if (input.command == help)
- success = c_help(input);
- else if (input.command == exitsim)
- res = mode_exit;
- if (success)
- return (res);
- return (mode_error);
+ t_symbol *sym_str;
+ size_t i;
+
+ sym_str = str_to_sym(str);
+ if (win->type != mode_command)
+ return ;
+ move_cursor(win, 0, 1);
+ win->cursor.x = 0;
+ i = 0;
+ while (sym_str[i].sym[0] != '\0')
+ {
+ if (win->cursor.x == win->size.x || sym_str[i].sym[0] == '\n')
+ {
+ move_cursor(win, 0, 1);
+ win->cursor.x = 0;
+ }
+ if (sym_str[i].sym[0] != '\n')
+ {
+ *(t_symbol *)ft_mat_access(&win->content, win->cursor.y, win->cursor.x) = sym_str[i];
+ ++win->cursor.x;
+ }
+ ++i;
+ }
+ free(sym_str);
+ draw_window(win);
+ return ;
+}
+
+t_window *process_input_schema(const char *input, t_tui *tui, __attribute__((unused)) t_vec *nodes, __attribute__((unused)) t_vec *mosfets)
+{
+ if (*input == '\033')
+ handle_escape_seq(input, tui->active_win);
+ else
+ {
+ while (*input != 0)
+ {
+ if (*input == 'l')
+ move_cursor(tui->active_win, 1, 0);
+ else if (*input == 'k')
+ move_cursor(tui->active_win, 0, -1);
+ else if (*input == 'j')
+ move_cursor(tui->active_win, 0, 1);
+ else if (*input == 'h')
+ move_cursor(tui->active_win, -1, 0);
+ else if (*input == 'i')
+ {
+ if (*(++input) != 0)
+ print_to_win(ft_vec_access(&tui->windows, MAIN_COMMAND_W),
+ "Rest of the input was lost.\n");
+ return (ft_vec_access(&tui->windows, MAIN_COMMAND_W));
+ }
+ ++input;
+ }
+ }
+ return (tui->active_win);
+}
+
+void loop(t_tui *tui, t_vec *nodes, t_vec *mosfets)
+{
+ size_t i;
+ char buffer[BUFFER_SIZE + 1];
+
+ print_start(ft_vec_access(&tui->windows, 0));
+ i = 1;
+ while (i < tui->windows.size)
+ draw_window(ft_vec_access(&tui->windows, i++));
+ while (tui->active_win)
+ {
+ i = read(STDIN_FILENO, buffer, BUFFER_SIZE);
+ buffer[i] = '\0';
+ if (tui->active_win->type == mode_schema)
+ tui->active_win = process_input_schema(buffer, tui, nodes, mosfets);
+ else if (tui->active_win->type == mode_command)
+ tui->active_win = process_input_command(buffer, tui, nodes, mosfets);
+ }
+ return ;
+}
+
+void cleanup_tui(t_tui *tui)
+{
+ ft_vec_free(&tui->windows, destroy_win);
+ return ;
}
-void cleanup(t_vec *nodes, t_vec *mosfets)
+void cleanup(t_vec *nodes, t_vec *mosfets, t_tui *tui)
{
+ cleanup_tui(tui);
update_nodes(NULL);
ft_vec_free(nodes, free_node);
ft_vec_free(mosfets, NULL);
return ;
}
-int main(int argc, char **argv)
+int main(__attribute__((unused))int argc, __attribute__((unused)) char **argv)
{
t_vec nodes;
t_vec mosfets;
- t_mode mode;
+ t_tui tui;
setup_terminal();
- print_start();
ft_vec_init(&nodes, sizeof(t_node));
ft_vec_init(&mosfets, sizeof(t_mosfet));
- if (argc > 1)
- build_graph(argv[1], &nodes, &mosfets);
- mode = mode_command;
- while (mode != mode_exit && mode != mode_error)
+ if (!init_tui(&tui))
{
- if (mode == mode_command)
- mode = process_input(&nodes, &mosfets, STDIN_FILENO);
-// else if (mode == mode_schema)
-// mode = schema_mode(&nodes, &mosfets, STDIN_FILENO);
+ //if (argc == 2)
+ //build_graph(argv[1], &nodes, &mosfets, &tui);
+ loop(&tui, &nodes, &mosfets);
}
- cleanup(&nodes, &mosfets);
+ cleanup(&nodes, &mosfets, &tui);
return (0);
}
#include "FET_sim.h"
#include "libft.h"
-static const char g_version_str[] = "0.0";
+#define VERSION "0.1"
static const char g_next_help_str[] = ""
"next [STEPS]\n"
static const char g_general_help_str[] = ""
"This is a FET_sim - simulator of FET (Field Effect Transistor) logic.\n"
- "Version number: %s"
- "You can use the following commands:\n\n"
+ "Version "
+ VERSION
+ "\nYou can use the following commands:\n\n"
"next [STEPS] \t\t- advances the simulation\n"
"draw [IND] \t\t- draws the state of the simulation\n"
"setnode IND STATE \t- sets the \"set_state\" of the node indexed by IND to STATE\n"
"help [COMMAND] \t\t- shows this help or help for COMMAND\n"
"exit [...] \t\t- exits this program\n\n";
-void print_help(t_command c)
+void print_help(t_window *win, t_command c)
{
if (c == next)
- ft_printf(g_next_help_str);
+ print_to_win(win, g_next_help_str);
else if (c == draw)
- ft_printf(g_draw_help_str);
+ print_to_win(win, g_draw_help_str);
else if (c == setnode)
- ft_printf(g_setnode_help_str);
+ print_to_win(win, g_setnode_help_str);
else if (c == addnode)
- ft_printf(g_addnode_help_str);
+ print_to_win(win, g_addnode_help_str);
else if (c == addfet)
- ft_printf(g_addfet_help_str);
+ print_to_win(win, g_addfet_help_str);
else if (c == bind)
- ft_printf(g_bind_help_str);
+ print_to_win(win, g_bind_help_str);
else if (c == help)
- ft_printf(g_help_help_str);
+ print_to_win(win, g_help_help_str);
else if (c == exitsim)
- ft_printf(g_help_exit_str);
+ print_to_win(win, g_help_exit_str);
else
- ft_printf(g_general_help_str, g_version_str);
+ print_to_win(win, g_general_help_str);
return ;
}
-void command_not_found(const char *input)
+void command_not_found(t_window *win, __attribute__((unused))const char *input)
{
- ft_printf("The command \"%s\" is not a proper FET_sim command.\n", input);
+ print_to_win(win, "The command \"%s\" is not a proper FET_sim command.\n");
+ //, input);
return ;
}
-void print_start(void)
+void print_start(t_window *win)
{
- ft_printf("FET_sim, version %s\n"
- "FET_sim is a simulator of FET logic.\n"
- "If you need some guidence, use the \"help\" command.\n",
- g_version_str);
+ print_to_win(win, "FET_sim, version "
+ VERSION
+ "\nFET_sim is a simulator of FET logic.\n"
+ "If you need some guidence, use the \"help\" command.\n");
return ;
}
-void print_index_error(size_t index, size_t size)
+void print_index_error(t_window *win, __attribute__((unused))size_t index, __attribute__((unused))size_t size)
{
if (size > 0)
{
- ft_printf("This action is invalid as given index %u "
- "is larger then the highest index present %u.\n",
- index, size - 1);
+ print_to_win(win, "This action is invalid as given index %u "
+ "is larger then the highest index present %u.\n");
+ //,index, size - 1);
}
else
{
- ft_printf("This action is invalid as there is no element yet.\n");
+ print_to_win(win, "This action is invalid as there is no element yet.\n");
}
return ;
}