diff options
| -rw-r--r-- | config.def.h | 47 | ||||
| -rw-r--r-- | st.c | 136 | ||||
| -rw-r--r-- | st.info | 4 |
3 files changed, 126 insertions, 61 deletions
diff --git a/config.def.h b/config.def.h index ced3000..c1afd88 100644 --- a/config.def.h +++ b/config.def.h | |||
| @@ -26,32 +26,33 @@ static const char *colorname[] = { | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | /* Default colors (colorname index) */ | 28 | /* Default colors (colorname index) */ |
| 29 | /* foreground, background, cursor */ | 29 | /* foreground, background, cursor */ |
| 30 | #define DefaultFG 7 | 30 | #define DefaultFG 7 |
| 31 | #define DefaultBG 0 | 31 | #define DefaultBG 0 |
| 32 | #define DefaultCS 1 | 32 | #define DefaultCS 1 |
| 33 | 33 | ||
| 34 | /* Special keys */ | 34 | /* Special keys (change & recompile st.info accordingly) */ |
| 35 | /* key, mask, output */ | ||
| 35 | static Key key[] = { | 36 | static Key key[] = { |
| 36 | { XK_BackSpace, "\177" }, | 37 | { XK_BackSpace, 0, "\177" }, |
| 37 | { XK_Insert, "\033[2~" }, | 38 | { XK_Insert, 0, "\033[2~" }, |
| 38 | { XK_Delete, "\033[3~" }, | 39 | { XK_Delete, 0, "\033[3~" }, |
| 39 | { XK_Home, "\033[1~" }, | 40 | { XK_Home, 0, "\033[1~" }, |
| 40 | { XK_End, "\033[4~" }, | 41 | { XK_End, 0, "\033[4~" }, |
| 41 | { XK_Prior, "\033[5~" }, | 42 | { XK_Prior, 0, "\033[5~" }, |
| 42 | { XK_Next, "\033[6~" }, | 43 | { XK_Next, 0, "\033[6~" }, |
| 43 | { XK_F1, "\033OP" }, | 44 | { XK_F1, 0, "\033OP" }, |
| 44 | { XK_F2, "\033OQ" }, | 45 | { XK_F2, 0, "\033OQ" }, |
| 45 | { XK_F3, "\033OR" }, | 46 | { XK_F3, 0, "\033OR" }, |
| 46 | { XK_F4, "\033OS" }, | 47 | { XK_F4, 0, "\033OS" }, |
| 47 | { XK_F5, "\033[15~" }, | 48 | { XK_F5, 0, "\033[15~" }, |
| 48 | { XK_F6, "\033[17~" }, | 49 | { XK_F6, 0, "\033[17~" }, |
| 49 | { XK_F7, "\033[18~" }, | 50 | { XK_F7, 0, "\033[18~" }, |
| 50 | { XK_F8, "\033[19~" }, | 51 | { XK_F8, 0, "\033[19~" }, |
| 51 | { XK_F9, "\033[20~" }, | 52 | { XK_F9, 0, "\033[20~" }, |
| 52 | { XK_F10, "\033[21~" }, | 53 | { XK_F10, 0, "\033[21~" }, |
| 53 | { XK_F11, "\033[23~" }, | 54 | { XK_F11, 0, "\033[23~" }, |
| 54 | { XK_F12, "\033[24~" }, | 55 | { XK_F12, 0, "\033[24~" }, |
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 57 | /* Line drawing characters (sometime specific to each font...) */ | 58 | /* Line drawing characters (sometime specific to each font...) */ |
| @@ -61,3 +62,7 @@ static char gfx[] = { | |||
| 61 | ['i'] = '#', | 62 | ['i'] = '#', |
| 62 | [255] = 0, | 63 | [255] = 0, |
| 63 | }; | 64 | }; |
| 65 | |||
| 66 | /* double-click timeout (in milliseconds) between clicks for selection */ | ||
| 67 | #define DOUBLECLICK_TIMEOUT 300 | ||
| 68 | #define TRIPLECLICK_TIMEOUT (2*DOUBLECLICK_TIMEOUT) | ||
| @@ -22,6 +22,9 @@ | |||
| 22 | #include <X11/cursorfont.h> | 22 | #include <X11/cursorfont.h> |
| 23 | #include <X11/keysym.h> | 23 | #include <X11/keysym.h> |
| 24 | 24 | ||
| 25 | #include <sys/time.h> | ||
| 26 | #include <time.h> | ||
| 27 | |||
| 25 | #if defined(__linux) | 28 | #if defined(__linux) |
| 26 | #include <pty.h> | 29 | #include <pty.h> |
| 27 | #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) | 30 | #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) |
| @@ -45,11 +48,12 @@ | |||
| 45 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | 48 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
| 46 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) | 49 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) |
| 47 | #define LEN(a) (sizeof(a) / sizeof(a[0])) | 50 | #define LEN(a) (sizeof(a) / sizeof(a[0])) |
| 48 | #define DEFAULT(a, b) (a) = (a) ? (a) : (b) | 51 | #define DEFAULT(a, b) (a) = (a) ? (a) : (b) |
| 49 | #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) | 52 | #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) |
| 50 | #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) | 53 | #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) |
| 51 | #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) | 54 | #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) |
| 52 | #define IS_SET(flag) (term.mode & (flag)) | 55 | #define IS_SET(flag) (term.mode & (flag)) |
| 56 | #define TIMEDIFFERENCE(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv_usec)/1000) | ||
| 53 | 57 | ||
| 54 | /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ | 58 | /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ |
| 55 | enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; | 59 | enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; |
| @@ -57,10 +61,9 @@ enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, | |||
| 57 | CURSOR_SAVE, CURSOR_LOAD }; | 61 | CURSOR_SAVE, CURSOR_LOAD }; |
| 58 | enum { CURSOR_DEFAULT = 0, CURSOR_HIDE = 1, CURSOR_WRAPNEXT = 2 }; | 62 | enum { CURSOR_DEFAULT = 0, CURSOR_HIDE = 1, CURSOR_WRAPNEXT = 2 }; |
| 59 | enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; | 63 | enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; |
| 60 | enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4, MODE_ALTSCREEN=8, | 64 | enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4, MODE_ALTSCREEN=8, |
| 61 | MODE_CRLF=16 }; | 65 | MODE_CRLF=16 }; |
| 62 | enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; | 66 | enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; |
| 63 | enum { SCREEN_UPDATE, SCREEN_REDRAW }; | ||
| 64 | enum { WIN_VISIBLE=1, WIN_REDRAW=2, WIN_FOCUSED=4 }; | 67 | enum { WIN_VISIBLE=1, WIN_REDRAW=2, WIN_FOCUSED=4 }; |
| 65 | 68 | ||
| 66 | #undef B0 | 69 | #undef B0 |
| @@ -87,21 +90,21 @@ typedef struct { | |||
| 87 | /* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */ | 90 | /* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */ |
| 88 | typedef struct { | 91 | typedef struct { |
| 89 | char buf[ESC_BUF_SIZ]; /* raw string */ | 92 | char buf[ESC_BUF_SIZ]; /* raw string */ |
| 90 | int len; /* raw string length */ | 93 | int len; /* raw string length */ |
| 91 | char priv; | 94 | char priv; |
| 92 | int arg[ESC_ARG_SIZ]; | 95 | int arg[ESC_ARG_SIZ]; |
| 93 | int narg; /* nb of args */ | 96 | int narg; /* nb of args */ |
| 94 | char mode; | 97 | char mode; |
| 95 | } CSIEscape; | 98 | } CSIEscape; |
| 96 | 99 | ||
| 97 | /* Internal representation of the screen */ | 100 | /* Internal representation of the screen */ |
| 98 | typedef struct { | 101 | typedef struct { |
| 99 | int row; /* nb row */ | 102 | int row; /* nb row */ |
| 100 | int col; /* nb col */ | 103 | int col; /* nb col */ |
| 101 | Line* line; /* screen */ | 104 | Line* line; /* screen */ |
| 102 | Line* alt; /* alternate screen */ | 105 | Line* alt; /* alternate screen */ |
| 103 | TCursor c; /* cursor */ | 106 | TCursor c; /* cursor */ |
| 104 | int top; /* top scroll limit */ | 107 | int top; /* top scroll limit */ |
| 105 | int bot; /* bottom scroll limit */ | 108 | int bot; /* bottom scroll limit */ |
| 106 | int mode; /* terminal mode flags */ | 109 | int mode; /* terminal mode flags */ |
| 107 | int esc; /* escape state flags */ | 110 | int esc; /* escape state flags */ |
| @@ -118,17 +121,18 @@ typedef struct { | |||
| 118 | XIM xim; | 121 | XIM xim; |
| 119 | XIC xic; | 122 | XIC xic; |
| 120 | int scr; | 123 | int scr; |
| 121 | int w; /* window width */ | 124 | int w; /* window width */ |
| 122 | int h; /* window height */ | 125 | int h; /* window height */ |
| 123 | int bufw; /* pixmap width */ | 126 | int bufw; /* pixmap width */ |
| 124 | int bufh; /* pixmap height */ | 127 | int bufh; /* pixmap height */ |
| 125 | int ch; /* char height */ | 128 | int ch; /* char height */ |
| 126 | int cw; /* char width */ | 129 | int cw; /* char width */ |
| 127 | char state; /* focus, redraw, visible */ | 130 | char state; /* focus, redraw, visible */ |
| 128 | } XWindow; | 131 | } XWindow; |
| 129 | 132 | ||
| 130 | typedef struct { | 133 | typedef struct { |
| 131 | KeySym k; | 134 | KeySym k; |
| 135 | unsigned int mask; | ||
| 132 | char s[ESC_BUF_SIZ]; | 136 | char s[ESC_BUF_SIZ]; |
| 133 | } Key; | 137 | } Key; |
| 134 | 138 | ||
| @@ -150,15 +154,18 @@ typedef struct { | |||
| 150 | int mode; | 154 | int mode; |
| 151 | int bx, by; | 155 | int bx, by; |
| 152 | int ex, ey; | 156 | int ex, ey; |
| 153 | struct {int x, y;} b, e; | 157 | struct {int x, y;} b, e; |
| 154 | char *clip; | 158 | char *clip; |
| 155 | Atom xtarget; | 159 | Atom xtarget; |
| 160 | struct timeval tclick1; | ||
| 161 | struct timeval tclick2; | ||
| 156 | } Selection; | 162 | } Selection; |
| 157 | 163 | ||
| 158 | #include "config.h" | 164 | #include "config.h" |
| 159 | 165 | ||
| 160 | static void die(const char *errstr, ...); | 166 | static void die(const char *errstr, ...); |
| 161 | static void draw(int); | 167 | static void draw(); |
| 168 | static void drawregion(int, int, int, int); | ||
| 162 | static void execsh(void); | 169 | static void execsh(void); |
| 163 | static void sigchld(int); | 170 | static void sigchld(int); |
| 164 | static void run(void); | 171 | static void run(void); |
| @@ -206,7 +213,7 @@ static void xresize(int, int); | |||
| 206 | static void expose(XEvent *); | 213 | static void expose(XEvent *); |
| 207 | static void visibility(XEvent *); | 214 | static void visibility(XEvent *); |
| 208 | static void unmap(XEvent *); | 215 | static void unmap(XEvent *); |
| 209 | static char* kmap(KeySym); | 216 | static char* kmap(KeySym, unsigned int state); |
| 210 | static void kpress(XEvent *); | 217 | static void kpress(XEvent *); |
| 211 | static void resize(XEvent *); | 218 | static void resize(XEvent *); |
| 212 | static void focus(XEvent *); | 219 | static void focus(XEvent *); |
| @@ -219,7 +226,7 @@ static void selrequest(XEvent *); | |||
| 219 | static void selinit(void); | 226 | static void selinit(void); |
| 220 | static inline int selected(int, int); | 227 | static inline int selected(int, int); |
| 221 | static void selcopy(void); | 228 | static void selcopy(void); |
| 222 | static void selpaste(void); | 229 | static void selpaste(); |
| 223 | 230 | ||
| 224 | static int utf8decode(char *, long *); | 231 | static int utf8decode(char *, long *); |
| 225 | static int utf8encode(long *, char *); | 232 | static int utf8encode(long *, char *); |
| @@ -340,7 +347,7 @@ isfullutf8(char *s, int b) { | |||
| 340 | else if((*c1&(B7|B6|B5)) == (B7|B6) && b == 1) | 347 | else if((*c1&(B7|B6|B5)) == (B7|B6) && b == 1) |
| 341 | return 0; | 348 | return 0; |
| 342 | else if((*c1&(B7|B6|B5|B4)) == (B7|B6|B5) && | 349 | else if((*c1&(B7|B6|B5|B4)) == (B7|B6|B5) && |
| 343 | ((b == 1) || | 350 | ((b == 1) || |
| 344 | ((b == 2) && (*c2&(B7|B6)) == B7))) | 351 | ((b == 2) && (*c2&(B7|B6)) == B7))) |
| 345 | return 0; | 352 | return 0; |
| 346 | else if((*c1&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4) && | 353 | else if((*c1&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4) && |
| @@ -362,12 +369,14 @@ utf8size(char *s) { | |||
| 362 | return 2; | 369 | return 2; |
| 363 | else if ((c&(B7|B6|B5|B4)) == (B7|B6|B5)) | 370 | else if ((c&(B7|B6|B5|B4)) == (B7|B6|B5)) |
| 364 | return 3; | 371 | return 3; |
| 365 | else | 372 | else |
| 366 | return 4; | 373 | return 4; |
| 367 | } | 374 | } |
| 368 | 375 | ||
| 369 | void | 376 | void |
| 370 | selinit(void) { | 377 | selinit(void) { |
| 378 | sel.tclick1.tv_sec = 0; | ||
| 379 | sel.tclick1.tv_usec = 0; | ||
| 371 | sel.mode = 0; | 380 | sel.mode = 0; |
| 372 | sel.bx = -1; | 381 | sel.bx = -1; |
| 373 | sel.clip = NULL; | 382 | sel.clip = NULL; |
| @@ -376,14 +385,14 @@ selinit(void) { | |||
| 376 | sel.xtarget = XA_STRING; | 385 | sel.xtarget = XA_STRING; |
| 377 | } | 386 | } |
| 378 | 387 | ||
| 379 | static inline int | 388 | static inline int |
| 380 | selected(int x, int y) { | 389 | selected(int x, int y) { |
| 381 | if(sel.ey == y && sel.by == y) { | 390 | if(sel.ey == y && sel.by == y) { |
| 382 | int bx = MIN(sel.bx, sel.ex); | 391 | int bx = MIN(sel.bx, sel.ex); |
| 383 | int ex = MAX(sel.bx, sel.ex); | 392 | int ex = MAX(sel.bx, sel.ex); |
| 384 | return BETWEEN(x, bx, ex); | 393 | return BETWEEN(x, bx, ex); |
| 385 | } | 394 | } |
| 386 | return ((sel.b.y < y&&y < sel.e.y) || (y==sel.e.y && x<=sel.e.x)) | 395 | return ((sel.b.y < y&&y < sel.e.y) || (y==sel.e.y && x<=sel.e.x)) |
| 387 | || (y==sel.b.y && x>=sel.b.x && (x<=sel.e.x || sel.b.y!=sel.e.y)); | 396 | || (y==sel.b.y && x>=sel.b.x && (x<=sel.e.x || sel.b.y!=sel.e.y)); |
| 388 | } | 397 | } |
| 389 | 398 | ||
| @@ -511,30 +520,63 @@ xsetsel(char *str) { | |||
| 511 | XFlush(xw.dpy); | 520 | XFlush(xw.dpy); |
| 512 | } | 521 | } |
| 513 | 522 | ||
| 514 | /* TODO: doubleclick to select word */ | ||
| 515 | void | 523 | void |
| 516 | brelease(XEvent *e) { | 524 | brelease(XEvent *e) { |
| 517 | int b; | 525 | int b; |
| 518 | sel.mode = 0; | 526 | sel.mode = 0; |
| 519 | getbuttoninfo(e, &b, &sel.ex, &sel.ey); | 527 | getbuttoninfo(e, &b, &sel.ex, &sel.ey); |
| 520 | if(sel.bx==sel.ex && sel.by==sel.ey) { | 528 | |
| 529 | if(sel.bx == sel.ex && sel.by == sel.ey) { | ||
| 521 | sel.bx = -1; | 530 | sel.bx = -1; |
| 522 | if(b==2) | 531 | if(b == 2) |
| 523 | selpaste(); | 532 | selpaste(); |
| 533 | |||
| 534 | else if(b == 1) { | ||
| 535 | /* double click to select word */ | ||
| 536 | struct timeval now; | ||
| 537 | gettimeofday(&now, NULL); | ||
| 538 | |||
| 539 | if(TIMEDIFFERENCE(now, sel.tclick1) <= DOUBLECLICK_TIMEOUT) { | ||
| 540 | sel.bx = sel.ex; | ||
| 541 | while(term.line[sel.ey][sel.bx-1].state & GLYPH_SET && | ||
| 542 | term.line[sel.ey][sel.bx-1].c[0] != ' ') sel.bx--; | ||
| 543 | sel.b.x = sel.bx; | ||
| 544 | while(term.line[sel.ey][sel.ex+1].state & GLYPH_SET && | ||
| 545 | term.line[sel.ey][sel.ex+1].c[0] != ' ') sel.ex++; | ||
| 546 | sel.e.x = sel.ex; | ||
| 547 | sel.b.y = sel.e.y = sel.ey; | ||
| 548 | selcopy(); | ||
| 549 | } | ||
| 550 | |||
| 551 | /* triple click on the line */ | ||
| 552 | if(TIMEDIFFERENCE(now, sel.tclick2) <= TRIPLECLICK_TIMEOUT) { | ||
| 553 | sel.b.x = sel.bx = 0; | ||
| 554 | sel.e.x = sel.ex = term.col; | ||
| 555 | sel.b.y = sel.e.y = sel.ey; | ||
| 556 | selcopy(); | ||
| 557 | } | ||
| 558 | } | ||
| 524 | } else { | 559 | } else { |
| 525 | if(b==1) | 560 | if(b == 1) |
| 526 | selcopy(); | 561 | selcopy(); |
| 527 | } | 562 | } |
| 528 | draw(1); | 563 | memcpy(&sel.tclick2, &sel.tclick1, sizeof(struct timeval)); |
| 564 | gettimeofday(&sel.tclick1, NULL); | ||
| 565 | draw(); | ||
| 529 | } | 566 | } |
| 530 | 567 | ||
| 531 | void | 568 | void |
| 532 | bmotion(XEvent *e) { | 569 | bmotion(XEvent *e) { |
| 533 | if (sel.mode) { | 570 | if(sel.mode) { |
| 571 | int oldey = sel.ey, | ||
| 572 | oldex = sel.ex; | ||
| 534 | getbuttoninfo(e, NULL, &sel.ex, &sel.ey); | 573 | getbuttoninfo(e, NULL, &sel.ex, &sel.ey); |
| 535 | /* XXX: draw() can't keep up, disabled for now. | 574 | |
| 536 | selection is visible on button release. | 575 | if(oldey != sel.ey || oldex != sel.ex) { |
| 537 | draw(1); */ | 576 | int starty = MIN(oldey, sel.ey); |
| 577 | int endy = MAX(oldey, sel.ey); | ||
| 578 | drawregion(0, (starty > 0 ? starty : 0), term.col, (sel.ey < term.row ? endy+1 : term.row)); | ||
| 579 | } | ||
| 538 | } | 580 | } |
| 539 | } | 581 | } |
| 540 | 582 | ||
| @@ -641,6 +683,10 @@ ttyread(void) { | |||
| 641 | 683 | ||
| 642 | void | 684 | void |
| 643 | ttywrite(const char *s, size_t n) { | 685 | ttywrite(const char *s, size_t n) { |
| 686 | {size_t nn; | ||
| 687 | for(nn = 0; nn < n; nn++) | ||
| 688 | dump(s[nn]); | ||
| 689 | } | ||
| 644 | if(write(cmdfd, s, n) == -1) | 690 | if(write(cmdfd, s, n) == -1) |
| 645 | die("write error on tty: %s\n", SERRNO); | 691 | die("write error on tty: %s\n", SERRNO); |
| 646 | } | 692 | } |
| @@ -1640,8 +1686,13 @@ xdrawc(int x, int y, Glyph g) { | |||
| 1640 | dc.gc, r.x, r.y+dc.font.ascent, g.c, sl); | 1686 | dc.gc, r.x, r.y+dc.font.ascent, g.c, sl); |
| 1641 | } | 1687 | } |
| 1642 | 1688 | ||
| 1689 | void | ||
| 1690 | drawregion(int x0, int x1, int y0, int y1) { | ||
| 1691 | draw(); | ||
| 1692 | } | ||
| 1693 | |||
| 1643 | void | 1694 | void |
| 1644 | draw(int dummy) { | 1695 | draw() { |
| 1645 | int x, y; | 1696 | int x, y; |
| 1646 | 1697 | ||
| 1647 | xclear(0, 0, term.col-1, term.row-1); | 1698 | xclear(0, 0, term.col-1, term.row-1); |
| @@ -1657,8 +1708,13 @@ draw(int dummy) { | |||
| 1657 | 1708 | ||
| 1658 | #else | 1709 | #else |
| 1659 | /* optimized drawing routine */ | 1710 | /* optimized drawing routine */ |
| 1711 | void | ||
| 1712 | draw() { | ||
| 1713 | drawregion(0, 0, term.col, term.row); | ||
| 1714 | } | ||
| 1715 | |||
| 1660 | void | 1716 | void |
| 1661 | draw(int redraw_all) { | 1717 | drawregion(int x1, int y1, int x2, int y2) { |
| 1662 | int ic, ib, x, y, ox, sl; | 1718 | int ic, ib, x, y, ox, sl; |
| 1663 | Glyph base, new; | 1719 | Glyph base, new; |
| 1664 | char buf[DRAW_BUF_SIZ]; | 1720 | char buf[DRAW_BUF_SIZ]; |
| @@ -1666,13 +1722,13 @@ draw(int redraw_all) { | |||
| 1666 | if(!(xw.state & WIN_VISIBLE)) | 1722 | if(!(xw.state & WIN_VISIBLE)) |
| 1667 | return; | 1723 | return; |
| 1668 | 1724 | ||
| 1669 | xclear(0, 0, term.col-1, term.row-1); | 1725 | xclear(x1, y1, x2-1, y2-1); |
| 1670 | for(y = 0; y < term.row; y++) { | 1726 | for(y = y1; y < y2; y++) { |
| 1671 | base = term.line[y][0]; | 1727 | base = term.line[y][0]; |
| 1672 | ic = ib = ox = 0; | 1728 | ic = ib = ox = 0; |
| 1673 | for(x = 0; x < term.col; x++) { | 1729 | for(x = x1; x < x2; x++) { |
| 1674 | new = term.line[y][x]; | 1730 | new = term.line[y][x]; |
| 1675 | if(sel.bx!=-1 && *(new.c) && selected(x, y)) | 1731 | if(sel.bx != -1 && *(new.c) && selected(x, y)) |
| 1676 | new.mode ^= ATTR_REVERSE; | 1732 | new.mode ^= ATTR_REVERSE; |
| 1677 | if(ib > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) || | 1733 | if(ib > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) || |
| 1678 | ib >= DRAW_BUF_SIZ-UTF_SIZ)) { | 1734 | ib >= DRAW_BUF_SIZ-UTF_SIZ)) { |
| @@ -1705,7 +1761,7 @@ expose(XEvent *ev) { | |||
| 1705 | if(xw.state & WIN_REDRAW) { | 1761 | if(xw.state & WIN_REDRAW) { |
| 1706 | if(!e->count) { | 1762 | if(!e->count) { |
| 1707 | xw.state &= ~WIN_REDRAW; | 1763 | xw.state &= ~WIN_REDRAW; |
| 1708 | draw(SCREEN_REDRAW); | 1764 | draw(); |
| 1709 | } | 1765 | } |
| 1710 | } else | 1766 | } else |
| 1711 | XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, e->x-BORDER, e->y-BORDER, | 1767 | XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, e->x-BORDER, e->y-BORDER, |
| @@ -1742,14 +1798,14 @@ focus(XEvent *ev) { | |||
| 1742 | xseturgency(0); | 1798 | xseturgency(0); |
| 1743 | } else | 1799 | } else |
| 1744 | xw.state &= ~WIN_FOCUSED; | 1800 | xw.state &= ~WIN_FOCUSED; |
| 1745 | draw(SCREEN_UPDATE); | 1801 | draw(); |
| 1746 | } | 1802 | } |
| 1747 | 1803 | ||
| 1748 | char* | 1804 | char* |
| 1749 | kmap(KeySym k) { | 1805 | kmap(KeySym k, unsigned int state) { |
| 1750 | int i; | 1806 | int i; |
| 1751 | for(i = 0; i < LEN(key); i++) | 1807 | for(i = 0; i < LEN(key); i++) |
| 1752 | if(key[i].k == k) | 1808 | if(key[i].k == k && (key[i].mask == 0 || key[i].mask & state)) |
| 1753 | return (char*)key[i].s; | 1809 | return (char*)key[i].s; |
| 1754 | return NULL; | 1810 | return NULL; |
| 1755 | } | 1811 | } |
| @@ -1770,7 +1826,7 @@ kpress(XEvent *ev) { | |||
| 1770 | len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); | 1826 | len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); |
| 1771 | 1827 | ||
| 1772 | /* 1. custom keys from config.h */ | 1828 | /* 1. custom keys from config.h */ |
| 1773 | if((customkey = kmap(ksym))) | 1829 | if((customkey = kmap(ksym, e->state))) |
| 1774 | ttywrite(customkey, strlen(customkey)); | 1830 | ttywrite(customkey, strlen(customkey)); |
| 1775 | /* 2. hardcoded (overrides X lookup) */ | 1831 | /* 2. hardcoded (overrides X lookup) */ |
| 1776 | else | 1832 | else |
| @@ -1779,7 +1835,7 @@ kpress(XEvent *ev) { | |||
| 1779 | case XK_Down: | 1835 | case XK_Down: |
| 1780 | case XK_Left: | 1836 | case XK_Left: |
| 1781 | case XK_Right: | 1837 | case XK_Right: |
| 1782 | sprintf(buf, "\033%c%c", IS_SET(MODE_APPKEYPAD) ? 'O' : '[', "DACB"[ksym - XK_Left]); | 1838 | sprintf(buf, "\033%c%c", IS_SET(MODE_APPKEYPAD) ? 'O' : '[', (shift ? "dacb":"DACB")[ksym - XK_Left]); |
| 1783 | ttywrite(buf, 3); | 1839 | ttywrite(buf, 3); |
| 1784 | break; | 1840 | break; |
| 1785 | case XK_Insert: | 1841 | case XK_Insert: |
| @@ -1817,7 +1873,7 @@ resize(XEvent *e) { | |||
| 1817 | if(col == term.col && row == term.row) | 1873 | if(col == term.col && row == term.row) |
| 1818 | return; | 1874 | return; |
| 1819 | if(tresize(col, row)) | 1875 | if(tresize(col, row)) |
| 1820 | draw(SCREEN_REDRAW); | 1876 | draw(); |
| 1821 | ttyresize(col, row); | 1877 | ttyresize(col, row); |
| 1822 | xresize(col, row); | 1878 | xresize(col, row); |
| 1823 | } | 1879 | } |
| @@ -1839,7 +1895,7 @@ run(void) { | |||
| 1839 | } | 1895 | } |
| 1840 | if(FD_ISSET(cmdfd, &rfd)) { | 1896 | if(FD_ISSET(cmdfd, &rfd)) { |
| 1841 | ttyread(); | 1897 | ttyread(); |
| 1842 | draw(SCREEN_UPDATE); | 1898 | draw(); |
| 1843 | } | 1899 | } |
| 1844 | while(XPending(xw.dpy)) { | 1900 | while(XPending(xw.dpy)) { |
| 1845 | XNextEvent(xw.dpy, &ev); | 1901 | XNextEvent(xw.dpy, &ev); |
| @@ -49,6 +49,10 @@ st| simpleterm, | |||
| 49 | kcud1=\E[B, | 49 | kcud1=\E[B, |
| 50 | kcuf1=\E[C, | 50 | kcuf1=\E[C, |
| 51 | kcuu1=\E[A, | 51 | kcuu1=\E[A, |
| 52 | kLFT=\E[d, | ||
| 53 | kRIT=\E[c, | ||
| 54 | kind=\E[a, | ||
| 55 | kri=\E[b, | ||
| 52 | kdch1=\E[3~, | 56 | kdch1=\E[3~, |
| 53 | kich1=\E[2~, | 57 | kich1=\E[2~, |
| 54 | kend=\E[4~, | 58 | kend=\E[4~, |
