[hackers] [st] Add OSC, DSC, PM, APC and settitle. || Christoph Lohmann

From: <hg_AT_suckless.org>
Date: Wed, 29 Aug 2012 23:17:05 +0200 (CEST)

changeset: 253:fce86b23b2ea
tag: tip
user: Christoph Lohmann <20h_AT_r-36.net>
date: Wed Aug 29 23:14:20 2012 +0200
files: TODO st.c
description:
Add OSC, DSC, PM, APC and settitle.


diff -r 0953577be747 -r fce86b23b2ea TODO
--- a/TODO Wed Aug 29 21:13:47 2012 +0200
+++ b/TODO Wed Aug 29 23:14:20 2012 +0200
_AT_@ -20,6 +20,7 @@
 * fix shift up/down (shift selection in emacs)
 * fix selection click
 * fix selection paste for xatom STRING
+* fix umlaut handling in settitle
 
 misc
 ----
diff -r 0953577be747 -r fce86b23b2ea st.c
--- a/st.c Wed Aug 29 21:13:47 2012 +0200
+++ b/st.c Wed Aug 29 23:14:20 2012 +0200
_AT_@ -43,9 +43,10 @@
 #define XEMBED_FOCUS_OUT 5
 
 /* Arbitrary sizes */
-#define ESC_TITLE_SIZ 256
 #define ESC_BUF_SIZ 256
 #define ESC_ARG_SIZ 16
+#define STR_BUF_SIZ 256
+#define STR_ARG_SIZ 16
 #define DRAW_BUF_SIZ 1024
 #define UTF_SIZ 4
 #define XK_NO_MOD UINT_MAX
