MODE_FOCUS = 65536,
MODE_MOUSEX10 = 131072,
MODE_MOUSEMANY = 262144,
+ MODE_BRCKTPASTE = 524288,
MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
|MODE_MOUSEMANY,
};
+enum charset {
+ CS_GRAPHIC0,
+ CS_GRAPHIC1,
+ CS_UK,
+ CS_USA,
+ CS_MULTI,
+ CS_GER,
+ CS_FIN
+};
+
enum escape_state {
ESC_START = 1,
ESC_CSI = 2,
int bot; /* bottom scroll limit */
int mode; /* terminal mode flags */
int esc; /* escape state flags */
+ char trantbl[4]; /* charset table translation */
+ int charset; /* current charset */
+ int icharset; /* selected charset for sequence */
bool numlock; /* lock numbers in keyboard */
bool *tabs;
} Term;
} XWindow;
typedef struct {
- int b;
+ uint b;
uint mask;
- char s[ESC_BUF_SIZ];
+ char *s;
} Mousekey;
typedef struct {
KeySym k;
uint mask;
- char s[ESC_BUF_SIZ];
+ char *s;
/* three valued logic variables: 0 indifferent, 1 on, -1 off */
signed char appkey; /* application keypad */
signed char appcursor; /* application cursor */
static void tfulldirt(void);
static void techo(char *, int);
static long tdefcolor(int *, int *, int);
+static void tselcs(void);
+static void tdeftran(char);
static inline bool match(uint, uint);
static void ttynew(void);
static void ttyread(void);
static void ttyresize(void);
+static void ttysend(char *, size_t);
static void ttywrite(const char *, size_t);
static void xdraws(char *, Glyph, int, int, int, int);
button = oldbutton + 32;
ox = x;
oy = y;
- } else if(!IS_SET(MODE_MOUSESGR)
- && (e->xbutton.type == ButtonRelease
- || button == AnyButton)) {
- button = 3;
} else {
- button -= Button1;
- if(button >= 3)
- button += 64 - 3;
+ if(!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) {
+ button = 3;
+ } else {
+ button -= Button1;
+ if(button >= 3)
+ button += 64 - 3;
+ }
if(e->xbutton.type == ButtonPress) {
oldbutton = button;
ox = x;
oy = y;
+ } else if(e->xbutton.type == ButtonRelease) {
+ oldbutton = 3;
+ /* MODE_MOUSEX10: no button release reporting */
+ if(IS_SET(MODE_MOUSEX10))
+ return;
}
}
e->xbutton.type == ButtonRelease ? 'm' : 'M');
} else if(x < 223 && y < 223) {
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
- IS_SET(MODE_MOUSEX10)? button-1 : 32+button,
- 32+x+1, 32+y+1);
+ 32+button, 32+x+1, 32+y+1);
} else {
return;
}
for(mk = mshortcuts; mk < mshortcuts + LEN(mshortcuts); mk++) {
if(e->xbutton.button == mk->b
&& match(mk->mask, e->xbutton.state)) {
- ttywrite(mk->s, strlen(mk->s));
- if(IS_SET(MODE_ECHO))
- techo(mk->s, strlen(mk->s));
+ ttysend(mk->s, strlen(mk->s));
return;
}
}
* st.
* FIXME: Fix the computer world.
*/
- if(y < sel.ne.y && !((gp-1)->mode & ATTR_WRAP))
+ if(y < sel.ne.y && x > 0 && !((gp-1)->mode & ATTR_WRAP))
*ptr++ = '\n';
/*
*repl++ = '\r';
}
- ttywrite((const char *)data, nitems * format / 8);
+ if(IS_SET(MODE_BRCKTPASTE))
+ ttywrite("\033[200~", 6);
+ ttysend((char *)data, nitems * format / 8);
+ if(IS_SET(MODE_BRCKTPASTE))
+ ttywrite("\033[201~", 6);
XFree(data);
/* number of 32-bit chunks returned */
ofs += nitems * format / 32;
die("write error on tty: %s\n", SERRNO);
}
+void
+ttysend(char *s, size_t n) {
+ ttywrite(s, n);
+ if(IS_SET(MODE_ECHO))
+ techo(s, n);
+}
+
void
ttyresize(void) {
struct winsize w;
void
tcursor(int mode) {
- static TCursor c;
+ static TCursor c[2];
+ bool alt = IS_SET(MODE_ALTSCREEN);
if(mode == CURSOR_SAVE) {
- c = term.c;
+ c[alt] = term.c;
} else if(mode == CURSOR_LOAD) {
- term.c = c;
- tmoveto(c.x, c.y);
+ term.c = c[alt];
+ tmoveto(c[alt].x, c[alt].y);
}
}
term.top = 0;
term.bot = term.row - 1;
term.mode = MODE_WRAP;
+ memset(term.trantbl, sizeof(term.trantbl), CS_USA);
+ term.charset = 0;
tclearregion(0, 0, term.col-1, term.row-1);
tmoveto(0, 0);
case 1034:
MODBIT(term.mode, set, MODE_8BIT);
break;
- case 1049: /* = 1047 and 1048 */
- case 47:
+ case 1049: /* swap screen & set/restore cursor as xterm */
+ tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD);
+ case 47: /* swap screen */
case 1047:
if (!allowaltscreen)
break;
-
alt = IS_SET(MODE_ALTSCREEN);
if(alt) {
tclearregion(0, 0, term.col-1,
case 1048:
tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD);
break;
+ case 2004: /* 2004: bracketed paste mode */
+ MODBIT(term.mode, set, MODE_BRCKTPASTE);
+ break;
/* Not implemented mouse modes. See comments there. */
case 1001: /* mouse highlight mode; can hang the
terminal by design when implemented. */
void
csihandle(void) {
+ char buf[40];
+ int len;
+
switch(csiescseq.mode) {
default:
unknown:
case 'm': /* SGR -- Terminal attribute (color) */
tsetattr(csiescseq.arg, csiescseq.narg);
break;
+ case 'n': /* DSR – Device Status Report (cursor position) */
+ if (csiescseq.arg[0] == 6) {
+ len = snprintf(buf, sizeof(buf),"\033[%i;%iR",
+ term.c.y+1, term.c.x+1);
+ ttywrite(buf, len);
+ break;
+ }
case 'r': /* DECSTBM -- Set Scrolling Region */
if(csiescseq.priv) {
goto unknown;
tputc(buf, len);
}
+void
+tdeftran(char ascii) {
+ char c, (*bp)[2];
+ static char tbl[][2] = {
+ {'0', CS_GRAPHIC0}, {'1', CS_GRAPHIC1}, {'A', CS_UK},
+ {'B', CS_USA}, {'<', CS_MULTI}, {'K', CS_GER},
+ {'5', CS_FIN}, {'C', CS_FIN},
+ {0, 0}
+ };
+
+ for (bp = &tbl[0]; (c = (*bp)[0]) && c != ascii; ++bp)
+ /* nothing */;
+
+ if (c == 0)
+ fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
+ else
+ term.trantbl[term.icharset] = (*bp)[1];
+}
+
+void
+tselcs(void) {
+ if (term.trantbl[term.charset] == CS_GRAPHIC0)
+ term.c.attr.mode |= ATTR_GFX;
+ else
+ term.c.attr.mode &= ~ATTR_GFX;
+}
+
void
tputc(char *c, int len) {
uchar ascii = *c;
case '\a': /* BEL */
if(!(xw.state & WIN_FOCUSED))
xseturgency(1);
+ if (bellvolume)
+ XBell(xw.dpy, bellvolume);
return;
case '\033': /* ESC */
csireset();
term.esc = ESC_START;
return;
case '\016': /* SO */
+ term.charset = 0;
+ tselcs();
+ return;
case '\017': /* SI */
- /*
- * Different charsets are hard to handle. Applications
- * should use the right alt charset escapes for the
- * only reason they still exist: line drawing. The
- * rest is incompatible history st should not support.
- */
+ term.charset = 1;
+ tselcs();
return;
case '\032': /* SUB */
case '\030': /* CAN */
if(ascii == '\\')
strhandle();
} else if(term.esc & ESC_ALTCHARSET) {
- switch(ascii) {
- case '0': /* Line drawing set */
- term.c.attr.mode |= ATTR_GFX;
- break;
- case 'B': /* USASCII */
- term.c.attr.mode &= ~ATTR_GFX;
- break;
- case 'A': /* UK (IGNORED) */
- case '<': /* multinational charset (IGNORED) */
- case '5': /* Finnish (IGNORED) */
- case 'C': /* Finnish (IGNORED) */
- case 'K': /* German (IGNORED) */
- break;
- default:
- fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
- }
+ tdeftran(ascii);
+ tselcs();
term.esc = 0;
} else if(term.esc & ESC_TEST) {
if(ascii == '8') { /* DEC screen alignment test. */
term.esc |= ESC_STR;
break;
case '(': /* set primary charset G0 */
+ case ')': /* set secondary charset G1 */
+ case '*': /* set tertiary charset G2 */
+ case '+': /* set quaternary charset G3 */
+ term.icharset = ascii - '(';
term.esc |= ESC_ALTCHARSET;
break;
- case ')': /* set secondary charset G1 (IGNORED) */
- case '*': /* set tertiary charset G2 (IGNORED) */
- case '+': /* set quaternary charset G3 (IGNORED) */
- term.esc = 0;
- break;
case 'D': /* IND -- Linefeed */
if(term.c.y == term.bot) {
tscrollup(term.top, 1);
kpress(XEvent *ev) {
XKeyEvent *e = &ev->xkey;
KeySym ksym;
- char xstr[31], buf[32], *customkey, *cp = buf;
- int len, ret;
+ char buf[32], *customkey;
+ int len;
long c;
Status status;
Shortcut *bp;
if(IS_SET(MODE_KBDLOCK))
return;
- len = XmbLookupString(xw.xic, e, xstr, sizeof(xstr), &ksym, &status);
+ len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status);
e->state &= ~Mod2Mask;
/* 1. shortcuts */
for(bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
/* 2. custom keys from config.h */
if((customkey = kmap(ksym, e->state))) {
- len = strlen(customkey);
- memcpy(buf, customkey, len);
- /* 3. hardcoded (overrides X lookup) */
- } else {
- if(len == 0)
- return;
+ ttysend(customkey, strlen(customkey));
+ return;
+ }
- if(len == 1 && e->state & Mod1Mask) {
- if(IS_SET(MODE_8BIT)) {
- if(*xstr < 0177) {
- c = *xstr | 0x80;
- ret = utf8encode(&c, cp);
- cp += ret;
- len = 0;
- }
- } else {
- *cp++ = '\033';
+ /* 3. composed string from input method */
+ if(len == 0)
+ return;
+ if(len == 1 && e->state & Mod1Mask) {
+ if(IS_SET(MODE_8BIT)) {
+ if(*buf < 0177) {
+ c = *buf | 0x80;
+ len = utf8encode(&c, buf);
}
+ } else {
+ buf[1] = buf[0];
+ buf[0] = '\033';
+ len = 2;
}
-
- memcpy(cp, xstr, len);
- len = cp - buf + len;
}
-
- ttywrite(buf, len);
- if(IS_SET(MODE_ECHO))
- techo(buf, len);
+ ttysend(buf, len);
}