xref: /inferno-os/libtk/frame.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include <lib9.h>
2*37da2899SCharles.Forsyth #include <kernel.h>
3*37da2899SCharles.Forsyth #include "draw.h"
4*37da2899SCharles.Forsyth #include "tk.h"
5*37da2899SCharles.Forsyth #include "frame.h"
6*37da2899SCharles.Forsyth 
7*37da2899SCharles.Forsyth char*
tkframe(TkTop * t,char * arg,char ** ret)8*37da2899SCharles.Forsyth tkframe(TkTop *t, char *arg, char **ret)
9*37da2899SCharles.Forsyth {
10*37da2899SCharles.Forsyth 	Tk *tk;
11*37da2899SCharles.Forsyth 	char *e;
12*37da2899SCharles.Forsyth 	TkOptab tko[2];
13*37da2899SCharles.Forsyth 	TkName *names;
14*37da2899SCharles.Forsyth 
15*37da2899SCharles.Forsyth 	tk = tknewobj(t, TKframe, sizeof(Tk));
16*37da2899SCharles.Forsyth 	if(tk == nil)
17*37da2899SCharles.Forsyth 		return TkNomem;
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth 	tko[0].ptr = tk;
20*37da2899SCharles.Forsyth 	tko[0].optab = tkgeneric;
21*37da2899SCharles.Forsyth 	tko[1].ptr = nil;
22*37da2899SCharles.Forsyth 	names = nil;
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth 	e = tkparse(t, arg, tko, &names);
25*37da2899SCharles.Forsyth 	if(e != nil) {
26*37da2899SCharles.Forsyth 		tkfreeobj(tk);
27*37da2899SCharles.Forsyth 		return e;
28*37da2899SCharles.Forsyth 	}
29*37da2899SCharles.Forsyth 	tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
30*37da2899SCharles.Forsyth 
31*37da2899SCharles.Forsyth 	e = tkaddchild(t, tk, &names);
32*37da2899SCharles.Forsyth 
33*37da2899SCharles.Forsyth 	tkfreename(names);
34*37da2899SCharles.Forsyth 	if(e != nil) {
35*37da2899SCharles.Forsyth 		tkfreeobj(tk);
36*37da2899SCharles.Forsyth 		return e;
37*37da2899SCharles.Forsyth 	}
38*37da2899SCharles.Forsyth 	tk->name->link = nil;
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth 	return tkvalue(ret, "%s", tk->name->name);
41*37da2899SCharles.Forsyth }
42*37da2899SCharles.Forsyth 
43*37da2899SCharles.Forsyth /*
44*37da2899SCharles.Forsyth  * Also used for windows, menus, separators
45*37da2899SCharles.Forsyth  */
46*37da2899SCharles.Forsyth void
tkfreeframe(Tk * tk)47*37da2899SCharles.Forsyth tkfreeframe(Tk *tk)
48*37da2899SCharles.Forsyth {
49*37da2899SCharles.Forsyth 	TkWin *tkw;
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth 	if((tk->flag & Tkwindow) == 0)
52*37da2899SCharles.Forsyth 		return;
53*37da2899SCharles.Forsyth 
54*37da2899SCharles.Forsyth 	if(tk->type == TKmenu) {
55*37da2899SCharles.Forsyth 		tkw = TKobj(TkWin, tk);
56*37da2899SCharles.Forsyth 		free(tkw->postcmd);
57*37da2899SCharles.Forsyth 		free(tkw->cascade);
58*37da2899SCharles.Forsyth 		free(tkw->cbname);
59*37da2899SCharles.Forsyth 	}
60*37da2899SCharles.Forsyth 
61*37da2899SCharles.Forsyth 	tkunmap(tk);		/* XXX do this only if (tk->flag&Tkswept)==0 ?? */
62*37da2899SCharles.Forsyth }
63*37da2899SCharles.Forsyth 
64*37da2899SCharles.Forsyth char*
tkdrawframe(Tk * tk,Point orig)65*37da2899SCharles.Forsyth tkdrawframe(Tk *tk, Point orig)
66*37da2899SCharles.Forsyth {
67*37da2899SCharles.Forsyth 	int bw;
68*37da2899SCharles.Forsyth 	Point p;
69*37da2899SCharles.Forsyth 	Image *i;
70*37da2899SCharles.Forsyth 	Tk *f;
71*37da2899SCharles.Forsyth 	Rectangle r, slaver;		/* dribbling, whipping or just square? */
72*37da2899SCharles.Forsyth 
73*37da2899SCharles.Forsyth 	i = tkimageof(tk);
74*37da2899SCharles.Forsyth 	if(i == nil)
75*37da2899SCharles.Forsyth 		return nil;
76*37da2899SCharles.Forsyth 
77*37da2899SCharles.Forsyth 	p.x = orig.x + tk->act.x + tk->borderwidth;
78*37da2899SCharles.Forsyth 	p.y = orig.y + tk->act.y + tk->borderwidth;
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth 	draw(i, rectaddpt(tk->dirty, p), tkgc(tk->env, TkCbackgnd), nil, ZP);
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth 	/*
83*37da2899SCharles.Forsyth 	 * doesn't matter about drawing TKseparator
84*37da2899SCharles.Forsyth 	 * oblivious of dirty rect, as it never has any children to sully anyway
85*37da2899SCharles.Forsyth 	 */
86*37da2899SCharles.Forsyth 	if(tk->type == TKseparator) {
87*37da2899SCharles.Forsyth 		r = rectaddpt(tkrect(tk, 1), p);
88*37da2899SCharles.Forsyth 		r.min.x += 4;
89*37da2899SCharles.Forsyth 		r.max.x -= 4;
90*37da2899SCharles.Forsyth 		r.min.y += (Dy(r) - 2)/2;
91*37da2899SCharles.Forsyth 		r.max.y = r.min.y+1;
92*37da2899SCharles.Forsyth 		draw(i, r, tkgc(tk->env, TkCbackgnddark), nil, ZP);
93*37da2899SCharles.Forsyth 		r.min.y += 1;
94*37da2899SCharles.Forsyth 		r.max.y += 1;
95*37da2899SCharles.Forsyth 		draw(i, r, tkgc(tk->env, TkCbackgndlght), nil, ZP);
96*37da2899SCharles.Forsyth 		return nil;
97*37da2899SCharles.Forsyth 	}
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth 	/*
100*37da2899SCharles.Forsyth 	 * make sure all the slaves inside the area we've just drawn
101*37da2899SCharles.Forsyth 	 * refresh themselves properly.
102*37da2899SCharles.Forsyth 	 */
103*37da2899SCharles.Forsyth 	for(f = tk->slave; f; f = f->next) {
104*37da2899SCharles.Forsyth 		bw = f->borderwidth;
105*37da2899SCharles.Forsyth 		slaver.min.x = f->act.x;
106*37da2899SCharles.Forsyth 		slaver.min.y = f->act.y;
107*37da2899SCharles.Forsyth 		slaver.max.x = slaver.min.x + f->act.width + 2*bw;
108*37da2899SCharles.Forsyth 		slaver.max.y = slaver.min.y + f->act.height + 2*bw;
109*37da2899SCharles.Forsyth 		if (rectclip(&slaver, tk->dirty)) {
110*37da2899SCharles.Forsyth 			f->flag |= Tkrefresh;
111*37da2899SCharles.Forsyth 			slaver = rectsubpt(slaver, Pt(f->act.x + bw, f->act.y + bw));
112*37da2899SCharles.Forsyth 			combinerect(&f->dirty, slaver);
113*37da2899SCharles.Forsyth 		}
114*37da2899SCharles.Forsyth 	}
115*37da2899SCharles.Forsyth 	p.x -= tk->borderwidth;
116*37da2899SCharles.Forsyth 	p.y -= tk->borderwidth;
117*37da2899SCharles.Forsyth 
118*37da2899SCharles.Forsyth 	if (!rectinrect(tk->dirty, tkrect(tk, 0)))
119*37da2899SCharles.Forsyth 		tkdrawrelief(i, tk, p, TkCbackgnd, tk->relief);
120*37da2899SCharles.Forsyth 	return nil;
121*37da2899SCharles.Forsyth }
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth /* Frame commands */
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth static char*
tkframecget(Tk * tk,char * arg,char ** val)126*37da2899SCharles.Forsyth tkframecget(Tk *tk, char *arg, char **val)
127*37da2899SCharles.Forsyth {
128*37da2899SCharles.Forsyth 	TkOptab tko[3];
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth 	tko[0].ptr = tk;
131*37da2899SCharles.Forsyth 	tko[0].optab = tkgeneric;
132*37da2899SCharles.Forsyth 	tko[1].ptr = nil;
133*37da2899SCharles.Forsyth 	if(tk->flag & Tkwindow){
134*37da2899SCharles.Forsyth 		tko[1].ptr = TKobj(TkWin, tk);
135*37da2899SCharles.Forsyth 		tko[1].optab = tktop;
136*37da2899SCharles.Forsyth 		tko[2].ptr = nil;
137*37da2899SCharles.Forsyth 	}
138*37da2899SCharles.Forsyth 
139*37da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, tk->env->top);
140*37da2899SCharles.Forsyth }
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth static char*
tkframeconf(Tk * tk,char * arg,char ** val)143*37da2899SCharles.Forsyth tkframeconf(Tk *tk, char *arg, char **val)
144*37da2899SCharles.Forsyth {
145*37da2899SCharles.Forsyth 	char *e;
146*37da2899SCharles.Forsyth 	TkGeom g;
147*37da2899SCharles.Forsyth 	int bd;
148*37da2899SCharles.Forsyth 	Point oldp;
149*37da2899SCharles.Forsyth 	TkOptab tko[3];
150*37da2899SCharles.Forsyth 	TkWin *tkw;
151*37da2899SCharles.Forsyth 
152*37da2899SCharles.Forsyth 	tko[0].ptr = tk;
153*37da2899SCharles.Forsyth 	tko[0].optab = tkgeneric;
154*37da2899SCharles.Forsyth 	tko[1].ptr = nil;
155*37da2899SCharles.Forsyth 	tkw = nil;
156*37da2899SCharles.Forsyth 	if(tk->flag & Tkwindow) {
157*37da2899SCharles.Forsyth 		tkw = TKobj(TkWin, tk);
158*37da2899SCharles.Forsyth 		tko[1].ptr = tkw;
159*37da2899SCharles.Forsyth 		tko[1].optab = tktop;
160*37da2899SCharles.Forsyth 		tko[2].ptr = nil;
161*37da2899SCharles.Forsyth 		oldp = tkw->act;
162*37da2899SCharles.Forsyth 	}
163*37da2899SCharles.Forsyth 
164*37da2899SCharles.Forsyth 	if(*arg == '\0')
165*37da2899SCharles.Forsyth 		return tkconflist(tko, val);
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth 	if(tkw != nil){
168*37da2899SCharles.Forsyth 		/*
169*37da2899SCharles.Forsyth 		 * see whether only -x or -y is being configured,
170*37da2899SCharles.Forsyth 		 * in which case just move the window; don't redraw
171*37da2899SCharles.Forsyth 		 * everything
172*37da2899SCharles.Forsyth 		 */
173*37da2899SCharles.Forsyth 		e = tkparse(tk->env->top, arg, &tko[1], nil);
174*37da2899SCharles.Forsyth 		if(e == nil){
175*37da2899SCharles.Forsyth 			if(!eqpt(oldp, tkw->req))
176*37da2899SCharles.Forsyth 				tkmovewin(tk, tkw->req);
177*37da2899SCharles.Forsyth 			return nil;
178*37da2899SCharles.Forsyth 		}
179*37da2899SCharles.Forsyth 	}
180*37da2899SCharles.Forsyth 
181*37da2899SCharles.Forsyth 	g = tk->req;
182*37da2899SCharles.Forsyth 	bd = tk->borderwidth;
183*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
184*37da2899SCharles.Forsyth 	tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
185*37da2899SCharles.Forsyth 	tk->req.x = tk->act.x;
186*37da2899SCharles.Forsyth 	tk->req.y = tk->act.y;
187*37da2899SCharles.Forsyth 	tkgeomchg(tk, &g, bd);
188*37da2899SCharles.Forsyth 	if(tkw != nil && !eqpt(oldp, tkw->act))
189*37da2899SCharles.Forsyth 		tkmovewin(tk, tkw->req);
190*37da2899SCharles.Forsyth 
191*37da2899SCharles.Forsyth 	tk->dirty = tkrect(tk, 1);
192*37da2899SCharles.Forsyth 
193*37da2899SCharles.Forsyth 	return e;
194*37da2899SCharles.Forsyth }
195*37da2899SCharles.Forsyth 
196*37da2899SCharles.Forsyth static char*
tkframesuspend(Tk * tk,char * arg,char ** val)197*37da2899SCharles.Forsyth tkframesuspend(Tk *tk, char *arg, char **val)
198*37da2899SCharles.Forsyth {
199*37da2899SCharles.Forsyth 	USED(arg);
200*37da2899SCharles.Forsyth 	USED(val);
201*37da2899SCharles.Forsyth 	if((tk->flag & Tkwindow) == 0)
202*37da2899SCharles.Forsyth 		return TkNotwm;
203*37da2899SCharles.Forsyth 	tk->flag |= Tksuspended;
204*37da2899SCharles.Forsyth 	return nil;
205*37da2899SCharles.Forsyth }
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth static char*
tkframemap(Tk * tk,char * arg,char ** val)208*37da2899SCharles.Forsyth tkframemap(Tk *tk, char *arg, char **val)
209*37da2899SCharles.Forsyth {
210*37da2899SCharles.Forsyth 	USED(arg);
211*37da2899SCharles.Forsyth 	USED(val);
212*37da2899SCharles.Forsyth 	if(tk->flag & Tkwindow)
213*37da2899SCharles.Forsyth 		return tkmap(tk);
214*37da2899SCharles.Forsyth 	return TkNotwm;
215*37da2899SCharles.Forsyth }
216*37da2899SCharles.Forsyth 
217*37da2899SCharles.Forsyth static char*
tkframeunmap(Tk * tk,char * arg,char ** val)218*37da2899SCharles.Forsyth tkframeunmap(Tk *tk, char *arg, char **val)
219*37da2899SCharles.Forsyth {
220*37da2899SCharles.Forsyth 	USED(arg);
221*37da2899SCharles.Forsyth 	USED(val);
222*37da2899SCharles.Forsyth 	if(tk->flag & Tkwindow) {
223*37da2899SCharles.Forsyth 		tkunmap(tk);
224*37da2899SCharles.Forsyth 		return nil;
225*37da2899SCharles.Forsyth 	}
226*37da2899SCharles.Forsyth 	return TkNotwm;
227*37da2899SCharles.Forsyth }
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth static void
tkframefocusorder(Tk * tk)230*37da2899SCharles.Forsyth tkframefocusorder(Tk *tk)
231*37da2899SCharles.Forsyth {
232*37da2899SCharles.Forsyth 	int i, n;
233*37da2899SCharles.Forsyth 	Tk *sub;
234*37da2899SCharles.Forsyth 	TkWinfo *inf;
235*37da2899SCharles.Forsyth 
236*37da2899SCharles.Forsyth 	n = 0;
237*37da2899SCharles.Forsyth 	for (sub = tk->slave; sub != nil; sub = sub->next)
238*37da2899SCharles.Forsyth 		n++;
239*37da2899SCharles.Forsyth 
240*37da2899SCharles.Forsyth 	if (n == 0)
241*37da2899SCharles.Forsyth 		return;
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth 	inf = malloc(sizeof(*inf) * n);
244*37da2899SCharles.Forsyth 	if (inf == nil)
245*37da2899SCharles.Forsyth 		return;
246*37da2899SCharles.Forsyth 	i = 0;
247*37da2899SCharles.Forsyth 	for (sub = tk->slave; sub != nil; sub = sub->next) {
248*37da2899SCharles.Forsyth 		inf[i].w = sub;
249*37da2899SCharles.Forsyth 		inf[i].r = rectaddpt(tkrect(sub, 1), Pt(sub->act.x, sub->act.y));
250*37da2899SCharles.Forsyth 		i++;
251*37da2899SCharles.Forsyth 	}
252*37da2899SCharles.Forsyth 	tksortfocusorder(inf, n);
253*37da2899SCharles.Forsyth 	for (i = 0; i < n; i++)
254*37da2899SCharles.Forsyth 		tkappendfocusorder(inf[i].w);
255*37da2899SCharles.Forsyth 	free(inf);
256*37da2899SCharles.Forsyth }
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth static
259*37da2899SCharles.Forsyth TkCmdtab tkframecmd[] =
260*37da2899SCharles.Forsyth {
261*37da2899SCharles.Forsyth 	"cget",			tkframecget,
262*37da2899SCharles.Forsyth 	"configure",		tkframeconf,
263*37da2899SCharles.Forsyth 	"map",			tkframemap,
264*37da2899SCharles.Forsyth 	"unmap",		tkframeunmap,
265*37da2899SCharles.Forsyth 	"suspend",		tkframesuspend,
266*37da2899SCharles.Forsyth 	nil
267*37da2899SCharles.Forsyth };
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth TkMethod framemethod = {
270*37da2899SCharles.Forsyth 	"frame",
271*37da2899SCharles.Forsyth 	tkframecmd,
272*37da2899SCharles.Forsyth 	tkfreeframe,
273*37da2899SCharles.Forsyth 	tkdrawframe,
274*37da2899SCharles.Forsyth 	nil,
275*37da2899SCharles.Forsyth 	nil,
276*37da2899SCharles.Forsyth 	tkframefocusorder
277*37da2899SCharles.Forsyth };
278