#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
+#include "term.h"
#include "util.h"
typedef struct term_char term_char_t;
typedef struct term_charbuf term_charbuf_t;
-typedef struct term_color term_color;
-typedef struct term_attr term_attr;
typedef struct term_cell term_cell;
typedef struct term_line term_line;
typedef struct term_page term_page;
typedef struct term_history term_history;
-typedef struct term_utf8 term_utf8;
-typedef struct term_seq term_seq;
-typedef struct term_parser term_parser;
typedef uint32_t term_charset[96];
-
-typedef struct term_screen term_screen;
+typedef struct term_state term_state;
/*
* Miscellaneous
int mk_wcswidth(const wchar_t *str, size_t len);
int mk_wcswidth_cjk(const wchar_t *str, size_t len);
-/*
- * Ageing
- * Redrawing terminals is quite expensive. Therefore, we avoid redrawing on
- * each single modification and mark modified cells instead. This way, we know
- * which cells to redraw on the next frame. However, a single DIRTY flag is not
- * enough for double/triple buffered screens, hence, we use an AGE field for
- * each cell. If the cell is modified, we simply increase the age by one. Each
- * framebuffer can then remember its last rendered age and request an update of
- * all newer cells.
- * TERM_AGE_NULL is special. If used as cell age, the cell must always be
- * redrawn (forced update). If used as framebuffer age, all cells are drawn.
- * This way, we can allow integer wrap-arounds.
- */
-
-typedef uint64_t term_age_t;
-
-#define TERM_AGE_NULL 0
-
/*
* Characters
* Each cell in a terminal page contains only a single character. This is
term_char_free(*p);
}
-/*
- * Attributes
- * Each cell in a terminal page can have its own set of attributes. These alter
- * the behavior of the renderer for this single cell. We use term_attr to
- * specify attributes.
- * The only non-obvious field is "ccode" for foreground and background colors.
- * This field contains the terminal color-code in case no full RGB information
- * was given by the host. It is also required for dynamic color palettes. If it
- * is set to TERM_CCODE_RGB, the "red", "green" and "blue" fields contain the
- * full RGB color.
- */
-
-enum {
- /* special color-codes */
- TERM_CCODE_DEFAULT, /* default foreground/background color */
- TERM_CCODE_256, /* 256color code */
- TERM_CCODE_RGB, /* color is specified as RGB */
-
- /* dark color-codes */
- TERM_CCODE_BLACK,
- TERM_CCODE_RED,
- TERM_CCODE_GREEN,
- TERM_CCODE_YELLOW,
- TERM_CCODE_BLUE,
- TERM_CCODE_MAGENTA,
- TERM_CCODE_CYAN,
- TERM_CCODE_WHITE, /* technically: light grey */
-
- /* light color-codes */
- TERM_CCODE_LIGHT_BLACK = TERM_CCODE_BLACK + 8, /* technically: dark grey */
- TERM_CCODE_LIGHT_RED = TERM_CCODE_RED + 8,
- TERM_CCODE_LIGHT_GREEN = TERM_CCODE_GREEN + 8,
- TERM_CCODE_LIGHT_YELLOW = TERM_CCODE_YELLOW + 8,
- TERM_CCODE_LIGHT_BLUE = TERM_CCODE_BLUE + 8,
- TERM_CCODE_LIGHT_MAGENTA = TERM_CCODE_MAGENTA + 8,
- TERM_CCODE_LIGHT_CYAN = TERM_CCODE_CYAN + 8,
- TERM_CCODE_LIGHT_WHITE = TERM_CCODE_WHITE + 8,
-
- TERM_CCODE_CNT,
-};
-
-struct term_color {
- uint8_t ccode;
- uint8_t c256;
- uint8_t red;
- uint8_t green;
- uint8_t blue;
-};
-
-struct term_attr {
- term_color fg; /* foreground color */
- term_color bg; /* background color */
-
- unsigned int bold : 1; /* bold font */
- unsigned int italic : 1; /* italic font */
- unsigned int underline : 1; /* underline text */
- unsigned int inverse : 1; /* inverse fg/bg */
- unsigned int protect : 1; /* protect from erase */
- unsigned int blink : 1; /* blink text */
- unsigned int hidden : 1; /* hidden */
-};
-
/*
* Cells
* The term_cell structure respresents a single cell in a terminal page. It
term_line *term_history_pop(term_history *history, unsigned int reserve_width, const term_attr *attr, term_age_t age);
unsigned int term_history_peek(term_history *history, unsigned int max, unsigned int reserve_width, const term_attr *attr, term_age_t age);
-/*
- * UTF-8
- * The UTF-decoder and encoder are adjusted for terminals and provide proper
- * fallbacks for invalid UTF-8. In terminals it's quite usual to use fallbacks
- * instead of rejecting invalid input. This way, old legacy applications still
- * work (this is especially important for 7bit/ASCII DEC modes).
- */
-
-struct term_utf8 {
- uint32_t chars[5];
- uint32_t ucs4;
-
- unsigned int i_bytes : 3;
- unsigned int n_bytes : 3;
- unsigned int valid : 1;
-};
-
-size_t term_utf8_encode(char *out_utf8, uint32_t g);
-const uint32_t *term_utf8_decode(term_utf8 *p, size_t *out_len, char c);
-
/*
* Parsers
* The term_parser object parses control-sequences for both host and terminal
bool is_host : 1;
};
-int term_parser_new(term_parser **out, bool host);
-term_parser *term_parser_free(term_parser *parser);
-int term_parser_feed(term_parser *parser, const term_seq **seq_out, uint32_t raw);
-
-#define _term_parser_free_ _cleanup_(term_parser_freep)
-DEFINE_TRIVIAL_CLEANUP_FUNC(term_parser*, term_parser_free);
-
/*
* Screens
* A term_screen object represents the terminal-side of the communication. It
*/
enum {
- TERM_FLAG_7BIT_MODE = (1U << 0), /* 7bit mode (default: off) */
+ TERM_FLAG_7BIT_MODE = (1U << 0), /* 7bit mode (default: on) */
TERM_FLAG_HIDE_CURSOR = (1U << 1), /* hide cursor caret (default: off) */
TERM_FLAG_INHIBIT_TPARM = (1U << 2), /* do not send TPARM unrequested (default: off) */
TERM_FLAG_NEWLINE_MODE = (1U << 3), /* perform carriage-return on line-feeds (default: off) */
- TERM_FLAG_ORIGIN_MODE = (1U << 4), /* in origin mode, the cursor is bound by the margins (default: off) */
- TERM_FLAG_PENDING_WRAP = (1U << 5), /* wrap-around is pending */
- TERM_FLAG_AUTO_WRAP = (1U << 6), /* auto-wrap mode causes line-wraps at line-ends (default: off) */
- TERM_FLAG_KEYPAD_MODE = (1U << 7), /* application-keypad mode (default: off) */
- TERM_FLAG_CURSOR_KEYS = (1U << 8), /* enable application cursor-keys (default: off) */
+ TERM_FLAG_PENDING_WRAP = (1U << 4), /* wrap-around is pending */
+ TERM_FLAG_KEYPAD_MODE = (1U << 5), /* application-keypad mode (default: off) */
+ TERM_FLAG_CURSOR_KEYS = (1U << 6), /* enable application cursor-keys (default: off) */
};
enum {
TERM_CONFORMANCE_LEVEL_CNT,
};
-typedef int (*term_screen_write_fn) (term_screen *screen, void *userdata, const void *buf, size_t size);
-typedef int (*term_screen_cmd_fn) (term_screen *screen, void *userdata, unsigned int cmd, const term_seq *seq);
+struct term_state {
+ unsigned int cursor_x;
+ unsigned int cursor_y;
+ term_attr attr;
+ term_charset **gl;
+ term_charset **gr;
+ term_charset **glt;
+ term_charset **grt;
+
+ bool auto_wrap : 1;
+ bool origin_mode : 1;
+};
struct term_screen {
unsigned long ref;
unsigned int flags;
unsigned int conformance_level;
- unsigned int cursor_x;
- unsigned int cursor_y;
- term_attr attr;
term_attr default_attr;
- term_charset **gl;
- term_charset **gr;
- term_charset **glt;
- term_charset **grt;
term_charset *g0;
term_charset *g1;
term_charset *g2;
char *answerback;
- struct {
- unsigned int cursor_x;
- unsigned int cursor_y;
- term_attr attr;
- term_charset **gl;
- term_charset **gr;
- term_charset **glt;
- term_charset **grt;
- unsigned int flags;
- } saved;
+ term_state state;
+ term_state saved;
+ term_state saved_alt;
};
-
-int term_screen_new(term_screen **out, term_screen_write_fn write_fn, void *write_fn_data, term_screen_cmd_fn cmd_fn, void *cmd_fn_data);
-term_screen *term_screen_ref(term_screen *screen);
-term_screen *term_screen_unref(term_screen *screen);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(term_screen*, term_screen_unref);
-
-int term_screen_feed_text(term_screen *screen, const uint8_t *in, size_t size);
-int term_screen_feed_keyboard(term_screen *screen, uint32_t keysym, uint32_t ascii, uint32_t ucs4, unsigned int mods);
-int term_screen_resize(term_screen *screen, unsigned int width, unsigned int height);
-void term_screen_soft_reset(term_screen *screen);
-void term_screen_hard_reset(term_screen *screen);
-
-int term_screen_set_answerback(term_screen *screen, const char *answerback);