Introduction
Introduction Statistics Contact Development Disclaimer Help
tselection clicks, shift+arrow keys, fast(er) redraw, key mask in config.h (thx…
git clone git://src.adamsgaard.dk/st
Log
Files
Refs
README
LICENSE
---
commit 9d5ea14b9dffac863b41432e4ce12b5624592000
parent d3c5aba2d9b0f6046e4cc72fb056cbd56c6314e6
Author: AurĂ©lien Aptel <[email protected]>
Date: Fri, 22 Apr 2011 00:18:53 +0200
selection clicks, shift+arrow keys, fast(er) redraw, key mask in config.h (thx …
Diffstat:
M config.def.h | 47 +++++++++++++++++------------…
M st.c | 136 ++++++++++++++++++++++-------…
M st.info | 4 ++++
3 files changed, 126 insertions(+), 61 deletions(-)
---
diff --git a/config.def.h b/config.def.h
t@@ -26,32 +26,33 @@ static const char *colorname[] = {
};
/* Default colors (colorname index) */
-/* foreground, background, cursor */
+/* foreground, background, cursor */
#define DefaultFG 7
#define DefaultBG 0
#define DefaultCS 1
-/* Special keys */
+/* Special keys (change & recompile st.info accordingly) */
+/* key, mask, output */
static Key key[] = {
- { XK_BackSpace, "\177" },
- { XK_Insert, "\033[2~" },
- { XK_Delete, "\033[3~" },
- { XK_Home, "\033[1~" },
- { XK_End, "\033[4~" },
- { XK_Prior, "\033[5~" },
- { XK_Next, "\033[6~" },
- { XK_F1, "\033OP" },
- { XK_F2, "\033OQ" },
- { XK_F3, "\033OR" },
- { XK_F4, "\033OS" },
- { XK_F5, "\033[15~" },
- { XK_F6, "\033[17~" },
- { XK_F7, "\033[18~" },
- { XK_F8, "\033[19~" },
- { XK_F9, "\033[20~" },
- { XK_F10, "\033[21~" },
- { XK_F11, "\033[23~" },
- { XK_F12, "\033[24~" },
+ { XK_BackSpace, 0, "\177" },
+ { XK_Insert, 0, "\033[2~" },
+ { XK_Delete, 0, "\033[3~" },
+ { XK_Home, 0, "\033[1~" },
+ { XK_End, 0, "\033[4~" },
+ { XK_Prior, 0, "\033[5~" },
+ { XK_Next, 0, "\033[6~" },
+ { XK_F1, 0, "\033OP" },
+ { XK_F2, 0, "\033OQ" },
+ { XK_F3, 0, "\033OR" },
+ { XK_F4, 0, "\033OS" },
+ { XK_F5, 0, "\033[15~" },
+ { XK_F6, 0, "\033[17~" },
+ { XK_F7, 0, "\033[18~" },
+ { XK_F8, 0, "\033[19~" },
+ { XK_F9, 0, "\033[20~" },
+ { XK_F10, 0, "\033[21~" },
+ { XK_F11, 0, "\033[23~" },
+ { XK_F12, 0, "\033[24~" },
};
/* Line drawing characters (sometime specific to each font...) */
t@@ -61,3 +62,7 @@ static char gfx[] = {
['i'] = '#',
[255] = 0,
};
+
+/* double-click timeout (in milliseconds) between clicks for selection */
+#define DOUBLECLICK_TIMEOUT 300
+#define TRIPLECLICK_TIMEOUT (2*DOUBLECLICK_TIMEOUT)
diff --git a/st.c b/st.c
t@@ -22,6 +22,9 @@
#include <X11/cursorfont.h>
#include <X11/keysym.h>
+#include <sys/time.h>
+#include <time.h>
+
#if defined(__linux)
#include <pty.h>
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
t@@ -45,11 +48,12 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a) / sizeof(a[0]))
-#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
+#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b))
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (…
#define IS_SET(flag) (term.mode & (flag))
+#define TIMEDIFFERENCE(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv…
/* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */
enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=…
t@@ -57,10 +61,9 @@ enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT,
CURSOR_SAVE, CURSOR_LOAD };
enum { CURSOR_DEFAULT = 0, CURSOR_HIDE = 1, CURSOR_WRAPNEXT = 2 };
enum { GLYPH_SET=1, GLYPH_DIRTY=2 };
-enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4, MODE_ALTSCREEN=8,
+enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4, MODE_ALTSCREEN=8,
MODE_CRLF=16 };
enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 };
-enum { SCREEN_UPDATE, SCREEN_REDRAW };
enum { WIN_VISIBLE=1, WIN_REDRAW=2, WIN_FOCUSED=4 };
#undef B0
t@@ -87,21 +90,21 @@ typedef struct {
/* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */
typedef struct {
char buf[ESC_BUF_SIZ]; /* raw string */
- int len; /* raw string length */
+ int len; /* raw string length */
char priv;
int arg[ESC_ARG_SIZ];
- int narg; /* nb of args */
+ int narg; /* nb of args */
char mode;
} CSIEscape;
/* Internal representation of the screen */
typedef struct {
- int row; /* nb row */
+ int row; /* nb row */
int col; /* nb col */
Line* line; /* screen */
Line* alt; /* alternate screen */
TCursor c; /* cursor */
- int top; /* top scroll limit */
+ int top; /* top scroll limit */
int bot; /* bottom scroll limit */
int mode; /* terminal mode flags */
int esc; /* escape state flags */
t@@ -118,17 +121,18 @@ typedef struct {
XIM xim;
XIC xic;
int scr;
- int w; /* window width */
+ int w; /* window width */
int h; /* window height */
int bufw; /* pixmap width */
int bufh; /* pixmap height */
int ch; /* char height */
int cw; /* char width */
char state; /* focus, redraw, visible */
-} XWindow;
+} XWindow;
typedef struct {
KeySym k;
+ unsigned int mask;
char s[ESC_BUF_SIZ];
} Key;
t@@ -150,15 +154,18 @@ typedef struct {
int mode;
int bx, by;
int ex, ey;
- struct {int x, y;} b, e;
+ struct {int x, y;} b, e;
char *clip;
Atom xtarget;
+ struct timeval tclick1;
+ struct timeval tclick2;
} Selection;
#include "config.h"
static void die(const char *errstr, ...);
-static void draw(int);
+static void draw();
+static void drawregion(int, int, int, int);
static void execsh(void);
static void sigchld(int);
static void run(void);
t@@ -206,7 +213,7 @@ static void xresize(int, int);
static void expose(XEvent *);
static void visibility(XEvent *);
static void unmap(XEvent *);
-static char* kmap(KeySym);
+static char* kmap(KeySym, unsigned int state);
static void kpress(XEvent *);
static void resize(XEvent *);
static void focus(XEvent *);
t@@ -219,7 +226,7 @@ static void selrequest(XEvent *);
static void selinit(void);
static inline int selected(int, int);
static void selcopy(void);
-static void selpaste(void);
+static void selpaste();
static int utf8decode(char *, long *);
static int utf8encode(long *, char *);
t@@ -340,7 +347,7 @@ isfullutf8(char *s, int b) {
else if((*c1&(B7|B6|B5)) == (B7|B6) && b == 1)
return 0;
else if((*c1&(B7|B6|B5|B4)) == (B7|B6|B5) &&
- ((b == 1) ||
+ ((b == 1) ||
((b == 2) && (*c2&(B7|B6)) == B7)))
return 0;
else if((*c1&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4) &&
t@@ -362,12 +369,14 @@ utf8size(char *s) {
return 2;
else if ((c&(B7|B6|B5|B4)) == (B7|B6|B5))
return 3;
- else
+ else
return 4;
}
void
selinit(void) {
+ sel.tclick1.tv_sec = 0;
+ sel.tclick1.tv_usec = 0;
sel.mode = 0;
sel.bx = -1;
sel.clip = NULL;
t@@ -376,14 +385,14 @@ selinit(void) {
sel.xtarget = XA_STRING;
}
-static inline int
+static inline int
selected(int x, int y) {
if(sel.ey == y && sel.by == y) {
int bx = MIN(sel.bx, sel.ex);
int ex = MAX(sel.bx, sel.ex);
return BETWEEN(x, bx, ex);
}
- return ((sel.b.y < y&&y < sel.e.y) || (y==sel.e.y && x<=sel.e.x))
+ return ((sel.b.y < y&&y < sel.e.y) || (y==sel.e.y && x<=sel.e.x))
|| (y==sel.b.y && x>=sel.b.x && (x<=sel.e.x || sel.b.y!=sel.e.…
}
t@@ -511,30 +520,63 @@ xsetsel(char *str) {
XFlush(xw.dpy);
}
-/* TODO: doubleclick to select word */
void
brelease(XEvent *e) {
int b;
sel.mode = 0;
getbuttoninfo(e, &b, &sel.ex, &sel.ey);
- if(sel.bx==sel.ex && sel.by==sel.ey) {
+
+ if(sel.bx == sel.ex && sel.by == sel.ey) {
sel.bx = -1;
- if(b==2)
+ if(b == 2)
selpaste();
+
+ else if(b == 1) {
+ /* double click to select word */
+ struct timeval now;
+ gettimeofday(&now, NULL);
+
+ if(TIMEDIFFERENCE(now, sel.tclick1) <= DOUBLECLICK_TIM…
+ sel.bx = sel.ex;
+ while(term.line[sel.ey][sel.bx-1].state & GLYP…
+ term.line[sel.ey][sel.bx-1].c[0] != …
+ sel.b.x = sel.bx;
+ while(term.line[sel.ey][sel.ex+1].state & GLYP…
+ term.line[sel.ey][sel.ex+1].c[0] != …
+ sel.e.x = sel.ex;
+ sel.b.y = sel.e.y = sel.ey;
+ selcopy();
+ }
+
+ /* triple click on the line */
+ if(TIMEDIFFERENCE(now, sel.tclick2) <= TRIPLECLICK_TIM…
+ sel.b.x = sel.bx = 0;
+ sel.e.x = sel.ex = term.col;
+ sel.b.y = sel.e.y = sel.ey;
+ selcopy();
+ }
+ }
} else {
- if(b==1)
+ if(b == 1)
selcopy();
}
- draw(1);
+ memcpy(&sel.tclick2, &sel.tclick1, sizeof(struct timeval));
+ gettimeofday(&sel.tclick1, NULL);
+ draw();
}
void
bmotion(XEvent *e) {
- if (sel.mode) {
+ if(sel.mode) {
+ int oldey = sel.ey,
+ oldex = sel.ex;
getbuttoninfo(e, NULL, &sel.ex, &sel.ey);
- /* XXX: draw() can't keep up, disabled for now.
- selection is visible on button release.
- draw(1); */
+
+ if(oldey != sel.ey || oldex != sel.ex) {
+ int starty = MIN(oldey, sel.ey);
+ int endy = MAX(oldey, sel.ey);
+ drawregion(0, (starty > 0 ? starty : 0), term.col, (se…
+ }
}
}
t@@ -641,6 +683,10 @@ ttyread(void) {
void
ttywrite(const char *s, size_t n) {
+ {size_t nn;
+ for(nn = 0; nn < n; nn++)
+ dump(s[nn]);
+ }
if(write(cmdfd, s, n) == -1)
die("write error on tty: %s\n", SERRNO);
}
t@@ -1640,8 +1686,13 @@ xdrawc(int x, int y, Glyph g) {
dc.gc, r.x, r.y+dc.font.ascent, g.c, sl);
}
+void
+drawregion(int x0, int x1, int y0, int y1) {
+ draw();
+}
+
void
-draw(int dummy) {
+draw() {
int x, y;
xclear(0, 0, term.col-1, term.row-1);
t@@ -1657,8 +1708,13 @@ draw(int dummy) {
#else
/* optimized drawing routine */
+void
+draw() {
+ drawregion(0, 0, term.col, term.row);
+}
+
void
-draw(int redraw_all) {
+drawregion(int x1, int y1, int x2, int y2) {
int ic, ib, x, y, ox, sl;
Glyph base, new;
char buf[DRAW_BUF_SIZ];
t@@ -1666,13 +1722,13 @@ draw(int redraw_all) {
if(!(xw.state & WIN_VISIBLE))
return;
- xclear(0, 0, term.col-1, term.row-1);
- for(y = 0; y < term.row; y++) {
+ xclear(x1, y1, x2-1, y2-1);
+ for(y = y1; y < y2; y++) {
base = term.line[y][0];
ic = ib = ox = 0;
- for(x = 0; x < term.col; x++) {
+ for(x = x1; x < x2; x++) {
new = term.line[y][x];
- if(sel.bx!=-1 && *(new.c) && selected(x, y))
+ if(sel.bx != -1 && *(new.c) && selected(x, y))
new.mode ^= ATTR_REVERSE;
if(ib > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base…
ib >= DRAW_BUF_SIZ-UTF_SIZ)) {
t@@ -1705,7 +1761,7 @@ expose(XEvent *ev) {
if(xw.state & WIN_REDRAW) {
if(!e->count) {
xw.state &= ~WIN_REDRAW;
- draw(SCREEN_REDRAW);
+ draw();
}
} else
XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, e->x-BORDER, e->y-BOR…
t@@ -1742,14 +1798,14 @@ focus(XEvent *ev) {
xseturgency(0);
} else
xw.state &= ~WIN_FOCUSED;
- draw(SCREEN_UPDATE);
+ draw();
}
char*
-kmap(KeySym k) {
+kmap(KeySym k, unsigned int state) {
int i;
for(i = 0; i < LEN(key); i++)
- if(key[i].k == k)
+ if(key[i].k == k && (key[i].mask == 0 || key[i].mask & state))
return (char*)key[i].s;
return NULL;
}
t@@ -1770,7 +1826,7 @@ kpress(XEvent *ev) {
len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status);
/* 1. custom keys from config.h */
- if((customkey = kmap(ksym)))
+ if((customkey = kmap(ksym, e->state)))
ttywrite(customkey, strlen(customkey));
/* 2. hardcoded (overrides X lookup) */
else
t@@ -1779,7 +1835,7 @@ kpress(XEvent *ev) {
case XK_Down:
case XK_Left:
case XK_Right:
- sprintf(buf, "\033%c%c", IS_SET(MODE_APPKEYPAD) ? 'O' …
+ sprintf(buf, "\033%c%c", IS_SET(MODE_APPKEYPAD) ? 'O' …
ttywrite(buf, 3);
break;
case XK_Insert:
t@@ -1817,7 +1873,7 @@ resize(XEvent *e) {
if(col == term.col && row == term.row)
return;
if(tresize(col, row))
- draw(SCREEN_REDRAW);
+ draw();
ttyresize(col, row);
xresize(col, row);
}
t@@ -1839,7 +1895,7 @@ run(void) {
}
if(FD_ISSET(cmdfd, &rfd)) {
ttyread();
- draw(SCREEN_UPDATE);
+ draw();
}
while(XPending(xw.dpy)) {
XNextEvent(xw.dpy, &ev);
diff --git a/st.info b/st.info
t@@ -49,6 +49,10 @@ st| simpleterm,
kcud1=\E[B,
kcuf1=\E[C,
kcuu1=\E[A,
+ kLFT=\E[d,
+ kRIT=\E[c,
+ kind=\E[a,
+ kri=\E[b,
kdch1=\E[3~,
kich1=\E[2~,
kend=\E[4~,
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.