xref: /inferno-os/libprefab/textbox.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
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