diff options
| author | Aurélien Aptel <aurelien.aptel@gmail.com> | 2010-02-08 23:16:55 +0100 |
|---|---|---|
| committer | Aurélien Aptel <aurelien.aptel@gmail.com> | 2010-02-08 23:16:55 +0100 |
| commit | eff05c7b90429ac4dddbbc53ac7d4c05dfc5efd4 (patch) | |
| tree | 41be2ccd915515b4223624d165a2bb08bd94692b | |
| parent | e6b3f5c755349ba7a339dd43958870e4cceb57bf (diff) | |
| download | st-eff05c7b90429ac4dddbbc53ac7d4c05dfc5efd4.tar.gz st-eff05c7b90429ac4dddbbc53ac7d4c05dfc5efd4.zip | |
more escapes & more compability:
cursor keys are handled in kpress according to the Application Mode (DECPAM).
define & enum were renamed.
tcursor() is now tmovecursor() which is more correct.
tcpos() is now tcursor(), as DECSC is also supposed to save attributes.
capnames are indicated whenever possible.
Currently:
alsamixer looks fine, totally usable.
ncmpc is almost ok.
emacs looks like shit.
| -rw-r--r-- | config.h | 5 | ||||
| -rw-r--r-- | st.c | 318 |
2 files changed, 178 insertions, 145 deletions
| @@ -31,10 +31,6 @@ static Key key[] = { | |||
| 31 | { XK_End, "\033[4~" }, | 31 | { XK_End, "\033[4~" }, |
| 32 | { XK_Prior, "\033[5~" }, | 32 | { XK_Prior, "\033[5~" }, |
| 33 | { XK_Next, "\033[6~" }, | 33 | { XK_Next, "\033[6~" }, |
| 34 | { XK_Left, "\033[D" }, | ||
| 35 | { XK_Right, "\033[C" }, | ||
| 36 | { XK_Up, "\033[A" }, | ||
| 37 | { XK_Down, "\033[B" }, | ||
| 38 | }; | 34 | }; |
| 39 | 35 | ||
| 40 | static char gfx[] = { | 36 | static char gfx[] = { |
| @@ -70,4 +66,5 @@ static char gfx[] = { | |||
| 70 | ['l'] = '+', | 66 | ['l'] = '+', |
| 71 | ['k'] = '+', | 67 | ['k'] = '+', |
| 72 | ['x'] = '|', | 68 | ['x'] = '|', |
| 69 | [255] = 0, | ||
| 73 | }; | 70 | }; |
| @@ -23,10 +23,10 @@ | |||
| 23 | #define TNAME "xterm" | 23 | #define TNAME "xterm" |
| 24 | 24 | ||
| 25 | /* Arbitrary sizes */ | 25 | /* Arbitrary sizes */ |
| 26 | #define TITLESIZ 256 | 26 | #define ESC_TITLE_SIZ 256 |
| 27 | #define ESCSIZ 256 | 27 | #define ESC_BUF_SIZ 256 |
| 28 | #define ESCARGSIZ 16 | 28 | #define ESC_ARG_SIZ 16 |
| 29 | #define MAXDRAWBUF 1024 | 29 | #define DRAW_BUF_SIZ 1024 |
| 30 | 30 | ||
| 31 | #define SERRNO strerror(errno) | 31 | #define SERRNO strerror(errno) |
| 32 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | 32 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
| @@ -38,21 +38,19 @@ | |||
| 38 | #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) | 38 | #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) |
| 39 | 39 | ||
| 40 | /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ | 40 | /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ |
| 41 | enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4, ATgfx=8 }; | 41 | enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; |
| 42 | enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSsave, CSload }; | 42 | enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, CURSOR_HIDE, CURSOR_DRAW, CURSOR_SAVE, CURSOR_LOAD }; |
| 43 | enum { CRset=1, CRupdate=2 }; | 43 | enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; |
| 44 | enum { TMwrap=1, TMinsert=2 }; | 44 | enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4 }; |
| 45 | enum { ESCin=1, ESCcsi=2, ESCosc=4, ESCtitle=8, ESCcharset=16 }; | 45 | enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; |
| 46 | enum { SCupdate, SCredraw }; | 46 | enum { SCREEN_UPDATE, SCREEN_REDRAW }; |
| 47 | |||
| 48 | typedef int Color; | ||
| 49 | 47 | ||
| 50 | typedef struct { | 48 | typedef struct { |
| 51 | char c; /* character code */ | 49 | char c; /* character code */ |
| 52 | char mode; /* attribute flags */ | 50 | char mode; /* attribute flags */ |
| 53 | Color fg; /* foreground */ | 51 | int fg; /* foreground */ |
| 54 | Color bg; /* background */ | 52 | int bg; /* background */ |
| 55 | char state; /* state flag */ | 53 | char state; /* state flags */ |
| 56 | } Glyph; | 54 | } Glyph; |
| 57 | 55 | ||
| 58 | typedef Glyph* Line; | 56 | typedef Glyph* Line; |
| @@ -67,11 +65,11 @@ typedef struct { | |||
| 67 | /* CSI Escape sequence structs */ | 65 | /* CSI Escape sequence structs */ |
| 68 | /* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */ | 66 | /* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */ |
| 69 | typedef struct { | 67 | typedef struct { |
| 70 | char buf[ESCSIZ]; /* raw string */ | 68 | char buf[ESC_BUF_SIZ]; /* raw string */ |
| 71 | int len; /* raw string length */ | 69 | int len; /* raw string length */ |
| 72 | char priv; | 70 | char priv; |
| 73 | int arg[ESCARGSIZ]; | 71 | int arg[ESC_ARG_SIZ]; |
| 74 | int narg; /* nb of args */ | 72 | int narg; /* nb of args */ |
| 75 | char mode; | 73 | char mode; |
| 76 | } CSIEscape; | 74 | } CSIEscape; |
| 77 | 75 | ||
| @@ -83,9 +81,9 @@ typedef struct { | |||
| 83 | TCursor c; /* cursor */ | 81 | TCursor c; /* cursor */ |
| 84 | int top; /* top scroll limit */ | 82 | int top; /* top scroll limit */ |
| 85 | int bot; /* bottom scroll limit */ | 83 | int bot; /* bottom scroll limit */ |
| 86 | int mode; /* terminal mode */ | 84 | int mode; /* terminal mode flags */ |
| 87 | int esc; | 85 | int esc; /* escape state flags */ |
| 88 | char title[TITLESIZ]; | 86 | char title[ESC_TITLE_SIZ]; |
| 89 | int titlelen; | 87 | int titlelen; |
| 90 | } Term; | 88 | } Term; |
| 91 | 89 | ||
| @@ -102,7 +100,7 @@ typedef struct { | |||
| 102 | 100 | ||
| 103 | typedef struct { | 101 | typedef struct { |
| 104 | KeySym k; | 102 | KeySym k; |
| 105 | char s[ESCSIZ]; | 103 | char s[ESC_BUF_SIZ]; |
| 106 | } Key; | 104 | } Key; |
| 107 | 105 | ||
| 108 | #include "config.h" | 106 | #include "config.h" |
| @@ -126,8 +124,8 @@ static void csiparse(void); | |||
| 126 | static void csireset(void); | 124 | static void csireset(void); |
| 127 | 125 | ||
| 128 | static void tclearregion(int, int, int, int); | 126 | static void tclearregion(int, int, int, int); |
| 129 | static void tcpos(int); | ||
| 130 | static void tcursor(int); | 127 | static void tcursor(int); |
| 128 | static void tmovecursor(int); | ||
| 131 | static void tdeletechar(int); | 129 | static void tdeletechar(int); |
| 132 | static void tdeleteline(int); | 130 | static void tdeleteline(int); |
| 133 | static void tinsertblank(int); | 131 | static void tinsertblank(int); |
| @@ -187,7 +185,7 @@ tdump(void) { | |||
| 187 | putchar('#'); | 185 | putchar('#'); |
| 188 | else { | 186 | else { |
| 189 | c = term.line[row][col]; | 187 | c = term.line[row][col]; |
| 190 | putchar(c.state & CRset ? c.c : '.'); | 188 | putchar(c.state & GLYPH_SET ? c.c : '.'); |
| 191 | } | 189 | } |
| 192 | } | 190 | } |
| 193 | putchar('\n'); | 191 | putchar('\n'); |
| @@ -218,7 +216,7 @@ xbell(void) { /* visual bell */ | |||
| 218 | XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); | 216 | XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); |
| 219 | XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1); | 217 | XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1); |
| 220 | /* usleep(30000); */ | 218 | /* usleep(30000); */ |
| 221 | draw(SCredraw); | 219 | draw(SCREEN_REDRAW); |
| 222 | } | 220 | } |
| 223 | 221 | ||
| 224 | void | 222 | void |
| @@ -281,13 +279,10 @@ ttyread(void) { | |||
| 281 | char buf[BUFSIZ] = {0}; | 279 | char buf[BUFSIZ] = {0}; |
| 282 | int ret; | 280 | int ret; |
| 283 | 281 | ||
| 284 | switch(ret = read(cmdfd, buf, BUFSIZ)) { | 282 | if((ret = read(cmdfd, buf, BUFSIZ)) < 0) |
| 285 | case -1: | ||
| 286 | die("Couldn't read from shell: %s\n", SERRNO); | 283 | die("Couldn't read from shell: %s\n", SERRNO); |
| 287 | break; | 284 | else |
| 288 | default: | ||
| 289 | tputs(buf, ret); | 285 | tputs(buf, ret); |
| 290 | } | ||
| 291 | } | 286 | } |
| 292 | 287 | ||
| 293 | void | 288 | void |
| @@ -308,14 +303,13 @@ ttyresize(int x, int y) { | |||
| 308 | } | 303 | } |
| 309 | 304 | ||
| 310 | void | 305 | void |
| 311 | tcpos(int mode) { | 306 | tcursor(int mode) { |
| 312 | static int x = 0; | 307 | static TCursor c; |
| 313 | static int y = 0; | 308 | |
| 314 | 309 | if(mode == CURSOR_SAVE) | |
| 315 | if(mode == CSsave) | 310 | c = term.c; |
| 316 | x = term.c.x, y = term.c.y; | 311 | else if(mode == CURSOR_LOAD) |
| 317 | else if(mode == CSload) | 312 | term.c = c, tmoveto(c.x, c.y); |
| 318 | tmoveto(x, y); | ||
| 319 | } | 313 | } |
| 320 | 314 | ||
| 321 | void | 315 | void |
| @@ -323,9 +317,9 @@ tnew(int col, int row) { /* screen size */ | |||
| 323 | term.row = row, term.col = col; | 317 | term.row = row, term.col = col; |
| 324 | term.top = 0, term.bot = term.row - 1; | 318 | term.top = 0, term.bot = term.row - 1; |
| 325 | /* mode */ | 319 | /* mode */ |
| 326 | term.mode = TMwrap; | 320 | term.mode = MODE_WRAP; |
| 327 | /* cursor */ | 321 | /* cursor */ |
| 328 | term.c.attr.mode = ATnone; | 322 | term.c.attr.mode = ATTR_NULL; |
| 329 | term.c.attr.fg = DefaultFG; | 323 | term.c.attr.fg = DefaultFG; |
| 330 | term.c.attr.bg = DefaultBG; | 324 | term.c.attr.bg = DefaultBG; |
| 331 | term.c.x = term.c.y = 0; | 325 | term.c.x = term.c.y = 0; |
| @@ -370,7 +364,7 @@ csiparse(void) { | |||
| 370 | escseq.arg[escseq.narg] *= 10; | 364 | escseq.arg[escseq.narg] *= 10; |
| 371 | escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */; | 365 | escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */; |
| 372 | } | 366 | } |
| 373 | if(*p == ';' && escseq.narg+1 < ESCARGSIZ) | 367 | if(*p == ';' && escseq.narg+1 < ESC_ARG_SIZ) |
| 374 | escseq.narg++, p++; | 368 | escseq.narg++, p++; |
| 375 | else { | 369 | else { |
| 376 | escseq.mode = *p; | 370 | escseq.mode = *p; |
| @@ -387,27 +381,27 @@ tmoveto(int x, int y) { | |||
| 387 | } | 381 | } |
| 388 | 382 | ||
| 389 | void | 383 | void |
| 390 | tcursor(int dir) { | 384 | tmovecursor(int dir) { |
| 391 | int xf = term.c.x, yf = term.c.y; | 385 | int xf = term.c.x, yf = term.c.y; |
| 392 | 386 | ||
| 393 | switch(dir) { | 387 | switch(dir) { |
| 394 | case CSup: | 388 | case CURSOR_UP: |
| 395 | yf--; | 389 | yf--; |
| 396 | break; | 390 | break; |
| 397 | case CSdown: | 391 | case CURSOR_DOWN: |
| 398 | yf++; | 392 | yf++; |
| 399 | break; | 393 | break; |
| 400 | case CSleft: | 394 | case CURSOR_LEFT: |
| 401 | xf--; | 395 | xf--; |
| 402 | if(term.mode & TMwrap && xf < 0) { | 396 | if(term.mode & MODE_WRAP && xf < 0) { |
| 403 | xf = term.col-1, yf--; | 397 | xf = term.col-1, yf--; |
| 404 | if(yf < term.top) | 398 | if(yf < term.top) |
| 405 | yf = term.top, xf = 0; | 399 | yf = term.top, xf = 0; |
| 406 | } | 400 | } |
| 407 | break; | 401 | break; |
| 408 | case CSright: | 402 | case CURSOR_RIGHT: |
| 409 | xf++; | 403 | xf++; |
| 410 | if(term.mode & TMwrap && xf >= term.col) { | 404 | if(term.mode & MODE_WRAP && xf >= term.col) { |
| 411 | xf = 0, yf++; | 405 | xf = 0, yf++; |
| 412 | if(yf > term.bot) | 406 | if(yf > term.bot) |
| 413 | yf = term.bot, tscroll(); | 407 | yf = term.bot, tscroll(); |
| @@ -421,7 +415,7 @@ void | |||
| 421 | tsetchar(char c) { | 415 | tsetchar(char c) { |
| 422 | term.line[term.c.y][term.c.x] = term.c.attr; | 416 | term.line[term.c.y][term.c.x] = term.c.attr; |
| 423 | term.line[term.c.y][term.c.x].c = c; | 417 | term.line[term.c.y][term.c.x].c = c; |
| 424 | term.line[term.c.y][term.c.x].state |= CRset | CRupdate; | 418 | term.line[term.c.y][term.c.x].state |= GLYPH_SET | GLYPH_DIRTY; |
| 425 | } | 419 | } |
| 426 | 420 | ||
| 427 | void | 421 | void |
| @@ -477,7 +471,7 @@ tsetlinestate(int n, int state) { | |||
| 477 | } | 471 | } |
| 478 | 472 | ||
| 479 | void | 473 | void |
| 480 | tinsertblankline (int n) { | 474 | tinsertblankline(int n) { |
| 481 | int i; | 475 | int i; |
| 482 | Line blank; | 476 | Line blank; |
| 483 | int bot = term.bot; | 477 | int bot = term.bot; |
| @@ -497,8 +491,8 @@ tinsertblankline (int n) { | |||
| 497 | term.line[i-n] = blank; | 491 | term.line[i-n] = blank; |
| 498 | /* blank it */ | 492 | /* blank it */ |
| 499 | memset(blank, 0, term.col * sizeof(Glyph)); | 493 | memset(blank, 0, term.col * sizeof(Glyph)); |
| 500 | tsetlinestate(i, CRupdate); | 494 | tsetlinestate(i, GLYPH_DIRTY); |
| 501 | tsetlinestate(i-n, CRupdate); | 495 | tsetlinestate(i-n, GLYPH_DIRTY); |
| 502 | } | 496 | } |
| 503 | } | 497 | } |
| 504 | 498 | ||
| @@ -523,8 +517,8 @@ tdeleteline(int n) { | |||
| 523 | term.line[i+n] = blank; | 517 | term.line[i+n] = blank; |
| 524 | /* blank it */ | 518 | /* blank it */ |
| 525 | memset(blank, 0, term.col * sizeof(Glyph)); | 519 | memset(blank, 0, term.col * sizeof(Glyph)); |
| 526 | tsetlinestate(i, CRupdate); | 520 | tsetlinestate(i, GLYPH_DIRTY); |
| 527 | tsetlinestate(i-n, CRupdate); | 521 | tsetlinestate(i-n, GLYPH_DIRTY); |
| 528 | } | 522 | } |
| 529 | } | 523 | } |
| 530 | 524 | ||
| @@ -535,30 +529,30 @@ tsetattr(int *attr, int l) { | |||
| 535 | for(i = 0; i < l; i++) { | 529 | for(i = 0; i < l; i++) { |
| 536 | switch(attr[i]) { | 530 | switch(attr[i]) { |
| 537 | case 0: | 531 | case 0: |
| 538 | term.c.attr.mode &= ~(ATreverse | ATunderline | ATbold); | 532 | term.c.attr.mode &= ~(ATTR_REVERSE | ATTR_UNDERLINE | ATTR_BOLD); |
| 539 | term.c.attr.fg = DefaultFG; | 533 | term.c.attr.fg = DefaultFG; |
| 540 | term.c.attr.bg = DefaultBG; | 534 | term.c.attr.bg = DefaultBG; |
| 541 | break; | 535 | break; |
| 542 | case 1: | 536 | case 1: |
| 543 | term.c.attr.mode |= ATbold; | 537 | term.c.attr.mode |= ATTR_BOLD; |
| 544 | break; | 538 | break; |
| 545 | case 4: | 539 | case 4: |
| 546 | term.c.attr.mode |= ATunderline; | 540 | term.c.attr.mode |= ATTR_UNDERLINE; |
| 547 | break; | 541 | break; |
| 548 | case 7: | 542 | case 7: |
| 549 | term.c.attr.mode |= ATreverse; | 543 | term.c.attr.mode |= ATTR_REVERSE; |
| 550 | break; | 544 | break; |
| 551 | case 8: | 545 | case 8: |
| 552 | term.c.hidden = CShide; | 546 | term.c.hidden = CURSOR_HIDE; |
| 553 | break; | 547 | break; |
| 554 | case 22: | 548 | case 22: |
| 555 | term.c.attr.mode &= ~ATbold; | 549 | term.c.attr.mode &= ~ATTR_BOLD; |
| 556 | break; | 550 | break; |
| 557 | case 24: | 551 | case 24: |
| 558 | term.c.attr.mode &= ~ATunderline; | 552 | term.c.attr.mode &= ~ATTR_UNDERLINE; |
| 559 | break; | 553 | break; |
| 560 | case 27: | 554 | case 27: |
| 561 | term.c.attr.mode &= ~ATreverse; | 555 | term.c.attr.mode &= ~ATTR_REVERSE; |
| 562 | break; | 556 | break; |
| 563 | case 39: | 557 | case 39: |
| 564 | term.c.attr.fg = DefaultFG; | 558 | term.c.attr.fg = DefaultFG; |
| @@ -593,57 +587,56 @@ tsetscroll(int t, int b) { | |||
| 593 | 587 | ||
| 594 | void | 588 | void |
| 595 | csihandle(void) { | 589 | csihandle(void) { |
| 596 | if(escseq.priv) | ||
| 597 | csidump(); | ||
| 598 | switch(escseq.mode) { | 590 | switch(escseq.mode) { |
| 599 | unknown: | ||
| 600 | default: | 591 | default: |
| 601 | fprintf(stderr, "erresc: unknown sequence\n"); | 592 | unknown: |
| 593 | printf("erresc: unknown sequence -- "); | ||
| 602 | csidump(); | 594 | csidump(); |
| 603 | /* die(""); */ | 595 | /* die(""); */ |
| 604 | break; | 596 | break; |
| 605 | case '@': /* Insert <n> blank char */ | 597 | case '@': /* ICH -- Insert <n> blank char */ |
| 606 | DEFAULT(escseq.arg[0], 1); | 598 | DEFAULT(escseq.arg[0], 1); |
| 607 | tinsertblank(escseq.arg[0]); | 599 | tinsertblank(escseq.arg[0]); |
| 608 | break; | 600 | break; |
| 609 | case 'A': /* Cursor <n> Up */ | 601 | case 'A': /* CUU -- Cursor <n> Up */ |
| 610 | case 'e': | 602 | case 'e': |
| 611 | DEFAULT(escseq.arg[0], 1); | 603 | DEFAULT(escseq.arg[0], 1); |
| 612 | tmoveto(term.c.x, term.c.y-escseq.arg[0]); | 604 | tmoveto(term.c.x, term.c.y-escseq.arg[0]); |
| 613 | break; | 605 | break; |
| 614 | case 'B': /* Cursor <n> Down */ | 606 | case 'B': /* CUD -- Cursor <n> Down */ |
| 615 | DEFAULT(escseq.arg[0], 1); | 607 | DEFAULT(escseq.arg[0], 1); |
| 616 | tmoveto(term.c.x, term.c.y+escseq.arg[0]); | 608 | tmoveto(term.c.x, term.c.y+escseq.arg[0]); |
| 617 | break; | 609 | break; |
| 618 | case 'C': /* Cursor <n> Forward */ | 610 | case 'C': /* CUF -- Cursor <n> Forward */ |
| 619 | case 'a': | 611 | case 'a': |
| 620 | DEFAULT(escseq.arg[0], 1); | 612 | DEFAULT(escseq.arg[0], 1); |
| 621 | tmoveto(term.c.x+escseq.arg[0], term.c.y); | 613 | tmoveto(term.c.x+escseq.arg[0], term.c.y); |
| 622 | break; | 614 | break; |
| 623 | case 'D': /* Cursor <n> Backward */ | 615 | case 'D': /* CUB -- Cursor <n> Backward */ |
| 624 | DEFAULT(escseq.arg[0], 1); | 616 | DEFAULT(escseq.arg[0], 1); |
| 625 | tmoveto(term.c.x-escseq.arg[0], term.c.y); | 617 | tmoveto(term.c.x-escseq.arg[0], term.c.y); |
| 626 | break; | 618 | break; |
| 627 | case 'E': /* Cursor <n> Down and first col */ | 619 | case 'E': /* CNL -- Cursor <n> Down and first col */ |
| 628 | DEFAULT(escseq.arg[0], 1); | 620 | DEFAULT(escseq.arg[0], 1); |
| 629 | tmoveto(0, term.c.y+escseq.arg[0]); | 621 | tmoveto(0, term.c.y+escseq.arg[0]); |
| 630 | break; | 622 | break; |
| 631 | case 'F': /* Cursor <n> Up and first col */ | 623 | case 'F': /* CPL -- Cursor <n> Up and first col */ |
| 632 | DEFAULT(escseq.arg[0], 1); | 624 | DEFAULT(escseq.arg[0], 1); |
| 633 | tmoveto(0, term.c.y-escseq.arg[0]); | 625 | tmoveto(0, term.c.y-escseq.arg[0]); |
| 634 | break; | 626 | break; |
| 635 | case 'G': /* Move to <col> */ | 627 | case 'G': /* CHA -- Move to <col> */ |
| 636 | case '`': | 628 | case '`': /* XXX: HPA -- same? */ |
| 637 | DEFAULT(escseq.arg[0], 1); | 629 | DEFAULT(escseq.arg[0], 1); |
| 638 | tmoveto(escseq.arg[0]-1, term.c.y); | 630 | tmoveto(escseq.arg[0]-1, term.c.y); |
| 639 | break; | 631 | break; |
| 640 | case 'H': /* Move to <row> <col> */ | 632 | case 'H': /* CUP -- Move to <row> <col> */ |
| 641 | case 'f': | 633 | case 'f': /* XXX: HVP -- same? */ |
| 642 | DEFAULT(escseq.arg[0], 1); | 634 | DEFAULT(escseq.arg[0], 1); |
| 643 | DEFAULT(escseq.arg[1], 1); | 635 | DEFAULT(escseq.arg[1], 1); |
| 644 | tmoveto(escseq.arg[1]-1, escseq.arg[0]-1); | 636 | tmoveto(escseq.arg[1]-1, escseq.arg[0]-1); |
| 645 | break; | 637 | break; |
| 646 | case 'J': /* Clear screen */ | 638 | /* XXX: (CSI n I) CHT -- Cursor Forward Tabulation <n> tab stops */ |
| 639 | case 'J': /* ED -- Clear screen */ | ||
| 647 | switch(escseq.arg[0]) { | 640 | switch(escseq.arg[0]) { |
| 648 | case 0: /* below */ | 641 | case 0: /* below */ |
| 649 | tclearregion(term.c.x, term.c.y, term.col-1, term.row-1); | 642 | tclearregion(term.c.x, term.c.y, term.col-1, term.row-1); |
| @@ -653,10 +646,13 @@ csihandle(void) { | |||
| 653 | break; | 646 | break; |
| 654 | case 2: /* all */ | 647 | case 2: /* all */ |
| 655 | tclearregion(0, 0, term.col-1, term.row-1); | 648 | tclearregion(0, 0, term.col-1, term.row-1); |
| 656 | break; | 649 | break; |
| 650 | case 3: /* XXX: erase saved lines (xterm) */ | ||
| 651 | default: | ||
| 652 | goto unknown; | ||
| 657 | } | 653 | } |
| 658 | break; | 654 | break; |
| 659 | case 'K': /* Clear line */ | 655 | case 'K': /* EL -- Clear line */ |
| 660 | switch(escseq.arg[0]) { | 656 | switch(escseq.arg[0]) { |
| 661 | case 0: /* right */ | 657 | case 0: /* right */ |
| 662 | tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); | 658 | tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); |
| @@ -669,54 +665,77 @@ csihandle(void) { | |||
| 669 | break; | 665 | break; |
| 670 | } | 666 | } |
| 671 | break; | 667 | break; |
| 672 | case 'S': | 668 | case 'S': /* XXX: SU -- Scroll <n> line up (faked) */ |
| 673 | case 'L': /* Insert <n> blank lines */ | 669 | case 'L': /* IL -- Insert <n> blank lines */ |
| 674 | DEFAULT(escseq.arg[0], 1); | 670 | DEFAULT(escseq.arg[0], 1); |
| 675 | tinsertblankline(escseq.arg[0]); | 671 | tinsertblankline(escseq.arg[0]); |
| 676 | break; | 672 | break; |
| 677 | case 'l': | 673 | case 'l': /* RM -- Reset Mode */ |
| 678 | if(escseq.priv) { | 674 | if(escseq.priv) { |
| 679 | switch(escseq.arg[0]) { | 675 | switch(escseq.arg[0]) { |
| 676 | case 1: | ||
| 677 | term.mode &= ~MODE_APPKEYPAD; | ||
| 678 | break; | ||
| 680 | case 7: | 679 | case 7: |
| 681 | term.mode &= ~TMwrap; | 680 | term.mode &= ~MODE_WRAP; |
| 681 | break; | ||
| 682 | case 12: /* att610 -- Stop blinking cursor (IGNORED) */ | ||
| 682 | break; | 683 | break; |
| 683 | case 25: | 684 | case 25: |
| 684 | term.c.hidden = 1; | 685 | term.c.hidden = 1; |
| 685 | break; | 686 | break; |
| 687 | case 1048: /* XXX: no alt. screen to erase/save */ | ||
| 688 | case 1049: | ||
| 689 | tcursor(CURSOR_LOAD); | ||
| 690 | tclearregion(0, 0, term.col-1, term.row-1); | ||
| 691 | break; | ||
| 692 | default: | ||
| 693 | goto unknown; | ||
| 686 | } | 694 | } |
| 687 | } | 695 | } else goto unknown; |
| 688 | break; | 696 | break; |
| 689 | case 'M': /* Delete <n> lines */ | 697 | case 'M': /* DL -- Delete <n> lines */ |
| 690 | DEFAULT(escseq.arg[0], 1); | 698 | DEFAULT(escseq.arg[0], 1); |
| 691 | tdeleteline(escseq.arg[0]); | 699 | tdeleteline(escseq.arg[0]); |
| 692 | break; | 700 | break; |
| 693 | case 'X': | 701 | case 'X': /* ECH -- Erase <n> char XXX: same? */ |
| 694 | case 'P': /* Delete <n> char */ | 702 | case 'P': /* DCH -- Delete <n> char */ |
| 695 | DEFAULT(escseq.arg[0], 1); | 703 | DEFAULT(escseq.arg[0], 1); |
| 696 | tdeletechar(escseq.arg[0]); | 704 | tdeletechar(escseq.arg[0]); |
| 697 | break; | 705 | break; |
| 698 | case 'd': /* Move to <row> */ | 706 | /* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation <n> tab stops */ |
| 707 | case 'd': /* VPA -- Move to <row> */ | ||
| 699 | DEFAULT(escseq.arg[0], 1); | 708 | DEFAULT(escseq.arg[0], 1); |
| 700 | tmoveto(term.c.x, escseq.arg[0]-1); | 709 | tmoveto(term.c.x, escseq.arg[0]-1); |
| 701 | break; | 710 | break; |
| 702 | case 'h': /* Set terminal mode */ | 711 | case 'h': /* SM -- Set terminal mode */ |
| 703 | if(escseq.priv) | 712 | if(escseq.priv) { |
| 704 | switch(escseq.arg[0]) { | 713 | switch(escseq.arg[0]) { |
| 714 | case 1: | ||
| 715 | term.mode |= MODE_APPKEYPAD; | ||
| 716 | break; | ||
| 705 | case 7: | 717 | case 7: |
| 706 | term.mode |= TMwrap; | 718 | term.mode |= MODE_WRAP; |
| 719 | break; | ||
| 720 | case 12: /* att610 -- Start blinking cursor (IGNORED) */ | ||
| 707 | break; | 721 | break; |
| 708 | case 25: | 722 | case 25: |
| 709 | term.c.hidden = 0; | 723 | term.c.hidden = 0; |
| 710 | break; | 724 | break; |
| 711 | case 1034: | 725 | case 1048: |
| 712 | /* XXX: Interpret "meta" key, sets eighth bit. */ | 726 | case 1049: /* XXX: no alt. screen to erase/save */ |
| 727 | tcursor(CURSOR_SAVE); | ||
| 728 | tclearregion(0, 0, term.col-1, term.row-1); | ||
| 713 | break; | 729 | break; |
| 730 | default: | ||
| 731 | goto unknown; | ||
| 714 | } | 732 | } |
| 733 | } else goto unknown; | ||
| 715 | break; | 734 | break; |
| 716 | case 'm': /* Terminal attribute (color) */ | 735 | case 'm': /* SGR -- Terminal attribute (color) */ |
| 717 | tsetattr(escseq.arg, escseq.narg); | 736 | tsetattr(escseq.arg, escseq.narg); |
| 718 | break; | 737 | break; |
| 719 | case 'r': | 738 | case 'r': /* DECSTBM -- Set Scrolling Region */ |
| 720 | if(escseq.priv) | 739 | if(escseq.priv) |
| 721 | goto unknown; | 740 | goto unknown; |
| 722 | else { | 741 | else { |
| @@ -725,11 +744,11 @@ csihandle(void) { | |||
| 725 | tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); | 744 | tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); |
| 726 | } | 745 | } |
| 727 | break; | 746 | break; |
| 728 | case 's': /* Save cursor position */ | 747 | case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ |
| 729 | tcpos(CSsave); | 748 | tcursor(CURSOR_SAVE); |
| 730 | break; | 749 | break; |
| 731 | case 'u': /* Load cursor position */ | 750 | case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ |
| 732 | tcpos(CSload); | 751 | tcursor(CURSOR_LOAD); |
| 733 | break; | 752 | break; |
| 734 | } | 753 | } |
| 735 | } | 754 | } |
| @@ -759,70 +778,82 @@ tputtab(void) { | |||
| 759 | space--; | 778 | space--; |
| 760 | 779 | ||
| 761 | for(; space > 0; space--) | 780 | for(; space > 0; space--) |
| 762 | tcursor(CSright); | 781 | tmovecursor(CURSOR_RIGHT); |
| 763 | } | 782 | } |
| 764 | 783 | ||
| 765 | void | 784 | void |
| 766 | tputc(char c) { | 785 | tputc(char c) { |
| 767 | #if 0 | 786 | /* dump(c); */ |
| 768 | dump(c); | 787 | if(term.esc & ESC_START) { |
| 769 | #endif | 788 | if(term.esc & ESC_CSI) { |
| 770 | if(term.esc & ESCin) { | ||
| 771 | if(term.esc & ESCcsi) { | ||
| 772 | escseq.buf[escseq.len++] = c; | 789 | escseq.buf[escseq.len++] = c; |
| 773 | if(BETWEEN(c, 0x40, 0x7E) || escseq.len >= ESCSIZ) { | 790 | if(BETWEEN(c, 0x40, 0x7E) || escseq.len >= ESC_BUF_SIZ) { |
| 774 | term.esc = 0; | 791 | term.esc = 0; |
| 775 | csiparse(), csihandle(); | 792 | csiparse(), csihandle(); |
| 776 | } | 793 | } |
| 777 | } else if (term.esc & ESCosc) { | 794 | } else if(term.esc & ESC_OSC) { |
| 778 | if(c == ';') { | 795 | if(c == ';') { |
| 779 | term.titlelen = 0; | 796 | term.titlelen = 0; |
| 780 | term.esc = ESCin | ESCtitle; | 797 | term.esc = ESC_START | ESC_TITLE; |
| 781 | } | 798 | } |
| 782 | } else if(term.esc & ESCtitle) { | 799 | } else if(term.esc & ESC_TITLE) { |
| 783 | if(c == '\a' || term.titlelen+1 >= TITLESIZ) { | 800 | if(c == '\a' || term.titlelen+1 >= ESC_TITLE_SIZ) { |
| 784 | term.esc = 0; | 801 | term.esc = 0; |
| 785 | term.title[term.titlelen] = '\0'; | 802 | term.title[term.titlelen] = '\0'; |
| 786 | XStoreName(xw.dis, xw.win, term.title); | 803 | XStoreName(xw.dis, xw.win, term.title); |
| 787 | } else { | 804 | } else { |
| 788 | term.title[term.titlelen++] = c; | 805 | term.title[term.titlelen++] = c; |
| 789 | } | 806 | } |
| 790 | } else if(term.esc & ESCcharset) { | 807 | } else if(term.esc & ESC_ALTCHARSET) { |
| 791 | printf("ESC ( %c\n", c); | ||
| 792 | switch(c) { | 808 | switch(c) { |
| 793 | case '0': /* Line drawing crap */ | 809 | case '0': /* Line drawing crap */ |
| 794 | term.c.attr.mode |= ATgfx; | 810 | term.c.attr.mode |= ATTR_GFX; |
| 795 | break; | 811 | break; |
| 796 | case 'B': /* Back to regular text */ | 812 | case 'B': /* Back to regular text */ |
| 797 | term.c.attr.mode &= ~ATgfx; | 813 | term.c.attr.mode &= ~ATTR_GFX; |
| 798 | break; | 814 | break; |
| 815 | default: | ||
| 816 | printf("esc unhandled charset: ESC ( %c\n", c); | ||
| 799 | } | 817 | } |
| 800 | term.esc = 0; | 818 | term.esc = 0; |
| 801 | } else { | 819 | } else { |
| 802 | switch(c) { | 820 | switch(c) { |
| 803 | case '[': | 821 | case '[': |
| 804 | term.esc |= ESCcsi; | 822 | term.esc |= ESC_CSI; |
| 805 | break; | 823 | break; |
| 806 | case ']': | 824 | case ']': |
| 807 | term.esc |= ESCosc; | 825 | term.esc |= ESC_OSC; |
| 808 | break; | 826 | break; |
| 809 | case '(': | 827 | case '(': |
| 810 | term.esc |= ESCcharset; | 828 | term.esc |= ESC_ALTCHARSET; |
| 811 | break; | 829 | break; |
| 812 | case 'A': | 830 | case 'A': |
| 813 | tmoveto(term.c.x, term.c.y-1); | 831 | tmoveto(term.c.x, term.c.y-1); |
| 832 | term.esc = 0; | ||
| 814 | break; | 833 | break; |
| 815 | case 'B': | 834 | case 'B': |
| 816 | tmoveto(term.c.x, term.c.y+1); | 835 | tmoveto(term.c.x, term.c.y+1); |
| 836 | term.esc = 0; | ||
| 817 | break; | 837 | break; |
| 818 | case 'C': | 838 | case 'C': |
| 819 | tmoveto(term.c.x+1, term.c.y); | 839 | tmoveto(term.c.x+1, term.c.y); |
| 840 | term.esc = 0; | ||
| 820 | break; | 841 | break; |
| 821 | case 'D': | 842 | case 'D': |
| 822 | tmoveto(term.c.x-1, term.c.y); | 843 | tmoveto(term.c.x-1, term.c.y); |
| 844 | term.esc = 0; | ||
| 845 | break; | ||
| 846 | case '=': /* DECPAM */ | ||
| 847 | term.mode |= MODE_APPKEYPAD; | ||
| 848 | term.esc = 0; | ||
| 849 | break; | ||
| 850 | case '>': /* DECPNM */ | ||
| 851 | term.mode &= ~MODE_APPKEYPAD; | ||
| 852 | term.esc = 0; | ||
| 823 | break; | 853 | break; |
| 824 | default: | 854 | default: |
| 825 | fprintf(stderr, "erresc: unknown sequence ESC %02X '%c'\n", c, isprint(c)?c:'.'); | 855 | fprintf(stderr, "erresc: unknown sequence ESC %02X '%c'\n", c, isprint(c)?c:'.'); |
| 856 | term.esc = 0; | ||
| 826 | } | 857 | } |
| 827 | } | 858 | } |
| 828 | } else { | 859 | } else { |
| @@ -831,7 +862,7 @@ tputc(char c) { | |||
| 831 | tputtab(); | 862 | tputtab(); |
| 832 | break; | 863 | break; |
| 833 | case '\b': | 864 | case '\b': |
| 834 | tcursor(CSleft); | 865 | tmovecursor(CURSOR_LEFT); |
| 835 | break; | 866 | break; |
| 836 | case '\r': | 867 | case '\r': |
| 837 | tmoveto(0, term.c.y); | 868 | tmoveto(0, term.c.y); |
| @@ -844,11 +875,11 @@ tputc(char c) { | |||
| 844 | break; | 875 | break; |
| 845 | case '\033': | 876 | case '\033': |
| 846 | csireset(); | 877 | csireset(); |
| 847 | term.esc = ESCin; | 878 | term.esc = ESC_START; |
| 848 | break; | 879 | break; |
| 849 | default: | 880 | default: |
| 850 | tsetchar(c); | 881 | tsetchar(c); |
| 851 | tcursor(CSright); | 882 | tmovecursor(CURSOR_RIGHT); |
| 852 | break; | 883 | break; |
| 853 | } | 884 | } |
| 854 | } | 885 | } |
| @@ -917,7 +948,7 @@ xscroll(void) { | |||
| 917 | int dsty = term.top * xw.ch; | 948 | int dsty = term.top * xw.ch; |
| 918 | int height = (term.bot-term.top) * xw.ch; | 949 | int height = (term.bot-term.top) * xw.ch; |
| 919 | 950 | ||
| 920 | xcursor(CShide); | 951 | xcursor(CURSOR_HIDE); |
| 921 | XCopyArea(xw.dis, xw.win, xw.win, dc.gc, 0, srcy, xw.w, height, 0, dsty); | 952 | XCopyArea(xw.dis, xw.win, xw.win, dc.gc, 0, srcy, xw.w, height, 0, dsty); |
| 922 | xclear(0, term.bot, term.col-1, term.bot); | 953 | xclear(0, term.bot, term.col-1, term.bot); |
| 923 | } | 954 | } |
| @@ -950,7 +981,7 @@ xinit(void) { | |||
| 950 | 981 | ||
| 951 | term.c.attr.fg = DefaultFG; | 982 | term.c.attr.fg = DefaultFG; |
| 952 | term.c.attr.bg = DefaultBG; | 983 | term.c.attr.bg = DefaultBG; |
| 953 | term.c.attr.mode = ATnone; | 984 | term.c.attr.mode = ATTR_NULL; |
| 954 | /* windows */ | 985 | /* windows */ |
| 955 | xw.h = term.row * xw.ch; | 986 | xw.h = term.row * xw.ch; |
| 956 | xw.w = term.col * xw.cw; | 987 | xw.w = term.col * xw.cw; |
| @@ -977,12 +1008,12 @@ xinit(void) { | |||
| 977 | } | 1008 | } |
| 978 | 1009 | ||
| 979 | void | 1010 | void |
| 980 | xdraws (char *s, Glyph base, int x, int y, int len) { | 1011 | xdraws(char *s, Glyph base, int x, int y, int len) { |
| 981 | unsigned long xfg, xbg; | 1012 | unsigned long xfg, xbg; |
| 982 | int winx = x*xw.cw, winy = y*xw.ch + dc.font->ascent, width = len*xw.cw; | 1013 | int winx = x*xw.cw, winy = y*xw.ch + dc.font->ascent, width = len*xw.cw; |
| 983 | int i; | 1014 | int i; |
| 984 | 1015 | ||
| 985 | if(base.mode & ATreverse) | 1016 | if(base.mode & ATTR_REVERSE) |
| 986 | xfg = dc.col[base.bg], xbg = dc.col[base.fg]; | 1017 | xfg = dc.col[base.bg], xbg = dc.col[base.fg]; |
| 987 | else | 1018 | else |
| 988 | xfg = dc.col[base.fg], xbg = dc.col[base.bg]; | 1019 | xfg = dc.col[base.fg], xbg = dc.col[base.bg]; |
| @@ -990,15 +1021,13 @@ xdraws (char *s, Glyph base, int x, int y, int len) { | |||
| 990 | XSetBackground(xw.dis, dc.gc, xbg); | 1021 | XSetBackground(xw.dis, dc.gc, xbg); |
| 991 | XSetForeground(xw.dis, dc.gc, xfg); | 1022 | XSetForeground(xw.dis, dc.gc, xfg); |
| 992 | 1023 | ||
| 993 | if(base.mode & ATgfx) { | 1024 | if(base.mode & ATTR_GFX) |
| 994 | |||
| 995 | for(i = 0; i < len; i++) | 1025 | for(i = 0; i < len; i++) |
| 996 | s[i] = gfx[s[i]]; | 1026 | s[i] = gfx[s[i]]; |
| 997 | } | ||
| 998 | 1027 | ||
| 999 | XDrawImageString(xw.dis, xw.win, dc.gc, winx, winy, s, len); | 1028 | XDrawImageString(xw.dis, xw.win, dc.gc, winx, winy, s, len); |
| 1000 | 1029 | ||
| 1001 | if(base.mode & ATunderline) | 1030 | if(base.mode & ATTR_UNDERLINE) |
| 1002 | XDrawLine(xw.dis, xw.win, dc.gc, winx, winy+1, winx+width-1, winy+1); | 1031 | XDrawLine(xw.dis, xw.win, dc.gc, winx, winy+1, winx+width-1, winy+1); |
| 1003 | } | 1032 | } |
| 1004 | 1033 | ||
| @@ -1008,7 +1037,7 @@ xdrawc(int x, int y, Glyph g) { | |||
| 1008 | unsigned long xfg, xbg; | 1037 | unsigned long xfg, xbg; |
| 1009 | 1038 | ||
| 1010 | /* reverse video */ | 1039 | /* reverse video */ |
| 1011 | if(g.mode & ATreverse) | 1040 | if(g.mode & ATTR_REVERSE) |
| 1012 | xfg = dc.col[g.bg], xbg = dc.col[g.fg]; | 1041 | xfg = dc.col[g.bg], xbg = dc.col[g.fg]; |
| 1013 | else | 1042 | else |
| 1014 | xfg = dc.col[g.fg], xbg = dc.col[g.bg]; | 1043 | xfg = dc.col[g.fg], xbg = dc.col[g.bg]; |
| @@ -1022,20 +1051,20 @@ void | |||
| 1022 | xcursor(int mode) { | 1051 | xcursor(int mode) { |
| 1023 | static int oldx = 0; | 1052 | static int oldx = 0; |
| 1024 | static int oldy = 0; | 1053 | static int oldy = 0; |
| 1025 | Glyph g = {' ', ATnone, DefaultBG, DefaultCS, 0}; | 1054 | Glyph g = {' ', ATTR_NULL, DefaultBG, DefaultCS, 0}; |
| 1026 | 1055 | ||
| 1027 | LIMIT(oldx, 0, term.col-1); | 1056 | LIMIT(oldx, 0, term.col-1); |
| 1028 | LIMIT(oldy, 0, term.row-1); | 1057 | LIMIT(oldy, 0, term.row-1); |
| 1029 | 1058 | ||
| 1030 | if(term.line[term.c.y][term.c.x].state & CRset) | 1059 | if(term.line[term.c.y][term.c.x].state & GLYPH_SET) |
| 1031 | g.c = term.line[term.c.y][term.c.x].c; | 1060 | g.c = term.line[term.c.y][term.c.x].c; |
| 1032 | /* remove the old cursor */ | 1061 | /* remove the old cursor */ |
| 1033 | if(term.line[oldy][oldx].state & CRset) | 1062 | if(term.line[oldy][oldx].state & GLYPH_SET) |
| 1034 | xdrawc(oldx, oldy, term.line[oldy][oldx]); | 1063 | xdrawc(oldx, oldy, term.line[oldy][oldx]); |
| 1035 | else | 1064 | else |
| 1036 | xclear(oldx, oldy, oldx, oldy); | 1065 | xclear(oldx, oldy, oldx, oldy); |
| 1037 | /* draw the new one */ | 1066 | /* draw the new one */ |
| 1038 | if(mode == CSdraw) { | 1067 | if(mode == CURSOR_DRAW) { |
| 1039 | xdrawc(term.c.x, term.c.y, g); | 1068 | xdrawc(term.c.x, term.c.y, g); |
| 1040 | oldx = term.c.x, oldy = term.c.y; | 1069 | oldx = term.c.x, oldy = term.c.y; |
| 1041 | } | 1070 | } |
| @@ -1045,14 +1074,14 @@ void | |||
| 1045 | draw(int redraw_all) { | 1074 | draw(int redraw_all) { |
| 1046 | int i, x, y, ox; | 1075 | int i, x, y, ox; |
| 1047 | Glyph base, new; | 1076 | Glyph base, new; |
| 1048 | char buf[MAXDRAWBUF]; | 1077 | char buf[DRAW_BUF_SIZ]; |
| 1049 | 1078 | ||
| 1050 | for(y = 0; y < term.row; y++) { | 1079 | for(y = 0; y < term.row; y++) { |
| 1051 | base = term.line[y][0]; | 1080 | base = term.line[y][0]; |
| 1052 | i = ox = 0; | 1081 | i = ox = 0; |
| 1053 | for(x = 0; x < term.col; x++) { | 1082 | for(x = 0; x < term.col; x++) { |
| 1054 | new = term.line[y][x]; | 1083 | new = term.line[y][x]; |
| 1055 | if(!ATTRCMP(base, new) && i < MAXDRAWBUF) | 1084 | if(!ATTRCMP(base, new) && i < DRAW_BUF_SIZ) |
| 1056 | buf[i++] = new.c; | 1085 | buf[i++] = new.c; |
| 1057 | else { | 1086 | else { |
| 1058 | xdraws(buf, base, ox, y, i); | 1087 | xdraws(buf, base, ox, y, i); |
| @@ -1065,12 +1094,12 @@ draw(int redraw_all) { | |||
| 1065 | xdraws(buf, base, ox, y, i); | 1094 | xdraws(buf, base, ox, y, i); |
| 1066 | } | 1095 | } |
| 1067 | if(!term.c.hidden) | 1096 | if(!term.c.hidden) |
| 1068 | xcursor(CSdraw); | 1097 | xcursor(CURSOR_DRAW); |
| 1069 | } | 1098 | } |
| 1070 | 1099 | ||
| 1071 | void | 1100 | void |
| 1072 | expose(XEvent *ev) { | 1101 | expose(XEvent *ev) { |
| 1073 | draw(SCredraw); | 1102 | draw(SCREEN_REDRAW); |
| 1074 | } | 1103 | } |
| 1075 | 1104 | ||
| 1076 | char* | 1105 | char* |
| @@ -1105,6 +1134,13 @@ kpress(XEvent *ev) { | |||
| 1105 | ttywrite(buf, len); | 1134 | ttywrite(buf, len); |
| 1106 | } else | 1135 | } else |
| 1107 | switch(ksym) { | 1136 | switch(ksym) { |
| 1137 | case XK_Up: | ||
| 1138 | case XK_Down: | ||
| 1139 | case XK_Left: | ||
| 1140 | case XK_Right: | ||
| 1141 | sprintf(buf, "\033%c%c", term.mode & MODE_APPKEYPAD ? 'O' : '[', "DACB"[ksym - XK_Left]); | ||
| 1142 | ttywrite(buf, 3); | ||
| 1143 | break; | ||
| 1108 | case XK_Insert: | 1144 | case XK_Insert: |
| 1109 | if(shift) | 1145 | if(shift) |
| 1110 | /* XXX: paste X clipboard */; | 1146 | /* XXX: paste X clipboard */; |
| @@ -1126,7 +1162,7 @@ resize(XEvent *e) { | |||
| 1126 | ttyresize(col, row); | 1162 | ttyresize(col, row); |
| 1127 | xw.w = e->xconfigure.width; | 1163 | xw.w = e->xconfigure.width; |
| 1128 | xw.h = e->xconfigure.height; | 1164 | xw.h = e->xconfigure.height; |
| 1129 | draw(SCredraw); | 1165 | draw(SCREEN_REDRAW); |
| 1130 | } | 1166 | } |
| 1131 | } | 1167 | } |
| 1132 | 1168 | ||
| @@ -1151,7 +1187,7 @@ run(void) { | |||
| 1151 | } | 1187 | } |
| 1152 | if(FD_ISSET(cmdfd, &rfd)) { | 1188 | if(FD_ISSET(cmdfd, &rfd)) { |
| 1153 | ttyread(); | 1189 | ttyread(); |
| 1154 | draw(SCupdate); | 1190 | draw(SCREEN_UPDATE); |
| 1155 | } | 1191 | } |
| 1156 | while(XPending(xw.dis)) { | 1192 | while(XPending(xw.dis)) { |
| 1157 | XNextEvent(xw.dis, &ev); | 1193 | XNextEvent(xw.dis, &ev); |
