~nloomans/ft_select

ref: a4ef762331941c5e33670f7bf81eb964fb761edb ft_select/src/render.c -rw-r--r-- 3.8 KiB
a4ef7623Noah Loomans fix build on linux 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* ************************************************************************** */
/*                                                                            */
/*                                                        ::::::::            */
/*   ft_select                                          :+:    :+:            */
/*                                                     +:+                    */
/*   Author: Noah Loomans                             +#+                     */
/*           <nloomans@student.codam.nl>             +#+                      */
/*                                                  #+#    #+#                */
/*   License: GPLv3                                ########   odam.nl         */
/*                                                                            */
/* ************************************************************************** */

#include <stdbool.h>
#include <unistd.h>
#include <ft_printf.h>
#include <libft.h>
#include "state.h"
#include "derive.h"
#include "terminal.h"
#include "render.h"

static void	box_top(const struct s_state_terminal terminal)
{
	size_t	i;

	ft_dprintf(STDERR_FILENO, "%*s\n", terminal.columns, "");
	ft_dprintf(STDERR_FILENO, "  ┏");
	i = 1;
	while (i < terminal.columns - 5)
	{
		ft_dprintf(STDERR_FILENO, "━");
		i++;
	}
	ft_dprintf(STDERR_FILENO, "┓  \n");
}

static void	box_bottom(const struct s_state_terminal terminal)
{
	size_t	i;

	ft_dprintf(STDERR_FILENO, "  ┗");
	i = 1;
	while (i < terminal.columns - 5)
	{
		ft_dprintf(STDERR_FILENO, "━");
		i++;
	}
	ft_dprintf(STDERR_FILENO, "┛  \n");
}

static void	box_option(char *option, bool selected, bool focus, size_t width)
{
	ft_dprintf(STDERR_FILENO, "%c%c", focus ? '[' : ' ', selected ? '*' : ' ');
	if (focus)
		terminal_send(TERMINAL_FMT_BEGIN_UNDERLINE);
	if (selected)
		terminal_send(TERMINAL_FMT_BEGIN_REVERSE_VIDEO);
	ft_dprintf(STDERR_FILENO, "%-*s", (int)width, option);
	terminal_send(TERMINAL_FMT_EXIT);
	ft_dprintf(STDERR_FILENO, "%c", focus ? ']' : ' ');
}

void		render(const struct s_state state)
{
	struct s_derived_dimensions	dimensions;
	size_t						*column_width;
	struct s_state_option		***rows;
	size_t						column_index;
	size_t						row_index;
	size_t						total_column_width;
	t_error						error;

	terminal_send(TERMINAL_CURSOR_HOME);
	error = derive_dimensions(&dimensions, state.terminal, state.options);
	if (is_error(error))
	{
		terminal_send(TERMINAL_CLEAR_SCREEN);
		ft_dprintf(STDERR_FILENO, "%s", error.msg);
		return ;
	}
	error = derive_column_width(&column_width, dimensions, state.options);
	if (is_error(error))
	{
		terminal_send(TERMINAL_CLEAR_SCREEN);
		ft_dprintf(STDERR_FILENO, "%s", error.msg);
		return ;
	}
	if (!derive_enough_columns(state.terminal, dimensions, column_width))
	{
		terminal_send(TERMINAL_CLEAR_SCREEN);
		ft_dprintf(STDERR_FILENO, "terminal too small to display options");
		return ;
	}
	error = derive_rows(&rows, dimensions, state.options);
	if (is_error(error))
	{
		ft_dprintf(STDERR_FILENO, "%s", error.msg);
		return ;
	}
	box_top(state.terminal);
	row_index = 0;
	while (row_index < dimensions.rows)
	{
		ft_dprintf(STDERR_FILENO, "  ┃ ");
		column_index = 0;
		total_column_width = 0;
		while (column_index < dimensions.columns &&
			rows[row_index][column_index] != NULL)
		{
			box_option(
				rows[row_index][column_index]->name,
				rows[row_index][column_index]->selected,
				unpack_option(state.cursor) == rows[row_index][column_index],
				column_width[column_index]);
			total_column_width += column_width[column_index]
				+ DERIVE_OPTION_PADDING_LEFT + DERIVE_OPTION_PADDING_RIGHT;
			column_index++;
		}
		ft_dprintf(STDERR_FILENO, "%*s ┃  \n",
			state.terminal.columns - total_column_width
			- DERIVE_PADDING_LEFT - DERIVE_PADDING_RIGHT, "");
		row_index++;
	}
	box_bottom(state.terminal);
	ft_memdel((void **)&column_width);
	derive_free_rows(dimensions, &rows);
}