_AT_@ -110,9 +111,9 @@
 enum escape_state {
         ESC_START = 1,
         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 {
_AT_@ -158,6 +159,16 @@
         char mode;
 } 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 */
 typedef struct {
         int row; /* nb row */
_AT_@ -170,8 +181,6 @@
         int bot; /* bottom scroll limit */
         int mode; /* terminal mode flags */
         int esc; /* escape state flags */
- char title[ESC_TITLE_SIZ];
- int titlelen;
         bool *tabs;
 } Term;
 
_AT_@ -239,6 +248,10 @@
 static void csihandle(void);
 static void csiparse(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 tcursor(int);
_AT_@ -323,7 +336,8 @@
 static DC dc;
 static XWindow xw;
 static Term term;
-static CSIEscape escseq;
+static CSIEscape csiescseq;
+static STREscape strescseq;
 static int cmdfd;
 static pid_t pid;
 static Selection sel;
_AT_@ -968,22 +982,22 @@
 void
 csiparse(void) {
         /* int noarg = 1; */
- char *p = escseq.buf;
+ char *p = csiescseq.buf;
 
- escseq.narg = 0;
+ csiescseq.narg = 0;
         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)) {
- 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 {
- escseq.mode = *p;
- escseq.narg++;
+ csiescseq.mode = *p;
+ csiescseq.narg++;
                         return;
                 }
         }
_AT_@ -1166,7 +1180,7 @@
 
 void
 csihandle(void) {
- switch(escseq.mode) {
+ switch(csiescseq.mode) {
         default:
         unknown:
                 fprintf(stderr, "erresc: unknown csi ");
_AT_@ -1174,37 +1188,37 @@
                 /* die(""); */
                 break;
         case '_AT_': /* ICH -- Insert <n> blank char */
- DEFAULT(escseq.arg[0], 1);
- tinsertblank(escseq.arg[0]);
+ DEFAULT(csiescseq.arg[0], 1);
+ tinsertblank(csiescseq.arg[0]);
                 break;
         case 'A': /* CUU -- Cursor <n> Up */
         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;
         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;
         case 'C': /* CUF -- Cursor <n> Forward */
         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;
         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;
         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;
         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;
         case 'g': /* TBC -- Tabulation clear */
- switch (escseq.arg[0]) {
+ switch (csiescseq.arg[0]) {
                 case 0: /* clear current tab stop */
                         term.tabs[term.c.x] = 0;
                         break;
_AT_@ -1217,23 +1231,23 @@
                 break;
         case 'G': /* CHA -- Move to <col> */
         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;
         case 'H': /* CUP -- Move to <row> <col> */
         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;
         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();
                 break;
         case 'J': /* ED -- Clear screen */
                 sel.bx = -1;
- switch(escseq.arg[0]) {
+ switch(csiescseq.arg[0]) {
                 case 0: /* below */
                         tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
                         if(term.c.y < term.row-1)
_AT_@ -1252,7 +1266,7 @@
                 }
                 break;
         case 'K': /* EL -- Clear line */
- switch(escseq.arg[0]) {
+ switch(csiescseq.arg[0]) {
                 case 0: /* right */
                         tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
                         break;
_AT_@ -1265,20 +1279,20 @@
                 }
                 break;
         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;
         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;
         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;
         case 'l': /* RM -- Reset Mode */
- if(escseq.priv) {
- switch(escseq.arg[0]) {
+ if(csiescseq.priv) {
+ switch(csiescseq.arg[0]) {
                         case 1:
                                 term.mode &= ~MODE_APPKEYPAD;
                                 break;
_AT_@ -1312,7 +1326,7 @@
                                         tclearregion(0, 0, term.col-1, term.row-1);
                                         tswapscreen();
                                 }
- if(escseq.arg[0] != 1049)
+ if(csiescseq.arg[0] != 1049)
                                         break;
                         case 1048:
                                 tcursor(CURSOR_LOAD);
_AT_@ -1321,7 +1335,7 @@
                                 goto unknown;
                         }
                 } else {
- switch(escseq.arg[0]) {
+ switch(csiescseq.arg[0]) {
                         case 4:
                                 term.mode &= ~MODE_INSERT;
                                 break;
_AT_@ -1331,25 +1345,25 @@
                 }
                 break;
         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;
         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;
         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;
         /* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation <n> tab stops */
         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;
         case 'h': /* SM -- Set terminal mode */
- if(escseq.priv) {
- switch(escseq.arg[0]) {
+ if(csiescseq.priv) {
+ switch(csiescseq.arg[0]) {
                         case 1:
                                 term.mode |= MODE_APPKEYPAD;
                                 break;
_AT_@ -1367,7 +1381,7 @@
                                 break;
                         case 12: /* att610 -- Start blinking cursor (IGNORED) */
                                  /* 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;
                         case 25:
                                 term.c.state &= ~CURSOR_HIDE;
_AT_@ -1385,7 +1399,7 @@
                                         tclearregion(0, 0, term.col-1, term.row-1);
                                 else
                                         tswapscreen();
- if(escseq.arg[0] != 1049)
+ if(csiescseq.arg[0] != 1049)
                                         break;
                         case 1048:
                                 tcursor(CURSOR_SAVE);
_AT_@ -1393,7 +1407,7 @@
                         default: goto unknown;
                         }
                 } else {
- switch(escseq.arg[0]) {
+ switch(csiescseq.arg[0]) {
                         case 4:
                                 term.mode |= MODE_INSERT;
                                 break;
_AT_@ -1402,15 +1416,15 @@
                 };
                 break;
         case 'm': /* SGR -- Terminal attribute (color) */
- tsetattr(escseq.arg, escseq.narg);
+ tsetattr(csiescseq.arg, csiescseq.narg);
                 break;
         case 'r': /* DECSTBM -- Set Scrolling Region */
- if(escseq.priv)
+ if(csiescseq.priv)
                         goto unknown;
                 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);
                 }
                 break;
_AT_@ -1427,8 +1441,8 @@
 csidump(void) {
         int i;
         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);
                 else if(c == '\n') printf("(\\n)");
                 else if(c == '\r') printf("(\\r)");
_AT_@ -1440,7 +1454,80 @@
 
 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
_AT_@ -1457,25 +1544,31 @@
         char ascii = *c;
         if(term.esc & ESC_START) {
                 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;
                                 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_STR) {
+ switch(ascii) {
+ case '\033':
+ term.esc = ESC_START | ESC_STR_END;
+ break;
+ case '\a': /* backwards compatibility to xterm */
+ term.esc = 0;
+ strhandle();
+ break;
+ default:
+ strescseq.buf[strescseq.len++] = ascii;
+ if (strescseq.len+1 >= STR_BUF_SIZ) {
+ term.esc = 0;
+ strhandle();
+ }
                         }
- } else if(term.esc & ESC_TITLE) {
- if(ascii == '\a' || term.titlelen+1 >= ESC_TITLE_SIZ) {
- term.esc = 0;
- term.title[term.titlelen] = '\0';
- XStoreName(xw.dpy, xw.win, term.title);
- } else {
- term.title[term.titlelen++] = ascii;
- }
+ } else if(term.esc & ESC_STR_END) {
+ term.esc = 0;
+ if(ascii == '\\')
+ strhandle();
                 } else if(term.esc & ESC_ALTCHARSET) {
                         switch(ascii) {
                         case '0': /* Line drawing crap */
_AT_@ -1493,8 +1586,13 @@
                         case '[':
                                 term.esc |= ESC_CSI;
                                 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;
                         case '(':
                                 term.esc |= ESC_ALTCHARSET;
_AT_@ -1541,6 +1639,9 @@
                                 tcursor(CURSOR_LOAD);
                                 term.esc = 0;
                                 break;
+ case '\\': /* ST -- Stop */
+ term.esc = 0;
+ break;
                         default:
                                 fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
                                     (uchar) ascii, isprint(ascii)?ascii:'.');
Received on Wed Aug 29 2012 - 23:17:05 CEST

This archive was generated by hypermail 2.3.0 : Wed Aug 29 2012 - 23:24:06 CEST