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