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