frame.c 4.9 KB

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