xref: /inferno-os/libprefab/elistelement.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include <lib9.h>
2*37da2899SCharles.Forsyth #include <draw.h>
3*37da2899SCharles.Forsyth #include <interp.h>
4*37da2899SCharles.Forsyth #include <isa.h>
5*37da2899SCharles.Forsyth #include "../libinterp/runt.h"
6*37da2899SCharles.Forsyth #include <drawif.h>
7*37da2899SCharles.Forsyth #include <prefab.h>
8*37da2899SCharles.Forsyth #include <kernel.h>
9*37da2899SCharles.Forsyth 
10*37da2899SCharles.Forsyth List*
prefabwrap(void * elem)11*37da2899SCharles.Forsyth prefabwrap(void *elem)
12*37da2899SCharles.Forsyth {
13*37da2899SCharles.Forsyth 	List *l;
14*37da2899SCharles.Forsyth 	Heap *h, *e;
15*37da2899SCharles.Forsyth 
16*37da2899SCharles.Forsyth 	e = D2H(elem);
17*37da2899SCharles.Forsyth 	h = nheap(sizeof(List) + sizeof(WORD*));
18*37da2899SCharles.Forsyth 	h->t = &Tlist;
19*37da2899SCharles.Forsyth 	Tlist.ref++;
20*37da2899SCharles.Forsyth 	l = H2D(List*, h);
21*37da2899SCharles.Forsyth 	l->tail = H;
22*37da2899SCharles.Forsyth 	l->t = &Tptr;
23*37da2899SCharles.Forsyth 	Tptr.ref++;
24*37da2899SCharles.Forsyth 	e->ref++;
25*37da2899SCharles.Forsyth 	*(WORD**)l->data = elem;
26*37da2899SCharles.Forsyth 	return l;
27*37da2899SCharles.Forsyth }
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth static
30*37da2899SCharles.Forsyth PElement*
elistelement1(Prefab_Environ * e,Prefab_Element * elem,Prefab_Element * new,enum Elementtype kind)31*37da2899SCharles.Forsyth elistelement1(Prefab_Environ *e, Prefab_Element *elem, Prefab_Element *new, enum Elementtype kind)
32*37da2899SCharles.Forsyth {
33*37da2899SCharles.Forsyth 	int first;
34*37da2899SCharles.Forsyth 	PElement *pelem;
35*37da2899SCharles.Forsyth 	List *atom;
36*37da2899SCharles.Forsyth 
37*37da2899SCharles.Forsyth 	if(badenviron(e, 0))
38*37da2899SCharles.Forsyth 		return H;
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth 	gchalt++;
41*37da2899SCharles.Forsyth 	first = 0;
42*37da2899SCharles.Forsyth 	if(new == H)
43*37da2899SCharles.Forsyth 		atom = H;
44*37da2899SCharles.Forsyth 	else
45*37da2899SCharles.Forsyth 		atom = prefabwrap(new);
46*37da2899SCharles.Forsyth 	if(elem == H){
47*37da2899SCharles.Forsyth 		pelem = mkelement(e, kind);
48*37da2899SCharles.Forsyth 		elem = &pelem->e;
49*37da2899SCharles.Forsyth 		pelem->first = H;
50*37da2899SCharles.Forsyth 		pelem->nkids = 0;
51*37da2899SCharles.Forsyth 	}else
52*37da2899SCharles.Forsyth 		pelem = (PElement*)elem;
53*37da2899SCharles.Forsyth 	if(atom == H)
54*37da2899SCharles.Forsyth 		goto Return;
55*37da2899SCharles.Forsyth 
56*37da2899SCharles.Forsyth 	if(elem->kids != pelem->first)
57*37da2899SCharles.Forsyth 		error("list Element has been modified externally");
58*37da2899SCharles.Forsyth 	if(elem->kids == H){
59*37da2899SCharles.Forsyth 		elem->kids = atom;
60*37da2899SCharles.Forsyth 		pelem->first = atom;
61*37da2899SCharles.Forsyth 		pelem->last = atom;
62*37da2899SCharles.Forsyth 		pelem->vfirst = atom;
63*37da2899SCharles.Forsyth 		pelem->vlast = atom;
64*37da2899SCharles.Forsyth 		first = 1;
65*37da2899SCharles.Forsyth 	}
66*37da2899SCharles.Forsyth 	if(new->kind!=ESeparator && Dx(elem->r)==0){
67*37da2899SCharles.Forsyth 		elem->r = new->r;
68*37da2899SCharles.Forsyth 		pelem->drawpt.x = elem->r.min.x;
69*37da2899SCharles.Forsyth 		pelem->drawpt.y = elem->r.min.y;
70*37da2899SCharles.Forsyth 	}
71*37da2899SCharles.Forsyth 	pelem->nkids++;
72*37da2899SCharles.Forsyth 	if(first)
73*37da2899SCharles.Forsyth 		goto Return;
74*37da2899SCharles.Forsyth 	pelem->last->tail = atom;
75*37da2899SCharles.Forsyth 	pelem->last = atom;
76*37da2899SCharles.Forsyth 	pelem->vlast = atom;
77*37da2899SCharles.Forsyth 	if(new->kind != ESeparator){
78*37da2899SCharles.Forsyth 		if(kind == EVertical){
79*37da2899SCharles.Forsyth 			elem->r.max.y += Dy(new->r);
80*37da2899SCharles.Forsyth 			if(elem->r.min.x > new->r.min.x)
81*37da2899SCharles.Forsyth 				elem->r.min.x = new->r.min.x;
82*37da2899SCharles.Forsyth 			if(elem->r.max.x < new->r.max.x)
83*37da2899SCharles.Forsyth 				elem->r.max.x = new->r.max.x;
84*37da2899SCharles.Forsyth 		}else{
85*37da2899SCharles.Forsyth 			elem->r.max.x += Dx(new->r);
86*37da2899SCharles.Forsyth 			if(elem->r.min.y > new->r.min.y)
87*37da2899SCharles.Forsyth 				elem->r.min.y = new->r.min.y;
88*37da2899SCharles.Forsyth 			if(elem->r.max.y < new->r.max.y)
89*37da2899SCharles.Forsyth 				elem->r.max.y = new->r.max.y;
90*37da2899SCharles.Forsyth 		}
91*37da2899SCharles.Forsyth 	}
92*37da2899SCharles.Forsyth 	pelem->pkind = kind;
93*37da2899SCharles.Forsyth 
94*37da2899SCharles.Forsyth     Return:
95*37da2899SCharles.Forsyth 	gchalt--;
96*37da2899SCharles.Forsyth 	return pelem;
97*37da2899SCharles.Forsyth }
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth PElement*
elistelement(Prefab_Environ * e,Prefab_Element * new,enum Elementtype kind)100*37da2899SCharles.Forsyth elistelement(Prefab_Environ *e, Prefab_Element *new, enum Elementtype kind)
101*37da2899SCharles.Forsyth {
102*37da2899SCharles.Forsyth 	return elistelement1(e, H, new, kind);
103*37da2899SCharles.Forsyth }
104*37da2899SCharles.Forsyth 
105*37da2899SCharles.Forsyth PElement*
appendelist(Prefab_Element * elem,Prefab_Element * new)106*37da2899SCharles.Forsyth appendelist(Prefab_Element *elem, Prefab_Element *new)
107*37da2899SCharles.Forsyth {
108*37da2899SCharles.Forsyth 	if(elem->kind!=EVertical && elem->kind!=EHorizontal){
109*37da2899SCharles.Forsyth 		kwerrstr("appendelist to non-list");
110*37da2899SCharles.Forsyth 		return H;
111*37da2899SCharles.Forsyth 	}
112*37da2899SCharles.Forsyth 	return elistelement1(elem->environ, elem, new, elem->kind);
113*37da2899SCharles.Forsyth }
114