xref: /inferno-os/libtk/panel.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "draw.h"
3*37da2899SCharles.Forsyth #include "tk.h"
4*37da2899SCharles.Forsyth 
5*37da2899SCharles.Forsyth #define	O(t, e)		((long)(&((t*)0)->e))
6*37da2899SCharles.Forsyth 
7*37da2899SCharles.Forsyth typedef struct TkPanel TkPanel;
8*37da2899SCharles.Forsyth struct TkPanel
9*37da2899SCharles.Forsyth {
10*37da2899SCharles.Forsyth 	Image*	image;
11*37da2899SCharles.Forsyth 	Image*	matte;
12*37da2899SCharles.Forsyth 	Point		view;	/* vector from image origin to widget origin */
13*37da2899SCharles.Forsyth 	Rectangle		r;		/* drawn rectangle (in image coords) */
14*37da2899SCharles.Forsyth 	int		anchor;
15*37da2899SCharles.Forsyth 	int		hasalpha;	/* does the image include an alpha channel? */
16*37da2899SCharles.Forsyth };
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth static TkOption tkpanelopts[] =
19*37da2899SCharles.Forsyth {
20*37da2899SCharles.Forsyth 	"anchor",	OPTflag,	O(TkPanel, anchor),	tkanchor,
21*37da2899SCharles.Forsyth 	nil
22*37da2899SCharles.Forsyth };
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth static int
tkdrawnrect(Image * image,Image * matte,Rectangle * r)25*37da2899SCharles.Forsyth tkdrawnrect(Image *image, Image *matte, Rectangle *r)
26*37da2899SCharles.Forsyth {
27*37da2899SCharles.Forsyth 	*r = image->clipr;
28*37da2899SCharles.Forsyth 	if (matte != nil) {
29*37da2899SCharles.Forsyth 		if (!rectclip(r, matte->clipr))
30*37da2899SCharles.Forsyth 			return 0;
31*37da2899SCharles.Forsyth 		if (!matte->repl && !rectclip(r, matte->r))
32*37da2899SCharles.Forsyth 			return 0;
33*37da2899SCharles.Forsyth 	}
34*37da2899SCharles.Forsyth 	if (!image->repl && !rectclip(r, image->r))
35*37da2899SCharles.Forsyth 		return 0;
36*37da2899SCharles.Forsyth 	return 1;
37*37da2899SCharles.Forsyth }
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth char*
tkpanel(TkTop * t,char * arg,char ** ret)40*37da2899SCharles.Forsyth tkpanel(TkTop *t, char *arg, char **ret)
41*37da2899SCharles.Forsyth {
42*37da2899SCharles.Forsyth 	TkOptab tko[3];
43*37da2899SCharles.Forsyth 	Tk *tk;
44*37da2899SCharles.Forsyth 	TkPanel *tkp;
45*37da2899SCharles.Forsyth 	TkName *names;
46*37da2899SCharles.Forsyth 	char *e;
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth 	tk = tknewobj(t, TKpanel, sizeof(Tk)+sizeof(TkPanel));
49*37da2899SCharles.Forsyth 	if(tk == nil)
50*37da2899SCharles.Forsyth 		return TkNomem;
51*37da2899SCharles.Forsyth 
52*37da2899SCharles.Forsyth 	tkp = TKobj(TkPanel, tk);
53*37da2899SCharles.Forsyth 	tkp->anchor = Tkcenter;
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth 	tko[0].ptr = tk;
56*37da2899SCharles.Forsyth 	tko[0].optab = tkgeneric;
57*37da2899SCharles.Forsyth 	tko[1].ptr = tkp;
58*37da2899SCharles.Forsyth 	tko[1].optab = tkpanelopts;
59*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
60*37da2899SCharles.Forsyth 	names = nil;
61*37da2899SCharles.Forsyth 
62*37da2899SCharles.Forsyth 	e = tkparse(t, arg, tko, &names);
63*37da2899SCharles.Forsyth 	if(e != nil) {
64*37da2899SCharles.Forsyth 		tkfreeobj(tk);
65*37da2899SCharles.Forsyth 		return e;
66*37da2899SCharles.Forsyth 	}
67*37da2899SCharles.Forsyth 
68*37da2899SCharles.Forsyth 	tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth 	e = tkaddchild(t, tk, &names);
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth 	tkfreename(names);
73*37da2899SCharles.Forsyth 	if (e != nil) {
74*37da2899SCharles.Forsyth 		tkfreeobj(tk);
75*37da2899SCharles.Forsyth 		return e;
76*37da2899SCharles.Forsyth 	}
77*37da2899SCharles.Forsyth 
78*37da2899SCharles.Forsyth 	tk->name->link = nil;
79*37da2899SCharles.Forsyth 	return tkvalue(ret, "%s", tk->name->name);
80*37da2899SCharles.Forsyth }
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth void
tkgetpanelimage(Tk * tk,Image ** i,Image ** m)83*37da2899SCharles.Forsyth tkgetpanelimage(Tk *tk, Image **i, Image **m)
84*37da2899SCharles.Forsyth {
85*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
86*37da2899SCharles.Forsyth 	*i = tkp->image;
87*37da2899SCharles.Forsyth 	*m = tkp->matte;
88*37da2899SCharles.Forsyth }
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth void
tksetpanelimage(Tk * tk,Image * image,Image * matte)91*37da2899SCharles.Forsyth tksetpanelimage(Tk *tk, Image *image, Image *matte)
92*37da2899SCharles.Forsyth {
93*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
94*37da2899SCharles.Forsyth 	int ishuge;
95*37da2899SCharles.Forsyth 	TkGeom g;
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth 	g = tk->req;
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth 	tkp->image = image;
100*37da2899SCharles.Forsyth 	tkp->matte = matte;
101*37da2899SCharles.Forsyth 
102*37da2899SCharles.Forsyth 	if (!tkdrawnrect(image, matte, &tkp->r)) {
103*37da2899SCharles.Forsyth 		tkp->r.min = image->r.min;
104*37da2899SCharles.Forsyth 		tkp->r.max = image->r.min;
105*37da2899SCharles.Forsyth 	}
106*37da2899SCharles.Forsyth 
107*37da2899SCharles.Forsyth 	tkp->view = tkp->r.min;		/* XXX do we actually want to keep the old one? */
108*37da2899SCharles.Forsyth 	/*
109*37da2899SCharles.Forsyth 	 * if both image and matte are replicated, then we've got no idea what
110*37da2899SCharles.Forsyth 	 * the rectangle should be, so request zero size, and set origin to (0, 0).
111*37da2899SCharles.Forsyth 	 */
112*37da2899SCharles.Forsyth 	ishuge = (Dx(tkp->r) >= 10000000);
113*37da2899SCharles.Forsyth 	if((tk->flag & Tksetwidth) == 0){
114*37da2899SCharles.Forsyth 		if(ishuge)
115*37da2899SCharles.Forsyth 			tk->req.width = 0;
116*37da2899SCharles.Forsyth 		else
117*37da2899SCharles.Forsyth 			tk->req.width = Dx(tkp->r);
118*37da2899SCharles.Forsyth 	}
119*37da2899SCharles.Forsyth 	if(ishuge)
120*37da2899SCharles.Forsyth 		tkp->view.x = 0;
121*37da2899SCharles.Forsyth 
122*37da2899SCharles.Forsyth 	ishuge = (Dy(tkp->r) >= 10000000);
123*37da2899SCharles.Forsyth 	if((tk->flag & Tksetheight) == 0){
124*37da2899SCharles.Forsyth 		if(ishuge)
125*37da2899SCharles.Forsyth 			tk->req.height = 0;
126*37da2899SCharles.Forsyth 		else
127*37da2899SCharles.Forsyth 			tk->req.height = Dy(tkp->r);
128*37da2899SCharles.Forsyth 	}
129*37da2899SCharles.Forsyth 	if(ishuge)
130*37da2899SCharles.Forsyth 		tkp->view.y = 0;
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth 	tkp->hasalpha = tkchanhastype(image->chan, CAlpha);
133*37da2899SCharles.Forsyth 	tkgeomchg(tk, &g, tk->borderwidth);
134*37da2899SCharles.Forsyth 	tksettransparent(tk, tkp->hasalpha || tkhasalpha(tk->env, TkCbackgnd));
135*37da2899SCharles.Forsyth 	tk->dirty = tkrect(tk, 0);
136*37da2899SCharles.Forsyth }
137*37da2899SCharles.Forsyth 
138*37da2899SCharles.Forsyth static void
tkfreepanel(Tk * tk)139*37da2899SCharles.Forsyth tkfreepanel(Tk *tk)
140*37da2899SCharles.Forsyth {
141*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
142*37da2899SCharles.Forsyth 	tkdelpanelimage(tk->env->top, tkp->image);
143*37da2899SCharles.Forsyth 	tkdelpanelimage(tk->env->top, tkp->matte);
144*37da2899SCharles.Forsyth }
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth static Point
tkpanelview(Tk * tk)147*37da2899SCharles.Forsyth tkpanelview(Tk *tk)
148*37da2899SCharles.Forsyth {
149*37da2899SCharles.Forsyth 	int dx, dy;
150*37da2899SCharles.Forsyth 	Point view;
151*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
152*37da2899SCharles.Forsyth 
153*37da2899SCharles.Forsyth 	dx = tk->act.width - Dx(tkp->r);
154*37da2899SCharles.Forsyth 	dy = tk->act.height - Dy(tkp->r);
155*37da2899SCharles.Forsyth 
156*37da2899SCharles.Forsyth 	view = tkp->view;
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth 	if (dx > 0) {
159*37da2899SCharles.Forsyth 		if((tkp->anchor & (Tkeast|Tkwest)) == 0)
160*37da2899SCharles.Forsyth 			view.x -= dx/2;
161*37da2899SCharles.Forsyth 		else
162*37da2899SCharles.Forsyth 		if(tkp->anchor & Tkeast)
163*37da2899SCharles.Forsyth 			view.x -= dx;
164*37da2899SCharles.Forsyth 	}
165*37da2899SCharles.Forsyth 	if (dy > 0) {
166*37da2899SCharles.Forsyth 		if((tkp->anchor & (Tknorth|Tksouth)) == 0)
167*37da2899SCharles.Forsyth 			view.y -= dy/2;
168*37da2899SCharles.Forsyth 		else
169*37da2899SCharles.Forsyth 		if(tkp->anchor & Tksouth)
170*37da2899SCharles.Forsyth 			view.y -= dy;
171*37da2899SCharles.Forsyth 	}
172*37da2899SCharles.Forsyth 	return view;
173*37da2899SCharles.Forsyth }
174*37da2899SCharles.Forsyth 
175*37da2899SCharles.Forsyth static char*
tkdrawpanel(Tk * tk,Point orig)176*37da2899SCharles.Forsyth tkdrawpanel(Tk *tk, Point orig)
177*37da2899SCharles.Forsyth {
178*37da2899SCharles.Forsyth 	Rectangle r, pr;
179*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
180*37da2899SCharles.Forsyth 	Image *i;
181*37da2899SCharles.Forsyth 	int any;
182*37da2899SCharles.Forsyth 	Point view, p;
183*37da2899SCharles.Forsyth 
184*37da2899SCharles.Forsyth 	i = tkimageof(tk);
185*37da2899SCharles.Forsyth 	if (i == nil)
186*37da2899SCharles.Forsyth 		return nil;
187*37da2899SCharles.Forsyth 
188*37da2899SCharles.Forsyth 	p.x = orig.x + tk->act.x + tk->borderwidth;
189*37da2899SCharles.Forsyth 	p.y = orig.y + tk->act.y + tk->borderwidth;
190*37da2899SCharles.Forsyth 
191*37da2899SCharles.Forsyth 	view = tkpanelview(tk);
192*37da2899SCharles.Forsyth 
193*37da2899SCharles.Forsyth 	/*
194*37da2899SCharles.Forsyth 	 * if the image doesn't fully cover the dirty rectangle, then
195*37da2899SCharles.Forsyth 	 * paint some background in there
196*37da2899SCharles.Forsyth 	 */
197*37da2899SCharles.Forsyth 	r = rectsubpt(tkp->r, view);		/* convert to widget coords */
198*37da2899SCharles.Forsyth 	pr = tkrect(tk, 0);
199*37da2899SCharles.Forsyth 	any = rectclip(&r, pr);				/* clip to inside widget borders */
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth 	if (!any || tkp->hasalpha || !rectinrect(tk->dirty, r))
202*37da2899SCharles.Forsyth 		draw(i, rectaddpt(tk->dirty, p), tkgc(tk->env, TkCbackgnd), nil, ZP);
203*37da2899SCharles.Forsyth 
204*37da2899SCharles.Forsyth 	if (any && rectclip(&r, tk->dirty))
205*37da2899SCharles.Forsyth 		draw(i, rectaddpt(r, p), tkp->image, tkp->matte, addpt(r.min, view));
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth 	if (!rectinrect(tk->dirty, pr)) {
208*37da2899SCharles.Forsyth 		p.x -= tk->borderwidth;
209*37da2899SCharles.Forsyth 		p.y -= tk->borderwidth;
210*37da2899SCharles.Forsyth 		tkdrawrelief(i, tk, p, TkCbackgnd, tk->relief);
211*37da2899SCharles.Forsyth 	}
212*37da2899SCharles.Forsyth 	return nil;
213*37da2899SCharles.Forsyth }
214*37da2899SCharles.Forsyth 
215*37da2899SCharles.Forsyth static char*
tkpanelcget(Tk * tk,char * arg,char ** val)216*37da2899SCharles.Forsyth tkpanelcget(Tk *tk, char *arg, char **val)
217*37da2899SCharles.Forsyth {
218*37da2899SCharles.Forsyth 	TkOptab tko[3];
219*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth 	tko[0].ptr = tk;
222*37da2899SCharles.Forsyth 	tko[0].optab = tkgeneric;
223*37da2899SCharles.Forsyth 	tko[1].ptr = tkp;
224*37da2899SCharles.Forsyth 	tko[1].optab = tkpanelopts;
225*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
226*37da2899SCharles.Forsyth 
227*37da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, tk->env->top);
228*37da2899SCharles.Forsyth }
229*37da2899SCharles.Forsyth 
230*37da2899SCharles.Forsyth static char*
tkpanelcvt(Tk * tk,char * arg,int rel,int * p)231*37da2899SCharles.Forsyth tkpanelcvt(Tk *tk, char *arg, int rel, int *p)
232*37da2899SCharles.Forsyth {
233*37da2899SCharles.Forsyth 	char buf[Tkmaxitem];
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
236*37da2899SCharles.Forsyth 	if(buf[0] == '\0')
237*37da2899SCharles.Forsyth 		return TkBadvl;
238*37da2899SCharles.Forsyth 	*p = atoi(buf) + rel;
239*37da2899SCharles.Forsyth 	return nil;
240*37da2899SCharles.Forsyth }
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth /*
243*37da2899SCharles.Forsyth  * screen to image
244*37da2899SCharles.Forsyth  */
245*37da2899SCharles.Forsyth static char*
tkpanelpanelx(Tk * tk,char * arg,char ** val)246*37da2899SCharles.Forsyth tkpanelpanelx(Tk *tk, char *arg, char **val)
247*37da2899SCharles.Forsyth {
248*37da2899SCharles.Forsyth 	Point p;
249*37da2899SCharles.Forsyth 	char *e;
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth 	USED(val);
252*37da2899SCharles.Forsyth 	p = subpt(tkposn(tk), tkpanelview(tk));
253*37da2899SCharles.Forsyth 	e = tkpanelcvt(tk, arg, -p.x, &p.x);
254*37da2899SCharles.Forsyth 	if (e != nil)
255*37da2899SCharles.Forsyth 		return e;
256*37da2899SCharles.Forsyth 	return tkvalue(val, "%d", p.x);
257*37da2899SCharles.Forsyth }
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth static char*
tkpanelpanely(Tk * tk,char * arg,char ** val)260*37da2899SCharles.Forsyth tkpanelpanely(Tk *tk, char *arg, char **val)
261*37da2899SCharles.Forsyth {
262*37da2899SCharles.Forsyth 	Point p;
263*37da2899SCharles.Forsyth 	char *e;
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth 	USED(val);
266*37da2899SCharles.Forsyth 	p = subpt(tkposn(tk), tkpanelview(tk));
267*37da2899SCharles.Forsyth 	e = tkpanelcvt(tk, arg, -p.y, &p.y);
268*37da2899SCharles.Forsyth 	if (e != nil)
269*37da2899SCharles.Forsyth 		return e;
270*37da2899SCharles.Forsyth 	return tkvalue(val, "%d", p.y);
271*37da2899SCharles.Forsyth }
272*37da2899SCharles.Forsyth 
273*37da2899SCharles.Forsyth /*
274*37da2899SCharles.Forsyth  * image to screen
275*37da2899SCharles.Forsyth  */
276*37da2899SCharles.Forsyth static char*
tkpanelscreenx(Tk * tk,char * arg,char ** val)277*37da2899SCharles.Forsyth tkpanelscreenx(Tk *tk, char *arg, char **val)
278*37da2899SCharles.Forsyth {
279*37da2899SCharles.Forsyth 	Point p;
280*37da2899SCharles.Forsyth 	char *e;
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth 	USED(val);
283*37da2899SCharles.Forsyth 	p = subpt(tkposn(tk), tkpanelview(tk));
284*37da2899SCharles.Forsyth 	e = tkpanelcvt(tk, arg, p.x, &p.x);
285*37da2899SCharles.Forsyth 	if (e != nil)
286*37da2899SCharles.Forsyth 		return e;
287*37da2899SCharles.Forsyth 	return tkvalue(val, "%d", p.x);
288*37da2899SCharles.Forsyth }
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth static char*
tkpanelscreeny(Tk * tk,char * arg,char ** val)291*37da2899SCharles.Forsyth tkpanelscreeny(Tk *tk, char *arg, char **val)
292*37da2899SCharles.Forsyth {
293*37da2899SCharles.Forsyth 	Point p;
294*37da2899SCharles.Forsyth 	char *e;
295*37da2899SCharles.Forsyth 
296*37da2899SCharles.Forsyth 	USED(val);
297*37da2899SCharles.Forsyth 	p = subpt(tkposn(tk), tkpanelview(tk));
298*37da2899SCharles.Forsyth 	e = tkpanelcvt(tk, arg, p.y, &p.y);
299*37da2899SCharles.Forsyth 	if (e != nil)
300*37da2899SCharles.Forsyth 		return e;
301*37da2899SCharles.Forsyth 	return tkvalue(val, "%d", p.y);
302*37da2899SCharles.Forsyth }
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth static char*
tkpanelconf(Tk * tk,char * arg,char ** val)305*37da2899SCharles.Forsyth tkpanelconf(Tk *tk, char *arg, char **val)
306*37da2899SCharles.Forsyth {
307*37da2899SCharles.Forsyth 	char *e;
308*37da2899SCharles.Forsyth 	TkGeom g;
309*37da2899SCharles.Forsyth 	int bd;
310*37da2899SCharles.Forsyth 	TkOptab tko[3];
311*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
312*37da2899SCharles.Forsyth 
313*37da2899SCharles.Forsyth 	tko[0].ptr = tk;
314*37da2899SCharles.Forsyth 	tko[0].optab = tkgeneric;
315*37da2899SCharles.Forsyth 	tko[1].ptr = tkp;
316*37da2899SCharles.Forsyth 	tko[1].optab = tkpanelopts;
317*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth 	if(*arg == '\0')
320*37da2899SCharles.Forsyth 		return tkconflist(tko, val);
321*37da2899SCharles.Forsyth 
322*37da2899SCharles.Forsyth 	g = tk->req;
323*37da2899SCharles.Forsyth 	bd = tk->borderwidth;
324*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
325*37da2899SCharles.Forsyth 	tkgeomchg(tk, &g, bd);
326*37da2899SCharles.Forsyth 	tksettransparent(tk, tkp->hasalpha || tkhasalpha(tk->env, TkCbackgnd));
327*37da2899SCharles.Forsyth 
328*37da2899SCharles.Forsyth 	tk->dirty = tkrect(tk, 1);
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth 	return e;
331*37da2899SCharles.Forsyth }
332*37da2899SCharles.Forsyth 
333*37da2899SCharles.Forsyth static char*
tkpaneldirty(Tk * tk,char * arg,char ** val)334*37da2899SCharles.Forsyth tkpaneldirty(Tk *tk, char *arg, char **val)
335*37da2899SCharles.Forsyth {
336*37da2899SCharles.Forsyth 	char buf[Tkmaxitem];
337*37da2899SCharles.Forsyth 	int n, coords[4];
338*37da2899SCharles.Forsyth 	Rectangle r;
339*37da2899SCharles.Forsyth 	char *e, *p;
340*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
341*37da2899SCharles.Forsyth 
342*37da2899SCharles.Forsyth 	USED(val);
343*37da2899SCharles.Forsyth 	n = 0;
344*37da2899SCharles.Forsyth 	while (n < 4) {
345*37da2899SCharles.Forsyth 		arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
346*37da2899SCharles.Forsyth 		if (buf[0] == 0)
347*37da2899SCharles.Forsyth 			break;
348*37da2899SCharles.Forsyth 		p = buf;
349*37da2899SCharles.Forsyth 		e = tkfrac(&p, &coords[n++], nil);
350*37da2899SCharles.Forsyth 		if (e != nil)
351*37da2899SCharles.Forsyth 			return TkBadvl;
352*37da2899SCharles.Forsyth 	}
353*37da2899SCharles.Forsyth 	if (n == 0)
354*37da2899SCharles.Forsyth 		r = tkp->r;
355*37da2899SCharles.Forsyth 	else {
356*37da2899SCharles.Forsyth 		 if (n != 4)
357*37da2899SCharles.Forsyth 			return TkBadvl;
358*37da2899SCharles.Forsyth 		r.min.x = TKF2I(coords[0]);
359*37da2899SCharles.Forsyth 		r.min.y = TKF2I(coords[1]);
360*37da2899SCharles.Forsyth 		r.max.x = TKF2I(coords[2]);
361*37da2899SCharles.Forsyth 		r.max.y = TKF2I(coords[3]);
362*37da2899SCharles.Forsyth 	}
363*37da2899SCharles.Forsyth 	if (rectclip(&r, tkp->r)) {
364*37da2899SCharles.Forsyth 		r = rectsubpt(r, tkpanelview(tk));		/* convert to widget coords */
365*37da2899SCharles.Forsyth 		if (rectclip(&r, tkrect(tk, 0)))			/* clip to visible area */
366*37da2899SCharles.Forsyth 			combinerect(&tk->dirty, r);
367*37da2899SCharles.Forsyth 	}
368*37da2899SCharles.Forsyth 	return nil;
369*37da2899SCharles.Forsyth }
370*37da2899SCharles.Forsyth 
371*37da2899SCharles.Forsyth static char*
tkpanelorigin(Tk * tk,char * arg,char ** val)372*37da2899SCharles.Forsyth tkpanelorigin(Tk *tk, char *arg, char **val)
373*37da2899SCharles.Forsyth {
374*37da2899SCharles.Forsyth 	char *e;
375*37da2899SCharles.Forsyth 	Point view;
376*37da2899SCharles.Forsyth 	TkPanel *tkp = TKobj(TkPanel, tk);
377*37da2899SCharles.Forsyth 
378*37da2899SCharles.Forsyth 	e = tkxyparse(tk, &arg, &view);
379*37da2899SCharles.Forsyth 	if (e != nil) {
380*37da2899SCharles.Forsyth 		if (e == TkOparg)
381*37da2899SCharles.Forsyth 			return tkvalue(val, "%d %d", tkp->view.x, tkp->view.y);
382*37da2899SCharles.Forsyth 		return e;
383*37da2899SCharles.Forsyth 	}
384*37da2899SCharles.Forsyth 	tkp->view = view;
385*37da2899SCharles.Forsyth 	tk->dirty = tkrect(tk, 0);
386*37da2899SCharles.Forsyth 	return nil;
387*37da2899SCharles.Forsyth }
388*37da2899SCharles.Forsyth 
389*37da2899SCharles.Forsyth static
390*37da2899SCharles.Forsyth TkCmdtab tkpanelcmd[] =
391*37da2899SCharles.Forsyth {
392*37da2899SCharles.Forsyth 	"cget",			tkpanelcget,
393*37da2899SCharles.Forsyth 	"configure",		tkpanelconf,
394*37da2899SCharles.Forsyth 	"dirty",			tkpaneldirty,
395*37da2899SCharles.Forsyth 	"origin",			tkpanelorigin,
396*37da2899SCharles.Forsyth 	"panelx",			tkpanelpanelx,
397*37da2899SCharles.Forsyth 	"panely",			tkpanelpanely,
398*37da2899SCharles.Forsyth 	"screenx",			tkpanelscreenx,
399*37da2899SCharles.Forsyth 	"screeny",			tkpanelscreeny,
400*37da2899SCharles.Forsyth 	nil
401*37da2899SCharles.Forsyth };
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth TkMethod panelmethod = {
404*37da2899SCharles.Forsyth 	"panel",
405*37da2899SCharles.Forsyth 	tkpanelcmd,
406*37da2899SCharles.Forsyth 	tkfreepanel,
407*37da2899SCharles.Forsyth 	tkdrawpanel
408*37da2899SCharles.Forsyth };
409