1 #include "lib9.h"
2 #include "draw.h"
3 #include "memdraw.h"
4 #include "memlayer.h"
5
6 /*
7 * Place i so i->r.min = log, i->layer->screenr.min == scr.
8 */
9 int
memlorigin(Memimage * i,Point log,Point scr)10 memlorigin(Memimage *i, Point log, Point scr)
11 {
12 Memlayer *l;
13 Memscreen *s;
14 Memimage *t, *shad, *nsave;
15 Rectangle x, newr, oldr;
16 Point delta;
17 int overlap, eqlog, eqscr, wasclear;
18
19 l = i->layer;
20 s = l->screen;
21 oldr = l->screenr;
22 newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr));
23 eqscr = eqpt(scr, oldr.min);
24 eqlog = eqpt(log, i->r.min);
25 if(eqscr && eqlog)
26 return 0;
27 nsave = nil;
28 if(eqlog==0 && l->save!=nil){
29 nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan);
30 if(nsave == nil)
31 return -1;
32 }
33
34 /*
35 * Bring it to front and move logical coordinate system.
36 */
37 memltofront(i);
38 wasclear = l->clear;
39 if(nsave){
40 if(!wasclear)
41 memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S);
42 freememimage(l->save);
43 l->save = nsave;
44 }
45 delta = subpt(log, i->r.min);
46 i->r = rectaddpt(i->r, delta);
47 i->clipr = rectaddpt(i->clipr, delta);
48 l->delta = subpt(l->screenr.min, i->r.min);
49 if(eqscr)
50 return 0;
51
52 /*
53 * To clean up old position, make a shadow window there, don't paint it,
54 * push it behind this one, and (later) delete it. Because the refresh function
55 * for this fake window is a no-op, this will cause no graphics action except
56 * to restore the background and expose the windows previously hidden.
57 */
58 shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill);
59 if(shad == nil)
60 return -1;
61 s->frontmost = i;
62 if(s->rearmost == i)
63 s->rearmost = shad;
64 else
65 l->rear->layer->front = shad;
66 shad->layer->front = i;
67 shad->layer->rear = l->rear;
68 l->rear = shad;
69 l->front = nil;
70 shad->layer->clear = 0;
71
72 /*
73 * Shadow is now holding down the fort at the old position.
74 * Move the window and hide things obscured by new position.
75 */
76 for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){
77 x = newr;
78 overlap = rectclip(&x, t->layer->screenr);
79 if(overlap){
80 memlhide(t, x);
81 t->layer->clear = 0;
82 }
83 }
84 l->screenr = newr;
85 l->delta = subpt(scr, i->r.min);
86 l->clear = rectinrect(newr, l->screen->image->clipr);
87
88 /*
89 * Everything's covered. Copy to new position and delete shadow window.
90 */
91 if(wasclear)
92 memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S);
93 else
94 memlexpose(i, newr);
95 memldelete(shad);
96
97 return 1;
98 }
99
100 void
memlnorefresh(Memimage * l,Rectangle r,void * v)101 memlnorefresh(Memimage *l, Rectangle r, void *v)
102 {
103 USED(l);
104 USED(r.min.x);
105 USED(v);
106 }
107