1 #include <lib9.h> 2 #include <kernel.h> 3 #include "draw.h" 4 #include "tk.h" 5 #include "frame.h" 6 7 char* 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 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* 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* 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* 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* 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* 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* 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 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