terminology/src/bin/termpty.h

430 lines
13 KiB
C
Raw Normal View History

#ifndef _TERMPTY_H__
#define _TERMPTY_H__ 1
#include "config.h"
2018-09-16 08:57:42 -07:00
#include "media.h"
2018-12-09 11:55:25 -08:00
#include "sb.h"
typedef struct _Termcell Termcell;
typedef struct _Termatt Termatt;
typedef struct _Termsave Termsave;
typedef struct _Termsavecomp Termsavecomp;
typedef struct _Termblock Termblock;
typedef struct _Termexp Termexp;
typedef struct _Termpty Termpty;
typedef struct _Termlink Term_Link;
typedef struct _TitleIconElem TitleIconElem;
#define COL_DEF 0
#define COL_BLACK 1
#define COL_RED 2
#define COL_GREEN 3
#define COL_YELLOW 4
#define COL_BLUE 5
#define COL_MAGENTA 6
#define COL_CYAN 7
#define COL_WHITE 8
#define COL_INVIS 9
#define COL_INVERSE 10
#define COL_INVERSEBG 11
#define MOUSE_OFF 0
#define MOUSE_X10 1 // Press only
#define MOUSE_NORMAL 2 // Press+release only
#define MOUSE_NORMAL_BTN_MOVE 3 // Press+release+motion while pressed
#define MOUSE_NORMAL_ALL_MOVE 4 // Press+release+all motion
#define MOUSE_EXT_NONE 0
#define MOUSE_EXT_UTF8 1
#define MOUSE_EXT_SGR 2
#define MOUSE_EXT_URXVT 3
// Only for testing purpose
//#define SUPPORT_80_132_COLUMNS 1
#define MOVIE_STATE_PLAY 0
#define MOVIE_STATE_PAUSE 1
#define MOVIE_STATE_STOP 2
#define HL_LINKS_MAX (1 << 16)
struct _Termlink
{
const char *key;
const char *url;
unsigned int refcount;
};
struct _Termatt
{
2020-06-12 15:02:49 -07:00
uint8_t fg, bg;
unsigned short bold : 1;
unsigned short faint : 1;
unsigned short italic : 1;
unsigned short dblwidth : 1;
unsigned short underline : 1;
unsigned short blink : 1; // don't intend to support this currently
unsigned short blink2 : 1; // don't intend to support this currently
unsigned short inverse : 1;
unsigned short invisible : 1;
unsigned short strike : 1;
unsigned short fg256 : 1;
unsigned short bg256 : 1;
unsigned short fgintense : 1;
unsigned short bgintense : 1;
// below used for working out text from selections
unsigned short autowrapped : 1;
unsigned short newline : 1;
2014-04-06 05:42:38 -07:00
unsigned short fraktur : 1;
unsigned short framed : 1;
unsigned short encircled : 1;
unsigned short overlined : 1; // TODO: support it
unsigned short tab_inserted : 1;
unsigned short tab_last : 1;
#if defined(SUPPORT_80_132_COLUMNS)
unsigned short is_80_132_mode_allowed : 1;
unsigned short bit_padding : 9;
#else
unsigned short bit_padding : 10;
#endif
uint16_t link_id;
};
typedef struct _Backlog_Beacon{
int screen_y;
int backlog_y;
} Backlog_Beacon;
typedef struct _Term_State {
Termatt att;
unsigned char charset;
unsigned char charsetch;
unsigned char chset[4];
int top_margin, bottom_margin;
int left_margin, right_margin;
int had_cr_x, had_cr_y;
unsigned int lr_margins : 1;
unsigned int restrict_cursor : 1;
unsigned int multibyte : 1;
unsigned int alt_kp : 1;
unsigned int insert : 1;
unsigned int appcursor : 1;
unsigned int wrap : 1;
unsigned int wrapnext : 1;
unsigned int crlf : 1;
unsigned int send_bs : 1;
unsigned int kbd_lock : 1;
unsigned int reverse : 1;
unsigned int no_autorepeat : 1;
unsigned int cjk_ambiguous_wide : 1;
unsigned int hide_cursor : 1;
unsigned int combining_strike : 1;
unsigned int sace_rectangular : 1;
} Term_State;
typedef struct _Term_Cursor {
int cx;
int cy;
} Term_Cursor;
struct _Termpty
{
Evas_Object *obj;
2019-06-23 10:00:10 -07:00
Config *config;
Ecore_Event_Handler *hand_exe_exit;
Ecore_Fd_Handler *hand_fd;
struct {
struct {
void (*func) (void *data);
void *data;
2013-11-10 13:13:19 -08:00
} change, set_title, set_icon, cancel_sel, exited, bell, command;
} cb;
struct {
const char *icon;
/* dynamic title set by xterm, keep it in case user don't want a
* title any more by setting a empty title
*/
const char *title;
/* set by user */
const char *user_title;
} prop;
const char *cur_cmd;
Termcell *screen, *screen2;
unsigned int *tabs;
int circular_offset;
int circular_offset2;
2015-02-23 13:20:18 -08:00
Eina_Unicode *buf;
size_t buflen;
Eina_Unicode last_char;
Eina_Bool buf_have_zero;
unsigned char oldbuf[4];
Termsave *back;
size_t backsize, backpos;
/* this beacon in the backlog tells about the top line in screen
* coordinates that maps to a line in the backlog */
Backlog_Beacon backlog_beacon;
int w, h;
int fd, slavefd;
2018-12-09 11:55:25 -08:00
struct ty_sb write_buffer;
struct {
int curid;
Eina_Hash *blocks;
Eina_Hash *chid_map;
Eina_List *active;
Eina_List *expecting;
2014-08-28 12:04:00 -07:00
unsigned char on : 1;
} block;
2013-09-29 08:55:24 -07:00
struct {
2015-01-21 13:56:16 -08:00
/* start is always the start of the selection
* so end.y can be < start.y */
2013-09-29 08:55:24 -07:00
struct {
int x, y;
2015-01-21 13:56:16 -08:00
} start, end, orig;
Eina_Unicode *codepoints;
2015-01-19 13:55:22 -08:00
time_t last_click;
2014-08-28 12:04:00 -07:00
unsigned char is_box : 1;
unsigned char is_active : 1; // there is a visible selection
unsigned char makesel : 1; // selection is being worked on
2015-01-21 13:56:16 -08:00
unsigned char by_word : 1;
unsigned char by_line : 1;
unsigned char is_top_to_bottom : 1;
2013-09-29 08:55:24 -07:00
} selection;
Term_State termstate;
Term_Cursor cursor_state;
Term_Cursor cursor_save[2];
int exit_code;
pid_t pid;
unsigned int altbuf : 1;
unsigned int mouse_mode : 3;
unsigned int mouse_ext : 2;
unsigned int bracketed_paste : 1;
unsigned int decoding_error : 1;
2021-11-02 15:28:37 -07:00
unsigned int focus_reporting : 1;
2018-09-26 10:59:33 -07:00
struct {
Term_Link *links;
uint8_t *bitmap;
2018-10-12 09:12:15 -07:00
uint32_t size;
2018-09-26 10:59:33 -07:00
} hl;
TitleIconElem *title_icon_stack;
};
struct _Termcell
{
2014-03-25 13:34:48 -07:00
Eina_Unicode codepoint;
Termatt att;
};
struct _Termsave
{
unsigned int gen : 8;
unsigned int comp : 1;
unsigned int z : 1;
unsigned int w : 22;
/* TODO: union ? */
Termcell *cells;
};
/* TODO: RESIZE rewrite Termsavecomp */
struct _Termsavecomp
{
unsigned int gen : 8;
unsigned int comp : 1;
unsigned int z : 1;
unsigned int w : 22; // compressed size in bytes
unsigned int wout; // output width in Termcells
};
struct _Termblock
{
Termpty *pty;
const char *path, *link, *chid;
Evas_Object *obj;
Eina_List *cmds;
int id;
2018-09-16 08:57:42 -07:00
Media_Type type;
int refs;
short w, h;
short x, y;
2014-08-28 12:04:00 -07:00
unsigned char scale_stretch : 1;
unsigned char scale_center : 1;
unsigned char scale_fill : 1;
unsigned char thumb : 1;
unsigned char edje : 1;
unsigned char active : 1;
unsigned char was_active : 1;
unsigned char was_active_before : 1;
unsigned char mov_state : 2; // movie state marker
};
struct _Termexp
{
Eina_Unicode ch;
int left, id;
int x, y, w, h;
};
2018-10-12 09:12:15 -07:00
void termpty_init(void);
void termpty_shutdown(void);
Termpty *termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd,
int w, int h, Config *config, const char *title,
Ecore_Window window_id);
void termpty_free(Termpty *ty);
2019-06-23 10:00:10 -07:00
void termpty_config_update(Termpty *ty, Config *config);
Termcell *termpty_cellrow_get(Termpty *ty, int y, ssize_t *wret);
2018-10-13 09:07:27 -07:00
Termcell * termpty_cell_get(Termpty *ty, int y_requested, int x_requested);
ssize_t termpty_row_length(Termpty *ty, int y);
#define TERMPTY_WRITE_STR(_S) \
termpty_write(ty, _S, strlen(_S))
void termpty_write(Termpty *ty, const char *input, int len);
void termpty_resize(Termpty *ty, int new_w, int new_h);
2017-05-16 15:05:15 -07:00
void termpty_resize_tabs(Termpty *ty, int old_w, int new_w);
void termpty_backscroll_adjust(Termpty *ty, int *scroll);
pid_t termpty_pid_get(const Termpty *ty);
void termpty_block_free(Termblock *tb);
Termblock *termpty_block_new(Termpty *ty, int w, int h, const char *path, const char *link);
void termpty_block_insert(Termpty *ty, int ch, Termblock *blk);
2017-07-06 11:55:02 -07:00
int termpty_block_id_get(const Termcell *cell, int *x, int *y);
Termblock *termpty_block_get(const Termpty *ty, int id);
void termpty_block_chid_update(Termpty *ty, Termblock *blk);
2017-07-06 11:55:02 -07:00
Termblock *termpty_block_chid_get(const Termpty *ty, const char *chid);
2014-03-25 13:34:48 -07:00
void termpty_cell_codepoint_att_fill(Termpty *ty, Eina_Unicode codepoint, Termatt att, Termcell *dst, int n);
void termpty_cells_set_content(Termpty *ty, Termcell *cells,
Eina_Unicode codepoint, int count);
void termpty_screen_swap(Termpty *ty);
ssize_t termpty_line_length(const Termcell *cells, ssize_t nb_cells);
void termpty_handle_buf(Termpty *ty, const Eina_Unicode *codepoints, int len);
void termpty_handle_block_codepoint_overwrite_heavy(Termpty *ty, int oldc, int newc);
Term_Link * term_link_new(Termpty *ty);
void term_link_free(Termpty *ty, Term_Link *link);
2019-05-26 13:55:22 -07:00
int
termpty_color_class_get(Termpty *ty, const char *key,
int *r, int *g, int *b, int *a);
2021-11-02 15:28:37 -07:00
void
termpty_focus_report(Termpty *ty, Eina_Bool focus);
2019-05-26 13:55:22 -07:00
extern int _termpty_log_dom;
#define TERMPTY_SCREEN(Tpty, X, Y) \
Tpty->screen[X + (((Y + Tpty->circular_offset) % Tpty->h) * Tpty->w)]
#define TERMPTY_RESTRICT_FIELD(Field, Min, Max) \
do { \
if (Field >= Max) \
Field = Max - 1; \
else if (Field < Min) \
Field = Min; \
} while (0)
/* Try to trick the compiler into inlining the first test */
#define HANDLE_BLOCK_CODEPOINT_OVERWRITE(Tpty, OLDC, NEWC) \
do { \
if (EINA_UNLIKELY((OLDC | NEWC) & 0x80000000)) \
termpty_handle_block_codepoint_overwrite_heavy(Tpty, OLDC, NEWC); \
} while (0)
#define TERMPTY_CELL_COPY(Tpty, Tsrc, Tdst, N) \
do { \
int __i; \
\
for (__i = 0; __i < N; __i++) \
{ \
HANDLE_BLOCK_CODEPOINT_OVERWRITE(Tpty, \
(Tdst)[__i].codepoint, \
(Tsrc)[__i].codepoint); \
2018-10-12 09:12:15 -07:00
if (EINA_UNLIKELY((Tdst)[__i].att.link_id)) \
term_link_refcount_dec(ty, (Tdst)[__i].att.link_id, 1); \
if (EINA_UNLIKELY((Tsrc)[__i].att.link_id)) \
term_link_refcount_inc(ty, (Tsrc)[__i].att.link_id, 1); \
} \
memcpy(Tdst, Tsrc, N * sizeof(Termcell)); \
} while (0)
2018-10-12 09:12:15 -07:00
static inline void
term_link_refcount_inc(Termpty *ty, uint16_t link_id, uint16_t count)
{
Term_Link *link;
link = &ty->hl.links[link_id];
link->refcount += count;
}
static inline void
term_link_refcount_dec(Termpty *ty, uint16_t link_id, uint16_t count)
{
Term_Link *link;
2018-09-26 10:59:33 -07:00
2018-10-12 09:12:15 -07:00
link = &ty->hl.links[link_id];
link->refcount -= count;
if (EINA_UNLIKELY(link->refcount == 0))
term_link_free(ty, link);
}
2018-09-26 10:59:33 -07:00
static inline Eina_Bool
term_link_eq(Termpty *ty, Term_Link *hl, uint16_t link_id)
{
Term_Link *hl2;
uint16_t hl_id;
if (link_id == 0)
return EINA_FALSE;
hl_id = hl - ty->hl.links;
if (hl_id == link_id)
return EINA_TRUE;
hl2 = &ty->hl.links[link_id];
if (!hl->key || !hl2->key ||
strcmp(hl->key, hl2->key) != 0)
return EINA_FALSE;
return (strcmp(hl->url, hl2->url) == 0);
}
2018-10-12 09:12:15 -07:00
static inline void
termpty_cell_fill(Termpty *ty, Termcell *src, Termcell *dst, int n)
{
int i;
if (src)
{
for (i = 0; i < n; i++)
{
HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, src[0].codepoint);
if (EINA_UNLIKELY(dst[i].att.link_id))
term_link_refcount_dec(ty, dst[i].att.link_id, 1);
dst[i] = src[0];
}
if (src[0].att.link_id)
term_link_refcount_inc(ty, src[0].att.link_id, n);
2018-10-12 09:12:15 -07:00
}
else
{
for (i = 0; i < n; i++)
{
HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, 0);
if (EINA_UNLIKELY(dst[i].att.link_id))
term_link_refcount_dec(ty, dst[i].att.link_id, 1);
memset(&(dst[i]), 0, sizeof(*dst));
}
}
}
#endif