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