xref: /inferno-os/libprefab/textbox.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
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 
9 PCompound*
10 layoutbox(Prefab_Environ *e, Draw_Rect rr, String *titletext, List *texttext)
11 {
12 	Draw_Rect er, r, lr;
13 	PCompound *pc;
14 	Prefab_Compound *c;
15 	PElement *title, *text;
16 	Image *disp;
17 	Draw_Image *ddisp;
18 	Screen *screen;
19 	Heap *h;
20 	Rectangle t;
21 	int wid, w;
22 	Point p, pt;
23 
24 	screen = lookupscreen(e->screen);
25 	if(screen == nil)
26 		return H;
27 
28 	gchalt++;
29 	wid = Dx(rr);
30 	P2P(p, rr.min);
31 	title = H;
32 	text = H;
33 	if(texttext != H){
34 		er.min.x = 0;
35 		er.min.y = 0;
36 		er.max.x = wid-5;
37 		er.max.y = Dy(rr);
38 		text = layoutelement(e, texttext, er, EText);
39 		if(text == H){
40 			gchalt--;
41 			return H;
42 		}
43 		if(wid <= 0)
44 			wid = Dx(text->e.r)+5;
45 	}
46 	if(titletext != H){
47 		/* see how wide title wants to be */
48 		memset(&er, 0, sizeof er);
49 		title = textelement(e, titletext, er, ETitle);
50 		if(title == H){
51     Errtitle:
52 			destroy(text);
53 			gchalt--;
54 			return H;
55 		}
56 		w = 2+1+3+Dx(title->e.r)+1;
57 		/* if title is wider than text, adjust wid accordingly */
58 		if(text!=0 && Dx(text->e.r)<w){
59 			if(Dx(text->e.r) < 100){	/* narrow text; don't let title get too wide */
60 				if(w > 250+5)
61 					w = 250+5;
62 				wid = w;
63 			}
64 			destroy(title);
65 			er.min.x = 0;
66 			er.min.y = 0;
67 			er.max.x = wid-5;
68 			er.max.y = 0;
69 			title = textelement(e, titletext, er, ETitle);
70 			if(title == H)
71 				goto Errtitle;
72 		}
73 		if(wid <= 0)
74 			wid = Dx(title->e.r)+5;
75 	}
76 
77 	h = heapz(TCompound);
78 	pc = H2D(PCompound*, h);
79 	c = &pc->c;
80 	c->title = (Prefab_Element*)title;
81 	c->contents = (Prefab_Element*)text;
82 	/* now can just destroy c to clean up */
83 
84 	r.min = DPOINT(p);
85 	r.max.x = r.min.x+wid;
86 	r.max.y = p.y+2+1 + 1+1;
87 	if(title != H)
88 		r.max.y += title->nkids*e->style->titlefont->height+1;
89 	if(text != H)
90 		r.max.y += Dy(text->e.r);
91 
92 	er = edgerect(e, DPOINT(p), &r);
93 
94 	R2R(t, er);
95 	disp = allocwindow(screen, t, Refbackup /*refreshcompound*/, DWhite);
96 	if(disp == nil){
97     Err:
98 		destroy(c);
99 		gchalt--;
100 		return H;
101 	}
102 	if((ddisp=mkdrawimage(disp, e->screen, e->screen->display, nil)) == H){
103 		freeimage(disp);
104 		goto Err;
105 	}
106 
107 	lr = r;
108 	if(title != H){
109 		pt.x = r.min.x+3;
110 		pt.y = r.min.y+3;
111 		translateelement(&title->e, pt);
112 		lr.min.y = title->e.r.max.y+1;
113 	}
114 
115 	if(text != H)
116 		translateelement((Prefab_Element*)text, subpt(IPOINT(lr.min), IPOINT(text->e.r.min)));
117 
118 	c->r = r;
119 	c->environ = e;
120 	c->image = ddisp;
121 	D2H(e)->ref++;
122 	pc->display = screen->display;
123 	gchalt--;
124 	return pc;
125 
126 }
127 
128 PCompound*
129 textbox(Prefab_Environ *e, Draw_Rect rr, String *titletext, String *texttext)
130 {
131 	PCompound *pc;
132 	List *l;
133 
134 	l = listoflayout(e->style, texttext, EText);
135 	pc = layoutbox(e, rr, titletext, l);
136 	free(l);
137 	return pc;
138 }
139