Introduction
Introduction Statistics Contact Development Disclaimer Help
tTERM set to xterm by default (which broke a lot of stuff), better escape handl…
git clone git://src.adamsgaard.dk/st
Log
Files
Refs
README
LICENSE
---
commit 0981437524b64579cc656f60b0108abdcdf8a0cd
parent f2dff29a16ef0eb1a0b680cdd753471ba406e4f5
Author: AurĂ©lien Aptel <[email protected]>
Date: Wed, 3 Feb 2010 03:25:35 +0100
TERM set to xterm by default (which broke a lot of stuff), better escape handli…
Diffstat:
M st.c | 389 +++++++++++++++--------------…
1 file changed, 190 insertions(+), 199 deletions(-)
---
diff --git a/st.c b/st.c
t@@ -20,11 +20,12 @@
#include <X11/keysym.h>
#include <X11/Xutil.h>
-#define TNAME "st"
+#define TNAME "xterm"
/* Arbitrary sizes */
+#define TITLESIZ 256
#define ESCSIZ 256
-#define ESCARG 16
+#define ESCARGSIZ 16
#define MAXDRAWBUF 1024
#define SERRNO strerror(errno)
t@@ -40,7 +41,8 @@
enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4 };
enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSwrap, CSsave, CSload };
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 };
typedef int Color;
t@@ -62,17 +64,16 @@ typedef struct {
int y;
} TCursor;
-/* Escape sequence structs */
-/* ESC <pre> [[ [<priv>] <arg> [;]] <mode>] */
+/* CSI Escape sequence structs */
+/* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */
typedef struct {
- char buf[ESCSIZ+1]; /* raw string */
+ char buf[ESCSIZ]; /* raw string */
int len; /* raw string length */
- char pre;
char priv;
- int arg[ESCARG+1];
+ int arg[ESCARGSIZ];
int narg; /* nb of args */
char mode;
-} Escseq;
+} CSIEscape;
/* Internal representation of the screen */
typedef struct {
t@@ -83,6 +84,9 @@ typedef struct {
int top; /* top scroll limit */
int bot; /* bottom scroll limit */
int mode; /* terminal mode */
+ int esc;
+ char title[TITLESIZ];
+ int titlelen;
} Term;
/* Purely graphic info */
t@@ -116,12 +120,10 @@ static void execsh(void);
static void sigchld(int);
static void run(void);
-static int escaddc(char);
-static int escfinal(char);
-static void escdump(void);
-static void eschandle(void);
-static void escparse(void);
-static void escreset(void);
+static void csidump(void);
+static void csihandle(void);
+static void csiparse(void);
+static void csireset(void);
static void tclearregion(int, int, int, int);
static void tcpos(int);
t@@ -168,7 +170,7 @@ static void (*handler[LASTEvent])(XEvent *) = {
static DC dc;
static XWindow xw;
static Term term;
-static Escseq escseq;
+static CSIEscape escseq;
static int cmdfd;
static pid_t pid;
static int running;
t@@ -269,7 +271,7 @@ ttynew(void) {
void
dump(char c) {
static int col;
- fprintf(stderr, " %02x %c ", c, isprint(c)?c:'.');
+ fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.');
if(++col % 10 == 0)
fprintf(stderr, "\n");
}
t@@ -305,24 +307,6 @@ ttyresize(int x, int y) {
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
tcpos(int mode) {
static int x = 0;
t@@ -372,44 +356,27 @@ tnewline(void) {
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
-escparse(void) {
+csiparse(void) {
/* int noarg = 1; */
char *p = escseq.buf;
escseq.narg = 0;
- switch(escseq.pre = *p++) {
- case '[': /* CSI */
- if(*p == '?')
- escseq.priv = 1, p++;
-
- while(p < escseq.buf+escseq.len) {
- while(isdigit(*p)) {
- escseq.arg[escseq.narg] *= 10;
- escseq.arg[escseq.narg] += *(p++) - '0'/*, noa…
- }
- if(*p == ';')
- escseq.narg++, p++;
- else {
- escseq.mode = *p;
- escseq.narg++;
- return;
- }
+ if(*p == '?')
+ escseq.priv = 1, p++;
+
+ while(p < escseq.buf+escseq.len) {
+ while(isdigit(*p)) {
+ escseq.arg[escseq.narg] *= 10;
+ escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */;
+ }
+ if(*p == ';' && escseq.narg+1 < ESCARGSIZ)
+ escseq.narg++, p++;
+ else {
+ escseq.mode = *p;
+ escseq.narg++;
+ return;
}
- break;
- case '(':
- /* XXX: graphic character set */
- break;
}
}
t@@ -625,146 +592,141 @@ tsetscroll(int t, int b) {
}
void
-eschandle(void) {
- switch(escseq.pre) {
+csihandle(void) {
+ switch(escseq.mode) {
default:
- goto unknown_seq;
- case '[':
- switch(escseq.mode) {
- default:
- unknown_seq:
- fprintf(stderr, "erresc: unknown sequence\n");
- escdump();
- break;
- case '@': /* Insert <n> blank char */
- DEFAULT(escseq.arg[0], 1);
- tinsertblank(escseq.arg[0]);
- break;
- case 'A': /* Cursor <n> Up */
- case 'e':
- DEFAULT(escseq.arg[0], 1);
- tmoveto(term.c.x, term.c.y-escseq.arg[0]);
- break;
- case 'B': /* Cursor <n> Down */
- DEFAULT(escseq.arg[0], 1);
- tmoveto(term.c.x, term.c.y+escseq.arg[0]);
- break;
- case 'C': /* Cursor <n> Forward */
- case 'a':
- DEFAULT(escseq.arg[0], 1);
- tmoveto(term.c.x+escseq.arg[0], term.c.y);
- break;
- case 'D': /* Cursor <n> Backward */
- DEFAULT(escseq.arg[0], 1);
- tmoveto(term.c.x-escseq.arg[0], term.c.y);
- break;
- case 'E': /* Cursor <n> Down and first col */
- DEFAULT(escseq.arg[0], 1);
- tmoveto(0, term.c.y+escseq.arg[0]);
- break;
- case 'F': /* Cursor <n> Up and first col */
- DEFAULT(escseq.arg[0], 1);
- tmoveto(0, term.c.y-escseq.arg[0]);
- break;
- case 'G': /* Move to <col> */
- case '`':
- DEFAULT(escseq.arg[0], 1);
- tmoveto(escseq.arg[0]-1, term.c.y);
+ fprintf(stderr, "erresc: unknown sequence\n");
+ csidump();
+ /* die(""); */
+ break;
+ case '@': /* Insert <n> blank char */
+ DEFAULT(escseq.arg[0], 1);
+ tinsertblank(escseq.arg[0]);
+ break;
+ case 'A': /* Cursor <n> Up */
+ case 'e':
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(term.c.x, term.c.y-escseq.arg[0]);
+ break;
+ case 'B': /* Cursor <n> Down */
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(term.c.x, term.c.y+escseq.arg[0]);
+ break;
+ case 'C': /* Cursor <n> Forward */
+ case 'a':
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(term.c.x+escseq.arg[0], term.c.y);
+ break;
+ case 'D': /* Cursor <n> Backward */
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(term.c.x-escseq.arg[0], term.c.y);
+ break;
+ case 'E': /* Cursor <n> Down and first col */
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(0, term.c.y+escseq.arg[0]);
+ break;
+ case 'F': /* Cursor <n> Up and first col */
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(0, term.c.y-escseq.arg[0]);
+ break;
+ case 'G': /* Move to <col> */
+ case '`':
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(escseq.arg[0]-1, term.c.y);
+ break;
+ case 'H': /* Move to <row> <col> */
+ case 'f':
+ DEFAULT(escseq.arg[0], 1);
+ DEFAULT(escseq.arg[1], 1);
+ tmoveto(escseq.arg[1]-1, escseq.arg[0]-1);
+ break;
+ case 'J': /* Clear screen */
+ switch(escseq.arg[0]) {
+ case 0: /* below */
+ tclearregion(term.c.x, term.c.y, term.col-1, term.row-…
break;
- case 'H': /* Move to <row> <col> */
- case 'f':
- DEFAULT(escseq.arg[0], 1);
- DEFAULT(escseq.arg[1], 1);
- tmoveto(escseq.arg[1]-1, escseq.arg[0]-1);
+ case 1: /* above */
+ tclearregion(0, 0, term.c.x, term.c.y);
break;
- case 'J': /* Clear screen */
- switch(escseq.arg[0]) {
- case 0: /* below */
- tclearregion(term.c.x, term.c.y, term.col-1, t…
- break;
- case 1: /* above */
- tclearregion(0, 0, term.c.x, term.c.y);
- break;
- case 2: /* all */
- tclearregion(0, 0, term.col-1, term.row-1);
- break;
- }
+ case 2: /* all */
+ tclearregion(0, 0, term.col-1, term.row-1);
+ break;
+ }
+ break;
+ case 'K': /* Clear line */
+ switch(escseq.arg[0]) {
+ case 0: /* right */
+ tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
break;
- case 'K': /* Clear line */
- switch(escseq.arg[0]) {
- case 0: /* right */
- tclearregion(term.c.x, term.c.y, term.col-1, t…
- break;
- case 1: /* left */
- tclearregion(0, term.c.y, term.c.x, term.c.y);
- break;
- case 2: /* all */
- tclearregion(0, term.c.y, term.col-1, term.c.y…
- break;
- }
+ case 1: /* left */
+ tclearregion(0, term.c.y, term.c.x, term.c.y);
break;
- case 'L': /* Insert <n> blank lines */
- DEFAULT(escseq.arg[0], 1);
- tinsertblankline(escseq.arg[0]);
+ case 2: /* all */
+ tclearregion(0, term.c.y, term.col-1, term.c.y);
break;
- case 'l':
- if(escseq.priv && escseq.arg[0] == 25)
+ }
+ break;
+ case 'S':
+ case 'L': /* Insert <n> blank lines */
+ DEFAULT(escseq.arg[0], 1);
+ tinsertblankline(escseq.arg[0]);
+ break;
+ case 'l':
+ if(escseq.priv && escseq.arg[0] == 25)
term.c.hidden = 1;
- break;
- case 'M': /* Delete <n> lines */
- DEFAULT(escseq.arg[0], 1);
- tdeleteline(escseq.arg[0]);
- break;
- case 'P': /* Delete <n> char */
- DEFAULT(escseq.arg[0], 1);
- tdeletechar(escseq.arg[0]);
- break;
- case 'd': /* Move to <row> */
+ break;
+ case 'M': /* Delete <n> lines */
+ DEFAULT(escseq.arg[0], 1);
+ tdeleteline(escseq.arg[0]);
+ break;
+ case 'X':
+ case 'P': /* Delete <n> char */
+ DEFAULT(escseq.arg[0], 1);
+ tdeletechar(escseq.arg[0]);
+ break;
+ case 'd': /* Move to <row> */
+ DEFAULT(escseq.arg[0], 1);
+ tmoveto(term.c.x, escseq.arg[0]-1);
+ break;
+ case 'h': /* Set terminal mode */
+ if(escseq.priv && escseq.arg[0] == 25)
+ term.c.hidden = 0;
+ break;
+ case 'm': /* Terminal attribute (color) */
+ tsetattr(escseq.arg, escseq.narg);
+ break;
+ case 'r':
+ if(escseq.priv)
+ ;
+ else {
DEFAULT(escseq.arg[0], 1);
- tmoveto(term.c.x, escseq.arg[0]-1);
- break;
- case 'h': /* Set terminal mode */
- if(escseq.priv && escseq.arg[0] == 25)
- term.c.hidden = 0;
- break;
- case 'm': /* Terminal attribute (color) */
- tsetattr(escseq.arg, escseq.narg);
- break;
- case 'r':
- if(escseq.priv)
- ;
- else {
- DEFAULT(escseq.arg[0], 1);
- DEFAULT(escseq.arg[1], term.row);
- tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1);
- }
- break;
- case 's': /* Save cursor position */
- tcpos(CSsave);
- break;
- case 'u': /* Load cursor position */
- tcpos(CSload);
- break;
+ DEFAULT(escseq.arg[1], term.row);
+ tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1);
}
break;
+ case 's': /* Save cursor position */
+ tcpos(CSsave);
+ break;
+ case 'u': /* Load cursor position */
+ tcpos(CSload);
+ break;
}
}
void
-escdump(void) {
+csidump(void) {
int i;
- printf("rawbuf : %s\n", escseq.buf);
- printf("prechar : %c\n", escseq.pre);
- printf("private : %c\n", escseq.priv ? '?' : ' ');
- printf("narg : %d\n", escseq.narg);
+ printf("ESC [ %s", escseq.priv ? "? " : "");
if(escseq.narg)
for(i = 0; i < escseq.narg; i++)
- printf("\targ %d = %d\n", i, escseq.arg[i]);
- printf("mode : %c\n", escseq.mode);
+ printf("%d ", escseq.arg[i]);
+ if(escseq.mode)
+ putchar(escseq.mode);
+ putchar('\n');
}
void
-escreset(void) {
+csireset(void) {
memset(&escseq, 0, sizeof(escseq));
}
t@@ -781,21 +743,41 @@ tputtab(void) {
void
tputc(char c) {
- static int inesc = 0;
#if 0
dump(c);
#endif
- /* start of escseq */
- if(c == '\033')
- escreset(), inesc = 1;
- else if(inesc) {
- inesc = escaddc(c);
- } /* normal char */
- else switch(c) {
- default:
- tsetchar(c);
- tcursor(CSright);
- break;
+ if(term.esc & ESCin) {
+ if(term.esc & ESCcsi) {
+ escseq.buf[escseq.len++] = c;
+ if(BETWEEN(c, 0x40, 0x7E) || escseq.len >= ESCSIZ) {
+ term.esc = 0;
+ csiparse(), csihandle();
+ }
+ } else if (term.esc & ESCosc) {
+ if(c == ';') {
+ 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;
+ }
+ }
+ } else {
+ switch(c) {
case '\t':
tputtab();
break;
t@@ -811,6 +793,15 @@ tputc(char c) {
case '\a':
xbell();
break;
+ case '\033':
+ csireset();
+ term.esc = ESCin;
+ break;
+ default:
+ tsetchar(c);
+ tcursor(CSright);
+ break;
+ }
}
}
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.