mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
patch 8.1.2374: unused parts of libvterm are included
Problem: Unused parts of libvterm are included. Solution: Delete the unused files.
This commit is contained in:
3
Filelist
3
Filelist
@@ -285,9 +285,6 @@ SRC_ALL = \
|
||||
src/libvterm/README \
|
||||
src/libvterm/tbl2inc_c.pl \
|
||||
src/libvterm/vterm.pc.in \
|
||||
src/libvterm/bin/unterm.c \
|
||||
src/libvterm/bin/vterm-ctrl.c \
|
||||
src/libvterm/bin/vterm-dump.c \
|
||||
src/libvterm/doc/URLs \
|
||||
src/libvterm/doc/seqs.txt \
|
||||
src/libvterm/include/vterm.h \
|
||||
|
@@ -1,288 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "vterm.h"
|
||||
|
||||
#define DEFINE_INLINES
|
||||
#include "../src/utf8.h" // fill_utf8
|
||||
|
||||
#define streq(a,b) (!strcmp(a,b))
|
||||
|
||||
static VTerm *vt;
|
||||
static VTermScreen *vts;
|
||||
|
||||
static int cols;
|
||||
static int rows;
|
||||
|
||||
static enum {
|
||||
FORMAT_PLAIN,
|
||||
FORMAT_SGR,
|
||||
} format = FORMAT_PLAIN;
|
||||
|
||||
static int col2index(VTermColor target)
|
||||
{
|
||||
int index;
|
||||
|
||||
for(index = 0; index < 256; index++) {
|
||||
VTermColor col;
|
||||
vterm_state_get_palette_color(NULL, index, &col);
|
||||
if(col.red == target.red && col.green == target.green && col.blue == target.blue)
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void dump_cell(const VTermScreenCell *cell, const VTermScreenCell *prevcell)
|
||||
{
|
||||
switch(format) {
|
||||
case FORMAT_PLAIN:
|
||||
break;
|
||||
case FORMAT_SGR:
|
||||
{
|
||||
// If all 7 attributes change, that means 7 SGRs max
|
||||
// Each colour could consume up to 3
|
||||
int sgr[7 + 2*3]; int sgri = 0;
|
||||
|
||||
if(!prevcell->attrs.bold && cell->attrs.bold)
|
||||
sgr[sgri++] = 1;
|
||||
if(prevcell->attrs.bold && !cell->attrs.bold)
|
||||
sgr[sgri++] = 22;
|
||||
|
||||
if(!prevcell->attrs.underline && cell->attrs.underline)
|
||||
sgr[sgri++] = 4;
|
||||
if(prevcell->attrs.underline && !cell->attrs.underline)
|
||||
sgr[sgri++] = 24;
|
||||
|
||||
if(!prevcell->attrs.italic && cell->attrs.italic)
|
||||
sgr[sgri++] = 3;
|
||||
if(prevcell->attrs.italic && !cell->attrs.italic)
|
||||
sgr[sgri++] = 23;
|
||||
|
||||
if(!prevcell->attrs.blink && cell->attrs.blink)
|
||||
sgr[sgri++] = 5;
|
||||
if(prevcell->attrs.blink && !cell->attrs.blink)
|
||||
sgr[sgri++] = 25;
|
||||
|
||||
if(!prevcell->attrs.reverse && cell->attrs.reverse)
|
||||
sgr[sgri++] = 7;
|
||||
if(prevcell->attrs.reverse && !cell->attrs.reverse)
|
||||
sgr[sgri++] = 27;
|
||||
|
||||
if(!prevcell->attrs.strike && cell->attrs.strike)
|
||||
sgr[sgri++] = 9;
|
||||
if(prevcell->attrs.strike && !cell->attrs.strike)
|
||||
sgr[sgri++] = 29;
|
||||
|
||||
if(!prevcell->attrs.font && cell->attrs.font)
|
||||
sgr[sgri++] = 10 + cell->attrs.font;
|
||||
if(prevcell->attrs.font && !cell->attrs.font)
|
||||
sgr[sgri++] = 10;
|
||||
|
||||
if(prevcell->fg.red != cell->fg.red ||
|
||||
prevcell->fg.green != cell->fg.green ||
|
||||
prevcell->fg.blue != cell->fg.blue) {
|
||||
int index = col2index(cell->fg);
|
||||
if(index == -1)
|
||||
sgr[sgri++] = 39;
|
||||
else if(index < 8)
|
||||
sgr[sgri++] = 30 + index;
|
||||
else if(index < 16)
|
||||
sgr[sgri++] = 90 + (index - 8);
|
||||
else {
|
||||
sgr[sgri++] = 38;
|
||||
sgr[sgri++] = 5 | CSI_ARG_FLAG_MORE;
|
||||
sgr[sgri++] = index | CSI_ARG_FLAG_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
if(prevcell->bg.red != cell->bg.red ||
|
||||
prevcell->bg.green != cell->bg.green ||
|
||||
prevcell->bg.blue != cell->bg.blue) {
|
||||
int index = col2index(cell->bg);
|
||||
if(index == -1)
|
||||
sgr[sgri++] = 49;
|
||||
else if(index < 8)
|
||||
sgr[sgri++] = 40 + index;
|
||||
else if(index < 16)
|
||||
sgr[sgri++] = 100 + (index - 8);
|
||||
else {
|
||||
sgr[sgri++] = 48;
|
||||
sgr[sgri++] = 5 | CSI_ARG_FLAG_MORE;
|
||||
sgr[sgri++] = index | CSI_ARG_FLAG_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
if(!sgri)
|
||||
break;
|
||||
|
||||
printf("\x1b[");
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < sgri; i++)
|
||||
printf(!i ? "%d" :
|
||||
CSI_ARG_HAS_MORE(sgr[i]) ? ":%d" :
|
||||
";%d",
|
||||
CSI_ARG(sgr[i]));
|
||||
}
|
||||
printf("m");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell->chars[i]; i++) {
|
||||
char bytes[6];
|
||||
bytes[fill_utf8(cell->chars[i], bytes)] = 0;
|
||||
printf("%s", bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_eol(const VTermScreenCell *prevcell)
|
||||
{
|
||||
switch(format) {
|
||||
case FORMAT_PLAIN:
|
||||
break;
|
||||
case FORMAT_SGR:
|
||||
if(prevcell->attrs.bold || prevcell->attrs.underline || prevcell->attrs.italic ||
|
||||
prevcell->attrs.blink || prevcell->attrs.reverse || prevcell->attrs.strike ||
|
||||
prevcell->attrs.font)
|
||||
printf("\x1b[m");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void dump_row(int row)
|
||||
{
|
||||
VTermPos pos;
|
||||
VTermScreenCell prevcell;
|
||||
pos.row = row;
|
||||
pos.col = 0;
|
||||
memset(&prevcell, 0, sizeof(prevcell));
|
||||
vterm_state_get_default_colors(vterm_obtain_state(vt), &prevcell.fg, &prevcell.bg);
|
||||
|
||||
while(pos.col < cols) {
|
||||
VTermScreenCell cell;
|
||||
vterm_screen_get_cell(vts, pos, &cell);
|
||||
|
||||
dump_cell(&cell, &prevcell);
|
||||
|
||||
pos.col += cell.width;
|
||||
prevcell = cell;
|
||||
}
|
||||
|
||||
dump_eol(&prevcell);
|
||||
}
|
||||
|
||||
static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user)
|
||||
{
|
||||
VTermScreenCell prevcell;
|
||||
int col;
|
||||
|
||||
memset(&prevcell, 0, sizeof(prevcell));
|
||||
vterm_state_get_default_colors(vterm_obtain_state(vt), &prevcell.fg, &prevcell.bg);
|
||||
|
||||
for(col = 0; col < cols; col++) {
|
||||
dump_cell(cells + col, &prevcell);
|
||||
prevcell = cells[col];
|
||||
}
|
||||
|
||||
dump_eol(&prevcell);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int screen_resize(int new_rows, int new_cols, void *user)
|
||||
{
|
||||
rows = new_rows;
|
||||
cols = new_cols;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static VTermScreenCallbacks cb_screen = {
|
||||
NULL, // damage
|
||||
NULL, // moverect
|
||||
NULL, // movecursor
|
||||
NULL, // settermprop
|
||||
NULL, // bell
|
||||
&screen_resize, // resize
|
||||
&screen_sb_pushline, // sb_pushline
|
||||
NULL, // popline
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
const char *file;
|
||||
int fd;
|
||||
int len;
|
||||
char buffer[1024];
|
||||
int row;
|
||||
|
||||
rows = 25;
|
||||
cols = 80;
|
||||
|
||||
while((opt = getopt(argc, argv, "f:l:c:")) != -1) {
|
||||
switch(opt) {
|
||||
case 'f':
|
||||
if(streq(optarg, "plain"))
|
||||
format = FORMAT_PLAIN;
|
||||
else if(streq(optarg, "sgr"))
|
||||
format = FORMAT_SGR;
|
||||
else {
|
||||
fprintf(stderr, "Unrecognised format '%s'\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
rows = atoi(optarg);
|
||||
if(!rows)
|
||||
rows = 25;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
cols = atoi(optarg);
|
||||
if(!cols)
|
||||
cols = 80;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file = argv[optind++];
|
||||
fd = open(file, O_RDONLY);
|
||||
if(fd == -1) {
|
||||
fprintf(stderr, "Cannot open %s - %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vt = vterm_new(rows, cols);
|
||||
vterm_set_utf8(vt, TRUE);
|
||||
|
||||
vts = vterm_obtain_screen(vt);
|
||||
vterm_screen_set_callbacks(vts, &cb_screen, NULL);
|
||||
|
||||
vterm_screen_reset(vts, 1);
|
||||
|
||||
while((len = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
vterm_input_write(vt, buffer, len);
|
||||
}
|
||||
|
||||
for(row = 0; row < rows; row++) {
|
||||
dump_row(row);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
vterm_free(vt);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,366 +0,0 @@
|
||||
#define _XOPEN_SOURCE 500 // strdup
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define streq(a,b) (strcmp(a,b)==0)
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
static char *getvalue(int *argip, int argc, char *argv[])
|
||||
{
|
||||
if(*argip >= argc) {
|
||||
fprintf(stderr, "Expected an option value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return argv[(*argip)++];
|
||||
}
|
||||
|
||||
static int getchoice(int *argip, int argc, char *argv[], const char *options[])
|
||||
{
|
||||
const char *arg = getvalue(argip, argc, argv);
|
||||
|
||||
int value = -1;
|
||||
while(options[++value])
|
||||
if(streq(arg, options[value]))
|
||||
return value;
|
||||
|
||||
fprintf(stderr, "Unrecognised option value %s\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
OFF,
|
||||
ON,
|
||||
QUERY,
|
||||
} BoolQuery;
|
||||
|
||||
static BoolQuery getboolq(int *argip, int argc, char *argv[])
|
||||
{
|
||||
const char *choices[] = {"off", "on", "query", NULL};
|
||||
return getchoice(argip, argc, argv, choices);
|
||||
}
|
||||
|
||||
static char *helptext[] = {
|
||||
"reset",
|
||||
"s8c1t [off|on]",
|
||||
"keypad [app|num]",
|
||||
"screen [off|on|query]",
|
||||
"cursor [off|on|query]",
|
||||
"curblink [off|on|query]",
|
||||
"curshape [block|under|bar|query]",
|
||||
"mouse [off|click|clickdrag|motion]",
|
||||
"reportfocus [off|on|query]",
|
||||
"altscreen [off|on|query]",
|
||||
"bracketpaste [off|on|query]",
|
||||
"icontitle [STR]",
|
||||
"icon [STR]",
|
||||
"title [STR]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int seticanon(int icanon, int echo)
|
||||
{
|
||||
struct termios termios;
|
||||
int ret;
|
||||
|
||||
tcgetattr(0, &termios);
|
||||
|
||||
ret = (termios.c_lflag & ICANON);
|
||||
|
||||
if(icanon) termios.c_lflag |= ICANON;
|
||||
else termios.c_lflag &= ~ICANON;
|
||||
|
||||
if(echo) termios.c_lflag |= ECHO;
|
||||
else termios.c_lflag &= ~ECHO;
|
||||
|
||||
tcsetattr(0, TCSANOW, &termios);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void await_c1(unsigned char c1)
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
// await CSI - 8bit or 2byte 7bit form
|
||||
int in_esc = FALSE;
|
||||
while((c = getchar())) {
|
||||
if(c == c1)
|
||||
break;
|
||||
if(in_esc && c == (char)(c1 - 0x40))
|
||||
break;
|
||||
if(!in_esc && c == 0x1b)
|
||||
in_esc = TRUE;
|
||||
else
|
||||
in_esc = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static char *read_csi()
|
||||
{
|
||||
unsigned char csi[32];
|
||||
int i = 0;
|
||||
|
||||
await_c1(0x9B); // CSI
|
||||
|
||||
// TODO: This really should be a more robust CSI parser
|
||||
for(; i < sizeof(csi)-1; i++) {
|
||||
int c = csi[i] = getchar();
|
||||
if(c >= 0x40 && c <= 0x7e)
|
||||
break;
|
||||
}
|
||||
csi[++i] = 0;
|
||||
|
||||
// TODO: returns longer than 32?
|
||||
|
||||
return strdup((char *)csi);
|
||||
}
|
||||
|
||||
static char *read_dcs()
|
||||
{
|
||||
unsigned char dcs[32];
|
||||
int in_esc = FALSE;
|
||||
int i;
|
||||
|
||||
await_c1(0x90);
|
||||
|
||||
for(i = 0; i < sizeof(dcs)-1; ) {
|
||||
char c = getchar();
|
||||
if(c == 0x9c) // ST
|
||||
break;
|
||||
if(in_esc && c == 0x5c)
|
||||
break;
|
||||
if(!in_esc && c == 0x1b)
|
||||
in_esc = TRUE;
|
||||
else {
|
||||
dcs[i++] = c;
|
||||
in_esc = FALSE;
|
||||
}
|
||||
}
|
||||
dcs[++i] = 0;
|
||||
|
||||
return strdup((char *)dcs);
|
||||
}
|
||||
|
||||
static void usage(int exitcode)
|
||||
{
|
||||
char **p;
|
||||
|
||||
fprintf(stderr, "Control a libvterm-based terminal\n"
|
||||
"\n"
|
||||
"Options:\n");
|
||||
|
||||
for(p = helptext; *p; p++)
|
||||
fprintf(stderr, " %s\n", *p);
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static int query_dec_mode(int mode)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
||||
printf("\x1b[?%d$p", mode);
|
||||
|
||||
do {
|
||||
int reply_mode, reply_value;
|
||||
char reply_cmd;
|
||||
|
||||
if(s)
|
||||
free(s);
|
||||
s = read_csi();
|
||||
|
||||
// expect "?" mode ";" value "$y"
|
||||
|
||||
// If the sscanf format string ends in a literal, we can't tell from
|
||||
// its return value if it matches. Hence we'll %c the cmd and check it
|
||||
// explicitly
|
||||
if(sscanf(s, "?%d;%d$%c", &reply_mode, &reply_value, &reply_cmd) < 3)
|
||||
continue;
|
||||
if(reply_cmd != 'y')
|
||||
continue;
|
||||
|
||||
if(reply_mode != mode)
|
||||
continue;
|
||||
|
||||
free(s);
|
||||
|
||||
if(reply_value == 1 || reply_value == 3)
|
||||
return TRUE;
|
||||
if(reply_value == 2 || reply_value == 4)
|
||||
return FALSE;
|
||||
|
||||
printf("Unrecognised reply to DECRQM: %d\n", reply_value);
|
||||
return FALSE;
|
||||
} while(1);
|
||||
}
|
||||
|
||||
static void do_dec_mode(int mode, BoolQuery val, const char *name)
|
||||
{
|
||||
switch(val) {
|
||||
case OFF:
|
||||
case ON:
|
||||
printf("\x1b[?%d%c", mode, val == ON ? 'h' : 'l');
|
||||
break;
|
||||
|
||||
case QUERY:
|
||||
if(query_dec_mode(mode))
|
||||
printf("%s on\n", name);
|
||||
else
|
||||
printf("%s off\n", name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int query_rqss_numeric(char *cmd)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
||||
printf("\x1bP$q%s\x1b\\", cmd);
|
||||
|
||||
do {
|
||||
int num;
|
||||
|
||||
if(s)
|
||||
free(s);
|
||||
s = read_dcs();
|
||||
|
||||
if(!s)
|
||||
return -1;
|
||||
if(strlen(s) < strlen(cmd))
|
||||
return -1;
|
||||
if(strcmp(s + strlen(s) - strlen(cmd), cmd) != 0) {
|
||||
printf("No match\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(s[0] != '1' || s[1] != '$' || s[2] != 'r')
|
||||
return -1;
|
||||
|
||||
if(sscanf(s + 3, "%d", &num) != 1)
|
||||
return -1;
|
||||
|
||||
return num;
|
||||
} while(1);
|
||||
}
|
||||
|
||||
int wasicanon;
|
||||
|
||||
void restoreicanon(void)
|
||||
{
|
||||
seticanon(wasicanon, TRUE);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int argi = 1;
|
||||
|
||||
if(argc == 1)
|
||||
usage(0);
|
||||
|
||||
wasicanon = seticanon(FALSE, FALSE);
|
||||
atexit(restoreicanon);
|
||||
|
||||
while(argi < argc) {
|
||||
const char *arg = argv[argi++];
|
||||
|
||||
if(streq(arg, "reset")) {
|
||||
printf("\x1b" "c");
|
||||
}
|
||||
else if(streq(arg, "s8c1t")) {
|
||||
const char *choices[] = {"off", "on", NULL};
|
||||
switch(getchoice(&argi, argc, argv, choices)) {
|
||||
case 0:
|
||||
printf("\x1b F"); break;
|
||||
case 1:
|
||||
printf("\x1b G"); break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "keypad")) {
|
||||
const char *choices[] = {"app", "num", NULL};
|
||||
switch(getchoice(&argi, argc, argv, choices)) {
|
||||
case 0:
|
||||
printf("\x1b="); break;
|
||||
case 1:
|
||||
printf("\x1b>"); break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "screen")) {
|
||||
do_dec_mode(5, getboolq(&argi, argc, argv), "screen");
|
||||
}
|
||||
else if(streq(arg, "cursor")) {
|
||||
do_dec_mode(25, getboolq(&argi, argc, argv), "cursor");
|
||||
}
|
||||
else if(streq(arg, "curblink")) {
|
||||
do_dec_mode(12, getboolq(&argi, argc, argv), "curblink");
|
||||
}
|
||||
else if(streq(arg, "curshape")) {
|
||||
// TODO: This ought to query the current value of DECSCUSR because it
|
||||
// may need blinking on or off
|
||||
const char *choices[] = {"block", "under", "bar", "query", NULL};
|
||||
int shape = getchoice(&argi, argc, argv, choices);
|
||||
switch(shape) {
|
||||
case 3: // query
|
||||
shape = query_rqss_numeric(" q");
|
||||
switch(shape) {
|
||||
case 1: case 2:
|
||||
printf("curshape block\n");
|
||||
break;
|
||||
case 3: case 4:
|
||||
printf("curshape under\n");
|
||||
break;
|
||||
case 5: case 6:
|
||||
printf("curshape bar\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
printf("\x1b[%d q", 1 + (shape * 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "mouse")) {
|
||||
const char *choices[] = {"off", "click", "clickdrag", "motion", NULL};
|
||||
switch(getchoice(&argi, argc, argv, choices)) {
|
||||
case 0:
|
||||
printf("\x1b[?1000l"); break;
|
||||
case 1:
|
||||
printf("\x1b[?1000h"); break;
|
||||
case 2:
|
||||
printf("\x1b[?1002h"); break;
|
||||
case 3:
|
||||
printf("\x1b[?1003h"); break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "reportfocus")) {
|
||||
do_dec_mode(1004, getboolq(&argi, argc, argv), "reportfocus");
|
||||
}
|
||||
else if(streq(arg, "altscreen")) {
|
||||
do_dec_mode(1049, getboolq(&argi, argc, argv), "altscreen");
|
||||
}
|
||||
else if(streq(arg, "bracketpaste")) {
|
||||
do_dec_mode(2004, getboolq(&argi, argc, argv), "bracketpaste");
|
||||
}
|
||||
else if(streq(arg, "icontitle")) {
|
||||
printf("\x1b]0;%s\a", getvalue(&argi, argc, argv));
|
||||
}
|
||||
else if(streq(arg, "icon")) {
|
||||
printf("\x1b]1;%s\a", getvalue(&argi, argc, argv));
|
||||
}
|
||||
else if(streq(arg, "title")) {
|
||||
printf("\x1b]2;%s\a", getvalue(&argi, argc, argv));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Unrecognised command %s\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -1,232 +0,0 @@
|
||||
// Require getopt(3)
|
||||
#define _XOPEN_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#define streq(a,b) (strcmp(a,b)==0)
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "vterm.h"
|
||||
|
||||
static const char *special_begin = "{";
|
||||
static const char *special_end = "}";
|
||||
|
||||
static int parser_text(const char bytes[], size_t len, void *user)
|
||||
{
|
||||
unsigned char *b = (unsigned char *)bytes;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < len; ) {
|
||||
if(b[i] < 0x20) // C0
|
||||
break;
|
||||
else if(b[i] < 0x80) // ASCII
|
||||
i++;
|
||||
else if(b[i] < 0xa0) // C1
|
||||
break;
|
||||
else if(b[i] < 0xc0) // UTF-8 continuation
|
||||
break;
|
||||
else if(b[i] < 0xe0) { // UTF-8 2-byte
|
||||
// 2-byte UTF-8
|
||||
if(len < i+2) break;
|
||||
i += 2;
|
||||
}
|
||||
else if(b[i] < 0xf0) { // UTF-8 3-byte
|
||||
if(len < i+3) break;
|
||||
i += 3;
|
||||
}
|
||||
else if(b[i] < 0xf8) { // UTF-8 4-byte
|
||||
if(len < i+4) break;
|
||||
i += 4;
|
||||
}
|
||||
else // otherwise invalid
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%.*s", i, b);
|
||||
return i;
|
||||
}
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
static const char *name_c0[] = {
|
||||
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "LS0", "LS1",
|
||||
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
|
||||
};
|
||||
static const char *name_c1[] = {
|
||||
NULL, NULL, "BPH", "NBH", NULL, "NEL", "SSA", "ESA", "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
|
||||
"DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA", "SOS", NULL, "SCI", "CSI", "ST", "OSC", "PM", "APC",
|
||||
};
|
||||
|
||||
static int parser_control(unsigned char control, void *user)
|
||||
{
|
||||
if(control < 0x20)
|
||||
printf("%s%s%s", special_begin, name_c0[control], special_end);
|
||||
else if(control >= 0x80 && control < 0xa0 && name_c1[control - 0x80])
|
||||
printf("%s%s%s", special_begin, name_c1[control - 0x80], special_end);
|
||||
else
|
||||
printf("%sCONTROL 0x%02x%s", special_begin, control, special_end);
|
||||
|
||||
if(control == 0x0a)
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_escape(const char bytes[], size_t len, void *user)
|
||||
{
|
||||
if(bytes[0] >= 0x20 && bytes[0] < 0x30) {
|
||||
if(len < 2)
|
||||
return -1;
|
||||
len = 2;
|
||||
}
|
||||
else {
|
||||
len = 1;
|
||||
}
|
||||
|
||||
printf("%sESC %.*s%s", special_begin, (int)len, bytes, special_end);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
static const char *name_csi_plain[] = {
|
||||
"ICH", "CUU", "CUD", "CUF", "CUB", "CNL", "CPL", "CHA", "CUP", "CHT", "ED", "EL", "IL", "DL", "EF", "EA",
|
||||
"DCH", "SSE", "CPR", "SU", "SD", "NP", "PP", "CTC", "ECH", "CVT", "CBT", "SRS", "PTX", "SDS", "SIMD",NULL,
|
||||
"HPA", "HPR", "REP", "DA", "VPA", "VPR", "HVP", "TBC", "SM", "MC", "HPB", "VPB", "RM", "SGR", "DSR", "DAQ",
|
||||
};
|
||||
|
||||
//0 4 8 B
|
||||
static const int newline_csi_plain[] = {
|
||||
0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
};
|
||||
|
||||
static int parser_csi(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user)
|
||||
{
|
||||
const char *name = NULL;
|
||||
if(!leader && !intermed && command < 0x70)
|
||||
name = name_csi_plain[command - 0x40];
|
||||
else if(leader && streq(leader, "?") && !intermed) {
|
||||
// DEC
|
||||
switch(command) {
|
||||
case 'h': name = "DECSM"; break;
|
||||
case 'l': name = "DECRM"; break;
|
||||
}
|
||||
if(name)
|
||||
leader = NULL;
|
||||
}
|
||||
|
||||
if(!leader && !intermed && command < 0x70 && newline_csi_plain[command - 0x40])
|
||||
printf("\n");
|
||||
|
||||
if(name)
|
||||
printf("%s%s", special_begin, name);
|
||||
else
|
||||
printf("%sCSI", special_begin);
|
||||
|
||||
if(leader && leader[0])
|
||||
printf(" %s", leader);
|
||||
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < argcount; i++) {
|
||||
printf(i ? "," : " ");
|
||||
}
|
||||
|
||||
if(args[i] == CSI_ARG_MISSING)
|
||||
printf("*");
|
||||
else {
|
||||
while(CSI_ARG_HAS_MORE(args[i]))
|
||||
printf("%ld+", CSI_ARG(args[i++]));
|
||||
printf("%ld", CSI_ARG(args[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if(intermed && intermed[0])
|
||||
printf(" %s", intermed);
|
||||
|
||||
if(name)
|
||||
printf("%s", special_end);
|
||||
else
|
||||
printf(" %c%s", command, special_end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_osc(const char *command, size_t cmdlen, void *user)
|
||||
{
|
||||
printf("%sOSC %.*s%s", special_begin, (int)cmdlen, command, special_end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_dcs(const char *command, size_t cmdlen, void *user)
|
||||
{
|
||||
printf("%sDCS %.*s%s", special_begin, (int)cmdlen, command, special_end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static VTermParserCallbacks parser_cbs = {
|
||||
&parser_text, // text
|
||||
&parser_control, // control
|
||||
&parser_escape, // escape
|
||||
&parser_csi, // csi
|
||||
&parser_osc, // osc
|
||||
&parser_dcs, // dcs
|
||||
NULL // resize
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int use_colour = isatty(1);
|
||||
const char *file;
|
||||
int fd;
|
||||
VTerm *vt;
|
||||
int len;
|
||||
char buffer[1024];
|
||||
|
||||
int opt;
|
||||
while((opt = getopt(argc, argv, "c")) != -1) {
|
||||
switch(opt) {
|
||||
case 'c': use_colour = 1; break;
|
||||
}
|
||||
}
|
||||
|
||||
file = argv[optind++];
|
||||
|
||||
if(!file || streq(file, "-"))
|
||||
fd = 0; // stdin
|
||||
else {
|
||||
fd = open(file, O_RDONLY);
|
||||
if(fd == -1) {
|
||||
fprintf(stderr, "Cannot open %s - %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if(use_colour) {
|
||||
special_begin = "\x1b[7m{";
|
||||
special_end = "}\x1b[m";
|
||||
}
|
||||
|
||||
// Size matters not for the parser
|
||||
vt = vterm_new(25, 80);
|
||||
vterm_set_utf8(vt, 1);
|
||||
vterm_parser_set_callbacks(vt, &parser_cbs, NULL);
|
||||
|
||||
while((len = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
vterm_input_write(vt, buffer, len);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
close(fd);
|
||||
vterm_free(vt);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -742,6 +742,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2374,
|
||||
/**/
|
||||
2373,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user