xref: /inferno-os/libmemlayer/lorigin.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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