diff options
author | Aurélien Aptel <aurelien.aptel@gmail.com> | 2011-04-22 00:18:53 +0200 |
---|---|---|
committer | Aurélien Aptel <aurelien.aptel@gmail.com> | 2011-04-22 00:18:53 +0200 |
commit | e4dd367a4f0f07d5e721adf97f882642e520f1ca (patch) | |
tree | 6665171645be9750ffcc409613887911c0e2ceaf | |
parent | 043fb982c5d4402c7635544753c0e59547f45277 (diff) | |
download | st-patched-e4dd367a4f0f07d5e721adf97f882642e520f1ca.tar.bz2 st-patched-e4dd367a4f0f07d5e721adf97f882642e520f1ca.tar.xz st-patched-e4dd367a4f0f07d5e721adf97f882642e520f1ca.zip |
selection clicks, shift+arrow keys, fast(er) redraw, key mask in config.h (thx Magnus Leuthner)
-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~, |