mirror of https://github.com/0intro/conterm
108 lines
2.4 KiB
C
108 lines
2.4 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <draw.h>
|
|
#include <memdraw.h>
|
|
#include <memlayer.h>
|
|
|
|
/*
|
|
* Place i so i->r.min = log, i->layer->screenr.min == scr.
|
|
*/
|
|
int
|
|
memlorigin(Memimage *i, Point log, Point scr)
|
|
{
|
|
Memlayer *l;
|
|
Memscreen *s;
|
|
Memimage *t, *shad, *nsave;
|
|
Rectangle x, newr, oldr;
|
|
Point delta;
|
|
int overlap, eqlog, eqscr, wasclear;
|
|
|
|
l = i->layer;
|
|
s = l->screen;
|
|
oldr = l->screenr;
|
|
newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr));
|
|
eqscr = eqpt(scr, oldr.min);
|
|
eqlog = eqpt(log, i->r.min);
|
|
if(eqscr && eqlog)
|
|
return 0;
|
|
nsave = nil;
|
|
if(eqlog==0 && l->save!=nil){
|
|
nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan);
|
|
if(nsave == nil)
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Bring it to front and move logical coordinate system.
|
|
*/
|
|
memltofront(i);
|
|
wasclear = l->clear;
|
|
if(nsave){
|
|
if(!wasclear)
|
|
memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S);
|
|
freememimage(l->save);
|
|
l->save = nsave;
|
|
}
|
|
delta = subpt(log, i->r.min);
|
|
i->r = rectaddpt(i->r, delta);
|
|
i->clipr = rectaddpt(i->clipr, delta);
|
|
l->delta = subpt(l->screenr.min, i->r.min);
|
|
if(eqscr)
|
|
return 0;
|
|
|
|
/*
|
|
* To clean up old position, make a shadow window there, don't paint it,
|
|
* push it behind this one, and (later) delete it. Because the refresh function
|
|
* for this fake window is a no-op, this will cause no graphics action except
|
|
* to restore the background and expose the windows previously hidden.
|
|
*/
|
|
shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill);
|
|
if(shad == nil)
|
|
return -1;
|
|
s->frontmost = i;
|
|
if(s->rearmost == i)
|
|
s->rearmost = shad;
|
|
else
|
|
l->rear->layer->front = shad;
|
|
shad->layer->front = i;
|
|
shad->layer->rear = l->rear;
|
|
l->rear = shad;
|
|
l->front = nil;
|
|
shad->layer->clear = 0;
|
|
|
|
/*
|
|
* Shadow is now holding down the fort at the old position.
|
|
* Move the window and hide things obscured by new position.
|
|
*/
|
|
for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){
|
|
x = newr;
|
|
overlap = rectclip(&x, t->layer->screenr);
|
|
if(overlap){
|
|
memlhide(t, x);
|
|
t->layer->clear = 0;
|
|
}
|
|
}
|
|
l->screenr = newr;
|
|
l->delta = subpt(scr, i->r.min);
|
|
l->clear = rectinrect(newr, l->screen->image->clipr);
|
|
|
|
/*
|
|
* Everything's covered. Copy to new position and delete shadow window.
|
|
*/
|
|
if(wasclear)
|
|
memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S);
|
|
else
|
|
memlexpose(i, newr);
|
|
memldelete(shad);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
memlnorefresh(Memimage *l, Rectangle r, void *v)
|
|
{
|
|
USED(l);
|
|
USED(r.min.x);
|
|
USED(v);
|
|
}
|