|
@ -43,9 +43,10 @@ |
|
|
#define XEMBED_FOCUS_OUT 5 |
|
|
#define XEMBED_FOCUS_OUT 5 |
|
|
|
|
|
|
|
|
/* Arbitrary sizes */ |
|
|
/* Arbitrary sizes */ |
|
|
#define ESC_TITLE_SIZ 256 |
|
|
|
|
|
#define ESC_BUF_SIZ 256 |
|
|
#define ESC_BUF_SIZ 256 |
|
|
#define ESC_ARG_SIZ 16 |
|
|
#define ESC_ARG_SIZ 16 |
|
|
|
|
|
#define STR_BUF_SIZ 256 |
|
|
|
|
|
#define STR_ARG_SIZ 16 |
|
|
#define DRAW_BUF_SIZ 1024 |
|
|
#define DRAW_BUF_SIZ 1024 |
|
|
#define UTF_SIZ 4 |
|
|
#define UTF_SIZ 4 |
|
|
#define XK_NO_MOD UINT_MAX |
|
|
#define XK_NO_MOD UINT_MAX |
|
@ -110,9 +111,9 @@ enum term_mode { |
|
|
enum escape_state { |
|
|
enum escape_state { |
|
|
ESC_START = 1, |
|
|
ESC_START = 1, |
|
|
ESC_CSI = 2, |
|
|
ESC_CSI = 2, |
|
|
ESC_OSC = 4, |
|
|
|
|
|
ESC_TITLE = 8, |
|
|
|
|
|
ESC_ALTCHARSET = 16 |
|
|
|
|
|
|
|
|
ESC_STR = 4, /* DSC, OSC, PM, APC */ |
|
|
|
|
|
ESC_ALTCHARSET = 8, |
|
|
|
|
|
ESC_STR_END = 16, /* a final string was encountered */ |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
enum window_state { |
|
|
enum window_state { |
|
@ -158,6 +159,16 @@ typedef struct { |
|
|
char mode; |
|
|
char mode; |
|
|
} CSIEscape; |
|
|
} CSIEscape; |
|
|
|
|
|
|
|
|
|
|
|
/* STR Escape sequence structs */ |
|
|
|
|
|
/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */ |
|
|
|
|
|
typedef struct { |
|
|
|
|
|
char type; /* ESC type ... */ |
|
|
|
|
|
char buf[STR_BUF_SIZ]; /* raw string */ |
|
|
|
|
|
int len; /* raw string length */ |
|
|
|
|
|
char *args[STR_ARG_SIZ]; |
|
|
|
|
|
int narg; /* nb of args */ |
|
|
|
|
|
} STREscape; |
|
|
|
|
|
|
|
|
/* Internal representation of the screen */ |
|
|
/* Internal representation of the screen */ |
|
|
typedef struct { |
|
|
typedef struct { |
|
|
int row; /* nb row */ |
|
|
int row; /* nb row */ |
|
@ -170,8 +181,6 @@ typedef struct { |
|
|
int bot; /* bottom scroll limit */ |
|
|
int bot; /* bottom scroll limit */ |
|
|
int mode; /* terminal mode flags */ |
|
|
int mode; /* terminal mode flags */ |
|
|
int esc; /* escape state flags */ |
|
|
int esc; /* escape state flags */ |
|
|
char title[ESC_TITLE_SIZ]; |
|
|
|
|
|
int titlelen; |
|
|
|
|
|
bool *tabs; |
|
|
bool *tabs; |
|
|
} Term; |
|
|
} Term; |
|
|
|
|
|
|
|
@ -239,6 +248,10 @@ static void csidump(void); |
|
|
static void csihandle(void); |
|
|
static void csihandle(void); |
|
|
static void csiparse(void); |
|
|
static void csiparse(void); |
|
|
static void csireset(void); |
|
|
static void csireset(void); |
|
|
|
|
|
static void strdump(void); |
|
|
|
|
|
static void strhandle(void); |
|
|
|
|
|
static void strparse(void); |
|
|
|
|
|
static void strreset(void); |
|
|
|
|
|
|
|
|
static void tclearregion(int, int, int, int); |
|
|
static void tclearregion(int, int, int, int); |
|
|
static void tcursor(int); |
|
|
static void tcursor(int); |
|
@ -323,7 +336,8 @@ static void (*handler[LASTEvent])(XEvent *) = { |
|
|
static DC dc; |
|
|
static DC dc; |
|
|
static XWindow xw; |
|
|
static XWindow xw; |
|
|
static Term term; |
|
|
static Term term; |
|
|
static CSIEscape escseq; |
|
|
|
|
|
|
|
|
static CSIEscape csiescseq; |
|
|
|
|
|
static STREscape strescseq; |
|
|
static int cmdfd; |
|
|
static int cmdfd; |
|
|
static pid_t pid; |
|
|
static pid_t pid; |
|
|
static Selection sel; |
|
|
static Selection sel; |
|
@ -968,22 +982,22 @@ tnewline(int first_col) { |
|
|
void |
|
|
void |
|
|
csiparse(void) { |
|
|
csiparse(void) { |
|
|
/* int noarg = 1; */ |
|
|
/* int noarg = 1; */ |
|
|
char *p = escseq.buf; |
|
|
|
|
|
|
|
|
char *p = csiescseq.buf; |
|
|
|
|
|
|
|
|
escseq.narg = 0; |
|
|
|
|
|
|
|
|
csiescseq.narg = 0; |
|
|
if(*p == '?') |
|
|
if(*p == '?') |
|
|
escseq.priv = 1, p++; |
|
|
|
|
|
|
|
|
csiescseq.priv = 1, p++; |
|
|
|
|
|
|
|
|
while(p < escseq.buf+escseq.len) { |
|
|
|
|
|
|
|
|
while(p < csiescseq.buf+csiescseq.len) { |
|
|
while(isdigit(*p)) { |
|
|
while(isdigit(*p)) { |
|
|
escseq.arg[escseq.narg] *= 10; |
|
|
|
|
|
escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */; |
|
|
|
|
|
|
|
|
csiescseq.arg[csiescseq.narg] *= 10; |
|
|
|
|
|
csiescseq.arg[csiescseq.narg] += *p++ - '0'/*, noarg = 0 */; |
|
|
} |
|
|
} |
|
|
if(*p == ';' && escseq.narg+1 < ESC_ARG_SIZ) |
|
|
|
|
|
escseq.narg++, p++; |
|
|
|
|
|
|
|
|
if(*p == ';' && csiescseq.narg+1 < ESC_ARG_SIZ) |
|
|
|
|
|
csiescseq.narg++, p++; |
|
|
else { |
|
|
else { |
|
|
escseq.mode = *p; |
|
|
|
|
|
escseq.narg++; |
|
|
|
|
|
|
|
|
csiescseq.mode = *p; |
|
|
|
|
|
csiescseq.narg++; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -1166,7 +1180,7 @@ tsetscroll(int t, int b) { |
|
|
|
|
|
|
|
|
void |
|
|
void |
|
|
csihandle(void) { |
|
|
csihandle(void) { |
|
|
switch(escseq.mode) { |
|
|
|
|
|
|
|
|
switch(csiescseq.mode) { |
|
|
default: |
|
|
default: |
|
|
unknown: |
|
|
unknown: |
|
|
fprintf(stderr, "erresc: unknown csi "); |
|
|
fprintf(stderr, "erresc: unknown csi "); |
|
@ -1174,37 +1188,37 @@ csihandle(void) { |
|
|
/* die(""); */ |
|
|
/* die(""); */ |
|
|
break; |
|
|
break; |
|
|
case '@': /* ICH -- Insert <n> blank char */ |
|
|
case '@': /* ICH -- Insert <n> blank char */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tinsertblank(escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tinsertblank(csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'A': /* CUU -- Cursor <n> Up */ |
|
|
case 'A': /* CUU -- Cursor <n> Up */ |
|
|
case 'e': |
|
|
case 'e': |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x, term.c.y-escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'B': /* CUD -- Cursor <n> Down */ |
|
|
case 'B': /* CUD -- Cursor <n> Down */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x, term.c.y+escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'C': /* CUF -- Cursor <n> Forward */ |
|
|
case 'C': /* CUF -- Cursor <n> Forward */ |
|
|
case 'a': |
|
|
case 'a': |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x+escseq.arg[0], term.c.y); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x+csiescseq.arg[0], term.c.y); |
|
|
break; |
|
|
break; |
|
|
case 'D': /* CUB -- Cursor <n> Backward */ |
|
|
case 'D': /* CUB -- Cursor <n> Backward */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x-escseq.arg[0], term.c.y); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x-csiescseq.arg[0], term.c.y); |
|
|
break; |
|
|
break; |
|
|
case 'E': /* CNL -- Cursor <n> Down and first col */ |
|
|
case 'E': /* CNL -- Cursor <n> Down and first col */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(0, term.c.y+escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(0, term.c.y+csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'F': /* CPL -- Cursor <n> Up and first col */ |
|
|
case 'F': /* CPL -- Cursor <n> Up and first col */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(0, term.c.y-escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(0, term.c.y-csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'g': /* TBC -- Tabulation clear */ |
|
|
case 'g': /* TBC -- Tabulation clear */ |
|
|
switch (escseq.arg[0]) { |
|
|
|
|
|
|
|
|
switch (csiescseq.arg[0]) { |
|
|
case 0: /* clear current tab stop */ |
|
|
case 0: /* clear current tab stop */ |
|
|
term.tabs[term.c.x] = 0; |
|
|
term.tabs[term.c.x] = 0; |
|
|
break; |
|
|
break; |
|
@ -1217,23 +1231,23 @@ csihandle(void) { |
|
|
break; |
|
|
break; |
|
|
case 'G': /* CHA -- Move to <col> */ |
|
|
case 'G': /* CHA -- Move to <col> */ |
|
|
case '`': /* XXX: HPA -- same? */ |
|
|
case '`': /* XXX: HPA -- same? */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(escseq.arg[0]-1, term.c.y); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(csiescseq.arg[0]-1, term.c.y); |
|
|
break; |
|
|
break; |
|
|
case 'H': /* CUP -- Move to <row> <col> */ |
|
|
case 'H': /* CUP -- Move to <row> <col> */ |
|
|
case 'f': /* XXX: HVP -- same? */ |
|
|
case 'f': /* XXX: HVP -- same? */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
DEFAULT(escseq.arg[1], 1); |
|
|
|
|
|
tmoveto(escseq.arg[1]-1, escseq.arg[0]-1); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
DEFAULT(csiescseq.arg[1], 1); |
|
|
|
|
|
tmoveto(csiescseq.arg[1]-1, csiescseq.arg[0]-1); |
|
|
break; |
|
|
break; |
|
|
case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */ |
|
|
case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
while (escseq.arg[0]--) |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
while (csiescseq.arg[0]--) |
|
|
tputtab(); |
|
|
tputtab(); |
|
|
break; |
|
|
break; |
|
|
case 'J': /* ED -- Clear screen */ |
|
|
case 'J': /* ED -- Clear screen */ |
|
|
sel.bx = -1; |
|
|
sel.bx = -1; |
|
|
switch(escseq.arg[0]) { |
|
|
|
|
|
|
|
|
switch(csiescseq.arg[0]) { |
|
|
case 0: /* below */ |
|
|
case 0: /* below */ |
|
|
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); |
|
|
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); |
|
|
if(term.c.y < term.row-1) |
|
|
if(term.c.y < term.row-1) |
|
@ -1252,7 +1266,7 @@ csihandle(void) { |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
case 'K': /* EL -- Clear line */ |
|
|
case 'K': /* EL -- Clear line */ |
|
|
switch(escseq.arg[0]) { |
|
|
|
|
|
|
|
|
switch(csiescseq.arg[0]) { |
|
|
case 0: /* right */ |
|
|
case 0: /* right */ |
|
|
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); |
|
|
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); |
|
|
break; |
|
|
break; |
|
@ -1265,20 +1279,20 @@ csihandle(void) { |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
case 'S': /* SU -- Scroll <n> line up */ |
|
|
case 'S': /* SU -- Scroll <n> line up */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tscrollup(term.top, escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tscrollup(term.top, csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'T': /* SD -- Scroll <n> line down */ |
|
|
case 'T': /* SD -- Scroll <n> line down */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tscrolldown(term.top, escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tscrolldown(term.top, csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'L': /* IL -- Insert <n> blank lines */ |
|
|
case 'L': /* IL -- Insert <n> blank lines */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tinsertblankline(escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tinsertblankline(csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'l': /* RM -- Reset Mode */ |
|
|
case 'l': /* RM -- Reset Mode */ |
|
|
if(escseq.priv) { |
|
|
|
|
|
switch(escseq.arg[0]) { |
|
|
|
|
|
|
|
|
if(csiescseq.priv) { |
|
|
|
|
|
switch(csiescseq.arg[0]) { |
|
|
case 1: |
|
|
case 1: |
|
|
term.mode &= ~MODE_APPKEYPAD; |
|
|
term.mode &= ~MODE_APPKEYPAD; |
|
|
break; |
|
|
break; |
|
@ -1312,7 +1326,7 @@ csihandle(void) { |
|
|
tclearregion(0, 0, term.col-1, term.row-1); |
|
|
tclearregion(0, 0, term.col-1, term.row-1); |
|
|
tswapscreen(); |
|
|
tswapscreen(); |
|
|
} |
|
|
} |
|
|
if(escseq.arg[0] != 1049) |
|
|
|
|
|
|
|
|
if(csiescseq.arg[0] != 1049) |
|
|
break; |
|
|
break; |
|
|
case 1048: |
|
|
case 1048: |
|
|
tcursor(CURSOR_LOAD); |
|
|
tcursor(CURSOR_LOAD); |
|
@ -1321,7 +1335,7 @@ csihandle(void) { |
|
|
goto unknown; |
|
|
goto unknown; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
switch(escseq.arg[0]) { |
|
|
|
|
|
|
|
|
switch(csiescseq.arg[0]) { |
|
|
case 4: |
|
|
case 4: |
|
|
term.mode &= ~MODE_INSERT; |
|
|
term.mode &= ~MODE_INSERT; |
|
|
break; |
|
|
break; |
|
@ -1331,25 +1345,25 @@ csihandle(void) { |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
case 'M': /* DL -- Delete <n> lines */ |
|
|
case 'M': /* DL -- Delete <n> lines */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tdeleteline(escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tdeleteline(csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
case 'X': /* ECH -- Erase <n> char */ |
|
|
case 'X': /* ECH -- Erase <n> char */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tclearregion(term.c.x, term.c.y, term.c.x + escseq.arg[0], term.c.y); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0], term.c.y); |
|
|
break; |
|
|
break; |
|
|
case 'P': /* DCH -- Delete <n> char */ |
|
|
case 'P': /* DCH -- Delete <n> char */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tdeletechar(escseq.arg[0]); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tdeletechar(csiescseq.arg[0]); |
|
|
break; |
|
|
break; |
|
|
/* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation <n> tab stops */ |
|
|
/* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation <n> tab stops */ |
|
|
case 'd': /* VPA -- Move to <row> */ |
|
|
case 'd': /* VPA -- Move to <row> */ |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x, escseq.arg[0]-1); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
tmoveto(term.c.x, csiescseq.arg[0]-1); |
|
|
break; |
|
|
break; |
|
|
case 'h': /* SM -- Set terminal mode */ |
|
|
case 'h': /* SM -- Set terminal mode */ |
|
|
if(escseq.priv) { |
|
|
|
|
|
switch(escseq.arg[0]) { |
|
|
|
|
|
|
|
|
if(csiescseq.priv) { |
|
|
|
|
|
switch(csiescseq.arg[0]) { |
|
|
case 1: |
|
|
case 1: |
|
|
term.mode |= MODE_APPKEYPAD; |
|
|
term.mode |= MODE_APPKEYPAD; |
|
|
break; |
|
|
break; |
|
@ -1367,7 +1381,7 @@ csihandle(void) { |
|
|
break; |
|
|
break; |
|
|
case 12: /* att610 -- Start blinking cursor (IGNORED) */ |
|
|
case 12: /* att610 -- Start blinking cursor (IGNORED) */ |
|
|
/* fallthrough for xterm cvvis = CSI [ ? 12 ; 25 h */ |
|
|
/* fallthrough for xterm cvvis = CSI [ ? 12 ; 25 h */ |
|
|
if(escseq.narg > 1 && escseq.arg[1] != 25) |
|
|
|
|
|
|
|
|
if(csiescseq.narg > 1 && csiescseq.arg[1] != 25) |
|
|
break; |
|
|
break; |
|
|
case 25: |
|
|
case 25: |
|
|
term.c.state &= ~CURSOR_HIDE; |
|
|
term.c.state &= ~CURSOR_HIDE; |
|
@ -1385,7 +1399,7 @@ csihandle(void) { |
|
|
tclearregion(0, 0, term.col-1, term.row-1); |
|
|
tclearregion(0, 0, term.col-1, term.row-1); |
|
|
else |
|
|
else |
|
|
tswapscreen(); |
|
|
tswapscreen(); |
|
|
if(escseq.arg[0] != 1049) |
|
|
|
|
|
|
|
|
if(csiescseq.arg[0] != 1049) |
|
|
break; |
|
|
break; |
|
|
case 1048: |
|
|
case 1048: |
|
|
tcursor(CURSOR_SAVE); |
|
|
tcursor(CURSOR_SAVE); |
|
@ -1393,7 +1407,7 @@ csihandle(void) { |
|
|
default: goto unknown; |
|
|
default: goto unknown; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
switch(escseq.arg[0]) { |
|
|
|
|
|
|
|
|
switch(csiescseq.arg[0]) { |
|
|
case 4: |
|
|
case 4: |
|
|
term.mode |= MODE_INSERT; |
|
|
term.mode |= MODE_INSERT; |
|
|
break; |
|
|
break; |
|
@ -1402,15 +1416,15 @@ csihandle(void) { |
|
|
}; |
|
|
}; |
|
|
break; |
|
|
break; |
|
|
case 'm': /* SGR -- Terminal attribute (color) */ |
|
|
case 'm': /* SGR -- Terminal attribute (color) */ |
|
|
tsetattr(escseq.arg, escseq.narg); |
|
|
|
|
|
|
|
|
tsetattr(csiescseq.arg, csiescseq.narg); |
|
|
break; |
|
|
break; |
|
|
case 'r': /* DECSTBM -- Set Scrolling Region */ |
|
|
case 'r': /* DECSTBM -- Set Scrolling Region */ |
|
|
if(escseq.priv) |
|
|
|
|
|
|
|
|
if(csiescseq.priv) |
|
|
goto unknown; |
|
|
goto unknown; |
|
|
else { |
|
|
else { |
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
|
|
DEFAULT(escseq.arg[1], term.row); |
|
|
|
|
|
tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); |
|
|
|
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1); |
|
|
|
|
|
DEFAULT(csiescseq.arg[1], term.row); |
|
|
|
|
|
tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); |
|
|
tmoveto(0, 0); |
|
|
tmoveto(0, 0); |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
@ -1427,8 +1441,8 @@ void |
|
|
csidump(void) { |
|
|
csidump(void) { |
|
|
int i; |
|
|
int i; |
|
|
printf("ESC["); |
|
|
printf("ESC["); |
|
|
for(i = 0; i < escseq.len; i++) { |
|
|
|
|
|
uint c = escseq.buf[i] & 0xff; |
|
|
|
|
|
|
|
|
for(i = 0; i < csiescseq.len; i++) { |
|
|
|
|
|
uint c = csiescseq.buf[i] & 0xff; |
|
|
if(isprint(c)) putchar(c); |
|
|
if(isprint(c)) putchar(c); |
|
|
else if(c == '\n') printf("(\\n)"); |
|
|
else if(c == '\n') printf("(\\n)"); |
|
|
else if(c == '\r') printf("(\\r)"); |
|
|
else if(c == '\r') printf("(\\r)"); |
|
@ -1440,7 +1454,80 @@ csidump(void) { |
|
|
|
|
|
|
|
|
void |
|
|
void |
|
|
csireset(void) { |
|
|
csireset(void) { |
|
|
memset(&escseq, 0, sizeof(escseq)); |
|
|
|
|
|
|
|
|
memset(&csiescseq, 0, sizeof(csiescseq)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
strhandle(void) { |
|
|
|
|
|
char *p; |
|
|
|
|
|
|
|
|
|
|
|
p = strescseq.buf; |
|
|
|
|
|
|
|
|
|
|
|
switch(strescseq.type) { |
|
|
|
|
|
case ']': /* OSC -- Operating System Command */ |
|
|
|
|
|
switch(p[0]) { |
|
|
|
|
|
case '0': |
|
|
|
|
|
case '2': |
|
|
|
|
|
/* |
|
|
|
|
|
* TODO: Handle special chars in string, like umlauts. |
|
|
|
|
|
*/ |
|
|
|
|
|
if(p[1] == ';') { |
|
|
|
|
|
if(!strncmp(strescseq.buf, "settitle ", 9)) { |
|
|
|
|
|
XStoreName(xw.dpy, xw.win, strescseq.buf+11); |
|
|
|
|
|
} else { |
|
|
|
|
|
XStoreName(xw.dpy, xw.win, strescseq.buf+2); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case ';': |
|
|
|
|
|
XStoreName(xw.dpy, xw.win, strescseq.buf+1); |
|
|
|
|
|
break; |
|
|
|
|
|
case '4': /* TODO: Set color (arg0) to "rgb:%hexr/$hexg/$hexb" (arg1) */ |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
fprintf(stderr, "erresc: unknown str "); |
|
|
|
|
|
strdump(); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case 'P': /* DSC -- Device Control String */ |
|
|
|
|
|
case '_': /* APC -- Application Program Command */ |
|
|
|
|
|
case '^': /* PM -- Privacy Message */ |
|
|
|
|
|
default: |
|
|
|
|
|
fprintf(stderr, "erresc: unknown str "); |
|
|
|
|
|
strdump(); |
|
|
|
|
|
/* die(""); */ |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
strparse(void) { |
|
|
|
|
|
/* |
|
|
|
|
|
* TODO: Implement parsing like for CSI when required. |
|
|
|
|
|
* Format: ESC type cmd ';' arg0 [';' argn] ESC \ |
|
|
|
|
|
*/ |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
strdump(void) { |
|
|
|
|
|
int i; |
|
|
|
|
|
printf("ESC%c", strescseq.type); |
|
|
|
|
|
for(i = 0; i < strescseq.len; i++) { |
|
|
|
|
|
uint c = strescseq.buf[i] & 0xff; |
|
|
|
|
|
if(isprint(c)) putchar(c); |
|
|
|
|
|
else if(c == '\n') printf("(\\n)"); |
|
|
|
|
|
else if(c == '\r') printf("(\\r)"); |
|
|
|
|
|
else if(c == 0x1b) printf("(\\e)"); |
|
|
|
|
|
else printf("(%02x)", c); |
|
|
|
|
|
} |
|
|
|
|
|
printf("ESC\\\n"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
strreset(void) { |
|
|
|
|
|
memset(&strescseq, 0, sizeof(strescseq)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void |
|
|
void |
|
@ -1457,25 +1544,31 @@ tputc(char *c) { |
|
|
char ascii = *c; |
|
|
char ascii = *c; |
|
|
if(term.esc & ESC_START) { |
|
|
if(term.esc & ESC_START) { |
|
|
if(term.esc & ESC_CSI) { |
|
|
if(term.esc & ESC_CSI) { |
|
|
escseq.buf[escseq.len++] = ascii; |
|
|
|
|
|
if(BETWEEN(ascii, 0x40, 0x7E) || escseq.len >= ESC_BUF_SIZ) { |
|
|
|
|
|
|
|
|
csiescseq.buf[csiescseq.len++] = ascii; |
|
|
|
|
|
if(BETWEEN(ascii, 0x40, 0x7E) || csiescseq.len >= ESC_BUF_SIZ) { |
|
|
term.esc = 0; |
|
|
term.esc = 0; |
|
|
csiparse(), csihandle(); |
|
|
csiparse(), csihandle(); |
|
|
} |
|
|
} |
|
|
/* TODO: handle other OSC */ |
|
|
|
|
|
} else if(term.esc & ESC_OSC) { |
|
|
|
|
|
if(ascii == ';') { |
|
|
|
|
|
term.titlelen = 0; |
|
|
|
|
|
term.esc = ESC_START | ESC_TITLE; |
|
|
|
|
|
} |
|
|
|
|
|
} else if(term.esc & ESC_TITLE) { |
|
|
|
|
|
if(ascii == '\a' || term.titlelen+1 >= ESC_TITLE_SIZ) { |
|
|
|
|
|
|
|
|
} else if(term.esc & ESC_STR) { |
|
|
|
|
|
switch(ascii) { |
|
|
|
|
|
case '\033': |
|
|
|
|
|
term.esc = ESC_START | ESC_STR_END; |
|
|
|
|
|
break; |
|
|
|
|
|
case '\a': /* backwards compatibility to xterm */ |
|
|
term.esc = 0; |
|
|
term.esc = 0; |
|
|
term.title[term.titlelen] = '\0'; |
|
|
|
|
|
XStoreName(xw.dpy, xw.win, term.title); |
|
|
|
|
|
} else { |
|
|
|
|
|
term.title[term.titlelen++] = ascii; |
|
|
|
|
|
|
|
|
strhandle(); |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
strescseq.buf[strescseq.len++] = ascii; |
|
|
|
|
|
if (strescseq.len+1 >= STR_BUF_SIZ) { |
|
|
|
|
|
term.esc = 0; |
|
|
|
|
|
strhandle(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} else if(term.esc & ESC_STR_END) { |
|
|
|
|
|
term.esc = 0; |
|
|
|
|
|
if(ascii == '\\') |
|
|
|
|
|
strhandle(); |
|
|
} else if(term.esc & ESC_ALTCHARSET) { |
|
|
} else if(term.esc & ESC_ALTCHARSET) { |
|
|
switch(ascii) { |
|
|
switch(ascii) { |
|
|
case '0': /* Line drawing crap */ |
|
|
case '0': /* Line drawing crap */ |
|
@ -1493,8 +1586,13 @@ tputc(char *c) { |
|
|
case '[': |
|
|
case '[': |
|
|
term.esc |= ESC_CSI; |
|
|
term.esc |= ESC_CSI; |
|
|
break; |
|
|
break; |
|
|
case ']': |
|
|
|
|
|
term.esc |= ESC_OSC; |
|
|
|
|
|
|
|
|
case 'P': /* DCS -- Device Control String */ |
|
|
|
|
|
case '_': /* APC -- Application Program Command */ |
|
|
|
|
|
case '^': /* PM -- Privacy Message */ |
|
|
|
|
|
case ']': /* OSC -- Operating System Command */ |
|
|
|
|
|
strreset(); |
|
|
|
|
|
strescseq.type = ascii; |
|
|
|
|
|
term.esc |= ESC_STR; |
|
|
break; |
|
|
break; |
|
|
case '(': |
|
|
case '(': |
|
|
term.esc |= ESC_ALTCHARSET; |
|
|
term.esc |= ESC_ALTCHARSET; |
|
@ -1541,6 +1639,9 @@ tputc(char *c) { |
|
|
tcursor(CURSOR_LOAD); |
|
|
tcursor(CURSOR_LOAD); |
|
|
term.esc = 0; |
|
|
term.esc = 0; |
|
|
break; |
|
|
break; |
|
|
|
|
|
case '\\': /* ST -- Stop */ |
|
|
|
|
|
term.esc = 0; |
|
|
|
|
|
break; |
|
|
default: |
|
|
default: |
|
|
fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", |
|
|
fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", |
|
|
(uchar) ascii, isprint(ascii)?ascii:'.'); |
|
|
(uchar) ascii, isprint(ascii)?ascii:'.'); |
|
|