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 misc Miscellaneous Definitions
55  * Miscellaneous definitions
56  *
57  * This section contains several miscellaneous definitions of small helpers and
58  * constants. These are shared between other parts of the API and have common
59  * semantics/syntax.
60  *
61  * @{
62  */
63 
64 /**
65  * Logging Callback
66  *
67  * @data: user-provided data
68  * @file: Source code file where the log message originated or NULL
69  * @line: Line number in source code or 0
70  * @func: C function name or NULL
71  * @subs: Subsystem where the message came from or NULL
72  * @sev: Kernel-style severity between 0=FATAL and 7=DEBUG
73  * @format: printf-formatted message
74  * @args: arguments for printf-style @format
75  *
76  * This is the type of a logging callback function. You can always pass NULL
77  * instead of such a function to disable logging.
78  */
79 typedef void (*tsm_log_t) (void *data,
80 			   const char *file,
81 			   int line,
82 			   const char *func,
83 			   const char *subs,
84 			   unsigned int sev,
85 			   const char *format,
86 			   va_list args);
87 
88 /** @} */
89 
90 /**
91  * @defgroup symbols Unicode Helpers
92  * Unicode helpers
93  *
94  * Unicode uses 32bit types to uniquely represent symbols. However, combining
95  * characters allow modifications of such symbols but require additional space.
96  * To avoid passing around allocated strings, TSM provides a symbol-table which
97  * can store combining-characters with their base-symbol to create a new symbol.
98  * This way, only the symbol-identifiers have to be passed around (which are
99  * simple integers). No string allocation is needed by the API user.
100  *
101  * The symbol table is currently not exported. Once the API is fixed, we will
102  * provide it to outside users.
103  *
104  * Additionally, this contains some general UTF8/UCS4 helpers.
105  *
106  * @{
107  */
108 
109 /* UCS4 helpers */
110 
111 #define TSM_UCS4_MAX (0x7fffffffUL)
112 #define TSM_UCS4_INVALID (TSM_UCS4_MAX + 1)
113 #define TSM_UCS4_REPLACEMENT (0xfffdUL)
114 
115 /* ucs4 to utf8 converter */
116 
117 unsigned int tsm_ucs4_get_width(uint32_t ucs4);
118 size_t tsm_ucs4_to_utf8(uint32_t ucs4, char *out);
119 char *tsm_ucs4_to_utf8_alloc(const uint32_t *ucs4, size_t len, size_t *len_out);
120 
121 /* symbols */
122 
123 typedef uint32_t tsm_symbol_t;
124 
125 /** @} */
126 
127 /**
128  * @defgroup screen Terminal Screens
129  * Virtual terminal-screen implementation
130  *
131  * A TSM screen respresents the real screen of a terminal/application. It does
132  * not render anything, but only provides a table of cells. Each cell contains
133  * the stored symbol, attributes and more. Applications iterate a screen to
134  * render each cell on their framebuffer.
135  *
136  * Screens provide all features that are expected from terminals. They include
137  * scroll-back buffers, alternate screens, cursor positions and selection
138  * support. Thus, it needs event-input from applications to drive these
139  * features. Most of them are optional, though.
140  *
141  * @{
142  */
143 
144 struct tsm_screen;
145 typedef uint_fast32_t tsm_age_t;
146 
147 #define TSM_SCREEN_INSERT_MODE	0x01
148 #define TSM_SCREEN_AUTO_WRAP	0x02
149 #define TSM_SCREEN_REL_ORIGIN	0x04
150 #define TSM_SCREEN_INVERSE	0x08
151 #define TSM_SCREEN_HIDE_CURSOR	0x10
152 #define TSM_SCREEN_FIXED_POS	0x20
153 #define TSM_SCREEN_ALTERNATE	0x40
154 
155 struct tsm_screen_attr {
156 	int8_t fccode;			/* foreground color code or <0 for rgb */
157 	int8_t bccode;			/* background color code or <0 for rgb */
158 	uint8_t fr;			/* foreground red */
159 	uint8_t fg;			/* foreground green */
160 	uint8_t fb;			/* foreground blue */
161 	uint8_t br;			/* background red */
162 	uint8_t bg;			/* background green */
163 	uint8_t bb;			/* background blue */
164 	unsigned int bold : 1;		/* bold character */
165 	unsigned int underline : 1;	/* underlined character */
166 	unsigned int inverse : 1;	/* inverse colors */
167 	unsigned int protect : 1;	/* cannot be erased */
168 	unsigned int blink : 1;		/* blinking character */
169 };
170 
171 typedef int (*tsm_screen_draw_cb) (struct tsm_screen *con,
172 				   uint32_t id,
173 				   const uint32_t *ch,
174 				   size_t len,
175 				   unsigned int width,
176 				   unsigned int posx,
177 				   unsigned int posy,
178 				   const struct tsm_screen_attr *attr,
179 				   tsm_age_t age,
180 				   void *data);
181 
182 int tsm_screen_new(struct tsm_screen **out, tsm_log_t log, void *log_data);
183 void tsm_screen_ref(struct tsm_screen *con);
184 void tsm_screen_unref(struct tsm_screen *con);
185 
186 unsigned int tsm_screen_get_width(struct tsm_screen *con);
187 unsigned int tsm_screen_get_height(struct tsm_screen *con);
188 int tsm_screen_resize(struct tsm_screen *con, unsigned int x,
189 		      unsigned int y);
190 int tsm_screen_set_margins(struct tsm_screen *con,
191 			   unsigned int top, unsigned int bottom);
192 void tsm_screen_set_max_sb(struct tsm_screen *con, unsigned int max);
193 void tsm_screen_clear_sb(struct tsm_screen *con);
194 
195 void tsm_screen_sb_up(struct tsm_screen *con, unsigned int num);
196 void tsm_screen_sb_down(struct tsm_screen *con, unsigned int num);
197 void tsm_screen_sb_page_up(struct tsm_screen *con, unsigned int num);
198 void tsm_screen_sb_page_down(struct tsm_screen *con, unsigned int num);
199 void tsm_screen_sb_reset(struct tsm_screen *con);
200 
201 void tsm_screen_set_def_attr(struct tsm_screen *con,
202 			     const struct tsm_screen_attr *attr);
203 void tsm_screen_reset(struct tsm_screen *con);
204 void tsm_screen_set_flags(struct tsm_screen *con, unsigned int flags);
205 void tsm_screen_reset_flags(struct tsm_screen *con, unsigned int flags);
206 unsigned int tsm_screen_get_flags(struct tsm_screen *con);
207 
208 unsigned int tsm_screen_get_cursor_x(struct tsm_screen *con);
209 unsigned int tsm_screen_get_cursor_y(struct tsm_screen *con);
210 
211 void tsm_screen_set_tabstop(struct tsm_screen *con);
212 void tsm_screen_reset_tabstop(struct tsm_screen *con);
213 void tsm_screen_reset_all_tabstops(struct tsm_screen *con);
214 
215 void tsm_screen_write(struct tsm_screen *con, tsm_symbol_t ch,
216 		      const struct tsm_screen_attr *attr);
217 void tsm_screen_newline(struct tsm_screen *con);
218 void tsm_screen_scroll_up(struct tsm_screen *con, unsigned int num);
219 void tsm_screen_scroll_down(struct tsm_screen *con, unsigned int num);
220 void tsm_screen_move_to(struct tsm_screen *con, unsigned int x,
221 			unsigned int y);
222 void tsm_screen_move_up(struct tsm_screen *con, unsigned int num,
223 			bool scroll);
224 void tsm_screen_move_down(struct tsm_screen *con, unsigned int num,
225 			  bool scroll);
226 void tsm_screen_move_left(struct tsm_screen *con, unsigned int num);
227 void tsm_screen_move_right(struct tsm_screen *con, unsigned int num);
228 void tsm_screen_move_line_end(struct tsm_screen *con);
229 void tsm_screen_move_line_home(struct tsm_screen *con);
230 void tsm_screen_tab_right(struct tsm_screen *con, unsigned int num);
231 void tsm_screen_tab_left(struct tsm_screen *con, unsigned int num);
232 void tsm_screen_insert_lines(struct tsm_screen *con, unsigned int num);
233 void tsm_screen_delete_lines(struct tsm_screen *con, unsigned int num);
234 void tsm_screen_insert_chars(struct tsm_screen *con, unsigned int num);
235 void tsm_screen_delete_chars(struct tsm_screen *con, unsigned int num);
236 void tsm_screen_erase_cursor(struct tsm_screen *con);
237 void tsm_screen_erase_chars(struct tsm_screen *con, unsigned int num);
238 void tsm_screen_erase_cursor_to_end(struct tsm_screen *con,
239 				    bool protect);
240 void tsm_screen_erase_home_to_cursor(struct tsm_screen *con,
241 				     bool protect);
242 void tsm_screen_erase_current_line(struct tsm_screen *con,
243 				   bool protect);
244 void tsm_screen_erase_screen_to_cursor(struct tsm_screen *con,
245 				       bool protect);
246 void tsm_screen_erase_cursor_to_screen(struct tsm_screen *con,
247 				       bool protect);
248 void tsm_screen_erase_screen(struct tsm_screen *con, bool protect);
249 
250 void tsm_screen_selection_reset(struct tsm_screen *con);
251 void tsm_screen_selection_start(struct tsm_screen *con,
252 				unsigned int posx,
253 				unsigned int posy);
254 void tsm_screen_selection_target(struct tsm_screen *con,
255 				 unsigned int posx,
256 				 unsigned int posy);
257 int tsm_screen_selection_copy(struct tsm_screen *con, char **out);
258 
259 tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
260 			  void *data);
261 
262 /** @} */
263 
264 /**
265  * @defgroup vte State Machine
266  * Virtual terminal emulation with state machine
267  *
268  * A TSM VTE object provides the terminal state machine. It takes input from the
269  * application (which usually comes from a TTY/PTY from a client), parses it,
270  * modifies the attach screen or returns data which has to be written back to
271  * the client.
272  *
273  * Furthermore, VTE objects accept keyboard or mouse input from the application
274  * which is interpreted compliant to DEV-VTs.
275  *
276  * @{
277  */
278 
279 /* virtual terminal emulator */
280 
281 struct tsm_vte;
282 
283 /* keep in sync with shl_xkb_mods */
284 enum tsm_vte_modifier {
285 	TSM_SHIFT_MASK		= (1 << 0),
286 	TSM_LOCK_MASK		= (1 << 1),
287 	TSM_CONTROL_MASK	= (1 << 2),
288 	TSM_ALT_MASK		= (1 << 3),
289 	TSM_LOGO_MASK		= (1 << 4),
290 };
291 
292 /* keep in sync with TSM_INPUT_INVALID */
293 #define TSM_VTE_INVALID 0xffffffff
294 
295 typedef void (*tsm_vte_write_cb) (struct tsm_vte *vte,
296 				  const char *u8,
297 				  size_t len,
298 				  void *data);
299 
300 int tsm_vte_new(struct tsm_vte **out, struct tsm_screen *con,
301 		tsm_vte_write_cb write_cb, void *data,
302 		tsm_log_t log, void *log_data);
303 void tsm_vte_ref(struct tsm_vte *vte);
304 void tsm_vte_unref(struct tsm_vte *vte);
305 
306 int tsm_vte_set_palette(struct tsm_vte *vte, const char *palette);
307 
308 void tsm_vte_reset(struct tsm_vte *vte);
309 void tsm_vte_hard_reset(struct tsm_vte *vte);
310 void tsm_vte_input(struct tsm_vte *vte, const char *u8, size_t len);
311 bool tsm_vte_handle_keyboard(struct tsm_vte *vte, uint32_t keysym,
312 			     uint32_t ascii, unsigned int mods,
313 			     uint32_t unicode);
314 
315 /** @} */
316 
317 #ifdef __cplusplus
318 }
319 #endif
320 
321 #endif /* TSM_LIBTSM_H */
322