History

snarf is working (but the code is even uglier than it should)

yiyus committed 15 years ago

Commit 3debbdb1 parent 352b96d7 files · +297 −15Browse files

Unified · Split

7 files
  1. devwsys/dat.h +13 −0
  2. devwsys/fns.h +2 −0
  3. devwsys/ixp_fsys.c +58 −5
  4. devwsys/x11/display.c +4 −0
  5. devwsys/x11/event.c +5 −0
  6. devwsys/x11/itrans.c +212 −10
  7. devwsys/x11/x.h +3 −0
devwsys/dat.h+13−0
@@ -32,6 +32,11 @@ enum { · 31 unmodified lines
32 CursorSize= 3232 CursorSize= 32
33};33};
34 34
35/* snarf buffer size */
36enum{
37 SnarfSize= 100*1024
38};
39
35/* Datatypes: */40/* Datatypes: */
36typedef struct Client Client;41typedef struct Client Client;
37typedef struct DImage DImage;42typedef struct DImage DImage;
@@ -44,6 +49,7 @@ typedef struct Kbdbuf Kbdbuf; · 6 unmodified lines
44typedef struct Refresh Refresh;49typedef struct Refresh Refresh;
45typedef struct Refx Refx;50typedef struct Refx Refx;
46typedef struct Cursor Cursor;51typedef struct Cursor Cursor;
52typedef struct Clip Clip;
47typedef struct Window Window;53typedef struct Window Window;
48 54
49/* Drawing device */55/* Drawing device */
@@ -167,6 +173,12 @@ struct Cursor { · 117 unmodified lines
167 uchar mask[(CursorSize/8)*CursorSize];173 uchar mask[(CursorSize/8)*CursorSize];
168};174};
169 175
176/* snarf buffer */
177struct Clip
178{
179 char buf[SnarfSize];
180};
181
170/* Window system */182/* Window system */
171struct Window183struct Window
172{184{
@@ -194,4 +206,5 @@ int nwindow; · 21 unmodified lines
194Window **window;206Window **window;
195int nclient;207int nclient;
196Client **client;208Client **client;
209Clip clip;
197 210
devwsys/fns.h+2−0
@@ -49,3 +49,5 @@ int xupdatelabel(Window*); · 48 unmodified lines
49void xtopwindow(Window*);49void xtopwindow(Window*);
50void xresizewindow(Window*, Rectangle);50void xresizewindow(Window*, Rectangle);
51void xsetcursor(Window*);51void xsetcursor(Window*);
52char* xgetsnarf(Window*);
53void xputsnarf(Window*, char*);
devwsys/ixp_fsys.c+58−5
@@ -140,6 +140,8 @@ static IxpDirtab* dirtab[] = { · 139 unmodified lines
140typedef char* (*MsgFunc)(void*, IxpMsg*);140typedef char* (*MsgFunc)(void*, IxpMsg*);
141typedef char* (*BufFunc)(void*);141typedef char* (*BufFunc)(void*);
142 142
143static char *snarfbuf;
144
143static void145static void
144dostat(IxpStat *s, IxpFileId *f) {146dostat(IxpStat *s, IxpFileId *f) {
145 s->type = 0;147 s->type = 0;
@@ -367,6 +369,13 @@ fs_open(Ixp9Req *r) { · 221 unmodified lines
367 w->mouseopen = 1;369 w->mouseopen = 1;
368 ixp_pending_pushfid(w->mousep, r->fid);370 ixp_pending_pushfid(w->mousep, r->fid);
369 break;371 break;
372 case FsFSnarf:
373 if((r->ifcall.topen.mode&3) == ORDWR){
374 /* one at a time please */
375 ixp_respond(r, Enoperm);
376 return;
377 }
378 break;
370 }379 }
371 380
372 if((r->ifcall.topen.mode&3) == OEXEC381 if((r->ifcall.topen.mode&3) == OEXEC
@@ -388,7 +397,7 @@ fs_walk(Ixp9Req *r) { · 15 unmodified lines
388 397
389void398void
390fs_read(Ixp9Req *r) {399fs_read(Ixp9Req *r) {
391 char buf[512];400 char buf[512], *s;
392 int n;401 int n;
393 IxpFileId *f;402 IxpFileId *f;
394 Client *cl;403 Client *cl;
@@ -461,6 +470,7 @@ fs_read(Ixp9Req *r) { · 66 unmodified lines
461 }470 }
462 n = readrefresh(buf, r->ifcall.io.count, cl);471 n = readrefresh(buf, r->ifcall.io.count, cl);
463 if(n > 0) {472 if(n > 0) {
473
464 ixp_srv_readbuf(r, buf, n);474 ixp_srv_readbuf(r, buf, n);
465 ixp_respond(r, nil);475 ixp_respond(r, nil);
466 }476 }
@@ -472,6 +482,11 @@ fs_read(Ixp9Req *r) { · 5 unmodified lines
472 ixp_srv_readbuf(r, w->label, strlen(w->label));482 ixp_srv_readbuf(r, w->label, strlen(w->label));
473 ixp_respond(r, nil);483 ixp_respond(r, nil);
474 return;484 return;
485 case FsFSnarf:
486 s= xgetsnarf(w);
487 ixp_srv_readbuf(r, s, strlen(s));
488 ixp_respond(r, nil);
489 return;
475 case FsFWctl:490 case FsFWctl:
476 // XXX TODO: visible, current491 // XXX TODO: visible, current
477 sprint(buf, "%11d %11d %11d %11d %s %s ", w->orig.x + w->screenr.min.x, w->orig.y + w->screenr.min.y, w->screenr.max.x, w->screenr.max.y, "visible", "current");492 sprint(buf, "%11d %11d %11d %11d %s %s ", w->orig.x + w->screenr.min.x, w->orig.y + w->screenr.min.y, w->screenr.max.x, w->screenr.max.y, "visible", "current");
@@ -534,7 +549,7 @@ fs_stat(Ixp9Req *r) { · 56 unmodified lines
534 549
535void550void
536fs_write(Ixp9Req *r) {551fs_write(Ixp9Req *r) {
537 char *label;552 char *label, *p;
538 char err[256];553 char err[256];
539 IxpFileId *f;554 IxpFileId *f;
540 Window *w;555 Window *w;
@@ -602,11 +617,38 @@ fs_write(Ixp9Req *r) { · 61 unmodified lines
602 label[r->ifcall.twrite.count] = 0;617 label[r->ifcall.twrite.count] = 0;
603 setlabel(w, label);618 setlabel(w, label);
604 break;619 break;
620 case FsFSnarf:
621 if(r->ifcall.twrite.offset+r->ifcall.twrite.count >= SnarfSize){
622 ixp_respond(r, "too much snarf");
623 return;
624 }
625 if(r->ifcall.twrite.count == 0){
626 r->ofcall.io.count = r->ifcall.io.count;
627 break;
628 }
629 if(snarfbuf == nil)
630 r->ofcall.io.count = 0;
631 else
632 r->ofcall.io.count = strlen(snarfbuf);
633 if(r->ifcall.twrite.offset+r->ifcall.twrite.count > r->ofcall.io.count){
634 r->ofcall.io.count = r->ifcall.twrite.offset+r->ifcall.twrite.count;
635 p = malloc(r->ofcall.io.count+1);
636 if(p == nil){
637 ixp_respond(r, Enomem);
638 return;
639 }
640 if(snarfbuf){
641 strcpy(p, snarfbuf);
642 free(snarfbuf);
643 }
644 snarfbuf = p;
645 }
646 memmove(snarfbuf+r->ifcall.twrite.offset, r->ifcall.twrite.data, r->ifcall.twrite.count);
647 break;
605 case FsFWctl:648 case FsFWctl:
606 r->ofcall.io.count = r->ifcall.io.count;649 r->ofcall.io.count = r->ifcall.io.count;
607 wctlmesg(w, r->ifcall.twrite.data, r->ofcall.rwrite.count, err);650 wctlmesg(w, r->ifcall.twrite.data, r->ofcall.rwrite.count, err);
608 ixp_respond(r, nil);651 break;
609 return;
610 }652 }
611 ixp_respond(r, nil);653 ixp_respond(r, nil);
612}654}
@@ -639,8 +681,19 @@ fs_clunk(Ixp9Req *r) { · 26 unmodified lines
639 }681 }
640 682
641 // TODO: ../../inferno-os/emu/port/devdraw.c:971683 // TODO: ../../inferno-os/emu/port/devdraw.c:971
642 if(f->tab.type == FsFCtl)684 switch(f->tab.type){
685 case FsFCtl:
643 cl->busy = 0;686 cl->busy = 0;
687 case FsFSnarf:
688 if(r->fid->omode == OWRITE){
689 if(snarfbuf)
690 xputsnarf(w, snarfbuf);
691 else
692 xputsnarf(w, "");
693 }
694 free(snarfbuf);
695
696 }
644 if(!iswindow(f->tab.type) && (decref(&cl->r)==0))697 if(!iswindow(f->tab.type) && (decref(&cl->r)==0))
645 drawfree(cl);698 drawfree(cl);
646 ixp_respond(r, nil);699 ixp_respond(r, nil);
devwsys/x11/display.c+4−0
@@ -4,6 +4,7 @@ · 3 unmodified lines
4#include <memlayer.h>4#include <memlayer.h>
5#include <cursor.h>5#include <cursor.h>
6#include "dat.h"6#include "dat.h"
7#include "fns.h"
7#include "inc.h"8#include "inc.h"
8#include "x.h"9#include "x.h"
9 10
@@ -182,6 +183,9 @@ xinit(void) · 172 unmodified lines
182 setupcmap(xconn.root);183 setupcmap(xconn.root);
183 }184 }
184 xconn.screenrect = Rect(0, 0, WidthOfScreen(xconn.screen), HeightOfScreen(xconn.screen));185 xconn.screenrect = Rect(0, 0, WidthOfScreen(xconn.screen), HeightOfScreen(xconn.screen));
186
187 xinitclipboard();
188
185 return 0;189 return 0;
186}190}
187 191
devwsys/x11/event.c+5−0
@@ -75,6 +75,10 @@ NextEvent: · 74 unmodified lines
75 writekbd(w, -1);;75 writekbd(w, -1);;
76 break;76 break;
77 77
78 case SelectionRequest:
79 xselect(&xev);
80 break;
81
78 default:82 default:
79 break;83 break;
80 }84 }
@@ -178,6 +182,7 @@ mouseevent(Window *w, XEvent xev) · 97 unmodified lines
178{182{
179 Mouse m;183 Mouse m;
180 184
185 xsetsnarfowner(w);
181 if(xtoplan9mouse(&xev, &m) < 0)186 if(xtoplan9mouse(&xev, &m) < 0)
182 return;187 return;
183 // debugev("Mouse event at window %d: x=%d y=%d b=%d\n", w->id, m.xy.x, m.xy.y, m.buttons);188 // debugev("Mouse event at window %d: x=%d y=%d b=%d\n", w->id, m.xy.x, m.xy.y, m.buttons);
devwsys/x11/itrans.c+212−10
@@ -8,6 +8,14 @@ · 7 unmodified lines
8#include "inc.h"8#include "inc.h"
9#include "x.h"9#include "x.h"
10 10
11/* for copy/paste, lifted from plan9ports via drawterm */
12static int putsnarf, assertsnarf;
13static Atom clipboard;
14static Atom utf8string;
15static Atom targets;
16static Atom text;
17static Atom compoundtext;
18
11long keysym2ucs(KeySym);19long keysym2ucs(KeySym);
12int20int
13xtoplan9kbd(XEvent *e)21xtoplan9kbd(XEvent *e)
@@ -126,16 +134,6 @@ xtoplan9mouse(XEvent *e, Mouse *m) · 112 unmodified lines
126 XButtonEvent *be;134 XButtonEvent *be;
127 XMotionEvent *me;135 XMotionEvent *me;
128 136
129 /* TODO
130 if(_x.putsnarf != _x.assertsnarf){
131 _x.assertsnarf = _x.putsnarf;
132 XSetSelectionOwner(_x.display, XA_PRIMARY, _x.drawable, CurrentTime);
133 if(_x.clipboard != None)
134 XSetSelectionOwner(_x.display, _x.clipboard, _x.drawable, CurrentTime);
135 XFlush(_x.display);
136 }
137 */
138
139 switch(e->type){137 switch(e->type){
140 case ButtonPress:138 case ButtonPress:
141 be = (XButtonEvent*)e;139 be = (XButtonEvent*)e;
@@ -222,3 +220,207 @@ xtoplan9mouse(XEvent *e, Mouse *m) · 80 unmodified lines
222 m->buttons |= 16;220 m->buttons |= 16;
223 return 0;221 return 0;
224}222}
223
224/*
225 * Cut and paste. Just couldn't stand to make this simple...
226 */
227
228void
229xinitclipboard(void){
230 clipboard = XInternAtom(xconn.display, "CLIPBOARD", False);
231 utf8string = XInternAtom(xconn.display, "UTF8_STRING", False);
232 targets = XInternAtom(xconn.display, "TARGETS", False);
233 text = XInternAtom(xconn.display, "TEXT", False);
234 compoundtext = XInternAtom(xconn.display, "COMPOUND_TEXT", False);
235}
236
237void
238xsetsnarfowner(Window *w)
239{
240 Xwin *xw;
241
242 xw = w->x;
243 if(putsnarf != assertsnarf){
244 assertsnarf = putsnarf;
245 XSetSelectionOwner(xconn.display, XA_PRIMARY, xw->drawable, CurrentTime);
246 if(clipboard != None)
247 XSetSelectionOwner(xconn.display, clipboard, xw->drawable, CurrentTime);
248 XFlush(xconn.display);
249 }
250}
251
252char*
253xgetsnarf(Window *window)
254{
255 uchar *data, *xdata;
256 Atom clipboard, type, prop;
257 unsigned long len, lastlen, dummy;
258 int fmt, i;
259 XWindow w, xdrawable;
260 XDisplay *xd;
261 Xwin *xw;
262
263 /*
264 * Have we snarfed recently and the X server hasn't caught up?
265 */
266 if(putsnarf != assertsnarf)
267 goto mine;
268
269 xd = xconn.display;
270 xw = window->x;
271 xdrawable = xw->drawable;
272
273 /*
274 * Is there a primary selection (highlighted text in an xterm)?
275 */
276 clipboard = XA_PRIMARY;
277 w = XGetSelectionOwner(xd, XA_PRIMARY);
278 if(w == xdrawable){
279 mine:
280 data = (uchar*)strdup(clip.buf);
281 goto out;
282 }
283
284 /*
285 * If not, is there a clipboard selection?
286 */
287 if(w == None && clipboard != None){
288 clipboard = clipboard;
289 w = XGetSelectionOwner(xd, clipboard);
290 if(w == xdrawable)
291 goto mine;
292 }
293
294 /*
295 * If not, give up.
296 */
297 if(w == None){
298 data = nil;
299 goto out;
300 }
301
302 /*
303 * We should be waiting for SelectionNotify here, but it might never
304 * come, and we have no way to time out. Instead, we will clear
305 * local property #1, request our buddy to fill it in for us, and poll
306 * until he's done or we get tired of waiting.
307 *
308 * We should try to go for utf8string instead of XA_STRING,
309 * but that would add to the polling.
310 */
311 prop = 1;
312 XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
313 XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime);
314 XFlush(xd);
315 lastlen = 0;
316 for(i=0; i<10 || (lastlen!=0 && i<30); i++){
317 usleep(10*1000);
318 XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType,
319 &type, &fmt, &dummy, &len, &data);
320 if(lastlen == len && len > 0)
321 break;
322 lastlen = len;
323 }
324 if(i == 10){
325 data = nil;
326 goto out;
327 }
328 /* get the property */
329 data = nil;
330 XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(unsigned long), 0,
331 AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
332 if((type != XA_STRING && type != utf8string) || len == 0){
333 if(xdata)
334 XFree(xdata);
335 data = nil;
336 }else{
337 if(xdata){
338 data = (uchar*)strdup((char*)xdata);
339 XFree(xdata);
340 }else
341 data = nil;
342 }
343out:
344 return (char*)data;
345}
346
347void
348xputsnarf(Window *window, char *data)
349{
350 XButtonEvent e;
351 XWindow xdrawable;
352 Xwin *xw;
353
354 if(strlen(data) >= SnarfSize)
355 return;
356 strcpy(clip.buf, data);
357
358 xw = window->x;
359 xdrawable = xw->drawable;
360
361 /* leave note for mouse proc to assert selection ownership */
362 putsnarf++;
363
364 /* send mouse a fake event so snarf is announced */
365 memset(&e, 0, sizeof e);
366 e.type = ButtonPress;
367 e.window = xdrawable;
368 e.state = ~0;
369 e.button = ~0;
370 XSendEvent(xconn.display, xdrawable, True, ButtonPressMask, (XEvent*)&e);
371 XFlush(xconn.display);
372}
373
374void
375xselect(XEvent *e)
376{
377 char *name;
378 XEvent r;
379 XSelectionRequestEvent *xe;
380 Atom a[4];
381 XDisplay *xd;
382
383 if(e->xany.type != SelectionRequest)
384 return;
385
386 xd = xconn.display;
387
388 memset(&r, 0, sizeof r);
389 xe = (XSelectionRequestEvent*)e;
390if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n",
391 xe->target, xe->requestor, xe->property, xe->selection);
392 r.xselection.property = xe->property;
393 if(xe->target == targets){
394 a[0] = XA_STRING;
395 a[1] = utf8string;
396 a[2] = text;
397 a[3] = compoundtext;
398
399 XChangeProperty(xd, xe->requestor, xe->property, xe->target,
400 8, PropModeReplace, (uchar*)a, sizeof a);
401 }else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){
402 /* if the target is STRING we're supposed to reply with Latin1 XXX */
403 XChangeProperty(xd, xe->requestor, xe->property, xe->target,
404 8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
405 }else{
406 iprint("get %d\n", xe->target);
407 name = XGetAtomName(xd, xe->target);
408 if(name == nil)
409 iprint("XGetAtomName failed\n");
410 else if(strcmp(name, "TIMESTAMP") != 0)
411 iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
412 r.xselection.property = None;
413 }
414
415 r.xselection.display = xe->display;
416 /* r.xselection.property filled above */
417 r.xselection.target = xe->target;
418 r.xselection.type = SelectionNotify;
419 r.xselection.requestor = xe->requestor;
420 r.xselection.time = xe->time;
421 r.xselection.send_event = True;
422 r.xselection.selection = xe->selection;
423 XSendEvent(xd, xe->requestor, False, 0, &r);
424 XFlush(xd);
425}
426
devwsys/x11/x.h+3−0
@@ -70,3 +70,6 @@ void xmovewindow(Window*, Rectangle); · 69 unmodified lines
70void xputxdata(Memimage*, Rectangle);70void xputxdata(Memimage*, Rectangle);
71void xmemimagedraw(Memimage*, Rectangle, Memimage*, Point,71void xmemimagedraw(Memimage*, Rectangle, Memimage*, Point,
72 Memimage*, Point, int);72 Memimage*, Point, int);
73void xinitclipboard(void);
74void xsetsnarfowner(Window*);
75void xselect(XEvent*);