Compare commits
No commits in common. "6499e884851d0a5df1518a33743d0dc303734237" and "56c4253a87f15968a41d0ef9149cf72af04ad39d" have entirely different histories.
6499e88485
...
56c4253a87
@ -90,10 +90,6 @@ int allowaltscreen = 1;
|
||||
setting the clipboard text */
|
||||
int allowwindowops = 0;
|
||||
|
||||
/* allow programs to set the clipboard via OSC 52. This is what tmux uses
|
||||
for set-clipboard, and what remote programs use to copy over ssh. */
|
||||
int allowclipboard = 1;
|
||||
|
||||
/*
|
||||
* draw latency range in ms - from new content/keypress/etc until drawing.
|
||||
* within this range, st draws when content stops arriving (idle). mostly it's
|
||||
|
||||
4
config.h
4
config.h
@ -90,10 +90,6 @@ int allowaltscreen = 1;
|
||||
setting the clipboard text */
|
||||
int allowwindowops = 0;
|
||||
|
||||
/* allow programs to set the clipboard via OSC 52. This is what tmux uses
|
||||
for set-clipboard, and what remote programs use to copy over ssh. */
|
||||
int allowclipboard = 1;
|
||||
|
||||
/*
|
||||
* draw latency range in ms - from new content/keypress/etc until drawing.
|
||||
* within this range, st draws when content stops arriving (idle). mostly it's
|
||||
|
||||
112
kitty.c
112
kitty.c
@ -2295,46 +2295,122 @@ kitty_find_virtual(uint32_t imgid, uint32_t plcid)
|
||||
/*
|
||||
* Blit the part of a virtual placement that corresponds to one screen cell.
|
||||
* (px, py) is the cell on screen, (row, col) the cell within the placement.
|
||||
*
|
||||
* The whole placement is scaled once into the placement's pixmap cache
|
||||
* (kitty_prepare), and each cell is then a cheap XRender copy out of it.
|
||||
*/
|
||||
static void
|
||||
kitty_blit_cell(KittyPlacement *p, int px, int py, int row, int col)
|
||||
{
|
||||
KittyImage *im = p->image;
|
||||
const unsigned char *base;
|
||||
unsigned char *cell;
|
||||
int cw = win.cw, ch = win.ch;
|
||||
int fullw, fullh, sx0, sy0, x, y, i, n;
|
||||
unsigned char *tile;
|
||||
Pixmap pm;
|
||||
XImage ximage;
|
||||
Picture src, dstpic;
|
||||
XRenderPictFormat *fmt;
|
||||
XRenderPictureAttributes pa;
|
||||
int w, h, bx, by, cw = win.cw, ch = win.ch;
|
||||
int sx, sy, cellw, cellh;
|
||||
int bx, by;
|
||||
|
||||
if (!p->image || row >= p->rows || col >= p->cols)
|
||||
return;
|
||||
if (!kitty_prepare(p, &w, &h))
|
||||
if (!im || row >= p->rows || col >= p->cols)
|
||||
return;
|
||||
|
||||
sx = col * cw;
|
||||
sy = row * ch;
|
||||
cellw = KMIN(cw, w - sx);
|
||||
cellh = KMIN(ch, h - sy);
|
||||
if (cellw <= 0 || cellh <= 0)
|
||||
fullw = p->cols * cw;
|
||||
fullh = p->rows * ch;
|
||||
if (fullw <= 0 || fullh <= 0)
|
||||
return;
|
||||
|
||||
base = kitty_frame_pixels(im, im->current_frame);
|
||||
if (!base)
|
||||
return;
|
||||
base += ((size_t)p->sy * im->width + p->sx) * 4;
|
||||
|
||||
/* scale just this cell out of the source rect */
|
||||
sx0 = col * cw;
|
||||
sy0 = row * ch;
|
||||
if (!(cell = malloc((size_t)cw * ch * 4)))
|
||||
return;
|
||||
for (y = 0; y < ch; y++) {
|
||||
double fy = ((double)(sy0 + y) + 0.5) * p->sh / fullh - 0.5;
|
||||
int y0 = (int)(fy < 0 ? 0 : fy);
|
||||
int y1 = KMIN(y0 + 1, p->sh - 1);
|
||||
int wy = (int)((fy - y0) * 256);
|
||||
if (wy < 0) wy = 0;
|
||||
if (wy > 256) wy = 256;
|
||||
for (x = 0; x < cw; x++) {
|
||||
double fx = ((double)(sx0 + x) + 0.5) * p->sw / fullw - 0.5;
|
||||
int x0 = (int)(fx < 0 ? 0 : fx);
|
||||
int x1 = KMIN(x0 + 1, p->sw - 1);
|
||||
int wx = (int)((fx - x0) * 256);
|
||||
const unsigned char *q00, *q01, *q10, *q11;
|
||||
unsigned char *o = cell + ((size_t)y * cw + x) * 4;
|
||||
int c;
|
||||
if (wx < 0) wx = 0;
|
||||
if (wx > 256) wx = 256;
|
||||
q00 = base + (size_t)y0 * im->width * 4 + x0 * 4;
|
||||
q01 = base + (size_t)y0 * im->width * 4 + x1 * 4;
|
||||
q10 = base + (size_t)y1 * im->width * 4 + x0 * 4;
|
||||
q11 = base + (size_t)y1 * im->width * 4 + x1 * 4;
|
||||
for (c = 0; c < 4; c++) {
|
||||
int t = q00[c] * (256 - wx) + q01[c] * wx;
|
||||
int b = q10[c] * (256 - wx) + q11[c] * wx;
|
||||
o[c] = (unsigned char)((t * (256 - wy) + b * wy) >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tile = cell;
|
||||
n = cw * ch;
|
||||
for (i = 0; i < n; i++) {
|
||||
unsigned char r = tile[4*i+0], g = tile[4*i+1];
|
||||
unsigned char b = tile[4*i+2], a = tile[4*i+3];
|
||||
tile[4*i+0] = (unsigned char)(b * a / 255);
|
||||
tile[4*i+1] = (unsigned char)(g * a / 255);
|
||||
tile[4*i+2] = (unsigned char)(r * a / 255);
|
||||
tile[4*i+3] = a;
|
||||
}
|
||||
|
||||
pm = XCreatePixmap(xw.dpy, xw.win, cw, ch, 32);
|
||||
if (!pm) {
|
||||
free(cell);
|
||||
return;
|
||||
}
|
||||
memset(&ximage, 0, sizeof ximage);
|
||||
ximage.format = ZPixmap;
|
||||
ximage.data = (char *)tile;
|
||||
ximage.width = cw;
|
||||
ximage.height = ch;
|
||||
ximage.byte_order = LSBFirst;
|
||||
ximage.bitmap_bit_order = MSBFirst;
|
||||
ximage.bits_per_pixel = 32;
|
||||
ximage.bytes_per_line = cw * 4;
|
||||
ximage.bitmap_unit = 32;
|
||||
ximage.bitmap_pad = 32;
|
||||
ximage.depth = 32;
|
||||
XInitImage(&ximage);
|
||||
{
|
||||
GC gc = XCreateGC(xw.dpy, pm, 0, NULL);
|
||||
XPutImage(xw.dpy, pm, gc, &ximage, 0, 0, 0, 0, cw, ch);
|
||||
XFreeGC(xw.dpy, gc);
|
||||
}
|
||||
free(cell);
|
||||
|
||||
kitty_border(&bx, &by);
|
||||
|
||||
memset(&pa, 0, sizeof pa);
|
||||
fmt = XRenderFindStandardFormat(xw.dpy, PictStandardARGB32);
|
||||
if (!fmt)
|
||||
return;
|
||||
src = XRenderCreatePicture(xw.dpy, (Drawable)p->pixmap, fmt, 0, &pa);
|
||||
if (fmt) {
|
||||
src = XRenderCreatePicture(xw.dpy, pm, fmt, 0, &pa);
|
||||
fmt = XRenderFindVisualFormat(xw.dpy, xw.vis);
|
||||
if (fmt) {
|
||||
dstpic = XRenderCreatePicture(xw.dpy, xw.buf, fmt, 0, &pa);
|
||||
XRenderComposite(xw.dpy, PictOpOver, src, None, dstpic, sx, sy, 0, 0,
|
||||
bx + px * cw, by + py * ch, cellw, cellh);
|
||||
XRenderComposite(xw.dpy, PictOpOver, src, None, dstpic, 0, 0, 0, 0,
|
||||
bx + px * cw, by + py * ch, cw, ch);
|
||||
XRenderFreePicture(xw.dpy, dstpic);
|
||||
}
|
||||
XRenderFreePicture(xw.dpy, src);
|
||||
}
|
||||
XFreePixmap(xw.dpy, pm);
|
||||
}
|
||||
|
||||
/* scan the visible screen for placeholder glyphs and draw their images */
|
||||
|
||||
@ -61,30 +61,6 @@ clearurl(void)
|
||||
url_y2 = -1;
|
||||
}
|
||||
|
||||
#if OSC7_OSC8_PATCH
|
||||
/* an explicit OSC 8 hyperlink takes precedence over text detection */
|
||||
static char *
|
||||
detecthyperlink(int col, int row, int draw)
|
||||
{
|
||||
int x1, y1, x2, y2;
|
||||
uint32_t id = hyperlink_at(col, row, &x1, &y1, &x2, &y2);
|
||||
const char *url;
|
||||
|
||||
if (!id || !(url = hyperlink_get(id)))
|
||||
return NULL;
|
||||
if (draw) {
|
||||
url_x1 = x1;
|
||||
url_x2 = x2;
|
||||
url_y1 = y1;
|
||||
url_y2 = y2;
|
||||
url_maxcol = x2;
|
||||
url_draw = 1;
|
||||
term.dirty[y1] = 1;
|
||||
}
|
||||
return (char *)url;
|
||||
}
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
|
||||
#if REFLOW_PATCH
|
||||
char *
|
||||
detecturl(int col, int row, int draw)
|
||||
@ -96,19 +72,11 @@ detecturl(int col, int row, int draw)
|
||||
int row_start = row, col_start = col;
|
||||
int minrow = tisaltscr() ? 0 : term.scr - term.histf;
|
||||
int maxrow = tisaltscr() ? term.row - 1 : term.scr + term.row - 1;
|
||||
#if OSC7_OSC8_PATCH
|
||||
char *link;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
|
||||
/* clear previously underlined url */
|
||||
if (draw)
|
||||
clearurl();
|
||||
|
||||
#if OSC7_OSC8_PATCH
|
||||
if ((link = detecthyperlink(col, row, draw)))
|
||||
return link;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
|
||||
url_maxcol = 0;
|
||||
line = TLINE(row);
|
||||
|
||||
@ -175,9 +143,6 @@ char *
|
||||
detecturl(int col, int row, int draw)
|
||||
{
|
||||
static char url[2048];
|
||||
#if OSC7_OSC8_PATCH
|
||||
char *link;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
int x1, y1, x2, y2, wrapped;
|
||||
int row_start = row;
|
||||
int col_start = col;
|
||||
@ -197,11 +162,6 @@ detecturl(int col, int row, int draw)
|
||||
if (draw)
|
||||
clearurl();
|
||||
|
||||
#if OSC7_OSC8_PATCH
|
||||
if ((link = detecthyperlink(col, row, draw)))
|
||||
return link;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
|
||||
if (!isvalidurlchar(TLINEURL(row)[col].u))
|
||||
return NULL;
|
||||
|
||||
|
||||
@ -68,9 +68,6 @@ tclearglyph(Glyph *gp, int usecurattr)
|
||||
#if KITTY_GRAPHICS_PATCH
|
||||
gp->kitty = 0;
|
||||
#endif // KITTY_GRAPHICS_PATCH
|
||||
#if OSC7_OSC8_PATCH
|
||||
gp->link = 0;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
}
|
||||
|
||||
#if SIXEL_PATCH
|
||||
|
||||
@ -357,14 +357,6 @@
|
||||
*/
|
||||
#define KITTY_GRAPHICS_PATCH 0
|
||||
|
||||
/* This patch adds support for OSC 7 (current working directory reporting) and
|
||||
* OSC 8 (hyperlinks). Shells and programs can mark ranges of text as links to
|
||||
* arbitrary URLs; with the openurlonclick patch these become clickable and
|
||||
* take precedence over URL text detection. The working directory reported by
|
||||
* the shell is stored in term.cwd for use by e.g. new window shortcuts.
|
||||
*/
|
||||
#define OSC7_OSC8_PATCH 0
|
||||
|
||||
/* This patch adds SIXEL graphics support for st.
|
||||
* Note that patch/sixel.c/sixel_hls.c come from mintty, licensed under GPL.
|
||||
* Known issues:
|
||||
|
||||
@ -357,14 +357,6 @@
|
||||
*/
|
||||
#define KITTY_GRAPHICS_PATCH 1
|
||||
|
||||
/* This patch adds support for OSC 7 (current working directory reporting) and
|
||||
* OSC 8 (hyperlinks). Shells and programs can mark ranges of text as links to
|
||||
* arbitrary URLs; with the openurlonclick patch these become clickable and
|
||||
* take precedence over URL text detection. The working directory reported by
|
||||
* the shell is stored in term.cwd for use by e.g. new window shortcuts.
|
||||
*/
|
||||
#define OSC7_OSC8_PATCH 1
|
||||
|
||||
/* This patch adds SIXEL graphics support for st.
|
||||
* Note that patch/sixel.c/sixel_hls.c come from mintty, licensed under GPL.
|
||||
* Known issues:
|
||||
|
||||
383
st.c
383
st.c
@ -117,7 +117,6 @@ enum escape_state {
|
||||
#if SIXEL_PATCH
|
||||
ESC_DCS =128,
|
||||
#endif // SIXEL_PATCH
|
||||
ESC_DCS_IGNORE =256, /* discarding an unknown DCS until ST */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -144,7 +143,6 @@ typedef struct {
|
||||
char buf[ESC_BUF_SIZ]; /* raw string */
|
||||
size_t len; /* raw string length */
|
||||
char priv;
|
||||
char prefix; /* '>', '<' or '=' private prefix */
|
||||
int arg[ESC_ARG_SIZ];
|
||||
int narg; /* nb of args */
|
||||
char mode[2];
|
||||
@ -228,7 +226,6 @@ static void tsetdirt(int, int);
|
||||
static void tsetscroll(int, int);
|
||||
static void tswapscreen(void);
|
||||
static void tsetmode(int, int, const int *, int);
|
||||
static int tmodestatus(int, int);
|
||||
static int twrite(const char *, int, int);
|
||||
static void tcontrolcode(uchar );
|
||||
static void tdectest(char );
|
||||
@ -273,115 +270,6 @@ static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF
|
||||
|
||||
#include "patch/st_include.h"
|
||||
|
||||
#if OSC7_OSC8_PATCH
|
||||
/*
|
||||
* OSC 8 hyperlinks. Each distinct (id, url) pair gets a numeric handle that
|
||||
* is stored in Glyph.link. Links with an explicit id= parameter are shared
|
||||
* between all cells using that id, so a link split across lines still counts
|
||||
* as one link.
|
||||
*/
|
||||
typedef struct {
|
||||
char *id; /* the id= parameter, or NULL */
|
||||
char *url;
|
||||
} Hyperlink;
|
||||
|
||||
static Hyperlink *hyperlinks; /* index 0 is unused (0 == no link) */
|
||||
static uint32_t nhyperlinks, hyperlinkcap;
|
||||
static uint32_t curlink; /* link applied to newly printed cells */
|
||||
|
||||
static uint32_t
|
||||
hyperlink_add(const char *id, const char *url)
|
||||
{
|
||||
uint32_t i;
|
||||
Hyperlink *h;
|
||||
|
||||
if (!url || !*url)
|
||||
return 0;
|
||||
|
||||
/* reuse an existing entry for the same id and url */
|
||||
for (i = 1; i < nhyperlinks; i++) {
|
||||
h = &hyperlinks[i];
|
||||
if (!strcmp(h->url, url) &&
|
||||
((!id && !h->id) || (id && h->id && !strcmp(id, h->id))))
|
||||
return i;
|
||||
}
|
||||
|
||||
if (nhyperlinks + 1 > hyperlinkcap) {
|
||||
uint32_t ncap = hyperlinkcap ? hyperlinkcap * 2 : 64;
|
||||
hyperlinks = xrealloc(hyperlinks, ncap * sizeof *hyperlinks);
|
||||
if (!nhyperlinks) {
|
||||
hyperlinks[0].id = hyperlinks[0].url = NULL;
|
||||
nhyperlinks = 1;
|
||||
}
|
||||
hyperlinkcap = ncap;
|
||||
}
|
||||
h = &hyperlinks[nhyperlinks];
|
||||
h->id = (id && *id) ? xstrdup(id) : NULL;
|
||||
h->url = xstrdup(url);
|
||||
return nhyperlinks++;
|
||||
}
|
||||
|
||||
const char *
|
||||
hyperlink_get(uint32_t id)
|
||||
{
|
||||
if (id == 0 || id >= nhyperlinks)
|
||||
return NULL;
|
||||
return hyperlinks[id].url;
|
||||
}
|
||||
|
||||
/* handle "OSC 8 ; params ; url": params is a ':'-separated key=value list */
|
||||
static void
|
||||
hyperlink_osc(const char *params, const char *url)
|
||||
{
|
||||
char idbuf[256], *id = NULL;
|
||||
const char *p = params;
|
||||
|
||||
while (p && *p) {
|
||||
const char *end = strchr(p, ':');
|
||||
size_t n = end ? (size_t)(end - p) : strlen(p);
|
||||
if (n > 3 && !strncmp(p, "id=", 3)) {
|
||||
n = MIN(n - 3, sizeof idbuf - 1);
|
||||
memcpy(idbuf, p + 3, n);
|
||||
idbuf[n] = '\0';
|
||||
id = idbuf;
|
||||
}
|
||||
p = end ? end + 1 : NULL;
|
||||
}
|
||||
curlink = hyperlink_add(id, url);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the extent of the link at (col, row) on the visible screen. Returns
|
||||
* the link handle, or 0 if the cell is not part of a link. The returned
|
||||
* rectangle covers the contiguous run on this row; use hyperlink_get() for
|
||||
* the url.
|
||||
*/
|
||||
uint32_t
|
||||
hyperlink_at(int col, int row, int *x1, int *y1, int *x2, int *y2)
|
||||
{
|
||||
Line line;
|
||||
uint32_t id;
|
||||
int x;
|
||||
|
||||
if (row < 0 || row >= term.row || col < 0 || col >= term.col)
|
||||
return 0;
|
||||
#if REFLOW_PATCH || SCROLLBACK_PATCH
|
||||
line = TLINE(row);
|
||||
#else
|
||||
line = term.line[row];
|
||||
#endif
|
||||
if (!(id = line[col].link))
|
||||
return 0;
|
||||
for (x = col; x > 0 && line[x-1].link == id; x--);
|
||||
*x1 = x;
|
||||
for (x = col; x < term.col-1 && line[x+1].link == id; x++);
|
||||
*x2 = x;
|
||||
*y1 = *y2 = row;
|
||||
return id;
|
||||
}
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
|
||||
|
||||
ssize_t
|
||||
xwrite(int fd, const char *s, size_t len)
|
||||
{
|
||||
@ -909,16 +797,6 @@ execsh(char *cmd, char **args)
|
||||
unsetenv("COLUMNS");
|
||||
unsetenv("LINES");
|
||||
unsetenv("TERMCAP");
|
||||
/*
|
||||
* A new st window is never inside a multiplexer, even when st itself
|
||||
* was launched from one. Programs such as kitten icat use these to
|
||||
* decide whether to wrap escape codes for tmux, which breaks them.
|
||||
*/
|
||||
unsetenv("TMUX");
|
||||
unsetenv("TMUX_PANE");
|
||||
unsetenv("STY");
|
||||
unsetenv("ZELLIJ");
|
||||
unsetenv("ZELLIJ_SESSION_NAME");
|
||||
setenv("LOGNAME", pw->pw_name, 1);
|
||||
setenv("USER", pw->pw_name, 1);
|
||||
setenv("SHELL", sh, 1);
|
||||
@ -1326,9 +1204,6 @@ treset(void)
|
||||
term.top = 0;
|
||||
term.bot = term.row - 1;
|
||||
term.mode = MODE_WRAP|MODE_UTF8;
|
||||
#if OSC7_OSC8_PATCH
|
||||
curlink = 0;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
memset(term.trantbl, CS_USA, sizeof(term.trantbl));
|
||||
term.charset = 0;
|
||||
#if REFLOW_PATCH
|
||||
@ -1633,13 +1508,9 @@ csiparse(void)
|
||||
int sep = ';'; /* colon or semi-colon, but not both */
|
||||
|
||||
csiescseq.narg = 0;
|
||||
csiescseq.prefix = '\0';
|
||||
if (*p == '?') {
|
||||
csiescseq.priv = 1;
|
||||
p++;
|
||||
} else if (*p == '>' || *p == '<' || *p == '=') {
|
||||
csiescseq.prefix = *p;
|
||||
p++;
|
||||
}
|
||||
|
||||
csiescseq.buf[csiescseq.len] = '\0';
|
||||
@ -1739,10 +1610,6 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
|
||||
term.line[y][x].mode |= ATTR_BOXDRAW;
|
||||
#endif // BOXDRAW_PATCH
|
||||
|
||||
#if OSC7_OSC8_PATCH
|
||||
term.line[y][x].link = curlink;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
|
||||
#if KITTY_GRAPHICS_PATCH
|
||||
term.line[y][x].kitty = 0;
|
||||
if (u == KITTY_PLACEHOLDER)
|
||||
@ -2084,50 +1951,6 @@ tsetscroll(int t, int b)
|
||||
term.bot = b;
|
||||
}
|
||||
|
||||
/* DECRQM: report the state of a mode */
|
||||
static int
|
||||
tmodestatus(int priv, int mode)
|
||||
{
|
||||
int wm = win.mode;
|
||||
|
||||
if (priv) {
|
||||
switch (mode) {
|
||||
case 1: return (wm & MODE_APPCURSOR) ? 1 : 2;
|
||||
case 6: return (term.c.state & CURSOR_ORIGIN) ? 1 : 2;
|
||||
case 7: return IS_SET(MODE_WRAP) ? 1 : 2;
|
||||
case 12: return 0;
|
||||
case 25: return (wm & MODE_HIDE) ? 2 : 1;
|
||||
case 47:
|
||||
case 1047:
|
||||
case 1049: return IS_SET(MODE_ALTSCREEN) ? 1 : 2;
|
||||
case 9: return (wm & MODE_MOUSEX10) ? 1 : 2;
|
||||
case 1000: return (wm & MODE_MOUSEBTN) ? 1 : 2;
|
||||
case 1002: return (wm & MODE_MOUSEMOTION) ? 1 : 2;
|
||||
case 1003: return (wm & MODE_MOUSEMANY) ? 1 : 2;
|
||||
case 1004: return (wm & MODE_FOCUS) ? 1 : 2;
|
||||
case 1006: return (wm & MODE_MOUSESGR) ? 1 : 2;
|
||||
case 1034: return (wm & MODE_8BIT) ? 1 : 2;
|
||||
case 2004: return (wm & MODE_BRCKTPASTE) ? 1 : 2;
|
||||
#if SYNC_PATCH
|
||||
case 2026: return su ? 1 : 2;
|
||||
#endif // SYNC_PATCH
|
||||
case 2031: return 4; /* theme change notifications: not supported */
|
||||
#if SIXEL_PATCH
|
||||
case 80: return IS_SET(MODE_SIXEL_SDM) ? 1 : 2;
|
||||
case 8452: return IS_SET(MODE_SIXEL_CUR_RT) ? 1 : 2;
|
||||
#endif // SIXEL_PATCH
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
switch (mode) {
|
||||
case 2: return 4; /* KAM, always reset */
|
||||
case 4: return IS_SET(MODE_INSERT) ? 1 : 2;
|
||||
case 12: return IS_SET(MODE_ECHO) ? 2 : 1;
|
||||
case 20: return IS_SET(MODE_CRLF) ? 1 : 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
tsetmode(int priv, int set, const int *args, int narg)
|
||||
{
|
||||
@ -2186,8 +2009,6 @@ tsetmode(int priv, int set, const int *args, int narg)
|
||||
case 1004: /* 1004: send focus events to tty */
|
||||
xsetmode(set, MODE_FOCUS);
|
||||
break;
|
||||
case 7727: /* 7727: extended keys (tmux/mintty), not supported */
|
||||
break;
|
||||
case 1006: /* 1006: extended reporting mode */
|
||||
xsetmode(set, MODE_MOUSESGR);
|
||||
break;
|
||||
@ -2342,22 +2163,6 @@ csihandle(void)
|
||||
}
|
||||
break;
|
||||
case 'c': /* DA -- Device Attributes */
|
||||
if (csiescseq.prefix == '>') {
|
||||
/*
|
||||
* DA2 -- Secondary Device Attributes: CSI > Pp ; Pv ; Pc c
|
||||
* Pp = 0 (VT100 class), Pv = firmware version, Pc = 0.
|
||||
* tmux and others use this to fingerprint the terminal.
|
||||
*/
|
||||
if (csiescseq.arg[0] == 0)
|
||||
ttywrite("\033[>0;95;0c", 10, 0);
|
||||
break;
|
||||
}
|
||||
if (csiescseq.prefix == '=') {
|
||||
/* DA3 -- Tertiary Device Attributes: unit id, all zeroes */
|
||||
if (csiescseq.arg[0] == 0)
|
||||
ttywrite("\033P!|00000000\033\\", 14, 0);
|
||||
break;
|
||||
}
|
||||
if (csiescseq.arg[0] == 0)
|
||||
ttywrite(vtiden, strlen(vtiden), 0);
|
||||
break;
|
||||
@ -2664,18 +2469,6 @@ csihandle(void)
|
||||
term.c.y+1, term.c.x+1);
|
||||
ttywrite(buffer, len, 0);
|
||||
break;
|
||||
case 996: /* colour scheme (dark/light) report: CSI ? 997 ; Ps n */
|
||||
if (csiescseq.priv) {
|
||||
unsigned char r, g, b;
|
||||
int dark = 1;
|
||||
if (!xgetcolor(defaultbg, &r, &g, &b))
|
||||
dark = (299*r + 587*g + 114*b) / 1000 < 128;
|
||||
len = snprintf(buffer, sizeof(buffer), "\033[?997;%dn",
|
||||
dark ? 1 : 2);
|
||||
ttywrite(buffer, len, 0);
|
||||
break;
|
||||
}
|
||||
goto unknown;
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
@ -2742,47 +2535,9 @@ csihandle(void)
|
||||
}
|
||||
break;
|
||||
#endif // CSI_22_23_PATCH | SIXEL_PATCH
|
||||
case 'u':
|
||||
if (csiescseq.priv) {
|
||||
/* CSI ? u -- kitty keyboard protocol: query flags. We do not
|
||||
* implement the protocol, so answer with no flags set. */
|
||||
ttywrite("\033[?0u", 5, 0);
|
||||
break;
|
||||
}
|
||||
if (csiescseq.prefix == '>' || csiescseq.prefix == '<' ||
|
||||
csiescseq.prefix == '=') {
|
||||
/* CSI > flags u (push), CSI < flags u (pop), CSI = flags ; mode u
|
||||
* (set): kitty keyboard protocol, silently ignored. */
|
||||
break;
|
||||
}
|
||||
/* DECRC -- Restore cursor position (ANSI.SYS) */
|
||||
case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */
|
||||
tcursor(CURSOR_LOAD);
|
||||
break;
|
||||
case 'q':
|
||||
if (csiescseq.prefix == '>') {
|
||||
/* XTVERSION -- CSI > Ps q: report terminal name and version */
|
||||
n = snprintf(buffer, sizeof(buffer), "\033P>|st(%s)\033\\", VERSION);
|
||||
ttywrite(buffer, n, 0);
|
||||
break;
|
||||
}
|
||||
goto unknown;
|
||||
case '$':
|
||||
switch (csiescseq.mode[1]) {
|
||||
case 'p': /* DECRQM -- request mode */
|
||||
/*
|
||||
* Reply: CSI ? Pd ; Ps $ y (ANSI: CSI Pd ; Ps $ y)
|
||||
* Ps: 0 not recognized, 1 set, 2 reset,
|
||||
* 3 permanently set, 4 permanently reset
|
||||
*/
|
||||
n = snprintf(buffer, sizeof(buffer), "\033[%s%d;%d$y",
|
||||
csiescseq.priv ? "?" : "", csiescseq.arg[0],
|
||||
tmodestatus(csiescseq.priv, csiescseq.arg[0]));
|
||||
ttywrite(buffer, n, 0);
|
||||
break;
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
break;
|
||||
case ' ':
|
||||
switch (csiescseq.mode[1]) {
|
||||
case 'q': /* DECSCUSR -- Set Cursor Style */
|
||||
@ -2913,7 +2668,7 @@ strhandle(void)
|
||||
#endif // CSI_22_23_PATCH
|
||||
return;
|
||||
case 52:
|
||||
if (narg > 2 && (allowwindowops || allowclipboard)) {
|
||||
if (narg > 2 && allowwindowops) {
|
||||
dec = base64dec(strescseq.args[2]);
|
||||
if (dec) {
|
||||
xsetsel(dec);
|
||||
@ -2923,29 +2678,8 @@ strhandle(void)
|
||||
}
|
||||
}
|
||||
return;
|
||||
#if OSC7_OSC8_PATCH
|
||||
case 7: /* current working directory: file://host/path */
|
||||
if (narg > 1) {
|
||||
p = strescseq.args[1];
|
||||
if (!strncmp(p, "file://", 7)) {
|
||||
/* skip the host part */
|
||||
p += 7;
|
||||
p = strchr(p, '/');
|
||||
}
|
||||
free(term.cwd);
|
||||
term.cwd = (p && *p == '/') ? xstrdup(p) : NULL;
|
||||
}
|
||||
return;
|
||||
case 8: /* hyperlink: OSC 8 ; params ; url */
|
||||
if (narg > 2 && strescseq.args[2][0])
|
||||
hyperlink_osc(strescseq.args[1], strescseq.args[2]);
|
||||
else
|
||||
curlink = 0;
|
||||
return;
|
||||
#else
|
||||
case 8: /* Clear Hyperlinks */
|
||||
return;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
@ -3411,13 +3145,9 @@ dcshandle(void)
|
||||
switch (csiescseq.mode[0]) {
|
||||
default:
|
||||
unknown:
|
||||
/*
|
||||
* An unknown DCS, e.g. the "DCS tmux;" passthrough wrapper or
|
||||
* XTGETTCAP. Its body must not be interpreted, so discard every
|
||||
* byte until the terminating ST. Note the body may contain ESC ESC
|
||||
* (tmux doubles them), which must not end the string.
|
||||
*/
|
||||
term.esc |= ESC_DCS_IGNORE;
|
||||
fprintf(stderr, "erresc: unknown csi ");
|
||||
csidump();
|
||||
/* die(""); */
|
||||
break;
|
||||
#if SYNC_PATCH
|
||||
case '=':
|
||||
@ -3587,23 +3317,6 @@ tputc(Rune u)
|
||||
* receives a ESC, a SUB, a ST or any other C1 control
|
||||
* character.
|
||||
*/
|
||||
if (term.esc & ESC_DCS_IGNORE) {
|
||||
static int sawesc;
|
||||
if (sawesc) {
|
||||
sawesc = 0;
|
||||
if (u == '\\') {
|
||||
term.esc = 0;
|
||||
return;
|
||||
}
|
||||
/* ESC ESC or ESC <other>: still inside the payload */
|
||||
if (u != 033)
|
||||
return;
|
||||
}
|
||||
if (u == 033)
|
||||
sawesc = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (term.esc & ESC_STR) {
|
||||
if (u == '\a' || u == 030 || u == 032 || u == 033 ||
|
||||
ISCONTROLC1(u)) {
|
||||
@ -3770,84 +3483,6 @@ check_control_code:
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a run of plain printable ASCII characters using the current cursor
|
||||
* attributes, writing whole cells directly into the current line. Returns the
|
||||
* number of bytes consumed, or 0 when the fast path does not apply and the
|
||||
* caller must fall back to tputc().
|
||||
*/
|
||||
static int
|
||||
tputcrun(const char *buf, int buflen)
|
||||
{
|
||||
Glyph attr = term.c.attr;
|
||||
Glyph *gp;
|
||||
int i, run, avail;
|
||||
|
||||
/* Only handle the simple, overwhelmingly common case. */
|
||||
if (term.esc || (term.mode & (MODE_PRINT|MODE_INSERT|MODE_SIXEL)) ||
|
||||
term.trantbl[term.charset] == CS_GRAPHIC0 ||
|
||||
(term.c.state & CURSOR_WRAPNEXT) ||
|
||||
sel.mode != SEL_IDLE || sel.ob.x != -1)
|
||||
return 0;
|
||||
|
||||
avail = term.col - term.c.x;
|
||||
if (avail <= 0)
|
||||
return 0;
|
||||
|
||||
/* Count leading printable ASCII bytes, bounded by the line width. */
|
||||
for (run = 0; run < buflen && run < avail; run++) {
|
||||
unsigned char c = (unsigned char)buf[run];
|
||||
if (c < 0x20 || c >= 0x7f)
|
||||
break;
|
||||
}
|
||||
if (run < 2)
|
||||
return 0; /* not worth it; keep tputc's semantics */
|
||||
|
||||
attr.mode |= ATTR_SET;
|
||||
attr.mode &= ~(ATTR_WIDE|ATTR_WDUMMY|ATTR_BOXDRAW|ATTR_KITTYPH);
|
||||
#if OSC7_OSC8_PATCH
|
||||
attr.link = curlink;
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
#if KITTY_GRAPHICS_PATCH
|
||||
attr.kitty = 0;
|
||||
#endif // KITTY_GRAPHICS_PATCH
|
||||
|
||||
gp = &term.line[term.c.y][term.c.x];
|
||||
|
||||
/* A wide glyph may straddle the start of the run. */
|
||||
if (gp->mode & ATTR_WDUMMY) {
|
||||
if (term.c.x == 0)
|
||||
return 0;
|
||||
gp[-1].u = ' ';
|
||||
gp[-1].mode &= ~ATTR_WIDE;
|
||||
}
|
||||
/* ...or the end of it. */
|
||||
if (run < avail && (gp[run].mode & ATTR_WDUMMY)) {
|
||||
gp[run].u = ' ';
|
||||
gp[run].mode &= ~ATTR_WDUMMY;
|
||||
}
|
||||
|
||||
for (i = 0; i < run; i++) {
|
||||
gp[i] = attr;
|
||||
gp[i].u = (unsigned char)buf[i];
|
||||
}
|
||||
|
||||
term.dirty[term.c.y] = 1;
|
||||
term.lastc = (unsigned char)buf[run-1];
|
||||
|
||||
if (term.c.x + run < term.col) {
|
||||
term.c.x += run;
|
||||
} else {
|
||||
term.c.x = term.col - 1;
|
||||
#if REFLOW_PATCH
|
||||
term.wrapcwidth[IS_SET(MODE_ALTSCREEN)] = 1;
|
||||
#endif // REFLOW_PATCH
|
||||
term.c.state |= CURSOR_WRAPNEXT;
|
||||
}
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
int
|
||||
twrite(const char *buf, int buflen, int show_ctrl)
|
||||
{
|
||||
@ -3861,14 +3496,6 @@ twrite(const char *buf, int buflen, int show_ctrl)
|
||||
#endif // SYNC_PATCH
|
||||
|
||||
for (n = 0; n < buflen; n += charsize) {
|
||||
/*
|
||||
* Fast path: a run of plain printable ASCII printed with the
|
||||
* current attributes onto the current line. This skips the
|
||||
* per-character tputc/tsetchar dispatch, which dominates the
|
||||
* profile while streaming large amounts of text.
|
||||
*/
|
||||
if (!show_ctrl && (charsize = tputcrun(buf + n, buflen - n)) > 0)
|
||||
continue;
|
||||
#if SIXEL_PATCH
|
||||
if (IS_SET(MODE_SIXEL) && sixel_st.state != PS_ESC) {
|
||||
charsize = sixel_parser_parse(&sixel_st, (const unsigned char*)buf + n, buflen - n);
|
||||
|
||||
12
st.h
12
st.h
@ -150,9 +150,6 @@ typedef struct {
|
||||
#if KITTY_GRAPHICS_PATCH
|
||||
uint32_t kitty; /* kitty Unicode placeholder row/column/msb */
|
||||
#endif // KITTY_GRAPHICS_PATCH
|
||||
#if OSC7_OSC8_PATCH
|
||||
uint32_t link; /* OSC 8 hyperlink id, 0 == none */
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
} Glyph;
|
||||
|
||||
typedef Glyph *Line;
|
||||
@ -211,9 +208,6 @@ typedef struct {
|
||||
ImageList *images_alt; /* sixel images for alternate screen */
|
||||
#endif // SIXEL_PATCH
|
||||
Rune lastc; /* last printed char outside of sequence, 0 if control */
|
||||
#if OSC7_OSC8_PATCH
|
||||
char *cwd; /* working directory reported via OSC 7, or NULL */
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
} Term;
|
||||
|
||||
typedef union {
|
||||
@ -382,11 +376,6 @@ char *getsel(void);
|
||||
|
||||
size_t utf8encode(Rune, char *);
|
||||
|
||||
#if OSC7_OSC8_PATCH
|
||||
const char *hyperlink_get(uint32_t id);
|
||||
uint32_t hyperlink_at(int col, int row, int *x1, int *y1, int *x2, int *y2);
|
||||
#endif // OSC7_OSC8_PATCH
|
||||
|
||||
void *xmalloc(size_t);
|
||||
void *xrealloc(void *, size_t);
|
||||
char *xstrdup(const char *);
|
||||
@ -415,7 +404,6 @@ extern wchar_t *kbds_ldelim;
|
||||
#endif // KEYBOARDSELECT_PATCH
|
||||
extern int allowaltscreen;
|
||||
extern int allowwindowops;
|
||||
extern int allowclipboard;
|
||||
extern char *termname;
|
||||
extern unsigned int tabspaces;
|
||||
extern unsigned int defaultfg;
|
||||
|
||||
9
st.info
9
st.info
@ -199,20 +199,11 @@ st-mono| simpleterm monocolor,
|
||||
# rep=%p1%c\E[%p2%{1}%-%db,
|
||||
# tmux extensions, see TERMINFO EXTENSIONS in tmux(1)
|
||||
Tc,
|
||||
RGB,
|
||||
Ms=\E]52;%p1%s;%p2%s\007,
|
||||
Se=\E[2 q,
|
||||
Ss=\E[%p1%d q,
|
||||
# sync patch / SYNC_PATCH
|
||||
Sync=\EP=%p1%ds\E\\,
|
||||
# undercurl patch / UNDERCURL_PATCH: styled and coloured underlines
|
||||
Smulx=\E[4:%p1%dm,
|
||||
Setulc=\E[58:2::%p1%{65536}%/%d:%p1%{256}%/%{255}%&%d:%p1%{255}%&%dm,
|
||||
# focus events (mode 1004), used by tmux focus-events
|
||||
kxIN=\E[I,
|
||||
kxOUT=\E[O,
|
||||
# hyperlinks / OSC7_OSC8_PATCH
|
||||
Hls=\E]8;id=%p1%s;%p2%s\E\\,
|
||||
|
||||
st| simpleterm,
|
||||
use=st-mono,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user