1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <draw.h>
4*8ccd4a63SDavid du Colombier #include <memdraw.h>
5*8ccd4a63SDavid du Colombier #include <memlayer.h>
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier /*
87dd7cddfSDavid du Colombier * Place i so i->r.min = log, i->layer->screenr.min == scr.
97dd7cddfSDavid du Colombier */
107dd7cddfSDavid du Colombier int
memlorigin(Memimage * i,Point log,Point scr)117dd7cddfSDavid du Colombier memlorigin(Memimage *i, Point log, Point scr)
127dd7cddfSDavid du Colombier {
137dd7cddfSDavid du Colombier Memlayer *l;
147dd7cddfSDavid du Colombier Memscreen *s;
157dd7cddfSDavid du Colombier Memimage *t, *shad, *nsave;
167dd7cddfSDavid du Colombier Rectangle x, newr, oldr;
177dd7cddfSDavid du Colombier Point delta;
187dd7cddfSDavid du Colombier int overlap, eqlog, eqscr, wasclear;
197dd7cddfSDavid du Colombier
207dd7cddfSDavid du Colombier l = i->layer;
217dd7cddfSDavid du Colombier s = l->screen;
227dd7cddfSDavid du Colombier oldr = l->screenr;
237dd7cddfSDavid du Colombier newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr));
247dd7cddfSDavid du Colombier eqscr = eqpt(scr, oldr.min);
257dd7cddfSDavid du Colombier eqlog = eqpt(log, i->r.min);
267dd7cddfSDavid du Colombier if(eqscr && eqlog)
277dd7cddfSDavid du Colombier return 0;
287dd7cddfSDavid du Colombier nsave = nil;
297dd7cddfSDavid du Colombier if(eqlog==0 && l->save!=nil){
307dd7cddfSDavid du Colombier nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan);
317dd7cddfSDavid du Colombier if(nsave == nil)
327dd7cddfSDavid du Colombier return -1;
337dd7cddfSDavid du Colombier }
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier /*
367dd7cddfSDavid du Colombier * Bring it to front and move logical coordinate system.
377dd7cddfSDavid du Colombier */
387dd7cddfSDavid du Colombier memltofront(i);
397dd7cddfSDavid du Colombier wasclear = l->clear;
407dd7cddfSDavid du Colombier if(nsave){
417dd7cddfSDavid du Colombier if(!wasclear)
42*8ccd4a63SDavid du Colombier memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S);
437dd7cddfSDavid du Colombier freememimage(l->save);
447dd7cddfSDavid du Colombier l->save = nsave;
457dd7cddfSDavid du Colombier }
467dd7cddfSDavid du Colombier delta = subpt(log, i->r.min);
477dd7cddfSDavid du Colombier i->r = rectaddpt(i->r, delta);
487dd7cddfSDavid du Colombier i->clipr = rectaddpt(i->clipr, delta);
497dd7cddfSDavid du Colombier l->delta = subpt(l->screenr.min, i->r.min);
507dd7cddfSDavid du Colombier if(eqscr)
517dd7cddfSDavid du Colombier return 0;
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier /*
547dd7cddfSDavid du Colombier * To clean up old position, make a shadow window there, don't paint it,
557dd7cddfSDavid du Colombier * push it behind this one, and (later) delete it. Because the refresh function
567dd7cddfSDavid du Colombier * for this fake window is a no-op, this will cause no graphics action except
577dd7cddfSDavid du Colombier * to restore the background and expose the windows previously hidden.
587dd7cddfSDavid du Colombier */
597dd7cddfSDavid du Colombier shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill);
607dd7cddfSDavid du Colombier if(shad == nil)
617dd7cddfSDavid du Colombier return -1;
627dd7cddfSDavid du Colombier s->frontmost = i;
637dd7cddfSDavid du Colombier if(s->rearmost == i)
647dd7cddfSDavid du Colombier s->rearmost = shad;
657dd7cddfSDavid du Colombier else
667dd7cddfSDavid du Colombier l->rear->layer->front = shad;
677dd7cddfSDavid du Colombier shad->layer->front = i;
687dd7cddfSDavid du Colombier shad->layer->rear = l->rear;
697dd7cddfSDavid du Colombier l->rear = shad;
707dd7cddfSDavid du Colombier l->front = nil;
717dd7cddfSDavid du Colombier shad->layer->clear = 0;
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier /*
747dd7cddfSDavid du Colombier * Shadow is now holding down the fort at the old position.
757dd7cddfSDavid du Colombier * Move the window and hide things obscured by new position.
767dd7cddfSDavid du Colombier */
777dd7cddfSDavid du Colombier for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){
787dd7cddfSDavid du Colombier x = newr;
797dd7cddfSDavid du Colombier overlap = rectclip(&x, t->layer->screenr);
807dd7cddfSDavid du Colombier if(overlap){
817dd7cddfSDavid du Colombier memlhide(t, x);
827dd7cddfSDavid du Colombier t->layer->clear = 0;
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier l->screenr = newr;
867dd7cddfSDavid du Colombier l->delta = subpt(scr, i->r.min);
877dd7cddfSDavid du Colombier l->clear = rectinrect(newr, l->screen->image->clipr);
887dd7cddfSDavid du Colombier
897dd7cddfSDavid du Colombier /*
907dd7cddfSDavid du Colombier * Everything's covered. Copy to new position and delete shadow window.
917dd7cddfSDavid du Colombier */
927dd7cddfSDavid du Colombier if(wasclear)
93*8ccd4a63SDavid du Colombier memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S);
947dd7cddfSDavid du Colombier else
957dd7cddfSDavid du Colombier memlexpose(i, newr);
967dd7cddfSDavid du Colombier memldelete(shad);
977dd7cddfSDavid du Colombier
987dd7cddfSDavid du Colombier return 1;
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier void
memlnorefresh(Memimage * l,Rectangle r,void * v)1027dd7cddfSDavid du Colombier memlnorefresh(Memimage *l, Rectangle r, void *v)
1037dd7cddfSDavid du Colombier {
1047dd7cddfSDavid du Colombier USED(l);
1057dd7cddfSDavid du Colombier USED(r.min.x);
1067dd7cddfSDavid du Colombier USED(v);
1077dd7cddfSDavid du Colombier }
108