17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier #define MAXSNARF 100*1024
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier char Einuse[] = "file in use";
177dd7cddfSDavid du Colombier char Edeleted[] = "window deleted";
187dd7cddfSDavid du Colombier char Ebadreq[] = "bad graphics request";
1959cc4ca5SDavid du Colombier char Etooshort[] = "buffer too small";
207dd7cddfSDavid du Colombier char Ebadtile[] = "unknown tile";
217dd7cddfSDavid du Colombier char Eshort[] = "short i/o request";
227dd7cddfSDavid du Colombier char Elong[] = "snarf buffer too long";
237dd7cddfSDavid du Colombier char Eunkid[] = "unknown id in attach";
247dd7cddfSDavid du Colombier char Ebadrect[] = "bad rectangle in attach";
257dd7cddfSDavid du Colombier char Ewindow[] = "cannot make window";
267dd7cddfSDavid du Colombier char Enowindow[] = "window has no image";
277dd7cddfSDavid du Colombier char Ebadmouse[] = "bad format on /dev/mouse";
287dd7cddfSDavid du Colombier char Ebadwrect[] = "rectangle outside screen";
297dd7cddfSDavid du Colombier char Ebadoffset[] = "window read not on scan line boundary";
3080ee5cbfSDavid du Colombier extern char Eperm[];
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier static Xfid *xfidfree;
337dd7cddfSDavid du Colombier static Xfid *xfid;
347dd7cddfSDavid du Colombier static Channel *cxfidalloc; /* chan(Xfid*) */
357dd7cddfSDavid du Colombier static Channel *cxfidfree; /* chan(Xfid*) */
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier static char *tsnarf;
387dd7cddfSDavid du Colombier static int ntsnarf;
397dd7cddfSDavid du Colombier
407dd7cddfSDavid du Colombier void
xfidallocthread(void *)417dd7cddfSDavid du Colombier xfidallocthread(void*)
427dd7cddfSDavid du Colombier {
437dd7cddfSDavid du Colombier Xfid *x;
447dd7cddfSDavid du Colombier enum { Alloc, Free, N };
457dd7cddfSDavid du Colombier static Alt alts[N+1];
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier alts[Alloc].c = cxfidalloc;
487dd7cddfSDavid du Colombier alts[Alloc].v = nil;
497dd7cddfSDavid du Colombier alts[Alloc].op = CHANRCV;
507dd7cddfSDavid du Colombier alts[Free].c = cxfidfree;
517dd7cddfSDavid du Colombier alts[Free].v = &x;
527dd7cddfSDavid du Colombier alts[Free].op = CHANRCV;
537dd7cddfSDavid du Colombier alts[N].op = CHANEND;
547dd7cddfSDavid du Colombier for(;;){
557dd7cddfSDavid du Colombier switch(alt(alts)){
567dd7cddfSDavid du Colombier case Alloc:
577dd7cddfSDavid du Colombier x = xfidfree;
587dd7cddfSDavid du Colombier if(x)
597dd7cddfSDavid du Colombier xfidfree = x->free;
607dd7cddfSDavid du Colombier else{
617dd7cddfSDavid du Colombier x = emalloc(sizeof(Xfid));
627dd7cddfSDavid du Colombier x->c = chancreate(sizeof(void(*)(Xfid*)), 0);
6380ee5cbfSDavid du Colombier x->flushc = chancreate(sizeof(int), 0); /* notification only; no data */
647dd7cddfSDavid du Colombier x->flushtag = -1;
657dd7cddfSDavid du Colombier x->next = xfid;
667dd7cddfSDavid du Colombier xfid = x;
677dd7cddfSDavid du Colombier threadcreate(xfidctl, x, 16384);
687dd7cddfSDavid du Colombier }
6959cc4ca5SDavid du Colombier if(x->ref != 0){
709a747e4fSDavid du Colombier fprint(2, "%p incref %ld\n", x, x->ref);
7159cc4ca5SDavid du Colombier error("incref");
7259cc4ca5SDavid du Colombier }
7359cc4ca5SDavid du Colombier if(x->flushtag != -1)
7459cc4ca5SDavid du Colombier error("flushtag in allocate");
757dd7cddfSDavid du Colombier incref(x);
767dd7cddfSDavid du Colombier sendp(cxfidalloc, x);
777dd7cddfSDavid du Colombier break;
787dd7cddfSDavid du Colombier case Free:
7959cc4ca5SDavid du Colombier if(x->ref != 0){
809a747e4fSDavid du Colombier fprint(2, "%p decref %ld\n", x, x->ref);
8159cc4ca5SDavid du Colombier error("decref");
8259cc4ca5SDavid du Colombier }
8359cc4ca5SDavid du Colombier if(x->flushtag != -1)
8459cc4ca5SDavid du Colombier error("flushtag in free");
857dd7cddfSDavid du Colombier x->free = xfidfree;
867dd7cddfSDavid du Colombier xfidfree = x;
877dd7cddfSDavid du Colombier break;
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier
927dd7cddfSDavid du Colombier Channel*
xfidinit(void)937dd7cddfSDavid du Colombier xfidinit(void)
947dd7cddfSDavid du Colombier {
957dd7cddfSDavid du Colombier cxfidalloc = chancreate(sizeof(Xfid*), 0);
967dd7cddfSDavid du Colombier cxfidfree = chancreate(sizeof(Xfid*), 0);
977dd7cddfSDavid du Colombier threadcreate(xfidallocthread, nil, STACK);
987dd7cddfSDavid du Colombier return cxfidalloc;
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier void
xfidctl(void * arg)1027dd7cddfSDavid du Colombier xfidctl(void *arg)
1037dd7cddfSDavid du Colombier {
1047dd7cddfSDavid du Colombier Xfid *x;
1057dd7cddfSDavid du Colombier void (*f)(Xfid*);
10659cc4ca5SDavid du Colombier char buf[64];
1077dd7cddfSDavid du Colombier
1087dd7cddfSDavid du Colombier x = arg;
10959cc4ca5SDavid du Colombier snprint(buf, sizeof buf, "xfid.%p", x);
11059cc4ca5SDavid du Colombier threadsetname(buf);
1117dd7cddfSDavid du Colombier for(;;){
1127dd7cddfSDavid du Colombier f = recvp(x->c);
1137dd7cddfSDavid du Colombier (*f)(x);
1147dd7cddfSDavid du Colombier if(decref(x) == 0)
1157dd7cddfSDavid du Colombier sendp(cxfidfree, x);
1167dd7cddfSDavid du Colombier }
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier void
xfidflush(Xfid * x)1207dd7cddfSDavid du Colombier xfidflush(Xfid *x)
1217dd7cddfSDavid du Colombier {
1227dd7cddfSDavid du Colombier Fcall t;
1237dd7cddfSDavid du Colombier Xfid *xf;
1247dd7cddfSDavid du Colombier
1257dd7cddfSDavid du Colombier for(xf=xfid; xf; xf=xf->next)
1267dd7cddfSDavid du Colombier if(xf->flushtag == x->oldtag){
1277dd7cddfSDavid du Colombier xf->flushtag = -1;
1287dd7cddfSDavid du Colombier xf->flushing = TRUE;
1297dd7cddfSDavid du Colombier incref(xf); /* to hold data structures up at tail of synchronization */
13059cc4ca5SDavid du Colombier if(xf->ref == 1)
13159cc4ca5SDavid du Colombier error("ref 1 in flush");
1327dd7cddfSDavid du Colombier if(canqlock(&xf->active)){
1337dd7cddfSDavid du Colombier qunlock(&xf->active);
13480ee5cbfSDavid du Colombier sendul(xf->flushc, 0);
1357dd7cddfSDavid du Colombier }else{
1367dd7cddfSDavid du Colombier qlock(&xf->active); /* wait for him to finish */
1377dd7cddfSDavid du Colombier qunlock(&xf->active);
1387dd7cddfSDavid du Colombier }
1397dd7cddfSDavid du Colombier xf->flushing = FALSE;
1407dd7cddfSDavid du Colombier if(decref(xf) == 0)
1417dd7cddfSDavid du Colombier sendp(cxfidfree, xf);
1427dd7cddfSDavid du Colombier break;
1437dd7cddfSDavid du Colombier }
1447dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, nil);
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier void
xfidattach(Xfid * x)1487dd7cddfSDavid du Colombier xfidattach(Xfid *x)
1497dd7cddfSDavid du Colombier {
1507dd7cddfSDavid du Colombier Fcall t;
1513ff48bf5SDavid du Colombier int id, hideit, scrollit;
1527dd7cddfSDavid du Colombier Window *w;
1539a747e4fSDavid du Colombier char *err, *n, *dir, errbuf[ERRMAX];
1547dd7cddfSDavid du Colombier int pid, newlymade;
1557dd7cddfSDavid du Colombier Rectangle r;
1567dd7cddfSDavid du Colombier Image *i;
1577dd7cddfSDavid du Colombier
1587dd7cddfSDavid du Colombier t.qid = x->f->qid;
1597dd7cddfSDavid du Colombier qlock(&all);
1607dd7cddfSDavid du Colombier w = nil;
1617dd7cddfSDavid du Colombier err = Eunkid;
1627dd7cddfSDavid du Colombier newlymade = FALSE;
1639a747e4fSDavid du Colombier hideit = 0;
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier if(x->aname[0] == 'N'){ /* N 100,100, 200, 200 - old syntax */
1667dd7cddfSDavid du Colombier n = x->aname+1;
1677dd7cddfSDavid du Colombier pid = strtoul(n, &n, 0);
1687dd7cddfSDavid du Colombier if(*n == ',')
1697dd7cddfSDavid du Colombier n++;
1707dd7cddfSDavid du Colombier r.min.x = strtoul(n, &n, 0);
1717dd7cddfSDavid du Colombier if(*n == ',')
1727dd7cddfSDavid du Colombier n++;
1737dd7cddfSDavid du Colombier r.min.y = strtoul(n, &n, 0);
1747dd7cddfSDavid du Colombier if(*n == ',')
1757dd7cddfSDavid du Colombier n++;
1767dd7cddfSDavid du Colombier r.max.x = strtoul(n, &n, 0);
1777dd7cddfSDavid du Colombier if(*n == ',')
1787dd7cddfSDavid du Colombier n++;
1797dd7cddfSDavid du Colombier r.max.y = strtoul(n, &n, 0);
18059cc4ca5SDavid du Colombier Allocate:
18159cc4ca5SDavid du Colombier if(!goodrect(r))
1827dd7cddfSDavid du Colombier err = Ebadrect;
1837dd7cddfSDavid du Colombier else{
1849a747e4fSDavid du Colombier if(hideit)
1859a747e4fSDavid du Colombier i = allocimage(display, r, screen->chan, 0, DWhite);
1869a747e4fSDavid du Colombier else
1877dd7cddfSDavid du Colombier i = allocwindow(wscreen, r, Refbackup, DWhite);
1887dd7cddfSDavid du Colombier if(i){
1897dd7cddfSDavid du Colombier border(i, r, Selborder, display->black, ZP);
1907dd7cddfSDavid du Colombier if(pid == 0)
1917dd7cddfSDavid du Colombier pid = -1; /* make sure we don't pop a shell! - UGH */
1923ff48bf5SDavid du Colombier w = new(i, hideit, scrolling, pid, nil, nil, nil);
1937dd7cddfSDavid du Colombier flushimage(display, 1);
1947dd7cddfSDavid du Colombier newlymade = TRUE;
1957dd7cddfSDavid du Colombier }else
1967dd7cddfSDavid du Colombier err = Ewindow;
1977dd7cddfSDavid du Colombier }
1987dd7cddfSDavid du Colombier }else if(strncmp(x->aname, "new", 3) == 0){ /* new -dx -dy - new syntax, as in wctl */
1997dd7cddfSDavid du Colombier pid = 0;
2003ff48bf5SDavid du Colombier if(parsewctl(nil, ZR, &r, &pid, nil, &hideit, &scrollit, &dir, x->aname, errbuf) < 0)
2017dd7cddfSDavid du Colombier err = errbuf;
2027dd7cddfSDavid du Colombier else
2037dd7cddfSDavid du Colombier goto Allocate;
2047dd7cddfSDavid du Colombier }else{
2057dd7cddfSDavid du Colombier id = atoi(x->aname);
2067dd7cddfSDavid du Colombier w = wlookid(id);
2077dd7cddfSDavid du Colombier }
2087dd7cddfSDavid du Colombier x->f->w = w;
2097dd7cddfSDavid du Colombier if(w == nil){
2107dd7cddfSDavid du Colombier qunlock(&all);
211*2906cf0cSDavid du Colombier x->f->busy = FALSE;
2127dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, err);
2137dd7cddfSDavid du Colombier return;
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier if(!newlymade) /* counteract dec() in winshell() */
2167dd7cddfSDavid du Colombier incref(w);
2177dd7cddfSDavid du Colombier qunlock(&all);
2187dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, nil);
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier void
xfidopen(Xfid * x)2227dd7cddfSDavid du Colombier xfidopen(Xfid *x)
2237dd7cddfSDavid du Colombier {
2247dd7cddfSDavid du Colombier Fcall t;
2257dd7cddfSDavid du Colombier Window *w;
2267dd7cddfSDavid du Colombier
2277dd7cddfSDavid du Colombier w = x->f->w;
2287dd7cddfSDavid du Colombier if(w->deleted){
2297dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, Edeleted);
2307dd7cddfSDavid du Colombier return;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier switch(FILE(x->f->qid)){
2337dd7cddfSDavid du Colombier case Qconsctl:
2347dd7cddfSDavid du Colombier if(w->ctlopen){
2357dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, Einuse);
2367dd7cddfSDavid du Colombier return;
2377dd7cddfSDavid du Colombier }
2387dd7cddfSDavid du Colombier w->ctlopen = TRUE;
2397dd7cddfSDavid du Colombier break;
24080ee5cbfSDavid du Colombier case Qkbdin:
24180ee5cbfSDavid du Colombier if(w != wkeyboard){
24280ee5cbfSDavid du Colombier filsysrespond(x->fs, x, &t, Eperm);
24380ee5cbfSDavid du Colombier return;
24480ee5cbfSDavid du Colombier }
24580ee5cbfSDavid du Colombier break;
2467dd7cddfSDavid du Colombier case Qmouse:
2477dd7cddfSDavid du Colombier if(w->mouseopen){
2487dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, Einuse);
2497dd7cddfSDavid du Colombier return;
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier /*
2527dd7cddfSDavid du Colombier * Reshaped: there's a race if the appl. opens the
2537dd7cddfSDavid du Colombier * window, is resized, and then opens the mouse,
2547dd7cddfSDavid du Colombier * but that's rare. The alternative is to generate
2557dd7cddfSDavid du Colombier * a resized event every time a new program starts
2567dd7cddfSDavid du Colombier * up in a window that has been resized since the
2577dd7cddfSDavid du Colombier * dawn of time. We choose the lesser evil.
2587dd7cddfSDavid du Colombier */
2597dd7cddfSDavid du Colombier w->resized = FALSE;
2607dd7cddfSDavid du Colombier w->mouseopen = TRUE;
2617dd7cddfSDavid du Colombier break;
2627dd7cddfSDavid du Colombier case Qsnarf:
2637dd7cddfSDavid du Colombier if(x->mode==ORDWR || x->mode==OWRITE){
2647dd7cddfSDavid du Colombier if(tsnarf)
2657dd7cddfSDavid du Colombier free(tsnarf); /* collision, but OK */
2667dd7cddfSDavid du Colombier ntsnarf = 0;
2677dd7cddfSDavid du Colombier tsnarf = malloc(1);
2687dd7cddfSDavid du Colombier }
2697dd7cddfSDavid du Colombier break;
27059cc4ca5SDavid du Colombier case Qwctl:
27159cc4ca5SDavid du Colombier if(x->mode==OREAD || x->mode==ORDWR){
27259cc4ca5SDavid du Colombier /*
27359cc4ca5SDavid du Colombier * It would be much nicer to implement fan-out for wctl reads,
27459cc4ca5SDavid du Colombier * so multiple people can see the resizings, but rio just isn't
27559cc4ca5SDavid du Colombier * structured for that. It's structured for /dev/cons, which gives
27659cc4ca5SDavid du Colombier * alternate data to alternate readers. So to keep things sane for
27759cc4ca5SDavid du Colombier * wctl, we compromise and give an error if two people try to
27859cc4ca5SDavid du Colombier * open it. Apologies.
27959cc4ca5SDavid du Colombier */
28059cc4ca5SDavid du Colombier if(w->wctlopen){
28159cc4ca5SDavid du Colombier filsysrespond(x->fs, x, &t, Einuse);
28259cc4ca5SDavid du Colombier return;
28359cc4ca5SDavid du Colombier }
28459cc4ca5SDavid du Colombier w->wctlopen = TRUE;
28559cc4ca5SDavid du Colombier w->wctlready = 1;
28659cc4ca5SDavid du Colombier wsendctlmesg(w, Wakeup, ZR, nil);
28759cc4ca5SDavid du Colombier }
28859cc4ca5SDavid du Colombier break;
2897dd7cddfSDavid du Colombier }
2907dd7cddfSDavid du Colombier t.qid = x->f->qid;
2919a747e4fSDavid du Colombier t.iounit = messagesize-IOHDRSZ;
2927dd7cddfSDavid du Colombier x->f->open = TRUE;
2937dd7cddfSDavid du Colombier x->f->mode = x->mode;
2947dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, nil);
2957dd7cddfSDavid du Colombier }
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier void
xfidclose(Xfid * x)2987dd7cddfSDavid du Colombier xfidclose(Xfid *x)
2997dd7cddfSDavid du Colombier {
3007dd7cddfSDavid du Colombier Fcall t;
3017dd7cddfSDavid du Colombier Window *w;
3027dd7cddfSDavid du Colombier int nb, nulls;
3037dd7cddfSDavid du Colombier
3047dd7cddfSDavid du Colombier w = x->f->w;
3057dd7cddfSDavid du Colombier switch(FILE(x->f->qid)){
3067dd7cddfSDavid du Colombier case Qconsctl:
3079a747e4fSDavid du Colombier if(w->rawing){
3089a747e4fSDavid du Colombier w->rawing = FALSE;
3097dd7cddfSDavid du Colombier wsendctlmesg(w, Rawoff, ZR, nil);
3109a747e4fSDavid du Colombier }
3119a747e4fSDavid du Colombier if(w->holding){
3129a747e4fSDavid du Colombier w->holding = FALSE;
3137dd7cddfSDavid du Colombier wsendctlmesg(w, Holdoff, ZR, nil);
3149a747e4fSDavid du Colombier }
3157dd7cddfSDavid du Colombier w->ctlopen = FALSE;
3167dd7cddfSDavid du Colombier break;
3177dd7cddfSDavid du Colombier case Qcursor:
3187dd7cddfSDavid du Colombier w->cursorp = nil;
3197dd7cddfSDavid du Colombier wsetcursor(w, FALSE);
3207dd7cddfSDavid du Colombier break;
3217dd7cddfSDavid du Colombier case Qmouse:
3227dd7cddfSDavid du Colombier w->resized = FALSE;
3237dd7cddfSDavid du Colombier w->mouseopen = FALSE;
3247dd7cddfSDavid du Colombier if(w->i != nil)
3257dd7cddfSDavid du Colombier wsendctlmesg(w, Refresh, w->i->r, nil);
3267dd7cddfSDavid du Colombier break;
3277dd7cddfSDavid du Colombier /* odd behavior but really ok: replace snarf buffer when /dev/snarf is closed */
3287dd7cddfSDavid du Colombier case Qsnarf:
3297dd7cddfSDavid du Colombier if(x->f->mode==ORDWR || x->f->mode==OWRITE){
3307dd7cddfSDavid du Colombier snarf = runerealloc(snarf, ntsnarf+1);
3317dd7cddfSDavid du Colombier cvttorunes(tsnarf, ntsnarf, snarf, &nb, &nsnarf, &nulls);
3327dd7cddfSDavid du Colombier free(tsnarf);
3337dd7cddfSDavid du Colombier tsnarf = nil;
3347dd7cddfSDavid du Colombier ntsnarf = 0;
3357dd7cddfSDavid du Colombier }
3367dd7cddfSDavid du Colombier break;
33759cc4ca5SDavid du Colombier case Qwctl:
33880ee5cbfSDavid du Colombier if(x->f->mode==OREAD || x->f->mode==ORDWR)
33959cc4ca5SDavid du Colombier w->wctlopen = FALSE;
34059cc4ca5SDavid du Colombier break;
3417dd7cddfSDavid du Colombier }
3427dd7cddfSDavid du Colombier wclose(w);
3437dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &t, nil);
3447dd7cddfSDavid du Colombier }
3457dd7cddfSDavid du Colombier
3467dd7cddfSDavid du Colombier void
xfidwrite(Xfid * x)3477dd7cddfSDavid du Colombier xfidwrite(Xfid *x)
3487dd7cddfSDavid du Colombier {
3497dd7cddfSDavid du Colombier Fcall fc;
3507dd7cddfSDavid du Colombier int c, cnt, qid, nb, off, nr;
3517dd7cddfSDavid du Colombier char buf[256], *p;
3527dd7cddfSDavid du Colombier Point pt;
3537dd7cddfSDavid du Colombier Window *w;
3547dd7cddfSDavid du Colombier Rune *r;
3557dd7cddfSDavid du Colombier Conswritemesg cwm;
3567dd7cddfSDavid du Colombier Stringpair pair;
35780ee5cbfSDavid du Colombier enum { CWdata, CWflush, NCW };
35880ee5cbfSDavid du Colombier Alt alts[NCW+1];
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier w = x->f->w;
3617dd7cddfSDavid du Colombier if(w->deleted){
3627dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, Edeleted);
3637dd7cddfSDavid du Colombier return;
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier qid = FILE(x->f->qid);
3667dd7cddfSDavid du Colombier cnt = x->count;
3677dd7cddfSDavid du Colombier off = x->offset;
3687dd7cddfSDavid du Colombier x->data[cnt] = 0;
3697dd7cddfSDavid du Colombier switch(qid){
3707dd7cddfSDavid du Colombier case Qcons:
3717dd7cddfSDavid du Colombier nr = x->f->nrpart;
3727dd7cddfSDavid du Colombier if(nr > 0){
3739a747e4fSDavid du Colombier memmove(x->data+nr, x->data, cnt); /* there's room: see malloc in filsysproc */
3747dd7cddfSDavid du Colombier memmove(x->data, x->f->rpart, nr);
3757dd7cddfSDavid du Colombier cnt += nr;
3767dd7cddfSDavid du Colombier x->f->nrpart = 0;
3777dd7cddfSDavid du Colombier }
3787dd7cddfSDavid du Colombier r = runemalloc(cnt);
3797dd7cddfSDavid du Colombier cvttorunes(x->data, cnt-UTFmax, r, &nb, &nr, nil);
3807dd7cddfSDavid du Colombier /* approach end of buffer */
3817dd7cddfSDavid du Colombier while(fullrune(x->data+nb, cnt-nb)){
3827dd7cddfSDavid du Colombier c = nb;
3837dd7cddfSDavid du Colombier nb += chartorune(&r[nr], x->data+c);
3847dd7cddfSDavid du Colombier if(r[nr])
3857dd7cddfSDavid du Colombier nr++;
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier if(nb < cnt){
3887dd7cddfSDavid du Colombier memmove(x->f->rpart, x->data+nb, cnt-nb);
3897dd7cddfSDavid du Colombier x->f->nrpart = cnt-nb;
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier x->flushtag = x->tag;
39280ee5cbfSDavid du Colombier
39380ee5cbfSDavid du Colombier alts[CWdata].c = w->conswrite;
39480ee5cbfSDavid du Colombier alts[CWdata].v = &cwm;
39580ee5cbfSDavid du Colombier alts[CWdata].op = CHANRCV;
39680ee5cbfSDavid du Colombier alts[CWflush].c = x->flushc;
39780ee5cbfSDavid du Colombier alts[CWflush].v = nil;
39880ee5cbfSDavid du Colombier alts[CWflush].op = CHANRCV;
39980ee5cbfSDavid du Colombier alts[NCW].op = CHANEND;
40080ee5cbfSDavid du Colombier
40180ee5cbfSDavid du Colombier switch(alt(alts)){
40280ee5cbfSDavid du Colombier case CWdata:
40380ee5cbfSDavid du Colombier break;
40480ee5cbfSDavid du Colombier case CWflush:
4057dd7cddfSDavid du Colombier filsyscancel(x);
4067dd7cddfSDavid du Colombier return;
4077dd7cddfSDavid du Colombier }
40880ee5cbfSDavid du Colombier
40980ee5cbfSDavid du Colombier /* received data */
41059cc4ca5SDavid du Colombier x->flushtag = -1;
4117dd7cddfSDavid du Colombier if(x->flushing){
41280ee5cbfSDavid du Colombier recv(x->flushc, nil); /* wake up flushing xfid */
4137dd7cddfSDavid du Colombier pair.s = runemalloc(1);
4147dd7cddfSDavid du Colombier pair.ns = 0;
4157dd7cddfSDavid du Colombier send(cwm.cw, &pair); /* wake up window with empty data */
4167dd7cddfSDavid du Colombier filsyscancel(x);
4177dd7cddfSDavid du Colombier return;
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier qlock(&x->active);
4207dd7cddfSDavid du Colombier pair.s = r;
4217dd7cddfSDavid du Colombier pair.ns = nr;
4227dd7cddfSDavid du Colombier send(cwm.cw, &pair);
4237dd7cddfSDavid du Colombier fc.count = x->count;
4247dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
4257dd7cddfSDavid du Colombier qunlock(&x->active);
4267dd7cddfSDavid du Colombier return;
4277dd7cddfSDavid du Colombier
4287dd7cddfSDavid du Colombier case Qconsctl:
4297dd7cddfSDavid du Colombier if(strncmp(x->data, "holdon", 6)==0){
4307dd7cddfSDavid du Colombier if(w->holding++ == 0)
4317dd7cddfSDavid du Colombier wsendctlmesg(w, Holdon, ZR, nil);
4327dd7cddfSDavid du Colombier break;
4337dd7cddfSDavid du Colombier }
4347dd7cddfSDavid du Colombier if(strncmp(x->data, "holdoff", 7)==0 && w->holding){
4357dd7cddfSDavid du Colombier if(--w->holding == FALSE)
4367dd7cddfSDavid du Colombier wsendctlmesg(w, Holdoff, ZR, nil);
4377dd7cddfSDavid du Colombier break;
4387dd7cddfSDavid du Colombier }
4397dd7cddfSDavid du Colombier if(strncmp(x->data, "rawon", 5)==0){
4403ff48bf5SDavid du Colombier if(w->holding){
4413ff48bf5SDavid du Colombier w->holding = FALSE;
4423ff48bf5SDavid du Colombier wsendctlmesg(w, Holdoff, ZR, nil);
4433ff48bf5SDavid du Colombier }
4447dd7cddfSDavid du Colombier if(w->rawing++ == 0)
4457dd7cddfSDavid du Colombier wsendctlmesg(w, Rawon, ZR, nil);
4467dd7cddfSDavid du Colombier break;
4477dd7cddfSDavid du Colombier }
4487dd7cddfSDavid du Colombier if(strncmp(x->data, "rawoff", 6)==0 && w->rawing){
4497dd7cddfSDavid du Colombier if(--w->rawing == 0)
4507dd7cddfSDavid du Colombier wsendctlmesg(w, Rawoff, ZR, nil);
4517dd7cddfSDavid du Colombier break;
4527dd7cddfSDavid du Colombier }
4537dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, "unknown control message");
4547dd7cddfSDavid du Colombier return;
4557dd7cddfSDavid du Colombier
4567dd7cddfSDavid du Colombier case Qcursor:
4577dd7cddfSDavid du Colombier if(cnt < 2*4+2*2*16)
4587dd7cddfSDavid du Colombier w->cursorp = nil;
4597dd7cddfSDavid du Colombier else{
4607dd7cddfSDavid du Colombier w->cursor.offset.x = BGLONG(x->data+0*4);
4617dd7cddfSDavid du Colombier w->cursor.offset.y = BGLONG(x->data+1*4);
4627dd7cddfSDavid du Colombier memmove(w->cursor.clr, x->data+2*4, 2*2*16);
4637dd7cddfSDavid du Colombier w->cursorp = &w->cursor;
4647dd7cddfSDavid du Colombier }
4657dd7cddfSDavid du Colombier wsetcursor(w, !sweeping);
4667dd7cddfSDavid du Colombier break;
4677dd7cddfSDavid du Colombier
4687dd7cddfSDavid du Colombier case Qlabel:
4699a747e4fSDavid du Colombier if(off != 0){
4709a747e4fSDavid du Colombier filsysrespond(x->fs, x, &fc, "non-zero offset writing label");
4719a747e4fSDavid du Colombier return;
4729a747e4fSDavid du Colombier }
4739a747e4fSDavid du Colombier free(w->label);
4749a747e4fSDavid du Colombier w->label = emalloc(cnt+1);
4759a747e4fSDavid du Colombier memmove(w->label, x->data, cnt);
4769a747e4fSDavid du Colombier w->label[cnt] = 0;
4777dd7cddfSDavid du Colombier break;
4787dd7cddfSDavid du Colombier
4797dd7cddfSDavid du Colombier case Qmouse:
4807dd7cddfSDavid du Colombier if(w!=input || Dx(w->screenr)<=0)
4817dd7cddfSDavid du Colombier break;
4827dd7cddfSDavid du Colombier if(x->data[0] != 'm'){
4837dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, Ebadmouse);
4847dd7cddfSDavid du Colombier return;
4857dd7cddfSDavid du Colombier }
4867dd7cddfSDavid du Colombier p = nil;
4877dd7cddfSDavid du Colombier pt.x = strtoul(x->data+1, &p, 0);
4887dd7cddfSDavid du Colombier if(p == nil){
4897dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, Eshort);
4907dd7cddfSDavid du Colombier return;
4917dd7cddfSDavid du Colombier }
4927dd7cddfSDavid du Colombier pt.y = strtoul(p, nil, 0);
4937dd7cddfSDavid du Colombier if(w==input && wpointto(mouse->xy)==w)
4947dd7cddfSDavid du Colombier wsendctlmesg(w, Movemouse, Rpt(pt, pt), nil);
4957dd7cddfSDavid du Colombier break;
4967dd7cddfSDavid du Colombier
4977dd7cddfSDavid du Colombier case Qsnarf:
4987dd7cddfSDavid du Colombier /* always append only */
4997dd7cddfSDavid du Colombier if(ntsnarf > MAXSNARF){ /* avoid thrashing when people cut huge text */
5007dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, Elong);
5017dd7cddfSDavid du Colombier return;
5027dd7cddfSDavid du Colombier }
5037dd7cddfSDavid du Colombier tsnarf = erealloc(tsnarf, ntsnarf+cnt+1); /* room for NUL */
5047dd7cddfSDavid du Colombier memmove(tsnarf+ntsnarf, x->data, cnt);
5057dd7cddfSDavid du Colombier ntsnarf += cnt;
50680ee5cbfSDavid du Colombier snarfversion++;
5077dd7cddfSDavid du Colombier break;
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier case Qwdir:
5107dd7cddfSDavid du Colombier if(cnt == 0)
5117dd7cddfSDavid du Colombier break;
5127dd7cddfSDavid du Colombier if(x->data[cnt-1] == '\n'){
5137dd7cddfSDavid du Colombier if(cnt == 1)
5147dd7cddfSDavid du Colombier break;
5157dd7cddfSDavid du Colombier x->data[cnt-1] = '\0';
5167dd7cddfSDavid du Colombier }
5177dd7cddfSDavid du Colombier /* assume data comes in a single write */
51880ee5cbfSDavid du Colombier /*
51980ee5cbfSDavid du Colombier * Problem: programs like dossrv, ftp produce illegal UTF;
52080ee5cbfSDavid du Colombier * we must cope by converting it first.
52180ee5cbfSDavid du Colombier */
52280ee5cbfSDavid du Colombier snprint(buf, sizeof buf, "%.*s", cnt, x->data);
52380ee5cbfSDavid du Colombier if(buf[0] == '/'){
5247dd7cddfSDavid du Colombier free(w->dir);
52580ee5cbfSDavid du Colombier w->dir = estrdup(buf);
5267dd7cddfSDavid du Colombier }else{
52780ee5cbfSDavid du Colombier p = emalloc(strlen(w->dir) + 1 + strlen(buf) + 1);
52880ee5cbfSDavid du Colombier sprint(p, "%s/%s", w->dir, buf);
5297dd7cddfSDavid du Colombier free(w->dir);
5307dd7cddfSDavid du Colombier w->dir = cleanname(p);
5317dd7cddfSDavid du Colombier }
5327dd7cddfSDavid du Colombier break;
5337dd7cddfSDavid du Colombier
53480ee5cbfSDavid du Colombier case Qkbdin:
53580ee5cbfSDavid du Colombier keyboardsend(x->data, cnt);
53680ee5cbfSDavid du Colombier break;
53780ee5cbfSDavid du Colombier
5387dd7cddfSDavid du Colombier case Qwctl:
5397dd7cddfSDavid du Colombier if(writewctl(x, buf) < 0){
5407dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, buf);
5417dd7cddfSDavid du Colombier return;
5427dd7cddfSDavid du Colombier }
5439a747e4fSDavid du Colombier flushimage(display, 1);
5447dd7cddfSDavid du Colombier break;
5457dd7cddfSDavid du Colombier
5467dd7cddfSDavid du Colombier default:
5479a747e4fSDavid du Colombier fprint(2, buf, "unknown qid %d in write\n", qid);
5487dd7cddfSDavid du Colombier sprint(buf, "unknown qid in write");
5497dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, buf);
5507dd7cddfSDavid du Colombier return;
5517dd7cddfSDavid du Colombier }
5527dd7cddfSDavid du Colombier fc.count = cnt;
5537dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
5547dd7cddfSDavid du Colombier }
5557dd7cddfSDavid du Colombier
5567dd7cddfSDavid du Colombier int
readwindow(Image * i,char * t,Rectangle r,int offset,int n)5579a747e4fSDavid du Colombier readwindow(Image *i, char *t, Rectangle r, int offset, int n)
5587dd7cddfSDavid du Colombier {
5597dd7cddfSDavid du Colombier int ww, y;
5607dd7cddfSDavid du Colombier
5617dd7cddfSDavid du Colombier offset -= 5*12;
5629a747e4fSDavid du Colombier ww = bytesperline(r, screen->depth);
5637dd7cddfSDavid du Colombier r.min.y += offset/ww;
5647dd7cddfSDavid du Colombier if(r.min.y >= r.max.y)
5657dd7cddfSDavid du Colombier return 0;
5667dd7cddfSDavid du Colombier y = r.min.y + n/ww;
5677dd7cddfSDavid du Colombier if(y < r.max.y)
5687dd7cddfSDavid du Colombier r.max.y = y;
5697dd7cddfSDavid du Colombier if(r.max.y <= r.min.y)
5707dd7cddfSDavid du Colombier return 0;
5719a747e4fSDavid du Colombier return unloadimage(i, r, (uchar*)t, n);
5727dd7cddfSDavid du Colombier }
5737dd7cddfSDavid du Colombier
5747dd7cddfSDavid du Colombier void
xfidread(Xfid * x)5757dd7cddfSDavid du Colombier xfidread(Xfid *x)
5767dd7cddfSDavid du Colombier {
5777dd7cddfSDavid du Colombier Fcall fc;
57880ee5cbfSDavid du Colombier int n, off, cnt, c;
5797dd7cddfSDavid du Colombier uint qid;
5807dd7cddfSDavid du Colombier char buf[128], *t;
5817dd7cddfSDavid du Colombier char cbuf[30];
5827dd7cddfSDavid du Colombier Window *w;
5837dd7cddfSDavid du Colombier Mouse ms;
5847dd7cddfSDavid du Colombier Rectangle r;
5857dd7cddfSDavid du Colombier Image *i;
5867dd7cddfSDavid du Colombier Channel *c1, *c2; /* chan (tuple(char*, int)) */
5877dd7cddfSDavid du Colombier Consreadmesg crm;
5887dd7cddfSDavid du Colombier Mousereadmesg mrm;
58959cc4ca5SDavid du Colombier Consreadmesg cwrm;
5907dd7cddfSDavid du Colombier Stringpair pair;
59180ee5cbfSDavid du Colombier enum { CRdata, CRflush, NCR };
59280ee5cbfSDavid du Colombier enum { MRdata, MRflush, NMR };
59380ee5cbfSDavid du Colombier enum { WCRdata, WCRflush, NWCR };
59480ee5cbfSDavid du Colombier Alt alts[NCR+1];
5957dd7cddfSDavid du Colombier
5967dd7cddfSDavid du Colombier w = x->f->w;
5977dd7cddfSDavid du Colombier if(w->deleted){
5987dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, Edeleted);
5997dd7cddfSDavid du Colombier return;
6007dd7cddfSDavid du Colombier }
6017dd7cddfSDavid du Colombier qid = FILE(x->f->qid);
6027dd7cddfSDavid du Colombier off = x->offset;
6037dd7cddfSDavid du Colombier cnt = x->count;
6047dd7cddfSDavid du Colombier switch(qid){
6057dd7cddfSDavid du Colombier case Qcons:
6067dd7cddfSDavid du Colombier x->flushtag = x->tag;
60780ee5cbfSDavid du Colombier
60880ee5cbfSDavid du Colombier alts[CRdata].c = w->consread;
60980ee5cbfSDavid du Colombier alts[CRdata].v = &crm;
61080ee5cbfSDavid du Colombier alts[CRdata].op = CHANRCV;
61180ee5cbfSDavid du Colombier alts[CRflush].c = x->flushc;
61280ee5cbfSDavid du Colombier alts[CRflush].v = nil;
61380ee5cbfSDavid du Colombier alts[CRflush].op = CHANRCV;
61480ee5cbfSDavid du Colombier alts[NMR].op = CHANEND;
61580ee5cbfSDavid du Colombier
61680ee5cbfSDavid du Colombier switch(alt(alts)){
61780ee5cbfSDavid du Colombier case CRdata:
61880ee5cbfSDavid du Colombier break;
61980ee5cbfSDavid du Colombier case CRflush:
6207dd7cddfSDavid du Colombier filsyscancel(x);
6217dd7cddfSDavid du Colombier return;
6227dd7cddfSDavid du Colombier }
62380ee5cbfSDavid du Colombier
62480ee5cbfSDavid du Colombier /* received data */
62580ee5cbfSDavid du Colombier x->flushtag = -1;
62680ee5cbfSDavid du Colombier c1 = crm.c1;
62780ee5cbfSDavid du Colombier c2 = crm.c2;
6287dd7cddfSDavid du Colombier t = malloc(cnt+UTFmax+1); /* room to unpack partial rune plus */
6297dd7cddfSDavid du Colombier pair.s = t;
6307dd7cddfSDavid du Colombier pair.ns = cnt;
6317dd7cddfSDavid du Colombier send(c1, &pair);
6327dd7cddfSDavid du Colombier if(x->flushing){
63380ee5cbfSDavid du Colombier recv(x->flushc, nil); /* wake up flushing xfid */
6347dd7cddfSDavid du Colombier recv(c2, nil); /* wake up window and toss data */
6357dd7cddfSDavid du Colombier free(t);
6367dd7cddfSDavid du Colombier filsyscancel(x);
6377dd7cddfSDavid du Colombier return;
6387dd7cddfSDavid du Colombier }
6397dd7cddfSDavid du Colombier qlock(&x->active);
6407dd7cddfSDavid du Colombier recv(c2, &pair);
6417dd7cddfSDavid du Colombier fc.data = pair.s;
6427dd7cddfSDavid du Colombier fc.count = pair.ns;
6437dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
6447dd7cddfSDavid du Colombier free(t);
6457dd7cddfSDavid du Colombier qunlock(&x->active);
6467dd7cddfSDavid du Colombier break;
6477dd7cddfSDavid du Colombier
6487dd7cddfSDavid du Colombier case Qlabel:
6497dd7cddfSDavid du Colombier n = strlen(w->label);
6507dd7cddfSDavid du Colombier if(off > n)
6517dd7cddfSDavid du Colombier off = n;
6527dd7cddfSDavid du Colombier if(off+cnt > n)
6537dd7cddfSDavid du Colombier cnt = n-off;
6547dd7cddfSDavid du Colombier fc.data = w->label+off;
6557dd7cddfSDavid du Colombier fc.count = cnt;
6567dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
6577dd7cddfSDavid du Colombier break;
6587dd7cddfSDavid du Colombier
6597dd7cddfSDavid du Colombier case Qmouse:
6607dd7cddfSDavid du Colombier x->flushtag = x->tag;
66180ee5cbfSDavid du Colombier
66280ee5cbfSDavid du Colombier alts[MRdata].c = w->mouseread;
66380ee5cbfSDavid du Colombier alts[MRdata].v = &mrm;
66480ee5cbfSDavid du Colombier alts[MRdata].op = CHANRCV;
66580ee5cbfSDavid du Colombier alts[MRflush].c = x->flushc;
66680ee5cbfSDavid du Colombier alts[MRflush].v = nil;
66780ee5cbfSDavid du Colombier alts[MRflush].op = CHANRCV;
66880ee5cbfSDavid du Colombier alts[NMR].op = CHANEND;
66980ee5cbfSDavid du Colombier
67080ee5cbfSDavid du Colombier switch(alt(alts)){
67180ee5cbfSDavid du Colombier case MRdata:
67280ee5cbfSDavid du Colombier break;
67380ee5cbfSDavid du Colombier case MRflush:
6747dd7cddfSDavid du Colombier filsyscancel(x);
6757dd7cddfSDavid du Colombier return;
6767dd7cddfSDavid du Colombier }
67780ee5cbfSDavid du Colombier
67880ee5cbfSDavid du Colombier /* received data */
67959cc4ca5SDavid du Colombier x->flushtag = -1;
6807dd7cddfSDavid du Colombier if(x->flushing){
68180ee5cbfSDavid du Colombier recv(x->flushc, nil); /* wake up flushing xfid */
68280ee5cbfSDavid du Colombier recv(mrm.cm, nil); /* wake up window and toss data */
6837dd7cddfSDavid du Colombier filsyscancel(x);
6847dd7cddfSDavid du Colombier return;
6857dd7cddfSDavid du Colombier }
6867dd7cddfSDavid du Colombier qlock(&x->active);
68780ee5cbfSDavid du Colombier recv(mrm.cm, &ms);
6887dd7cddfSDavid du Colombier c = 'm';
6897dd7cddfSDavid du Colombier if(w->resized)
6907dd7cddfSDavid du Colombier c = 'r';
6917dd7cddfSDavid du Colombier n = sprint(buf, "%c%11d %11d %11d %11ld ", c, ms.xy.x, ms.xy.y, ms.buttons, ms.msec);
6927dd7cddfSDavid du Colombier w->resized = 0;
6937dd7cddfSDavid du Colombier fc.data = buf;
6947dd7cddfSDavid du Colombier fc.count = min(n, cnt);
6957dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
6967dd7cddfSDavid du Colombier qunlock(&x->active);
6977dd7cddfSDavid du Colombier break;
6987dd7cddfSDavid du Colombier
6997dd7cddfSDavid du Colombier case Qcursor:
7007dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, "cursor read not implemented");
7017dd7cddfSDavid du Colombier break;
7027dd7cddfSDavid du Colombier
7037dd7cddfSDavid du Colombier /* The algorithm for snarf and text is expensive but easy and rarely used */
7047dd7cddfSDavid du Colombier case Qsnarf:
70580ee5cbfSDavid du Colombier getsnarf();
7067dd7cddfSDavid du Colombier if(nsnarf)
7077dd7cddfSDavid du Colombier t = runetobyte(snarf, nsnarf, &n);
7087dd7cddfSDavid du Colombier else {
7097dd7cddfSDavid du Colombier t = nil;
7107dd7cddfSDavid du Colombier n = 0;
7117dd7cddfSDavid du Colombier }
7127dd7cddfSDavid du Colombier goto Text;
7137dd7cddfSDavid du Colombier
7147dd7cddfSDavid du Colombier case Qtext:
7157dd7cddfSDavid du Colombier t = wcontents(w, &n);
7167dd7cddfSDavid du Colombier goto Text;
7177dd7cddfSDavid du Colombier
7187dd7cddfSDavid du Colombier Text:
7197dd7cddfSDavid du Colombier if(off > n){
7207dd7cddfSDavid du Colombier off = n;
7217dd7cddfSDavid du Colombier cnt = 0;
7227dd7cddfSDavid du Colombier }
7237dd7cddfSDavid du Colombier if(off+cnt > n)
7247dd7cddfSDavid du Colombier cnt = n-off;
7257dd7cddfSDavid du Colombier fc.data = t+off;
7267dd7cddfSDavid du Colombier fc.count = cnt;
7277dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
7287dd7cddfSDavid du Colombier free(t);
7297dd7cddfSDavid du Colombier break;
7307dd7cddfSDavid du Colombier
7317dd7cddfSDavid du Colombier case Qwdir:
7327dd7cddfSDavid du Colombier t = estrdup(w->dir);
7337dd7cddfSDavid du Colombier n = strlen(t);
7347dd7cddfSDavid du Colombier goto Text;
7357dd7cddfSDavid du Colombier
7367dd7cddfSDavid du Colombier case Qwinid:
7377dd7cddfSDavid du Colombier n = sprint(buf, "%11d ", w->id);
7387dd7cddfSDavid du Colombier t = estrdup(buf);
7397dd7cddfSDavid du Colombier goto Text;
7407dd7cddfSDavid du Colombier
7417dd7cddfSDavid du Colombier
7427dd7cddfSDavid du Colombier case Qwinname:
7437dd7cddfSDavid du Colombier n = strlen(w->name);
7447dd7cddfSDavid du Colombier if(n == 0){
7457dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, "window has no name");
7467dd7cddfSDavid du Colombier break;
7477dd7cddfSDavid du Colombier }
7487dd7cddfSDavid du Colombier t = estrdup(w->name);
7497dd7cddfSDavid du Colombier goto Text;
7507dd7cddfSDavid du Colombier
7517dd7cddfSDavid du Colombier case Qwindow:
7527dd7cddfSDavid du Colombier i = w->i;
75380ee5cbfSDavid du Colombier if(i == nil || Dx(w->screenr)<=0){
7547dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, Enowindow);
7557dd7cddfSDavid du Colombier return;
7567dd7cddfSDavid du Colombier }
7577dd7cddfSDavid du Colombier r = w->screenr;
7587dd7cddfSDavid du Colombier goto caseImage;
7597dd7cddfSDavid du Colombier
7607dd7cddfSDavid du Colombier case Qscreen:
7617dd7cddfSDavid du Colombier i = display->image;
7629a747e4fSDavid du Colombier if(i == nil){
7639a747e4fSDavid du Colombier filsysrespond(x->fs, x, &fc, "no top-level screen");
7649a747e4fSDavid du Colombier break;
7659a747e4fSDavid du Colombier }
7667dd7cddfSDavid du Colombier r = i->r;
7677dd7cddfSDavid du Colombier /* fall through */
7687dd7cddfSDavid du Colombier
7697dd7cddfSDavid du Colombier caseImage:
7707dd7cddfSDavid du Colombier if(off < 5*12){
7717dd7cddfSDavid du Colombier n = sprint(buf, "%11s %11d %11d %11d %11d ",
7729a747e4fSDavid du Colombier chantostr(cbuf, screen->chan),
7737dd7cddfSDavid du Colombier i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y);
7747dd7cddfSDavid du Colombier t = estrdup(buf);
7757dd7cddfSDavid du Colombier goto Text;
7767dd7cddfSDavid du Colombier }
7777dd7cddfSDavid du Colombier t = malloc(cnt);
7787dd7cddfSDavid du Colombier fc.data = t;
7799a747e4fSDavid du Colombier n = readwindow(i, t, r, off, cnt); /* careful; fc.count is unsigned */
7809a747e4fSDavid du Colombier if(n < 0){
7817dd7cddfSDavid du Colombier buf[0] = 0;
7829a747e4fSDavid du Colombier errstr(buf, sizeof buf);
7837dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, buf);
7849a747e4fSDavid du Colombier }else{
7859a747e4fSDavid du Colombier fc.count = n;
7867dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
7879a747e4fSDavid du Colombier }
7887dd7cddfSDavid du Colombier free(t);
7897dd7cddfSDavid du Colombier return;
7907dd7cddfSDavid du Colombier
79159cc4ca5SDavid du Colombier case Qwctl: /* read returns rectangle, hangs if not resized */
79259cc4ca5SDavid du Colombier if(cnt < 4*12){
79359cc4ca5SDavid du Colombier filsysrespond(x->fs, x, &fc, Etooshort);
79459cc4ca5SDavid du Colombier break;
79559cc4ca5SDavid du Colombier }
79659cc4ca5SDavid du Colombier x->flushtag = x->tag;
79780ee5cbfSDavid du Colombier
79880ee5cbfSDavid du Colombier alts[WCRdata].c = w->wctlread;
79980ee5cbfSDavid du Colombier alts[WCRdata].v = &cwrm;
80080ee5cbfSDavid du Colombier alts[WCRdata].op = CHANRCV;
80180ee5cbfSDavid du Colombier alts[WCRflush].c = x->flushc;
80280ee5cbfSDavid du Colombier alts[WCRflush].v = nil;
80380ee5cbfSDavid du Colombier alts[WCRflush].op = CHANRCV;
80480ee5cbfSDavid du Colombier alts[NMR].op = CHANEND;
80580ee5cbfSDavid du Colombier
80680ee5cbfSDavid du Colombier switch(alt(alts)){
80780ee5cbfSDavid du Colombier case WCRdata:
80880ee5cbfSDavid du Colombier break;
80980ee5cbfSDavid du Colombier case WCRflush:
81059cc4ca5SDavid du Colombier filsyscancel(x);
81159cc4ca5SDavid du Colombier return;
81259cc4ca5SDavid du Colombier }
81380ee5cbfSDavid du Colombier
81480ee5cbfSDavid du Colombier /* received data */
81559cc4ca5SDavid du Colombier x->flushtag = -1;
81680ee5cbfSDavid du Colombier c1 = cwrm.c1;
81780ee5cbfSDavid du Colombier c2 = cwrm.c2;
81880ee5cbfSDavid du Colombier t = malloc(cnt+1); /* be sure to have room for NUL */
81980ee5cbfSDavid du Colombier pair.s = t;
82080ee5cbfSDavid du Colombier pair.ns = cnt+1;
82180ee5cbfSDavid du Colombier send(c1, &pair);
82259cc4ca5SDavid du Colombier if(x->flushing){
82380ee5cbfSDavid du Colombier recv(x->flushc, nil); /* wake up flushing xfid */
82459cc4ca5SDavid du Colombier recv(c2, nil); /* wake up window and toss data */
82559cc4ca5SDavid du Colombier free(t);
82659cc4ca5SDavid du Colombier filsyscancel(x);
82759cc4ca5SDavid du Colombier return;
82859cc4ca5SDavid du Colombier }
82959cc4ca5SDavid du Colombier qlock(&x->active);
83059cc4ca5SDavid du Colombier recv(c2, &pair);
83159cc4ca5SDavid du Colombier fc.data = pair.s;
83280ee5cbfSDavid du Colombier if(pair.ns > cnt)
83380ee5cbfSDavid du Colombier pair.ns = cnt;
83459cc4ca5SDavid du Colombier fc.count = pair.ns;
83559cc4ca5SDavid du Colombier filsysrespond(x->fs, x, &fc, nil);
83659cc4ca5SDavid du Colombier free(t);
83759cc4ca5SDavid du Colombier qunlock(&x->active);
83859cc4ca5SDavid du Colombier break;
83959cc4ca5SDavid du Colombier
8407dd7cddfSDavid du Colombier default:
8419a747e4fSDavid du Colombier fprint(2, "unknown qid %d in read\n", qid);
8427dd7cddfSDavid du Colombier sprint(buf, "unknown qid in read");
8437dd7cddfSDavid du Colombier filsysrespond(x->fs, x, &fc, buf);
8447dd7cddfSDavid du Colombier break;
8457dd7cddfSDavid du Colombier }
8467dd7cddfSDavid du Colombier }
847