#include <jerq.h> #include <font.h> #include <layer.h> #include <queue.h> #include <jerqproc.h> #include <setup.h> #include "../msgs.h" #include "pconfig.h" #include "proto.h" #include "packets.h" struct Pchannel pconvs[4]; /* Should be NPROC!!! */ extern struct Proc *debugger; extern int recvchars(), sendpkt(); extern boot(); short usermouse=0; /* kbdproc (a USER proc) has the mouse under its paw */ extern short second; #define crecvchars recvchars struct Pconfig pconfig={ sendpkt, recvchars, (void(*)())crecvchars }; Texture cup = { 0x0100, 0x00E0, 0x0010, 0x03E0, 0x0400, 0x0FE0, 0x123C, 0x1FE2, 0x101A, 0x101A, 0x1002, 0x103C, 0x1810, 0x6FEC, 0x4004, 0x3FF8, }; Texture deadmouse = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000C, 0x0082, 0x0441, 0xFFE1, 0x5FF1, 0x3FFE, 0x17F0, 0x03E0, 0x0000, 0x0000, 0x0000, }; Texture bullseye = { 0x07E0, 0x1FF8, 0x399C, 0x63C6, 0x6FF6, 0xCDB3, 0xD99B, 0xFFFF, 0xFFFF, 0xD99B, 0xCDB3, 0x6FF6, 0x63C6, 0x399C, 0x1FF8, 0x07E0, }; Texture boxcurs = { 0x43FF, 0xE001, 0x7001, 0x3801, 0x1D01, 0x0F01, 0x8701, 0x8F01, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0xFFFF, }; Texture eightball = { 0x07E0, 0x1FF8, 0x21FC, 0x4CFE, 0x52FE, 0xCCFF, 0xD2FF, 0xCCFF, 0xE1FF, 0xFFFF, 0xFFFF, 0x7FFE, 0x7FFE, 0x3FFC, 0x1FF8, 0x07E0, }; #define INSET 3 Layer *whichlayer(); struct Proc *kbdproc=0; #define DEMUX 0 #define CONTROL 1 #define UP 0 #define DOWN 1 int control(), windowproc(), demux(); struct Mouse mouse; main(){ register struct Proc *p; *DADDR=0; BonW(); qinit(); aciainit(baud_speeds[VALBAUD]); binit(); kbdinit(); cursinit(); if(VALMAXADDR){ /* 1024Kb */ NPROC=4; p=proctab+NPROC; allocinit(((char *)p), ((char *)p)+512*1024L); }else{ /* 256Kb */ NPROC=7; p=proctab+NPROC; allocinit(((char *)p), ((char *)p)+25*1024L); } gcinit(); bufinit(); if(pinit(NPROC)==-1) error("pinit", "-1"); Lgrey(&display); spl0(); swinit(); P=newproc(demux); /* process 0 */ setrun(newproc(control)); /* process 1 */ /* * sw(0) will switch out of our local stack onto the control stack. * we will never return to this stack */ sw(0); /*NOTREACHED*/ } buttons(updown) { do; while((button123()!=0) != updown); } Sw() { if(second){ second=0; if(Ptflag) ptimeout(); } sw(P!=&proctab[CONTROL]); /* if control, clock will restart us */ } control(){ register Layer *lp; register struct Proc *p, *pp; for(;;){ pp=0; lp=whichlayer(); for(p=&proctab[CONTROL+1]; p<&proctab[NPROC]; p++){ if(p->state&WAKEUP){ p->state&=~WAKEUP; setrun(p); } if((p->state&KBDLOCAL)==0 && p->kbdqueue.c_cc>0 && p->text!=(char *)boot){ register c=qpeekc(&p->kbdqueue); if(c==0x80){ /* BREAKKEY */ if(muxkill(2, p)!=-1) (void)qgetc(&p->kbdqueue); }else if(muxsendchar(c, p)!=-1) (void)qgetc(&p->kbdqueue); } if(lp && p->layer==lp) pp=p; /* pp pointed at by mouse */ } if(usermouse && (pp!=kbdproc || (pp->state&GOTMOUSE)==0)){ usermouse=0; cursswitch((Texture *)0); cursallow(); }else if(!usermouse && pp){ Check_mouse: if(pp==kbdproc && (pp->state&GOTMOUSE)){ usermouse=1; cursswitch(pp->cursor); if(pp->inhibited) cursinhibit(); } } if(button123()){ if(lp==0 || (pp->state&GOTMOUSE)==0){ dobutton(whichbutton()); /* make sure kbdproc doesn't think buttons are down */ if(kbdproc){ givemouse(kbdproc); goto Check_mouse; /* usermouse==0 */ } } if(pp && pp->state&GOTMOUSE) givemouse(pp); } if(RCVQUEUE.c_cc) setrun(&proctab[DEMUX]); Sw(); } } New(){ newwindow(windowproc); } Psend(a, b, c, d) char *b; { while(psend(a, b, c, d)==-1) Sw(); } Delete(){ delete(whichlayer()); } delete(l) register Layer *l; { register struct Proc *p; register w; if(l){ w=whichproc(l); p= &proctab[w]; muxmesg(w, C_DELETE); delproc(p); dellayer(l); if(kbdproc==p) kbdproc=0; } } delproc(p) register struct Proc *p; { p->state=0; /* exit(w) */ p->nticks=0; p->inhibited=0; qclear(&p->kbdqueue); freemem(p); p->layer=0; /* sigh */ } Top(){ upfront(whichlayer()); } Bottom(){ downback(whichlayer()); } Current(){ register Layer *l; l=whichlayer(); if(l) tolayer(l); } Rectangle canon(p1, p2) Point p1, p2; { Rectangle r; r.origin.x = min(p1.x, p2.x); r.origin.y = min(p1.y, p2.y); r.corner.x = max(p1.x, p2.x); r.corner.y = max(p1.y, p2.y); return(r); } Rectangle getrectb(n) int n; { Rectangle r; Point p1, p2; cursswitch(&boxcurs); buttons(UP); buttons(DOWN); if(!(mouse.buttons&n)){ r.origin.x=r.origin.y=r.corner.x=r.corner.y=0; buttons(UP); goto Return; } p1=mouse.xy; p2=p1; r=canon(p1, p2); outline(r); for(; mouse.buttons&n; nap(2)){ outline(r); p2=mouse.xy; r=canon(p1, p2); outline(r); } outline(r); /* undraw for the last time */ Return: cursswitch((P->state&USER)? P->cursor : (Texture *)0); return r; } Rectangle getrect(n) { return getrectb(8>>n); } Reshape(){ register Layer *l; register struct Proc *p; Rectangle r; Point save; /*SFBOTCH*/ l=whichlayer(); if(l==0) return; p= &proctab[whichproc(l)]; r=getrect3(); if(r.corner.x-r.origin.x>100 && r.corner.y-r.origin.y>40){ /*SFBOTCHPoint save;*/ save=l->rect.origin; dellayer(l); p->state&=~MOVED; p->state|=RESHAPED; l=newlayer(r); if(l==0){ r.origin=save; r.corner=add(save, Pt(100, 50)); l=newlayer(r); if(l==0){ /* oh shit */ delproc(p); muxmesg((int)(p-proctab), C_DELETE); return; } } p->layer=l; p->rect=inset(r, INSET); setborder(p); } if(p->state&USER) setdata(p); muxnewwind(p, C_RESHAPE); } Move(){ register Layer *l, *nl; register struct Proc *procp; Point p, op, dp; l=whichlayer(); if(l==0) return; procp= &proctab[whichproc(l)]; dp=sub(l->rect.corner, l->rect.origin); cursset(l->rect.origin); cursswitch(&boxcurs); p=l->rect.origin; while(button3()){ if(button12()) goto Return; outline(Rpt(p, add(p, dp))); nap(2); op=p; p=mouse.xy; /* using boxcurs, can't get off top or left! */ if(p.x+dp.x >= XMAX-9) p.x=XMAX-9-dp.x; if(p.y+dp.y >= YMAX-9) p.y=YMAX-9-dp.y; outline(Rpt(op, add(op, dp))); cursset(p); } cursswitch(&deadmouse); nl=newlayer(Rpt(p, add(p, dp))); if(nl==0) goto Return; Ubitblt(l, l->rect, nl, p, F_STORE); procp->layer=nl; procp->rect=inset(nl->rect, INSET); dellayer(l); if(procp->state&USER) setdata(procp); if((procp->state&RESHAPED) == 0) procp->state|=MOVED|RESHAPED; /* turn on RESHAPED for old progs */ l=nl; setborder(procp); Return: cursset(div(add(l->rect.origin, l->rect.corner), 2)); cursswitch((Texture *)0); /* No C_RESHAPE required */ } /* button hit to indicate which process, invoked by debugger */ struct Proc * debug(){ debugger=P; } struct Proc * getproc(){ register Layer *l; struct Proc *z=0; cursswitch(&bullseye); buttons(DOWN); if(button3() && (l=whichlayer())) z=&proctab[whichproc(l)]; buttons(UP); return z; } struct Proc * getproctab(){ return proctab; } char *menutext[]={ "New", "Reshape", "Move", "Top", "Bottom", "Current", "Delete", 0 }; int (*menufn[])()={ New, Reshape,Move, Top, Bottom, Current, Delete, 0, }; Menu windowmenu={ menutext }; dobutton(b) { register hit; register Layer *l; switch(b){ case 1: if(l=whichlayer()){ upfront(l); tolayer(l); } break; case 2: break; /* dunno... */ case 3: if((hit=menuhit(&windowmenu, 3))>=0){ if(hit==0) /* a little different because of getrect */ New(); else{ cursswitch(&bullseye); buttons(DOWN); if(button3()) (*menufn[hit])(); cursswitch((Texture *)0); } } break; default: break; } buttons(UP); } whichproc(l) register Layer *l; { register struct Proc *p; for(p=proctab+CONTROL+1; p<proctab+NPROC; p++) if(p->layer==l && (p->state&BUSY)) return((int)(p-proctab)); return(CONTROL+1); /* HELP?? */ } whichbutton() { static int which[]={0, 3, 2, 2, 1, 1, 2, 2, }; return which[mouse.buttons&7]; } newwindow(fn) int (*fn)(); { register struct Proc *p; Rectangle r; r=getrect3(); cursswitch(&deadmouse); if(r.corner.x-r.origin.x>100 && r.corner.y-r.origin.y>40){ if(p=newproc(fn)){ /* Assignment = */ p->rect=inset(r, INSET); if(p->layer=newlayer(r)){ muxnewwind(p, C_NEW); tolayer(p->layer); setrun(p); }else p->state=0; } } cursswitch((Texture *)0); } void sendnchars(n, p) int n; char * p; { register int cc; do{ if((cc=n)>MAXPKTDSIZE-1) cc=MAXPKTDSIZE-1; Psend((int)(P-proctab), p, cc, C_SENDNCHARS); }while(p+=cc, (n-=cc)>0); } void sendwithdelim(n, p) int n; char * p; { register int cc; for(;;){ if((cc=n)>MAXPKTDSIZE-1) cc=MAXPKTDSIZE-1; if ((n-=cc) <= 0) break; Psend((int)(P-proctab), p, cc, C_SENDNCHARS); p+=cc; } Psend((int)(P-proctab), p, cc, C_SENDNCHARD); } /* void sendwithdelim(n, p) int n; char * p; { register int cc; sendnchars(n, p); delim(); } */ delim(){ Psend((int)(P-proctab), (char *)0, 0, C_DELIM); } short sendbusy; int sendpkt(p, n) register char * p; register int n; { register int sr; static Rectangle r={0, 0, 50, 50}; while(sendbusy) sw(1); sendbusy=1; while(OUTQUEUE.c_cc>CBSIZE/2) sw(1); if (*p & P_CNTL) OUTQUEUE.state |= QPRIORITY; do if (!qputc(&OUTQUEUE, *(unsigned char *)p++)) { rectf(&display, r, F_XOR); if ((r.origin.y += 50) >= 1000) r.origin.y = 0; r.corner.y = r.origin.y + 50; } while(--n); OUTQUEUE.state &= ~QPRIORITY; sendbusy=0; aciatrint(); return 0; } muxnewwind(p, c) register struct Proc *p; char c; { char mesg[6]; register int dx, dy; register char * cp = mesg; dx=p->rect.corner.x-p->rect.origin.x; dy=p->rect.corner.y-p->rect.origin.y; *cp++=(dx-6)/p->defaultfont->info['0'].width; *cp++=(dy-6)/p->defaultfont->height; *cp++=dx; *cp++=(dx>>8); *cp++=dy; *cp++=(dy>>8); Psend((int)(p-proctab), mesg, sizeof mesg, c); } int muxsendchar(c, p) char c; struct Proc *p; { if(sendbusy || (OUTQUEUE.c_cc >= (CBSIZE/2))) return -1; /* avoid "sw" in "sendpkt" */ return psend((int)(p-proctab), &c, 1, C_SENDCHAR); } int muxkill(s, p) char s; struct Proc *p; { Psend((int)(p-proctab), &s, 1, C_KILL); } muxmesg(w, m){ Psend(w, (char *)0, 0, m); } muxublk(p) register struct Proc *p; { register int l = p-proctab; while(pconvs[l].user > 0){ pconvs[l].user--; Psend(l, (char *)0, 0, C_UNBLK); } } Point jline(p, dp) Point p, dp; { dp.x+=p.x; dp.y+=p.y; segment(&display, p, dp, F_XOR); return dp; } outline(r) Rectangle r; { register dx=r.corner.x-r.origin.x-1, dy=r.corner.y-r.origin.y-1; Point p; p=jline(r.origin, Pt(dx, 0)); p=jline(p, Pt(0, dy)); p=jline(p, Pt(-dx,0)); (void)jline(p, Pt(0,-dy)); } min(a, b){ return(a<b? a : b); } max(a, b){ return(a>b? a : b); } Layer * whichlayer() { register Layer *lp; for(lp=lfront; lp; lp=lp->back) if(ptinrect(mouse.xy, lp->rect)) return(lp); return(0); } tolayer(l) register Layer *l; { register struct Proc *p, *okbdproc; for(p=proctab; p<&proctab[NPROC]; p++) if((p->state&BUSY) && l==p->layer){ if(kbdproc!=p){ okbdproc=kbdproc; kbdproc=p; if(okbdproc){ setborder(okbdproc); okbdproc->state&=~GOTMOUSE; } setborder(p); } if(p->state&MOUSELOCAL){ p->state|=GOTMOUSE; setrun(p); } break; } } clear(r, inh) Rectangle r; { if(inh) cursinhibit(); lrectf(P->layer, r, F_CLR); if(inh) cursallow(); } border(l, r, i, c) /* no flashing! */ register Layer *l; Rectangle r; register i; Code c; { Urectf(l, Rect(r.origin.x, r.origin.y, r.corner.x, r.origin.y+i), c); Urectf(l, Rect(r.origin.x, r.corner.y-i, r.corner.x, r.corner.y), c); Urectf(l, Rect(r.origin.x, r.origin.y+i, r.origin.x+i, r.corner.y-i), c); Urectf(l, Rect(r.corner.x-i, r.origin.y+i, r.corner.x, r.corner.y-i), c); } setborder(p) register struct Proc *p; { border(p->layer, p->layer->rect, INSET, F_OR); if(p!=kbdproc) border(p->layer, inset(p->layer->rect, 1), INSET-1, F_XOR); } cansend(channel) { register i; register Pch_p pcp=&pconvs[channel]; register Pks_p psp; for(psp=pcp->nextpkt,i=NPCBUFS; i--;){ if(psp->state!=PX_WAIT) return SEND; if(++psp>=&pcp->pkts[NPCBUFS]) psp=pcp->pkts; } return 0; }