~nloomans/ft_select

ref: 2571843e455f1f30d23d0575c30c7426e4cca0ce ft_select/src/event.c -rw-r--r-- 4.2 KiB
2571843eNoah Loomans fix linux build 1 year, 10 months 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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <ft_printf.h>
#include "event.h"
#include "terminal.h"
#include "action.h"
#include "read.h"
#include "error.h"

bool							g_event_sigwinch = false;
bool							g_event_sigcont = false;

static void						handle_generic(int signum);

static void						handle_suspend(int signum)
{
	(void)signum;
	terminal_configure(TERMINAL_CONFIGURE_RESTORE);
	signal(SIGTSTP, SIG_DFL);
	ioctl(STDIN_FILENO, TIOCSTI, "\032");
}

static void						handle_continue(int signum)
{
	(void)signum;
	terminal_configure(TERMINAL_CONFIGURE_SETUP);
	signal(SIGTSTP, handle_suspend);
	handle_generic(signum);
}

static void						handle_exit_signal(int signum)
{
	terminal_configure(TERMINAL_CONFIGURE_RESTORE);
	ft_dprintf(STDERR_FILENO, "ft_select: received '%s' signal, exiting...\n",
		sys_siglist[signum]);
	exit(1);
}

const struct s_event_signal_map	g_event_signal_map[] = {
	[SIGHUP]	= { .handler = handle_exit_signal },
	[SIGINT]	= { .handler = handle_exit_signal },
	[SIGQUIT]	= { .handler = handle_exit_signal },
	[SIGILL]	= { .handler = handle_exit_signal },
	[SIGTRAP]	= { .handler = handle_exit_signal },
	[SIGABRT]	= { .handler = handle_exit_signal },
	[SIGFPE]	= { .handler = handle_exit_signal },
	[SIGBUS]	= { .handler = handle_exit_signal },
	[SIGSEGV]	= { .handler = handle_exit_signal },
	[SIGSYS]	= { .handler = handle_exit_signal },
	[SIGPIPE]	= { .handler = handle_exit_signal },
	[SIGALRM]	= { .handler = handle_exit_signal },
	[SIGTERM]	= { .handler = handle_exit_signal },
	[SIGTSTP]	= { .handler = handle_suspend },
	[SIGCONT]	= {
		.handler = handle_continue,
		.global = &g_event_sigcont,
		.action = action_update_size,
	},
	[SIGTTIN]	= { .handler = handle_exit_signal },
	[SIGTTOU]	= { .handler = handle_exit_signal },
	[SIGXCPU]	= { .handler = handle_exit_signal },
	[SIGXFSZ]	= { .handler = handle_exit_signal },
	[SIGVTALRM]	= { .handler = handle_exit_signal },
	[SIGPROF]	= { .handler = handle_exit_signal },
	[SIGWINCH]	= {
		.global = &g_event_sigwinch,
		.action = action_update_size
	},

#ifdef SIGEMT

	[SIGEMT]	= { .handler = handle_exit_signal },

#endif
};

static void						handle_generic(int signum)
{
	*g_event_signal_map[signum].global = true;
}

const t_action	g_event_key_map[READ_TYPE_AMOUNT][128] = {
	[ READ_TYPE_REG ] = {
		[ 'q' ] = action_quit,
		[ 'j' ] = action_down,
		[ 'k' ] = action_up,
		[ 'h' ] = action_left,
		[ 'l' ] = action_right,
		[ ' ' ] = action_select,
		[ '\x7f' ] = action_delete,
		[ '\n' ] = action_confirm,
	},
	[ READ_TYPE_ESC ] = {
		[ 'A' ] = action_up,
		[ 'B' ] = action_down,
		[ 'D' ] = action_left,
		[ 'C' ] = action_right,
	},
	[ READ_TYPE_ESC_SQL ] = {
		[ '3' ] = action_delete,
	},
};


t_error							event_init(void)
{
	size_t	signum;

	signum = 0;
	while (signum < sizeof(g_event_signal_map) / sizeof(*g_event_signal_map))
	{
		if (g_event_signal_map[signum].handler)
		{
			if (signal(signum, g_event_signal_map[signum].handler) == SIG_ERR)
			{
				return (errorf("unable to bind signal %d: %s",
					signum, strerror(errno)));
			}
		}
		else if (g_event_signal_map[signum].action)
		{
			if (signal(signum, handle_generic) == SIG_ERR)
			{
				return (errorf("unable to bind signal %d: %s",
					signum, strerror(errno)));
			}
		}
		signum++;
	}
	return (ERROR_NULL);
}

static t_action				next_signal(void)
{
	size_t	signum;

	signum = 0;
	while (signum < sizeof(g_event_signal_map) / sizeof(*g_event_signal_map))
	{
		if (g_event_signal_map[signum].action &&
			*g_event_signal_map[signum].global)
		{
			*g_event_signal_map[signum].global = false;
			return (g_event_signal_map[signum].action);
		}
		signum++;
	}
	return (NULL);
}

static t_error				next_key(t_action *dest)
{
	struct s_read_seq	seq;

	seq = read_seq();
	if (is_error(seq.error))
		return (errorf("failed to read input sequence: %s", seq.error.msg));
	*dest = g_event_key_map[seq.type][(unsigned char)seq.c];
	return (ERROR_NULL);
}

t_error						event_next(t_action *dest)
{
	t_error			error;

	*dest = next_signal();
	if (*dest != NULL)
		return (ERROR_NULL);
	error = next_key(dest);
	if (is_error(error) || *dest != NULL)
		return (error);
	return (ERROR_NULL);
}