|
|
@ -20,11 +20,12 @@ |
|
|
|
#include <X11/keysym.h> |
|
|
|
#include <X11/keysym.h> |
|
|
|
#include <X11/Xutil.h> |
|
|
|
#include <X11/Xutil.h> |
|
|
|
|
|
|
|
|
|
|
|
#define TNAME "st" |
|
|
|
#define TNAME "xterm" |
|
|
|
|
|
|
|
|
|
|
|
/* Arbitrary sizes */ |
|
|
|
/* Arbitrary sizes */ |
|
|
|
|
|
|
|
#define TITLESIZ 256 |
|
|
|
#define ESCSIZ 256 |
|
|
|
#define ESCSIZ 256 |
|
|
|
#define ESCARG 16 |
|
|
|
#define ESCARGSIZ 16 |
|
|
|
#define MAXDRAWBUF 1024 |
|
|
|
#define MAXDRAWBUF 1024 |
|
|
|
|
|
|
|
|
|
|
|
#define SERRNO strerror(errno) |
|
|
|
#define SERRNO strerror(errno) |
|
|
@ -40,7 +41,8 @@ |
|
|
|
enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4 }; |
|
|
|
enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4 }; |
|
|
|
enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSwrap, CSsave, CSload }; |
|
|
|
enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSwrap, CSsave, CSload }; |
|
|
|
enum { CRset=1, CRupdate=2 }; |
|
|
|
enum { CRset=1, CRupdate=2 }; |
|
|
|
enum { TMwrap=1, TMinsert=2 }; |
|
|
|
enum { TMwrap=1, TMinsert=2, TMtitle=4 }; |
|
|
|
|
|
|
|
enum { ESCin = 1, ESCcsi = 2, ESCosc = 4, ESCtitle = 8 }; |
|
|
|
enum { SCupdate, SCredraw }; |
|
|
|
enum { SCupdate, SCredraw }; |
|
|
|
|
|
|
|
|
|
|
|
typedef int Color; |
|
|
|
typedef int Color; |
|
|
@ -62,17 +64,16 @@ typedef struct { |
|
|
|
int y; |
|
|
|
int y; |
|
|
|
} TCursor; |
|
|
|
} TCursor; |
|
|
|
|
|
|
|
|
|
|
|
/* Escape sequence structs */ |
|
|
|
/* CSI Escape sequence structs */ |
|
|
|
/* ESC <pre> [[ [<priv>] <arg> [;]] <mode>] */ |
|
|
|
/* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */ |
|
|
|
typedef struct { |
|
|
|
typedef struct { |
|
|
|
char buf[ESCSIZ+1]; /* raw string */ |
|
|
|
char buf[ESCSIZ]; /* raw string */ |
|
|
|
int len; /* raw string length */ |
|
|
|
int len; /* raw string length */ |
|
|
|
char pre;
|
|
|
|
|
|
|
|
char priv; |
|
|
|
char priv; |
|
|
|
int arg[ESCARG+1]; |
|
|
|
int arg[ESCARGSIZ]; |
|
|
|
int narg; /* nb of args */ |
|
|
|
int narg; /* nb of args */ |
|
|
|
char mode; |
|
|
|
char mode; |
|
|
|
} Escseq; |
|
|
|
} CSIEscape; |
|
|
|
|
|
|
|
|
|
|
|
/* Internal representation of the screen */ |
|
|
|
/* Internal representation of the screen */ |
|
|
|
typedef struct { |
|
|
|
typedef struct { |
|
|
@ -83,6 +84,9 @@ typedef struct { |
|
|
|
int top; /* top scroll limit */ |
|
|
|
int top; /* top scroll limit */ |
|
|
|
int bot; /* bottom scroll limit */ |
|
|
|
int bot; /* bottom scroll limit */ |
|
|
|
int mode; /* terminal mode */ |
|
|
|
int mode; /* terminal mode */ |
|
|
|
|
|
|
|
int esc; |
|
|
|
|
|
|
|
char title[TITLESIZ]; |
|
|
|
|
|
|
|
int titlelen; |
|
|
|
} Term; |
|
|
|
} Term; |
|
|
|
|
|
|
|
|
|
|
|
/* Purely graphic info */ |
|
|
|
/* Purely graphic info */ |
|
|
@ -116,12 +120,10 @@ static void execsh(void); |
|
|
|
static void sigchld(int); |
|
|
|
static void sigchld(int); |
|
|
|
static void run(void); |
|
|
|
static void run(void); |
|
|
|
|
|
|
|
|
|
|
|
static int escaddc(char); |
|
|
|
static void csidump(void); |
|
|
|
static int escfinal(char); |
|
|
|
static void csihandle(void); |
|
|
|
static void escdump(void); |
|
|
|
static void csiparse(void); |
|
|
|
static void eschandle(void); |
|
|
|
static void csireset(void); |
|
|
|
static void escparse(void); |
|
|
|
|
|
|
|
static void escreset(void); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void tclearregion(int, int, int, int); |
|
|
|
static void tclearregion(int, int, int, int); |
|
|
|
static void tcpos(int); |
|
|
|
static void tcpos(int); |
|
|
@ -168,7 +170,7 @@ static void (*handler[LASTEvent])(XEvent *) = { |
|
|
|
static DC dc; |
|
|
|
static DC dc; |
|
|
|
static XWindow xw; |
|
|
|
static XWindow xw; |
|
|
|
static Term term; |
|
|
|
static Term term; |
|
|
|
static Escseq escseq; |
|
|
|
static CSIEscape escseq; |
|
|
|
static int cmdfd; |
|
|
|
static int cmdfd; |
|
|
|
static pid_t pid; |
|
|
|
static pid_t pid; |
|
|
|
static int running; |
|
|
|
static int running; |
|
|
@ -269,7 +271,7 @@ ttynew(void) { |
|
|
|
void |
|
|
|
void |
|
|
|
dump(char c) { |
|
|
|
dump(char c) { |
|
|
|
static int col; |
|
|
|
static int col; |
|
|
|
fprintf(stderr, " %02x %c ", c, isprint(c)?c:'.'); |
|
|
|
fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.'); |
|
|
|
if(++col % 10 == 0) |
|
|
|
if(++col % 10 == 0) |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
} |
|
|
|
} |
|
|
@ -305,24 +307,6 @@ ttyresize(int x, int y) { |
|
|
|
fprintf(stderr, "Couldn't set window size: %s\n", SERRNO); |
|
|
|
fprintf(stderr, "Couldn't set window size: %s\n", SERRNO); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
|
|
escfinal(char c) { |
|
|
|
|
|
|
|
if(escseq.len == 1) |
|
|
|
|
|
|
|
switch(c) { |
|
|
|
|
|
|
|
case '[': |
|
|
|
|
|
|
|
case ']': |
|
|
|
|
|
|
|
case '(': |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
case '=': |
|
|
|
|
|
|
|
case '>': |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(BETWEEN(c, 0x40, 0x7E)) |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
tcpos(int mode) { |
|
|
|
tcpos(int mode) { |
|
|
|
static int x = 0; |
|
|
|
static int x = 0; |
|
|
@ -372,33 +356,21 @@ tnewline(void) { |
|
|
|
tmoveto(0, y); |
|
|
|
tmoveto(0, y); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
|
|
escaddc(char c) { |
|
|
|
|
|
|
|
escseq.buf[escseq.len++] = c; |
|
|
|
|
|
|
|
if(escfinal(c) || escseq.len >= ESCSIZ) { |
|
|
|
|
|
|
|
escparse(), eschandle(); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
escparse(void) { |
|
|
|
csiparse(void) { |
|
|
|
/* int noarg = 1; */ |
|
|
|
/* int noarg = 1; */ |
|
|
|
char *p = escseq.buf; |
|
|
|
char *p = escseq.buf; |
|
|
|
|
|
|
|
|
|
|
|
escseq.narg = 0; |
|
|
|
escseq.narg = 0; |
|
|
|
switch(escseq.pre = *p++) { |
|
|
|
|
|
|
|
case '[': /* CSI */ |
|
|
|
|
|
|
|
if(*p == '?') |
|
|
|
if(*p == '?') |
|
|
|
escseq.priv = 1, p++; |
|
|
|
escseq.priv = 1, p++; |
|
|
|
|
|
|
|
|
|
|
|
while(p < escseq.buf+escseq.len) { |
|
|
|
while(p < escseq.buf+escseq.len) { |
|
|
|
while(isdigit(*p)) { |
|
|
|
while(isdigit(*p)) { |
|
|
|
escseq.arg[escseq.narg] *= 10; |
|
|
|
escseq.arg[escseq.narg] *= 10; |
|
|
|
escseq.arg[escseq.narg] += *(p++) - '0'/*, noarg = 0 */; |
|
|
|
escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */; |
|
|
|
} |
|
|
|
} |
|
|
|
if(*p == ';') |
|
|
|
if(*p == ';' && escseq.narg+1 < ESCARGSIZ) |
|
|
|
escseq.narg++, p++; |
|
|
|
escseq.narg++, p++; |
|
|
|
else { |
|
|
|
else { |
|
|
|
escseq.mode = *p; |
|
|
|
escseq.mode = *p; |
|
|
@ -406,11 +378,6 @@ escparse(void) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case '(': |
|
|
|
|
|
|
|
/* XXX: graphic character set */ |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
@ -625,16 +592,12 @@ tsetscroll(int t, int b) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
eschandle(void) { |
|
|
|
csihandle(void) { |
|
|
|
switch(escseq.pre) { |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
goto unknown_seq; |
|
|
|
|
|
|
|
case '[': |
|
|
|
|
|
|
|
switch(escseq.mode) { |
|
|
|
switch(escseq.mode) { |
|
|
|
default: |
|
|
|
default: |
|
|
|
unknown_seq: |
|
|
|
|
|
|
|
fprintf(stderr, "erresc: unknown sequence\n"); |
|
|
|
fprintf(stderr, "erresc: unknown sequence\n"); |
|
|
|
escdump(); |
|
|
|
csidump(); |
|
|
|
|
|
|
|
/* die(""); */ |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '@': /* Insert <n> blank char */ |
|
|
|
case '@': /* Insert <n> blank char */ |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
@ -703,6 +666,7 @@ eschandle(void) { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'S': |
|
|
|
case 'L': /* Insert <n> blank lines */ |
|
|
|
case 'L': /* Insert <n> blank lines */ |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
tinsertblankline(escseq.arg[0]); |
|
|
|
tinsertblankline(escseq.arg[0]); |
|
|
@ -715,6 +679,7 @@ eschandle(void) { |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
tdeleteline(escseq.arg[0]); |
|
|
|
tdeleteline(escseq.arg[0]); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'X': |
|
|
|
case 'P': /* Delete <n> char */ |
|
|
|
case 'P': /* Delete <n> char */ |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
DEFAULT(escseq.arg[0], 1); |
|
|
|
tdeletechar(escseq.arg[0]); |
|
|
|
tdeletechar(escseq.arg[0]); |
|
|
@ -746,25 +711,22 @@ eschandle(void) { |
|
|
|
tcpos(CSload); |
|
|
|
tcpos(CSload); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
escdump(void) {
|
|
|
|
csidump(void) {
|
|
|
|
int i; |
|
|
|
int i; |
|
|
|
printf("rawbuf : %s\n", escseq.buf); |
|
|
|
printf("ESC [ %s", escseq.priv ? "? " : ""); |
|
|
|
printf("prechar : %c\n", escseq.pre); |
|
|
|
|
|
|
|
printf("private : %c\n", escseq.priv ? '?' : ' '); |
|
|
|
|
|
|
|
printf("narg : %d\n", escseq.narg); |
|
|
|
|
|
|
|
if(escseq.narg) |
|
|
|
if(escseq.narg) |
|
|
|
for(i = 0; i < escseq.narg; i++) |
|
|
|
for(i = 0; i < escseq.narg; i++) |
|
|
|
printf("\targ %d = %d\n", i, escseq.arg[i]); |
|
|
|
printf("%d ", escseq.arg[i]); |
|
|
|
printf("mode : %c\n", escseq.mode); |
|
|
|
if(escseq.mode) |
|
|
|
|
|
|
|
putchar(escseq.mode); |
|
|
|
|
|
|
|
putchar('\n'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
escreset(void) { |
|
|
|
csireset(void) { |
|
|
|
memset(&escseq, 0, sizeof(escseq)); |
|
|
|
memset(&escseq, 0, sizeof(escseq)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -781,21 +743,41 @@ tputtab(void) { |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
tputc(char c) { |
|
|
|
tputc(char c) { |
|
|
|
static int inesc = 0; |
|
|
|
|
|
|
|
#if 0 |
|
|
|
#if 0 |
|
|
|
dump(c); |
|
|
|
dump(c); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
/* start of escseq */ |
|
|
|
if(term.esc & ESCin) { |
|
|
|
if(c == '\033') |
|
|
|
if(term.esc & ESCcsi) { |
|
|
|
escreset(), inesc = 1; |
|
|
|
escseq.buf[escseq.len++] = c; |
|
|
|
else if(inesc) { |
|
|
|
if(BETWEEN(c, 0x40, 0x7E) || escseq.len >= ESCSIZ) { |
|
|
|
inesc = escaddc(c); |
|
|
|
term.esc = 0; |
|
|
|
} /* normal char */
|
|
|
|
csiparse(), csihandle(); |
|
|
|
else switch(c) {
|
|
|
|
} |
|
|
|
default: |
|
|
|
} else if (term.esc & ESCosc) { |
|
|
|
tsetchar(c); |
|
|
|
if(c == ';') { |
|
|
|
tcursor(CSright); |
|
|
|
term.titlelen = 0; |
|
|
|
|
|
|
|
term.esc = ESCin | ESCtitle; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if(term.esc & ESCtitle) { |
|
|
|
|
|
|
|
if(c == '\a' || term.titlelen+1 >= TITLESIZ) { |
|
|
|
|
|
|
|
term.esc = 0; |
|
|
|
|
|
|
|
term.title[term.titlelen] = '\0'; |
|
|
|
|
|
|
|
XStoreName(xw.dis, xw.win, term.title); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
term.title[term.titlelen++] = c; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
switch(c) { |
|
|
|
|
|
|
|
case '[': |
|
|
|
|
|
|
|
term.esc |= ESCcsi; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case ']': |
|
|
|
|
|
|
|
term.esc |= ESCosc; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
switch(c) { |
|
|
|
case '\t': |
|
|
|
case '\t': |
|
|
|
tputtab(); |
|
|
|
tputtab(); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -811,6 +793,15 @@ tputc(char c) { |
|
|
|
case '\a': |
|
|
|
case '\a': |
|
|
|
xbell(); |
|
|
|
xbell(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case '\033': |
|
|
|
|
|
|
|
csireset(); |
|
|
|
|
|
|
|
term.esc = ESCin; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
tsetchar(c); |
|
|
|
|
|
|
|
tcursor(CSright); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|