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