aboutsummaryrefslogtreecommitdiff
path: root/st.c
diff options
context:
space:
mode:
authorpancake <pancake@nopcode.org>2010-08-30 23:41:37 +0200
committerpancake <pancake@nopcode.org>2010-08-30 23:41:37 +0200
commit0ba53e48c76a2a2668dfa270cfd0227461c3a91b (patch)
treeed1d0b42e43d038eb66ca79c6e0bdb5e067e7e16 /st.c
parente1ce89f2678628b1c0e904800822a553de2817de (diff)
downloadst-0ba53e48c76a2a2668dfa270cfd0227461c3a91b.tar.gz
st-0ba53e48c76a2a2668dfa270cfd0227461c3a91b.zip
initial implementation of selection and clipboard
Diffstat (limited to 'st.c')
-rw-r--r--st.c111
1 files changed, 108 insertions, 3 deletions
diff --git a/st.c b/st.c
index fb1172a..864dfc7 100644
--- a/st.c
+++ b/st.c
@@ -177,6 +177,9 @@ static char* kmap(KeySym);
177static void kpress(XEvent *); 177static void kpress(XEvent *);
178static void resize(XEvent *); 178static void resize(XEvent *);
179static void focus(XEvent *); 179static void focus(XEvent *);
180static void brelease(XEvent *e);
181static void bpress(XEvent *e);
182static void bmotion(XEvent *e);
180 183
181 184
182static void (*handler[LASTEvent])(XEvent *) = { 185static void (*handler[LASTEvent])(XEvent *) = {
@@ -185,6 +188,9 @@ static void (*handler[LASTEvent])(XEvent *) = {
185 [ConfigureNotify] = resize, 188 [ConfigureNotify] = resize,
186 [FocusIn] = focus, 189 [FocusIn] = focus,
187 [FocusOut] = focus, 190 [FocusOut] = focus,
191 [MotionNotify] = bmotion,
192 [ButtonPress] = bpress,
193 [ButtonRelease] = brelease,
188}; 194};
189 195
190/* Globals */ 196/* Globals */
@@ -195,6 +201,103 @@ static CSIEscape escseq;
195static int cmdfd; 201static int cmdfd;
196static pid_t pid; 202static pid_t pid;
197 203
204/* selection */
205// TODO: use X11 clipboard
206static int selmode = 0;
207static int selbx = -1, selby;
208static int selex, seley;
209int sb[2], se[2];
210static const char *clipboard = NULL;
211
212static inline int selected(int x, int y) {
213 if ((seley==y && selby==y)) {
214 int bx = MIN(selbx, selex);
215 int ex = MAX(selbx, selex);
216 return if(x>=bx && x<=ex)
217 }
218 return (((y>sb[1] && y<se[1]) || (y==se[1] && x<=se[0])) || \
219 (y==sb[1] && x>=sb[0] && (x<=se[0] || sb[1]!=se[1])))
220}
221
222static void getbuttoninfo(XEvent *e, int *b, int *x, int *y) {
223 if(b) *b = e->xbutton.state,
224 *b=*b==4096?5:*b==2048?4:*b==1024?3:*b==512?2:*b==256?1:-1;
225 *x = e->xbutton.x/xw.cw;
226 *y = e->xbutton.y/xw.ch;
227 sb[0] = selby<seley?selbx:selex;
228 sb[1] = MIN(selby, seley);
229 se[0] = selby<seley?selex:selbx;
230 se[1] = MAX(selby, seley);
231}
232
233static void bpress(XEvent *e) {
234 selmode = 1;
235 selex = selbx = e->xbutton.x/xw.cw;
236 seley = selby = e->xbutton.y/xw.ch;
237}
238
239static char *getseltext() {
240 char *str, *ptr;
241 int ls, x, y, sz;
242 if(selbx==-1)
243 return NULL;
244 sz = ((xw.w/xw.ch) * (se[1]-sb[1]+2));
245 ptr = str = malloc (sz);
246 for(y = 0; y < term.row; y++) {
247 for(x = 0; x < term.col; x++) {
248 if(term.line[y][x].c && (ls=selected(x, y))) {
249 *ptr = term.line[y][x].c;
250 ptr++;
251 }
252 }
253 if (ls) {
254 *ptr = '\n';
255 ptr++;
256 }
257 }
258 *ptr = 0;
259 return str;
260}
261
262static void clipboard_copy(const char *str) {
263 free((void *)clipboard);
264 clipboard = str;
265}
266
267static void clipboard_paste() {
268 if(clipboard)
269 ttywrite(clipboard, strlen(clipboard));
270}
271
272// TODO: doubleclick to select word
273static void brelease(XEvent *e) {
274 int b;
275 selmode = 0;
276 getbuttoninfo(e, &b, &selex, &seley);
277 if(b==4)
278 tscrollup(1);
279 else
280 if(b==5)
281 tscrolldown(1);
282 else
283 if(selbx==selex && selby==seley) {
284 selbx = -1;
285 if(b==2)
286 clipboard_paste();
287 } else {
288 if(b==1)
289 clipboard_copy(getseltext());
290 }
291 draw(1);
292}
293
294static void bmotion(XEvent *e) {
295 if (selmode) {
296 getbuttoninfo(e, NULL, &selex, &seley);
297 draw(1);
298 }
299}
300
198#ifdef DEBUG 301#ifdef DEBUG
199void 302void
200tdump(void) { 303tdump(void) {
@@ -1210,7 +1313,7 @@ draw(int redraw_all) {
1210 int i, x, y, ox; 1313 int i, x, y, ox;
1211 Glyph base, new; 1314 Glyph base, new;
1212 char buf[DRAW_BUF_SIZ]; 1315 char buf[DRAW_BUF_SIZ];
1213 1316
1214 XSetForeground(xw.dis, dc.gc, dc.col[DefaultBG]); 1317 XSetForeground(xw.dis, dc.gc, dc.col[DefaultBG]);
1215 XFillRectangle(xw.dis, xw.buf, dc.gc, 0, 0, xw.bufw, xw.bufh); 1318 XFillRectangle(xw.dis, xw.buf, dc.gc, 0, 0, xw.bufw, xw.bufh);
1216 for(y = 0; y < term.row; y++) { 1319 for(y = 0; y < term.row; y++) {
@@ -1218,8 +1321,10 @@ draw(int redraw_all) {
1218 i = ox = 0; 1321 i = ox = 0;
1219 for(x = 0; x < term.col; x++) { 1322 for(x = 0; x < term.col; x++) {
1220 new = term.line[y][x]; 1323 new = term.line[y][x];
1324 if(selbx!=-1 && new.c && selected(x, y))
1325 new.mode = ATTR_REVERSE;
1221 if(i > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) || 1326 if(i > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) ||
1222 i >= DRAW_BUF_SIZ)) { 1327 i >= DRAW_BUF_SIZ)) {
1223 xdraws(buf, base, ox, y, i); 1328 xdraws(buf, base, ox, y, i);
1224 i = 0; 1329 i = 0;
1225 } 1330 }
@@ -1335,7 +1440,7 @@ run(void) {
1335 XEvent ev; 1440 XEvent ev;
1336 fd_set rfd; 1441 fd_set rfd;
1337 int xfd = XConnectionNumber(xw.dis); 1442 int xfd = XConnectionNumber(xw.dis);
1338 long mask = ExposureMask | KeyPressMask | StructureNotifyMask | FocusChangeMask; 1443 long mask = ExposureMask | KeyPressMask | StructureNotifyMask | FocusChangeMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
1339 1444
1340 XSelectInput(xw.dis, xw.win, mask); 1445 XSelectInput(xw.dis, xw.win, mask);
1341 XResizeWindow(xw.dis, xw.win, xw.w, xw.h); /* XXX: fix resize bug in wmii (?) */ 1446 XResizeWindow(xw.dis, xw.win, xw.w, xw.h); /* XXX: fix resize bug in wmii (?) */