aboutsummaryrefslogtreecommitdiff
path: root/termo-internal.h
blob: 54948b08aa0efdf122c665562eb9d0245d453fd5 (plain)
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
#ifndef TERMO_INTERNAL_H
#define TERMO_INTERNAL_H

#include "termo.h"

#include <stdint.h>
#include <termios.h>
#include <stdbool.h>
#include <iconv.h>

typedef struct termo_driver termo_driver_t;
struct termo_driver
{
	const char *name;
	void *(*new_driver) (termo_t *tk, const char *term);
	void (*free_driver) (void *info);
	int (*start_driver) (termo_t *tk, void *info);
	int (*stop_driver) (termo_t *tk, void *info);
	termo_result_t (*peekkey) (termo_t *tk,
		void *info, termo_key_t *key, int force, size_t *nbytes);
};

typedef struct keyinfo keyinfo_t;
struct keyinfo
{
	termo_type_t type;
	termo_sym_t sym;
	int modifier_mask;
	int modifier_set;
};

typedef struct termo_driver_node termo_driver_node_t;
struct termo_driver_node
{
	termo_driver_t *driver;
	void *info;
	termo_driver_node_t *next;
};

enum peekey_flags
{
	PEEKKEY_FORCE        = 1 << 0,
	PEEKKEY_ALT_PREFIXED = 1 << 1
};

struct termo
{
	int fd;
	int flags;
	int canonflags;

	unsigned char *buffer;
	size_t buffstart; // First offset in buffer
	size_t buffcount; // Number of entires valid in buffer
	size_t buffsize; // Total malloc'ed size

	// Position beyond buffstart at which peekkey() should next start.
	// Normally 0, but see also termo_interpret_csi().
	size_t hightide;

	struct termios restore_termios;
	bool restore_termios_valid;

	int waittime; // In milliseconds

	bool is_closed; // We've received EOF
	bool is_started;

	int nkeynames;
	const char **keynames;

	keyinfo_t c0[32]; // There are 32 C0 codes
	iconv_t to_utf32_conv;
	iconv_t from_utf32_conv;
	termo_driver_node_t *drivers;

	// Now some "protected" methods for the driver to call but which we don't
	// want exported as real symbols in the library
	struct
	{
		void (*emit_codepoint) (termo_t *tk,
			uint32_t codepoint, termo_key_t *key);
		termo_result_t (*peekkey_simple) (termo_t *tk,
			termo_key_t *key, int flags, size_t *nbytes);
		termo_result_t (*peekkey_mouse) (termo_t *tk,
			termo_key_t *key, size_t *nbytes);
	}
	method;

	// What we think should be the mouse protocol
	termo_mouse_proto_t guessed_mouse_proto;
	// The active mouse protocol
	termo_mouse_proto_t mouse_proto;
	// Mouse tracking mode
	termo_mouse_tracking_t mouse_tracking;

	// The mouse unfortunately directly depends on the terminfo driver to let
	// it handle changes in the mouse protocol.

	void *ti_data; // termo_ti_t pointer

	struct
	{
		bool (*set_mouse_proto) (void *, termo_mouse_proto_t, bool);
		bool (*set_mouse_tracking_mode) (void *, termo_mouse_tracking_t, bool);
	}
	ti_method;
};

static inline void
termo_key_get_linecol (const termo_key_t *key, int *line, int *col)
{
	if (col)
		*col = key->code.mouse.x;

	if (line)
		*line = key->code.mouse.y;
}

static inline void
termo_key_set_linecol (termo_key_t *key, int line, int col)
{
	if (line > UINT16_MAX)
		line = UINT16_MAX;

	if (col > UINT16_MAX)
		col = UINT16_MAX;

	key->code.mouse.x = col;
	key->code.mouse.y = line;
}

extern termo_driver_t termo_driver_csi;
extern termo_driver_t termo_driver_ti;

#endif  // ! TERMO_INTERNAL_H