1 /*
2  * TSM - Main Header
3  *
4  * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #ifndef TSM_LIBTSM_H
27 #define TSM_LIBTSM_H
28 
29 #include <inttypes.h>
30 #include <stdarg.h>
31 #include <stdbool.h>
32 #include <stdlib.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /**
39  * @mainpage
40  *
41  * TSM is a Terminal-emulator State Machine. It implements all common DEC-VT100
42  * to DEC-VT520 control codes and features. A state-machine is used to parse TTY
43  * input and saved in a virtual screen. TSM does not provide any rendering,
44  * glyph/font handling or anything more advanced. TSM is just a simple
45  * state-machine for control-codes handling.
46  * The main use-case for TSM are terminal-emulators. TSM has no dependencies
47  * other than an ISO-C99 compiler and C-library. Any terminal emulator for any
48  * window-environment or rendering-pipline can make use of TSM. However, TSM can
49  * also be used for control-code validation, TTY-screen-capturing or other
50  * advanced users of terminal escape-sequences.
51  */
52 
53 /**
54  * @defgroup symbols Unicode Helpers
55  * Unicode helpers
56  *
57  * Unicode uses 32bit types to uniquely represent symbols. However, combining
58  * characters allow modifications of such symbols but require additional space.
59  * To avoid passing around allocated strings, TSM provides a symbol-table which
60  * can store combining-characters with their base-symbol to create a new symbol.
61  * This way, only the symbol-identifiers have to be passed around (which are
62  * simple integers). No string allocation is needed by the API user.
63  *
64  * The symbol table is currently not exported. Once the API is fixed, we will
65  * provide it to outside users.
66  *
67  * Additionally, this contains some general UTF8/UCS4 helpers.
68  *
69  * @{
70  */
71 
72 /* UCS4 helpers */
73 
74 #define TSM_UCS4_MAX (0x7fffffffUL)
75 #define TSM_UCS4_INVALID (TSM_UCS4_MAX + 1)
76 #define TSM_UCS4_REPLACEMENT (0xfffdUL)
77 
78 /* ucs4 to utf8 converter */
79 
80 size_t tsm_ucs4_to_utf8(uint32_t ucs4, char *out);
81 char *tsm_ucs4_to_utf8_alloc(const uint32_t *ucs4, size_t len, size_t *len_out);
82 
83 /* symbols */
84 
85 typedef uint32_t tsm_symbol_t;
86 
87 /** @} */
88 
89 /**
90  * @defgroup screen Terminal Screens
91  * Virtual terminal-screen implementation
92  *
93  * A TSM screen respresents the real screen of a terminal/application. It does
94  * not render anything, but only provides a table of cells. Each cell contains
95  * the stored symbol, attributes and more. Applications iterate a screen to
96  * render each cell on their framebuffer.
97  *
98  * Screens provide all features that are expected from terminals. They include
99  * scroll-back buffers, alternate screens, cursor positions and selection
100  * support. Thus, it needs event-input from applications to drive these
101  * features. Most of them are optional, though.
102  *
103  * @{
104  */
105 
106 struct tsm_screen;
107 typedef uint_fast32_t tsm_age_t;
108 
109 #define TSM_SCREEN_INSERT_MODE	0x01
110 #define TSM_SCREEN_AUTO_WRAP	0x02
111 #define TSM_SCREEN_REL_ORIGIN	0x04
112 #define TSM_SCREEN_INVERSE	0x08
113 #define TSM_SCREEN_HIDE_CURSOR	0x10
114 #define TSM_SCREEN_FIXED_POS	0x20
115 #define TSM_SCREEN_ALTERNATE	0x40
116 
117 struct tsm_screen_attr {
118 	int8_t fccode;			/* foreground color code or <0 for rgb */
119 	int8_t bccode;			/* background color code or <0 for rgb */
120 	uint8_t fr;			/* foreground red */
121 	uint8_t fg;			/* foreground green */
122 	uint8_t fb;			/* foreground blue */
123 	uint8_t br;			/* background red */
124 	uint8_t bg;			/* background green */
125 	uint8_t bb;			/* background blue */
126 	unsigned int bold : 1;		/* bold character */
127 	unsigned int underline : 1;	/* underlined character */
128 	unsigned int inverse : 1;	/* inverse colors */
129 	unsigned int protect : 1;	/* cannot be erased */
130 	unsigned int blink : 1;		/* blinking character */
131 };
132 
133 typedef int (*tsm_screen_draw_cb) (struct tsm_screen *con,
134 				   uint32_t id,
135 				   const uint32_t *ch,
136 				   size_t len,
137 				   int width,
138 				   int posx,
139 				   int posy,
140 				   const struct tsm_screen_attr *attr,
141 				   tsm_age_t age,
142 				   void *data);
143 
144 int tsm_screen_new(struct tsm_screen **out);
145 void tsm_screen_ref(struct tsm_screen *con);
146 void tsm_screen_unref(struct tsm_screen *con);
147 
148 int tsm_screen_get_width(struct tsm_screen *con);
149 int tsm_screen_get_height(struct tsm_screen *con);
150 int tsm_screen_resize(struct tsm_screen *con, int x, int y);
151 int tsm_screen_set_margins(struct tsm_screen *con, int top, int bottom);
152 void tsm_screen_set_max_sb(struct tsm_screen *con, int max);
153 void tsm_screen_clear_sb(struct tsm_screen *con);
154 
155 void tsm_screen_sb_up(struct tsm_screen *con, int num);
156 void tsm_screen_sb_down(struct tsm_screen *con, int num);
157 void tsm_screen_sb_page_up(struct tsm_screen *con, int num);
158 void tsm_screen_sb_page_down(struct tsm_screen *con, int num);
159 void tsm_screen_sb_reset(struct tsm_screen *con);
160 
161 void tsm_screen_set_def_attr(struct tsm_screen *con,
162 			     const struct tsm_screen_attr *attr);
163 void tsm_screen_reset(struct tsm_screen *con);
164 void tsm_screen_set_flags(struct tsm_screen *con, unsigned int flags);
165 void tsm_screen_reset_flags(struct tsm_screen *con, unsigned int flags);
166 unsigned int tsm_screen_get_flags(struct tsm_screen *con);
167 
168 int tsm_screen_get_cursor_x(struct tsm_screen *con);
169 int tsm_screen_get_cursor_y(struct tsm_screen *con);
170 
171 void tsm_screen_set_tabstop(struct tsm_screen *con);
172 void tsm_screen_reset_tabstop(struct tsm_screen *con);
173 void tsm_screen_reset_all_tabstops(struct tsm_screen *con);
174 
175 void tsm_screen_write(struct tsm_screen *con, tsm_symbol_t ch,
176 		      const struct tsm_screen_attr *attr);
177 void tsm_screen_newline(struct tsm_screen *con);
178 void tsm_screen_scroll_up(struct tsm_screen *con, int num);
179 void tsm_screen_scroll_down(struct tsm_screen *con, int num);
180 void tsm_screen_move_to(struct tsm_screen *con, int x, int y);
181 void tsm_screen_move_up(struct tsm_screen *con, int num, bool scroll);
182 void tsm_screen_move_down(struct tsm_screen *con, int num, bool scroll);
183 void tsm_screen_move_left(struct tsm_screen *con, int num);
184 void tsm_screen_move_right(struct tsm_screen *con, int num);
185 void tsm_screen_move_line_end(struct tsm_screen *con);
186 void tsm_screen_move_line_home(struct tsm_screen *con);
187 void tsm_screen_tab_right(struct tsm_screen *con, int num);
188 void tsm_screen_tab_left(struct tsm_screen *con, int num);
189 void tsm_screen_insert_lines(struct tsm_screen *con, int num);
190 void tsm_screen_delete_lines(struct tsm_screen *con, int num);
191 void tsm_screen_insert_chars(struct tsm_screen *con, int num);
192 void tsm_screen_delete_chars(struct tsm_screen *con, int num);
193 void tsm_screen_erase_cursor(struct tsm_screen *con);
194 void tsm_screen_erase_chars(struct tsm_screen *con, int num);
195 void tsm_screen_erase_cursor_to_end(struct tsm_screen *con, bool protect);
196 void tsm_screen_erase_home_to_cursor(struct tsm_screen *con, bool protect);
197 void tsm_screen_erase_current_line(struct tsm_screen *con, bool protect);
198 void tsm_screen_erase_screen_to_cursor(struct tsm_screen *con, bool protect);
199 void tsm_screen_erase_cursor_to_screen(struct tsm_screen *con, bool protect);
200 void tsm_screen_erase_screen(struct tsm_screen *con, bool protect);
201 
202 void tsm_screen_selection_reset(struct tsm_screen *con);
203 void tsm_screen_selection_start(struct tsm_screen *con, int posx, int posy);
204 void tsm_screen_selection_target(struct tsm_screen *con, int posx, int posy);
205 int tsm_screen_selection_copy(struct tsm_screen *con, char **out);
206 
207 tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
208 			  void *data);
209 
210 /** @} */
211 
212 /**
213  * @defgroup vte State Machine
214  * Virtual terminal emulation with state machine
215  *
216  * A TSM VTE object provides the terminal state machine. It takes input from the
217  * application (which usually comes from a TTY/PTY from a client), parses it,
218  * modifies the attach screen or returns data which has to be written back to
219  * the client.
220  *
221  * Furthermore, VTE objects accept keyboard or mouse input from the application
222  * which is interpreted compliant to DEV-VTs.
223  *
224  * @{
225  */
226 
227 /* virtual terminal emulator */
228 
229 struct tsm_vte;
230 
231 /* keep in sync with shl_xkb_mods */
232 enum tsm_vte_modifier {
233 	TSM_SHIFT_MASK		= (1 << 0),
234 	TSM_LOCK_MASK		= (1 << 1),
235 	TSM_CONTROL_MASK	= (1 << 2),
236 	TSM_ALT_MASK		= (1 << 3),
237 	TSM_LOGO_MASK		= (1 << 4),
238 };
239 
240 /* keep in sync with TSM_INPUT_INVALID */
241 #define TSM_VTE_INVALID 0xffffffff
242 
243 typedef void (*tsm_vte_write_cb) (struct tsm_vte *vte,
244 				  const char *u8,
245 				  size_t len,
246 				  void *data);
247 
248 int tsm_vte_new(struct tsm_vte **out, struct tsm_screen *con,
249 		tsm_vte_write_cb write_cb, void *data);
250 void tsm_vte_ref(struct tsm_vte *vte);
251 void tsm_vte_unref(struct tsm_vte *vte);
252 
253 #define TSM_COLOR_NUM 18
254 enum tsm_vte_color {
255 	TSM_COLOR_BLACK,
256 	TSM_COLOR_RED,
257 	TSM_COLOR_GREEN,
258 	TSM_COLOR_YELLOW,
259 	TSM_COLOR_BLUE,
260 	TSM_COLOR_MAGENTA,
261 	TSM_COLOR_CYAN,
262 	TSM_COLOR_LIGHT_GREY,
263 	TSM_COLOR_DARK_GREY,
264 	TSM_COLOR_LIGHT_RED,
265 	TSM_COLOR_LIGHT_GREEN,
266 	TSM_COLOR_LIGHT_YELLOW,
267 	TSM_COLOR_LIGHT_BLUE,
268 	TSM_COLOR_LIGHT_MAGENTA,
269 	TSM_COLOR_LIGHT_CYAN,
270 	TSM_COLOR_WHITE,
271 
272 	TSM_COLOR_FOREGROUND,
273 	TSM_COLOR_BACKGROUND
274 };
275 
276 int tsm_vte_set_palette(struct tsm_vte *vte, uint8_t (*palette)[3]);
277 void tsm_vte_get_def_attr(struct tsm_vte *vte, struct tsm_screen_attr *out);
278 
279 void tsm_vte_reset(struct tsm_vte *vte);
280 void tsm_vte_hard_reset(struct tsm_vte *vte);
281 void tsm_vte_input(struct tsm_vte *vte, const char *u8, size_t len);
282 bool tsm_vte_handle_keyboard(struct tsm_vte *vte, uint32_t keysym,
283 			     uint32_t ascii, unsigned int mods,
284 			     uint32_t unicode);
285 void tsm_vte_paste_begin(struct tsm_vte *vte);
286 void tsm_vte_paste_end(struct tsm_vte *vte);
287 
288 /** @} */
289 
290 #ifdef __cplusplus
291 }
292 #endif
293 
294 #endif /* TSM_LIBTSM_H */
295