aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Lohmann <20h@r-36.net>2012-08-29 23:14:20 +0200
committerChristoph Lohmann <20h@r-36.net>2012-08-29 23:14:20 +0200
commit6696ef8563a58ee07e4de5b3a74b52b91934f6a9 (patch)
tree557431b3487c6db551f89ac7d2613720e1cf7fb9
parentff040e9894f62fe28bf100488211d0a407740668 (diff)
downloadst-6696ef8563a58ee07e4de5b3a74b52b91934f6a9.tar.gz
st-6696ef8563a58ee07e4de5b3a74b52b91934f6a9.zip
Add OSC, DSC, PM, APC and settitle.
-rw-r--r--TODO1
-rw-r--r--st.c279
2 files changed, 191 insertions, 89 deletions
diff --git a/TODO b/TODO
index ea37a96..3ddeeb4 100644
--- a/TODO
+++ b/TODO
@@ -20,6 +20,7 @@ bugs
20* fix shift up/down (shift selection in emacs) 20* fix shift up/down (shift selection in emacs)
21* fix selection click 21* fix selection click
22* fix selection paste for xatom STRING 22* fix selection paste for xatom STRING
23* fix umlaut handling in settitle
23 24
24misc 25misc
25---- 26----
diff --git a/st.c b/st.c
index b9bab29..d8acce4 100644
--- a/st.c
+++ b/st.c
@@ -43,9 +43,10 @@
43#define XEMBED_FOCUS_OUT 5 43#define XEMBED_FOCUS_OUT 5
44 44
45/* Arbitrary sizes */ 45/* Arbitrary sizes */
46#define ESC_TITLE_SIZ 256
47#define ESC_BUF_SIZ 256 46#define ESC_BUF_SIZ 256
48#define ESC_ARG_SIZ 16 47#define ESC_ARG_SIZ 16
48#define STR_BUF_SIZ 256
49#define STR_ARG_SIZ 16
49#define DRAW_BUF_SIZ 1024 50#define DRAW_BUF_SIZ 1024
50#define UTF_SIZ 4 51#define UTF_SIZ 4
51#define XK_NO_MOD UINT_MAX 52#define XK_NO_MOD UINT_MAX
@@ -110,9 +111,9 @@ enum term_mode {
110enum escape_state { 111enum escape_state {
111 ESC_START = 1, 112 ESC_START = 1,
112 ESC_CSI = 2, 113 ESC_CSI = 2,
113 ESC_OSC = 4, 114 ESC_STR = 4, /* DSC, OSC, PM, APC */
114 ESC_TITLE = 8, 115 ESC_ALTCHARSET = 8,
115 ESC_ALTCHARSET = 16 116 ESC_STR_END = 16, /* a final string was encountered */
116}; 117};
117 118
118enum window_state { 119enum window_state {
@@ -158,6 +159,16 @@ typedef struct {
158 char mode; 159 char mode;
159} CSIEscape; 160} CSIEscape;
160 161
162/* STR Escape sequence structs */
163/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */
164typedef struct {
165 char type; /* ESC type ... */
166 char buf[STR_BUF_SIZ]; /* raw string */
167 int len; /* raw string length */
168 char *args[STR_ARG_SIZ];
169 int narg; /* nb of args */
170} STREscape;
171
161/* Internal representation of the screen */ 172/* Internal representation of the screen */
162typedef struct { 173typedef struct {
163 int row; /* nb row */ 174 int row; /* nb row */
@@ -170,8 +181,6 @@ typedef struct {
170 int bot; /* bottom scroll limit */ 181 int bot; /* bottom scroll limit */
171 int mode; /* terminal mode flags */ 182 int mode; /* terminal mode flags */
172 int esc; /* escape state flags */ 183 int esc; /* escape state flags */
173 char title[ESC_TITLE_SIZ];
174 int titlelen;
175 bool *tabs; 184 bool *tabs;
176} Term; 185} Term;
177 186
@@ -239,6 +248,10 @@ static void csidump(void);
239static void csihandle(void); 248static void csihandle(void);
240static void csiparse(void); 249static void csiparse(void);
241static void csireset(void); 250static void csireset(void);
251static void strdump(void);
252static void strhandle(void);
253static void strparse(void);
254static void strreset(void);
242 255
243static void tclearregion(int, int, int, int); 256static void tclearregion(int, int, int, int);
244static void tcursor(int); 257static void tcursor(int);
@@ -323,7 +336,8 @@ static void (*handler[LASTEvent])(XEvent *) = {
323static DC dc; 336static DC dc;
324static XWindow xw; 337static XWindow xw;
325static Term term; 338static Term term;
326static CSIEscape escseq; 339static CSIEscape csiescseq;
340static STREscape strescseq;
327static int cmdfd; 341static int cmdfd;
328static pid_t pid; 342static pid_t pid;
329static Selection sel; 343static Selection sel;
@@ -968,22 +982,22 @@ tnewline(int first_col) {
968void 982void
969csiparse(void) { 983csiparse(void) {
970 /* int noarg = 1; */ 984 /* int noarg = 1; */
971 char *p = escseq.buf; 985 char *p = csiescseq.buf;
972 986
973 escseq.narg = 0; 987 csiescseq.narg = 0;
974 if(*p == '?') 988 if(*p == '?')
975 escseq.priv = 1, p++; 989 csiescseq.priv = 1, p++;
976 990
977 while(p < escseq.buf+escseq.len) { 991 while(p < csiescseq.buf+csiescseq.len) {
978 while(isdigit(*p)) { 992 while(isdigit(*p)) {
979 escseq.arg[escseq.narg] *= 10; 993 csiescseq.arg[csiescseq.narg] *= 10;
980 escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */; 994 csiescseq.arg[csiescseq.narg] += *p++ - '0'/*, noarg = 0 */;
981 } 995 }
982 if(*p == ';' && escseq.narg+1 < ESC_ARG_SIZ) 996 if(*p == ';' && csiescseq.narg+1 < ESC_ARG_SIZ)
983 escseq.narg++, p++; 997 csiescseq.narg++, p++;
984 else { 998 else {
985 escseq.mode = *p; 999 csiescseq.mode = *p;
986 escseq.narg++; 1000 csiescseq.narg++;
987 return; 1001 return;
988 } 1002 }
989 } 1003 }
@@ -1166,7 +1180,7 @@ tsetscroll(int t, int b) {
1166 1180
1167void 1181void
1168csihandle(void) { 1182csihandle(void) {
1169 switch(escseq.mode) { 1183 switch(csiescseq.mode) {
1170 default: 1184 default:
1171 unknown: 1185 unknown:
1172 fprintf(stderr, "erresc: unknown csi "); 1186 fprintf(stderr, "erresc: unknown csi ");
@@ -1174,37 +1188,37 @@ csihandle(void) {
1174 /* die(""); */ 1188 /* die(""); */
1175 break; 1189 break;
1176 case '@': /* ICH -- Insert <n> blank char */ 1190 case '@': /* ICH -- Insert <n> blank char */
1177 DEFAULT(escseq.arg[0], 1); 1191 DEFAULT(csiescseq.arg[0], 1);
1178 tinsertblank(escseq.arg[0]); 1192 tinsertblank(csiescseq.arg[0]);
1179 break; 1193 break;
1180 case 'A': /* CUU -- Cursor <n> Up */ 1194 case 'A': /* CUU -- Cursor <n> Up */
1181 case 'e': 1195 case 'e':
1182 DEFAULT(escseq.arg[0], 1); 1196 DEFAULT(csiescseq.arg[0], 1);
1183 tmoveto(term.c.x, term.c.y-escseq.arg[0]); 1197 tmoveto(term.c.x, term.c.y-csiescseq.arg[0]);
1184 break; 1198 break;
1185 case 'B': /* CUD -- Cursor <n> Down */ 1199 case 'B': /* CUD -- Cursor <n> Down */
1186 DEFAULT(escseq.arg[0], 1); 1200 DEFAULT(csiescseq.arg[0], 1);
1187 tmoveto(term.c.x, term.c.y+escseq.arg[0]); 1201 tmoveto(term.c.x, term.c.y+csiescseq.arg[0]);
1188 break; 1202 break;
1189 case 'C': /* CUF -- Cursor <n> Forward */ 1203 case 'C': /* CUF -- Cursor <n> Forward */
1190 case 'a': 1204 case 'a':
1191 DEFAULT(escseq.arg[0], 1); 1205 DEFAULT(csiescseq.arg[0], 1);
1192 tmoveto(term.c.x+escseq.arg[0], term.c.y); 1206 tmoveto(term.c.x+csiescseq.arg[0], term.c.y);
1193 break; 1207 break;
1194 case 'D': /* CUB -- Cursor <n> Backward */ 1208 case 'D': /* CUB -- Cursor <n> Backward */
1195 DEFAULT(escseq.arg[0], 1); 1209 DEFAULT(csiescseq.arg[0], 1);
1196 tmoveto(term.c.x-escseq.arg[0], term.c.y); 1210 tmoveto(term.c.x-csiescseq.arg[0], term.c.y);
1197 break; 1211 break;
1198 case 'E': /* CNL -- Cursor <n> Down and first col */ 1212 case 'E': /* CNL -- Cursor <n> Down and first col */
1199 DEFAULT(escseq.arg[0], 1); 1213 DEFAULT(csiescseq.arg[0], 1);
1200 tmoveto(0, term.c.y+escseq.arg[0]); 1214 tmoveto(0, term.c.y+csiescseq.arg[0]);
1201 break; 1215 break;
1202 case 'F': /* CPL -- Cursor <n> Up and first col */ 1216 case 'F': /* CPL -- Cursor <n> Up and first col */
1203 DEFAULT(escseq.arg[0], 1); 1217 DEFAULT(csiescseq.arg[0], 1);
1204 tmoveto(0, term.c.y-escseq.arg[0]); 1218 tmoveto(0, term.c.y-csiescseq.arg[0]);
1205 break; 1219 break;
1206 case 'g': /* TBC -- Tabulation clear */ 1220 case 'g': /* TBC -- Tabulation clear */
1207 switch (escseq.arg[0]) { 1221 switch (csiescseq.arg[0]) {
1208 case 0: /* clear current tab stop */ 1222 case 0: /* clear current tab stop */
1209 term.tabs[term.c.x] = 0; 1223 term.tabs[term.c.x] = 0;
1210 break; 1224 break;
@@ -1217,23 +1231,23 @@ csihandle(void) {
1217 break; 1231 break;
1218 case 'G': /* CHA -- Move to <col> */ 1232 case 'G': /* CHA -- Move to <col> */
1219 case '`': /* XXX: HPA -- same? */ 1233 case '`': /* XXX: HPA -- same? */
1220 DEFAULT(escseq.arg[0], 1); 1234 DEFAULT(csiescseq.arg[0], 1);
1221 tmoveto(escseq.arg[0]-1, term.c.y); 1235 tmoveto(csiescseq.arg[0]-1, term.c.y);
1222 break; 1236 break;
1223 case 'H': /* CUP -- Move to <row> <col> */ 1237 case 'H': /* CUP -- Move to <row> <col> */
1224 case 'f': /* XXX: HVP -- same? */ 1238 case 'f': /* XXX: HVP -- same? */
1225 DEFAULT(escseq.arg[0], 1); 1239 DEFAULT(csiescseq.arg[0], 1);
1226 DEFAULT(escseq.arg[1], 1); 1240 DEFAULT(csiescseq.arg[1], 1);
1227 tmoveto(escseq.arg[1]-1, escseq.arg[0]-1); 1241 tmoveto(csiescseq.arg[1]-1, csiescseq.arg[0]-1);
1228 break; 1242 break;
1229 case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */ 1243 case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */
1230 DEFAULT(escseq.arg[0], 1); 1244 DEFAULT(csiescseq.arg[0], 1);
1231 while (escseq.arg[0]--) 1245 while (csiescseq.arg[0]--)
1232 tputtab(); 1246 tputtab();
1233 break; 1247 break;
1234 case 'J': /* ED -- Clear screen */ 1248 case 'J': /* ED -- Clear screen */
1235 sel.bx = -1; 1249 sel.bx = -1;
1236 switch(escseq.arg[0]) { 1250 switch(csiescseq.arg[0]) {
1237 case 0: /* below */ 1251 case 0: /* below */
1238 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); 1252 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
1239 if(term.c.y < term.row-1) 1253 if(term.c.y < term.row-1)
@@ -1252,7 +1266,7 @@ csihandle(void) {
1252 } 1266 }
1253 break; 1267 break;
1254 case 'K': /* EL -- Clear line */ 1268 case 'K': /* EL -- Clear line */
1255 switch(escseq.arg[0]) { 1269 switch(csiescseq.arg[0]) {
1256 case 0: /* right */ 1270 case 0: /* right */
1257 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); 1271 tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
1258 break; 1272 break;
@@ -1265,20 +1279,20 @@ csihandle(void) {
1265 } 1279 }
1266 break; 1280 break;
1267 case 'S': /* SU -- Scroll <n> line up */ 1281 case 'S': /* SU -- Scroll <n> line up */
1268 DEFAULT(escseq.arg[0], 1); 1282 DEFAULT(csiescseq.arg[0], 1);
1269 tscrollup(term.top, escseq.arg[0]); 1283 tscrollup(term.top, csiescseq.arg[0]);
1270 break; 1284 break;
1271 case 'T': /* SD -- Scroll <n> line down */ 1285 case 'T': /* SD -- Scroll <n> line down */
1272 DEFAULT(escseq.arg[0], 1); 1286 DEFAULT(csiescseq.arg[0], 1);
1273 tscrolldown(term.top, escseq.arg[0]); 1287 tscrolldown(term.top, csiescseq.arg[0]);
1274 break; 1288 break;
1275 case 'L': /* IL -- Insert <n> blank lines */ 1289 case 'L': /* IL -- Insert <n> blank lines */
1276 DEFAULT(escseq.arg[0], 1); 1290 DEFAULT(csiescseq.arg[0], 1);
1277 tinsertblankline(escseq.arg[0]); 1291 tinsertblankline(csiescseq.arg[0]);
1278 break; 1292 break;
1279 case 'l': /* RM -- Reset Mode */ 1293 case 'l': /* RM -- Reset Mode */
1280 if(escseq.priv) { 1294 if(csiescseq.priv) {
1281 switch(escseq.arg[0]) { 1295 switch(csiescseq.arg[0]) {
1282 case 1: 1296 case 1:
1283 term.mode &= ~MODE_APPKEYPAD; 1297 term.mode &= ~MODE_APPKEYPAD;
1284 break; 1298 break;
@@ -1312,7 +1326,7 @@ csihandle(void) {
1312 tclearregion(0, 0, term.col-1, term.row-1); 1326 tclearregion(0, 0, term.col-1, term.row-1);
1313 tswapscreen(); 1327 tswapscreen();
1314 } 1328 }
1315 if(escseq.arg[0] != 1049) 1329 if(csiescseq.arg[0] != 1049)
1316 break; 1330 break;
1317 case 1048: 1331 case 1048:
1318 tcursor(CURSOR_LOAD); 1332 tcursor(CURSOR_LOAD);
@@ -1321,7 +1335,7 @@ csihandle(void) {
1321 goto unknown; 1335 goto unknown;
1322 } 1336 }
1323 } else { 1337 } else {
1324 switch(escseq.arg[0]) { 1338 switch(csiescseq.arg[0]) {
1325 case 4: 1339 case 4:
1326 term.mode &= ~MODE_INSERT; 1340 term.mode &= ~MODE_INSERT;
1327 break; 1341 break;
@@ -1331,25 +1345,25 @@ csihandle(void) {
1331 } 1345 }
1332 break; 1346 break;
1333 case 'M': /* DL -- Delete <n> lines */ 1347 case 'M': /* DL -- Delete <n> lines */
1334 DEFAULT(escseq.arg[0], 1); 1348 DEFAULT(csiescseq.arg[0], 1);
1335 tdeleteline(escseq.arg[0]); 1349 tdeleteline(csiescseq.arg[0]);
1336 break; 1350 break;
1337 case 'X': /* ECH -- Erase <n> char */ 1351 case 'X': /* ECH -- Erase <n> char */
1338 DEFAULT(escseq.arg[0], 1); 1352 DEFAULT(csiescseq.arg[0], 1);
1339 tclearregion(term.c.x, term.c.y, term.c.x + escseq.arg[0], term.c.y); 1353 tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0], term.c.y);
1340 break; 1354 break;
1341 case 'P': /* DCH -- Delete <n> char */ 1355 case 'P': /* DCH -- Delete <n> char */
1342 DEFAULT(escseq.arg[0], 1); 1356 DEFAULT(csiescseq.arg[0], 1);
1343 tdeletechar(escseq.arg[0]); 1357 tdeletechar(csiescseq.arg[0]);
1344 break; 1358 break;
1345 /* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation <n> tab stops */ 1359 /* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation <n> tab stops */
1346 case 'd': /* VPA -- Move to <row> */ 1360 case 'd': /* VPA -- Move to <row> */
1347 DEFAULT(escseq.arg[0], 1); 1361 DEFAULT(csiescseq.arg[0], 1);
1348 tmoveto(term.c.x, escseq.arg[0]-1); 1362 tmoveto(term.c.x, csiescseq.arg[0]-1);
1349 break; 1363 break;
1350 case 'h': /* SM -- Set terminal mode */ 1364 case 'h': /* SM -- Set terminal mode */
1351 if(escseq.priv) { 1365 if(csiescseq.priv) {
1352 switch(escseq.arg[0]) { 1366 switch(csiescseq.arg[0]) {
1353 case 1: 1367 case 1:
1354 term.mode |= MODE_APPKEYPAD; 1368 term.mode |= MODE_APPKEYPAD;
1355 break; 1369 break;
@@ -1367,7 +1381,7 @@ csihandle(void) {
1367 break; 1381 break;
1368 case 12: /* att610 -- Start blinking cursor (IGNORED) */ 1382 case 12: /* att610 -- Start blinking cursor (IGNORED) */
1369 /* fallthrough for xterm cvvis = CSI [ ? 12 ; 25 h */ 1383 /* fallthrough for xterm cvvis = CSI [ ? 12 ; 25 h */
1370 if(escseq.narg > 1 && escseq.arg[1] != 25) 1384 if(csiescseq.narg > 1 && csiescseq.arg[1] != 25)
1371 break; 1385 break;
1372 case 25: 1386 case 25:
1373 term.c.state &= ~CURSOR_HIDE; 1387 term.c.state &= ~CURSOR_HIDE;
@@ -1385,7 +1399,7 @@ csihandle(void) {
1385 tclearregion(0, 0, term.col-1, term.row-1); 1399 tclearregion(0, 0, term.col-1, term.row-1);
1386 else 1400 else
1387 tswapscreen(); 1401 tswapscreen();
1388 if(escseq.arg[0] != 1049) 1402 if(csiescseq.arg[0] != 1049)
1389 break; 1403 break;
1390 case 1048: 1404 case 1048:
1391 tcursor(CURSOR_SAVE); 1405 tcursor(CURSOR_SAVE);
@@ -1393,7 +1407,7 @@ csihandle(void) {
1393 default: goto unknown; 1407 default: goto unknown;
1394 } 1408 }
1395 } else { 1409 } else {
1396 switch(escseq.arg[0]) { 1410 switch(csiescseq.arg[0]) {
1397 case 4: 1411 case 4:
1398 term.mode |= MODE_INSERT; 1412 term.mode |= MODE_INSERT;
1399 break; 1413 break;
@@ -1402,15 +1416,15 @@ csihandle(void) {
1402 }; 1416 };
1403 break; 1417 break;
1404 case 'm': /* SGR -- Terminal attribute (color) */ 1418 case 'm': /* SGR -- Terminal attribute (color) */
1405 tsetattr(escseq.arg, escseq.narg); 1419 tsetattr(csiescseq.arg, csiescseq.narg);
1406 break; 1420 break;
1407 case 'r': /* DECSTBM -- Set Scrolling Region */ 1421 case 'r': /* DECSTBM -- Set Scrolling Region */
1408 if(escseq.priv) 1422 if(csiescseq.priv)
1409 goto unknown; 1423 goto unknown;
1410 else { 1424 else {
1411 DEFAULT(escseq.arg[0], 1); 1425 DEFAULT(csiescseq.arg[0], 1);
1412 DEFAULT(escseq.arg[1], term.row); 1426 DEFAULT(csiescseq.arg[1], term.row);
1413 tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); 1427 tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1);
1414 tmoveto(0, 0); 1428 tmoveto(0, 0);
1415 } 1429 }
1416 break; 1430 break;
@@ -1427,8 +1441,8 @@ void
1427csidump(void) { 1441csidump(void) {
1428 int i; 1442 int i;
1429 printf("ESC["); 1443 printf("ESC[");
1430 for(i = 0; i < escseq.len; i++) { 1444 for(i = 0; i < csiescseq.len; i++) {
1431 uint c = escseq.buf[i] & 0xff; 1445 uint c = csiescseq.buf[i] & 0xff;
1432 if(isprint(c)) putchar(c); 1446 if(isprint(c)) putchar(c);
1433 else if(c == '\n') printf("(\\n)"); 1447 else if(c == '\n') printf("(\\n)");
1434 else if(c == '\r') printf("(\\r)"); 1448 else if(c == '\r') printf("(\\r)");
@@ -1440,7 +1454,80 @@ csidump(void) {
1440 1454
1441void 1455void
1442csireset(void) { 1456csireset(void) {
1443 memset(&escseq, 0, sizeof(escseq)); 1457 memset(&csiescseq, 0, sizeof(csiescseq));
1458}
1459
1460void
1461strhandle(void) {
1462 char *p;
1463
1464 p = strescseq.buf;
1465
1466 switch(strescseq.type) {
1467 case ']': /* OSC -- Operating System Command */
1468 switch(p[0]) {
1469 case '0':
1470 case '2':
1471 /*
1472 * TODO: Handle special chars in string, like umlauts.
1473 */
1474 if(p[1] == ';') {
1475 if(!strncmp(strescseq.buf, "settitle ", 9)) {
1476 XStoreName(xw.dpy, xw.win, strescseq.buf+11);
1477 } else {
1478 XStoreName(xw.dpy, xw.win, strescseq.buf+2);
1479 }
1480 }
1481 break;
1482 case ';':
1483 XStoreName(xw.dpy, xw.win, strescseq.buf+1);
1484 break;
1485 case '4': /* TODO: Set color (arg0) to "rgb:%hexr/$hexg/$hexb" (arg1) */
1486 break;
1487 default:
1488 fprintf(stderr, "erresc: unknown str ");
1489 strdump();
1490 break;
1491 }
1492 break;
1493 case 'P': /* DSC -- Device Control String */
1494 case '_': /* APC -- Application Program Command */
1495 case '^': /* PM -- Privacy Message */
1496 default:
1497 fprintf(stderr, "erresc: unknown str ");
1498 strdump();
1499 /* die(""); */
1500 break;
1501 }
1502}
1503
1504void
1505strparse(void) {
1506 /*
1507 * TODO: Implement parsing like for CSI when required.
1508 * Format: ESC type cmd ';' arg0 [';' argn] ESC \
1509 */
1510 return;
1511}
1512
1513void
1514strdump(void) {
1515 int i;
1516 printf("ESC%c", strescseq.type);
1517 for(i = 0; i < strescseq.len; i++) {
1518 uint c = strescseq.buf[i] & 0xff;
1519 if(isprint(c)) putchar(c);
1520 else if(c == '\n') printf("(\\n)");
1521 else if(c == '\r') printf("(\\r)");
1522 else if(c == 0x1b) printf("(\\e)");
1523 else printf("(%02x)", c);
1524 }
1525 printf("ESC\\\n");
1526}
1527
1528void
1529strreset(void) {
1530 memset(&strescseq, 0, sizeof(strescseq));
1444} 1531}
1445 1532
1446void 1533void
@@ -1457,25 +1544,31 @@ tputc(char *c) {
1457 char ascii = *c; 1544 char ascii = *c;
1458 if(term.esc & ESC_START) { 1545 if(term.esc & ESC_START) {
1459 if(term.esc & ESC_CSI) { 1546 if(term.esc & ESC_CSI) {
1460 escseq.buf[escseq.len++] = ascii; 1547 csiescseq.buf[csiescseq.len++] = ascii;
1461 if(BETWEEN(ascii, 0x40, 0x7E) || escseq.len >= ESC_BUF_SIZ) { 1548 if(BETWEEN(ascii, 0x40, 0x7E) || csiescseq.len >= ESC_BUF_SIZ) {
1462 term.esc = 0; 1549 term.esc = 0;
1463 csiparse(), csihandle(); 1550 csiparse(), csihandle();
1464 } 1551 }
1465 /* TODO: handle other OSC */ 1552 } else if(term.esc & ESC_STR) {
1466 } else if(term.esc & ESC_OSC) { 1553 switch(ascii) {
1467 if(ascii == ';') { 1554 case '\033':
1468 term.titlelen = 0; 1555 term.esc = ESC_START | ESC_STR_END;
1469 term.esc = ESC_START | ESC_TITLE; 1556 break;
1470 } 1557 case '\a': /* backwards compatibility to xterm */
1471 } else if(term.esc & ESC_TITLE) {
1472 if(ascii == '\a' || term.titlelen+1 >= ESC_TITLE_SIZ) {
1473 term.esc = 0; 1558 term.esc = 0;
1474 term.title[term.titlelen] = '\0'; 1559 strhandle();
1475 XStoreName(xw.dpy, xw.win, term.title); 1560 break;
1476 } else { 1561 default:
1477 term.title[term.titlelen++] = ascii; 1562 strescseq.buf[strescseq.len++] = ascii;
1563 if (strescseq.len+1 >= STR_BUF_SIZ) {
1564 term.esc = 0;
1565 strhandle();
1566 }
1478 } 1567 }
1568 } else if(term.esc & ESC_STR_END) {
1569 term.esc = 0;
1570 if(ascii == '\\')
1571 strhandle();
1479 } else if(term.esc & ESC_ALTCHARSET) { 1572 } else if(term.esc & ESC_ALTCHARSET) {
1480 switch(ascii) { 1573 switch(ascii) {
1481 case '0': /* Line drawing crap */ 1574 case '0': /* Line drawing crap */
@@ -1493,8 +1586,13 @@ tputc(char *c) {
1493 case '[': 1586 case '[':
1494 term.esc |= ESC_CSI; 1587 term.esc |= ESC_CSI;
1495 break; 1588 break;
1496 case ']': 1589 case 'P': /* DCS -- Device Control String */
1497 term.esc |= ESC_OSC; 1590 case '_': /* APC -- Application Program Command */
1591 case '^': /* PM -- Privacy Message */
1592 case ']': /* OSC -- Operating System Command */
1593 strreset();
1594 strescseq.type = ascii;
1595 term.esc |= ESC_STR;
1498 break; 1596 break;
1499 case '(': 1597 case '(':
1500 term.esc |= ESC_ALTCHARSET; 1598 term.esc |= ESC_ALTCHARSET;
@@ -1541,6 +1639,9 @@ tputc(char *c) {
1541 tcursor(CURSOR_LOAD); 1639 tcursor(CURSOR_LOAD);
1542 term.esc = 0; 1640 term.esc = 0;
1543 break; 1641 break;
1642 case '\\': /* ST -- Stop */
1643 term.esc = 0;
1644 break;
1544 default: 1645 default:
1545 fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", 1646 fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
1546 (uchar) ascii, isprint(ascii)?ascii:'.'); 1647 (uchar) ascii, isprint(ascii)?ascii:'.');