/* * TSM - Main Header * * Copyright (c) 2011-2013 David Herrmann * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef TSM_LIBTSM_H #define TSM_LIBTSM_H #include #include #include #include #include #include "shl-array.h" #include "shl-htable.h" /** * @mainpage * * TSM is a Terminal-emulator State Machine. It implements all common DEC-VT100 * to DEC-VT520 control codes and features. A state-machine is used to parse TTY * input and saved in a virtual screen. TSM does not provide any rendering, * glyph/font handling or anything more advanced. TSM is just a simple * state-machine for control-codes handling. * The main use-case for TSM are terminal-emulators. TSM has no dependencies * other than an ISO-C99 compiler and C-library. Any terminal emulator for any * window-environment or rendering-pipline can make use of TSM. However, TSM can * also be used for control-code validation, TTY-screen-capturing or other * advanced users of terminal escape-sequences. */ /** * @defgroup symbols Unicode Helpers * Unicode helpers * * Unicode uses 32bit types to uniquely represent symbols. However, combining * characters allow modifications of such symbols but require additional space. * To avoid passing around allocated strings, TSM provides a symbol-table which * can store combining-characters with their base-symbol to create a new symbol. * This way, only the symbol-identifiers have to be passed around (which are * simple integers). No string allocation is needed by the API user. * * The symbol table is currently not exported. Once the API is fixed, we will * provide it to outside users. * * Additionally, this contains some general UTF8/UCS4 helpers. * * @{ */ /* UCS4 helpers */ #define TSM_UCS4_MAX (0x7fffffffUL) unsigned int tsm_ucs4_get_width(uint32_t ucs4); /* symbols */ typedef uint32_t tsm_symbol_t; /** @} */ /** * @defgroup screen Terminal Screens * Virtual terminal-screen implementation * * A TSM screen respresents the real screen of a terminal/application. It does * not render anything, but only provides a table of cells. Each cell contains * the stored symbol, attributes and more. Applications iterate a screen to * render each cell on their framebuffer. * * Screens provide all features that are expected from terminals. They include * scroll-back buffers, alternate screens, cursor positions and selection * support. Thus, it needs event-input from applications to drive these * features. Most of them are optional, though. * * @{ */ struct tsm_screen; typedef uint_fast32_t tsm_age_t; #define TSM_SCREEN_INSERT_MODE 0x01 #define TSM_SCREEN_AUTO_WRAP 0x02 #define TSM_SCREEN_REL_ORIGIN 0x04 #define TSM_SCREEN_INVERSE 0x08 #define TSM_SCREEN_HIDE_CURSOR 0x10 #define TSM_SCREEN_FIXED_POS 0x20 #define TSM_SCREEN_ALTERNATE 0x40 struct tsm_screen_attr { int8_t fccode; /* foreground color code or <0 for rgb */ int8_t bccode; /* background color code or <0 for rgb */ uint8_t fr; /* foreground red */ uint8_t fg; /* foreground green */ uint8_t fb; /* foreground blue */ uint8_t br; /* background red */ uint8_t bg; /* background green */ uint8_t bb; /* background blue */ unsigned int flags; }; #define TSM_ATTR_BOLD (1 << 0) #define TSM_ATTR_UNDERLINE (1 << 1) #define TSM_ATTR_INVERSE (1 << 2) #define TSM_ATTR_PROTECT (1 << 3) #define TSM_ATTR_BLINK (1 << 4) typedef int (*tsm_screen_draw_cb) (struct tsm_screen *con, uint32_t id, const uint32_t *ch, size_t len, unsigned int width, unsigned int posx, unsigned int posy, const struct tsm_screen_attr *attr, tsm_age_t age, void *data); int tsm_screen_new(struct tsm_screen *con, unsigned int x, unsigned int y); void tsm_screen_old(struct tsm_screen *con); int tsm_screen_resize(struct tsm_screen *con, unsigned int x, unsigned int y); int tsm_screen_set_margins(struct tsm_screen *con, unsigned int top, unsigned int bottom); void tsm_screen_set_max_sb(struct tsm_screen *con, unsigned int max); void tsm_screen_clear_sb(struct tsm_screen *con); void tsm_screen_sb_up(struct tsm_screen *con, unsigned int num); void tsm_screen_sb_down(struct tsm_screen *con, unsigned int num); void tsm_screen_sb_page_up(struct tsm_screen *con, unsigned int num); void tsm_screen_sb_page_down(struct tsm_screen *con, unsigned int num); void tsm_screen_sb_reset(struct tsm_screen *con); void tsm_screen_reset(struct tsm_screen *con); void tsm_screen_set_flags(struct tsm_screen *con, unsigned int flags); void tsm_screen_set_tabstop(struct tsm_screen *con); void tsm_screen_reset_tabstop(struct tsm_screen *con); void tsm_screen_reset_all_tabstops(struct tsm_screen *con); void tsm_screen_write(struct tsm_screen *con, tsm_symbol_t ch, const struct tsm_screen_attr *attr); void tsm_screen_newline(struct tsm_screen *con); void tsm_screen_scroll_up(struct tsm_screen *con, unsigned int num); void tsm_screen_scroll_down(struct tsm_screen *con, unsigned int num); void tsm_screen_move_to(struct tsm_screen *con, unsigned int x, unsigned int y); void tsm_screen_move_up(struct tsm_screen *con, unsigned int num, bool scroll); void tsm_screen_move_down(struct tsm_screen *con, unsigned int num, bool scroll); void tsm_screen_move_left(struct tsm_screen *con, unsigned int num); void tsm_screen_move_right(struct tsm_screen *con, unsigned int num); void tsm_screen_move_line_end(struct tsm_screen *con); void tsm_screen_move_line_home(struct tsm_screen *con); void tsm_screen_tab_right(struct tsm_screen *con, unsigned int num); void tsm_screen_tab_left(struct tsm_screen *con, unsigned int num); void tsm_screen_insert_lines(struct tsm_screen *con, unsigned int num); void tsm_screen_delete_lines(struct tsm_screen *con, unsigned int num); void tsm_screen_insert_chars(struct tsm_screen *con, unsigned int num); void tsm_screen_delete_chars(struct tsm_screen *con, unsigned int num); void tsm_screen_erase_cursor(struct tsm_screen *con); void tsm_screen_erase_chars(struct tsm_screen *con, unsigned int num); void screen_erase_region(struct tsm_screen *, unsigned int, unsigned int, unsigned int, unsigned int, bool); void tsm_screen_selection_reset(struct tsm_screen *con); void tsm_screen_selection_start(struct tsm_screen *con, unsigned int posx, unsigned int posy); void tsm_screen_selection_target(struct tsm_screen *con, unsigned int posx, unsigned int posy); int tsm_screen_selection_copy(struct tsm_screen *con, char **out); tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb, void *data); /** @} */ #define SHL_EXPORT __attribute__((visibility("default"))) /* max combined-symbol length */ #define TSM_UCS4_MAXLEN 10 /* symbols */ struct tsm_symbol_table; extern const tsm_symbol_t tsm_symbol_default; int tsm_symbol_table_new(struct tsm_symbol_table *tbl); void tsm_symbol_table_old(struct tsm_symbol_table *tbl); const uint32_t *tsm_symbol_get(struct tsm_symbol_table *tbl, tsm_symbol_t *sym, size_t *size); unsigned int tsm_symbol_get_width(struct tsm_symbol_table *tbl, tsm_symbol_t sym); /* TSM screen */ struct cell { tsm_symbol_t ch; /* stored character */ unsigned int width; /* character width */ struct tsm_screen_attr attr; /* cell attributes */ tsm_age_t age; /* age of the single cell */ }; struct line { struct line *next; /* next line (NULL if not sb) */ struct line *prev; /* prev line (NULL if not sb) */ unsigned int size; /* real width */ struct cell *cells; /* actuall cells */ uint64_t sb_id; /* sb ID */ tsm_age_t age; /* age of the whole line */ }; #define SELECTION_TOP -1 struct selection_pos { struct line *line; unsigned int x; int y; }; struct tsm_symbol_table { uint32_t next_id; struct shl_array index; struct shl_htable symbols; }; struct tsm_screen { unsigned int opts; unsigned int flags; struct tsm_symbol_table sym_table; /* default attributes for new cells */ struct tsm_screen_attr def_attr; /* ageing */ tsm_age_t age_cnt; /* current age counter */ unsigned int age_reset : 1; /* age-overflow flag */ /* current buffer */ unsigned int size_x; /* width of screen */ unsigned int size_y; /* height of screen */ unsigned int margin_top; /* top-margin index */ unsigned int margin_bottom; /* bottom-margin index */ unsigned int line_num; /* real number of allocated lines */ struct line **lines; /* active lines; copy of main/alt */ struct line **main_lines; /* real main lines */ struct line **alt_lines; /* real alternative lines */ tsm_age_t age; /* whole screen age */ /* scroll-back buffer */ unsigned int sb_count; /* number of lines in sb */ struct line *sb_first; /* first line; was moved first */ struct line *sb_last; /* last line; was moved last*/ unsigned int sb_max; /* max-limit of lines in sb */ struct line *sb_pos; /* current position in sb or NULL */ uint64_t sb_last_id; /* last id given to sb-line */ /* cursor: positions are always in-bound, but cursor_x might be * bigger than size_x if new-line is pending */ unsigned int cursor_x; /* current cursor x-pos */ unsigned int cursor_y; /* current cursor y-pos */ /* tab ruler */ bool *tab_ruler; /* tab-flag for all cells of one row */ /* selection */ bool sel_active; struct selection_pos sel_start; struct selection_pos sel_end; }; void screen_cell_init(struct tsm_screen *con, struct cell *cell); void tsm_screen_set_opts(struct tsm_screen *scr, unsigned int opts); void tsm_screen_reset_opts(struct tsm_screen *scr, unsigned int opts); static inline void screen_inc_age(struct tsm_screen *con) { if (!++con->age_cnt) { con->age_reset = 1; ++con->age_cnt; } } #endif /* TSM_LIBTSM_H */