Plan 9 from Bell Labs’s /usr/web/sources/contrib/nemo/octopus/port/live/owpimage.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


implement Pimpl;
include "mods.m";
mods, debug, win, tree: import dat;


Cpointer, cols, panelback, maxpt, cookclick, drawtag, TEXT : import gui;
Ptag, Pedit, Pdead, intag, Predraw, Panel: import wpanel;
panelctl, panelkbd, panelmouse, tagmouse, Tree: import wtree;

Icache: adt {
	data:	array of byte;
	sum:	int;
	i:	ref Image;

	alloc:	fn(d: array of byte): ref Icache;
	close:	fn(ic: self ref Icache);
};

Pimage: adt {
	ic:	ref Icache;
	off:	Point;	# x/y offset for page
};

panels: array of ref Pimage;
images: array of ref Icache;

init(d: Livedat): string
{
	prefixes = list of {"image:", "page:"};
	dat = d;
	initmods();
	panels = array[0] of ref Pimage;
	images = array[0] of ref Icache;
	return nil;
}

samedata(d1, d2: array of byte): int
{
	if (len d1 != len d2)
		return 0;
	for (i := 0; i < len d1; i++)
		if (d1[i] != d2[i])
			return 0;
	return 1;
}

Icache.alloc(d: array of byte): ref Icache
{
	dpy := win.display;
	sum := 0;
	for (i := 0; i < len d; i++)
		sum += int d[i];
	for (i = 0; i < len images ; i++)
		if ((ic := images[i]) != nil)
		if (sum == ic.sum && samedata(ic.data, d))
			return ic;
	# not found in cache. install a new entry
	fname := sprint("/tmp/owinimg.%d", sys->pctl(0,nil));
	fd := create(fname, ORDWR|ORCLOSE, 8r644);
	if (fd == nil)
		return nil;
	if (write(fd, d, len d) != len d)
		return nil;
	sys->seek(fd, big 0, 0);
	img := dpy.readimage(fd);
	if (img == nil)
		return nil;
	ic = ref Icache(d, sum, img);
	for (i = 0; i < len images; i++)
		if (images[i] == nil){
			images[i] = ic;
			return ic;
		}
	nimages := array[len images + 1] of ref Icache;
	nimages[0:] = images;
	nimages[len images] = ic;
	images = nimages;
	return ic;
}

Icache.close(ic: self ref Icache)
{
	if (ic != nil){
		for (i := 0; i < len images; i++)
			if (images[i] == ic)
				images[i] = nil;
	}
	# Pimages referencing ic will keep their refs valid
}

pimpl(p: ref Panel): ref Pimage
{
	if (p.implid < 0 || p.implid > len panels || panels[p.implid] == nil)
		panic("image: bug: no impl");
	return panels[p.implid];
}

pinit(p: ref Panel)
{
	if (tree == nil)
		tree = dat->tree;
	for (i := 0; i < len panels; i++)
		if (panels[i] == nil)
			break;
	if (i == len panels){
		npanels := array[i+16] of ref Pimage;
		npanels[0:] = panels;
		panels = npanels;
	}
	p.implid = i;
	panels[i] = ref Pimage(nil, Point(0,0));
	p.minsz = Point(48, 48);
	p.flags |= Pedit;
	if (len p.name > 6 && p.name[0:6] == "image:")
		p.wants = Point(0, 0);
	else
		p.wants = Point(1, 1);
	
}

pterm(p: ref Panel)
{
	if (p.implid != -1){
		pimpl(p);	# check
		panels[p.implid] = nil;
		p.implid = -1;
	}
}

pctl(p: ref Panel, s: string)
{
	panelctl(tree, p, s);
}

pupdate(p: ref Panel, d: array of byte)
{
	pi := pimpl(p);
	if (pi == nil)
		return;
	if (pi.ic != nil && samedata(pi.ic.data, d))
		return;
	ic := pi.ic;
	pi.ic =Icache.alloc(d);
	if (pi.ic == nil){
		pi.ic = ic;
		return;
	}
	oldr := Rect((0,0), (48,48));
	if (ic != nil && ic.i != nil)
		oldr = ic.i.r;
	ic.close();
	pi.off = Point(0,0);
	if (!p.wants.x){
		p.minsz.x = pi.ic.i.r.dx();
		p.minsz.y = pi.ic.i.r.dy();
	}
	p.flags |= Predraw;
}

pevent(nil: ref Panel, nil: string)
{
	# no ins/del events
}

pdraw(p: ref Panel)
{
	pi := pimpl(p);
	if (pi == nil)
		return;
	back := panelback(p);
	ic := pi.ic;
	win.image.draw(p.rect, back, nil, (0,0));
	if (ic != nil) {
		pt := Point(0,0);
		if (p.wants.x)
			pt = pi.off;
		pt = ic.i.r.min.add(pt);
		if (p.wants.x)
			win.image.draw(p.rect, back, nil, (0,0));
		win.image.draw(p.rect, ic.i, nil, pt);
	}
	if (p.flags&Ptag)
		drawtag(p);
}

ijump(p: ref Panel, pt: Point)
{
	pi := pimpl(p);
	if (pi == nil)
		return;
	if (pt.x < 0)
		pt.x = 0;
	if (pt.y < 0)
		pt.y = 0;
	dy := p.rect.dy();
	diy:= pi.ic.i.r.dy();
	dx := p.rect.dx();
	dix:= pi.ic.i.r.dx();
	pi.off.y = pt.y * diy / dy;
	pi.off.x = pt.x * dix / dx;
	if (pi.off.y < 0)
		pi.off.y = 0;
	if (diy <= dy)
		pi.off.y = 0;
	else if (pi.off.y > diy - dy)
		pi.off.y = diy - dy ;
	if (pi.off.x < 0)
		pi.off.x = 0;
	if (dix <= dx)
		pi.off.x = 0;
	else if (pi.off.x > dix - dx)
		pi.off.x = dix - dx;
}

pmouse(p: ref Panel, m: ref Cpointer, mc: chan of ref Cpointer)
{
	if ((p.flags&Ptag) && intag(p, m.xy)){
		tagmouse(tree, p, m, mc);
		return;
	}
	case m.buttons {
	4 =>
		m = <-mc;
		if (p.flags&Pdead)
			return;
		if (m.buttons == 0)
			p.fsctl(sprint("look %s\n", p.name), 1);
		else {
			while(m.buttons & 4){
				if (p.flags&Pdead)
					return;
				xy := m.xy.sub(p.rect.min);
				ijump(p, xy);
				pdraw(p);
				m = <-mc;
			}
			while(m.buttons != 0)
				m = <-mc;
		}
	2 =>
		if (cookclick(m, mc))
			p.fsctl(sprint("exec %s\n", p.name), 1);
	}
}

pkbd(p: ref Panel, r: int)
{
	panelkbd(nil, p, r);
}

psync(nil: ref Panel)
{
	# can't edit, no need to sync
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.