xref: /plan9/sys/src/cmd/unix/drawterm/libmemlayer/lorigin.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
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