compound.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include <lib9.h>
  2. #include <draw.h>
  3. #include <interp.h>
  4. #include <isa.h>
  5. #include "../libinterp/runt.h"
  6. #include <drawif.h>
  7. #include <prefab.h>
  8. extern void queuerefresh(Image *i, Rectangle r, Reffn reffn, void *refptr);
  9. Draw_Rect
  10. edgerect(Prefab_Environ *e, Draw_Point p, Draw_Rect *rin)
  11. {
  12. Draw_Rect r;
  13. Screen *s;
  14. r.min.x = p.x;
  15. r.min.y = p.y;
  16. r.max.x = p.x + 1 + Dx(*rin) + 1;
  17. r.max.y = p.y + 1 + Dy(*rin) + 1;
  18. /* outer box computed; now make sure it's all visible */
  19. s = lookupscreen(e->screen);
  20. if(s != nil)
  21. fitrect((Rectangle*)&r, s->display->image->r);
  22. rin->min.x = r.min.x+1;
  23. rin->min.y = r.min.y+1;
  24. rin->max.x = r.max.x-1;
  25. rin->max.y = r.max.y-1;
  26. return r;
  27. }
  28. /*
  29. * Draw edge around r.
  30. * Assume geometry has already been clipped and adjusted.
  31. */
  32. void
  33. edge(Prefab_Environ *e, Image *box, Draw_Rect dr, Draw_Rect dclipr)
  34. {
  35. Rectangle r, r1, clipr;
  36. Image *ec;
  37. Screen *s;
  38. R2R(r, dr);
  39. R2R(clipr, dclipr);
  40. r.min.x -= 1;
  41. r.min.y -= 1;
  42. r.max.x += 1;
  43. r.max.y += 1;
  44. s = lookupscreen(e->screen);
  45. if(s == nil)
  46. return;
  47. ec = lookupimage(e->style->edgecolor);
  48. if(ec == nil)
  49. return;
  50. r1 = r;
  51. r1.min.y++;
  52. r1.max.y = r1.min.y+2;
  53. r1.max.x = r1.min.x+2*(r1.max.x-r1.min.x)/3;
  54. if(rectclip(&r1, clipr))
  55. draw(box, r1, ec, nil, r1.min);
  56. r1 = r;
  57. r1.min.x++;
  58. r1.max.x = r1.min.x+2;
  59. r1.max.y = r1.min.y+2*(r1.max.y-r1.min.y)/3;
  60. if(rectclip(&r1, clipr))
  61. draw(box, r1, ec, nil, r1.min);
  62. r1=r;
  63. r1.min.x = r1.max.x-1;
  64. if(rectclip(&r1, clipr))
  65. draw(box, r1, ec, nil, r1.min);
  66. r1=r;
  67. r1.min.y = r1.max.y-1;
  68. if(rectclip(&r1, clipr))
  69. draw(box, r1, ec, nil, r1.min);
  70. r1 = r;
  71. r1.max.y = r1.min.y+1;
  72. if(rectclip(&r1, clipr))
  73. draw(box, r1, ec, nil, r1.min);
  74. r1=r;
  75. r1.max.x = r1.min.x+1;
  76. if(rectclip(&r1, clipr))
  77. draw(box, r1, ec, nil, r1.min);
  78. }
  79. void
  80. redrawcompound(Image *i, Rectangle clipr, Prefab_Compound *c)
  81. {
  82. Rectangle r1, rt, r;
  83. int l, len;
  84. Prefab_Style *s;
  85. Image *elemcolor, *edgecolor;
  86. List *list;
  87. Font *font;
  88. Prefab_Element *e;
  89. if(c==H || badenviron(c->environ, 0))
  90. return;
  91. r = clipr;
  92. s = c->environ->style;
  93. elemcolor = lookupimage(s->elemcolor);
  94. edgecolor = lookupimage(s->edgecolor);
  95. if(elemcolor==nil || edgecolor==nil)
  96. return;
  97. draw(i, r, elemcolor, nil, r.min);
  98. if(lookupelement(c->title) != H){
  99. R2R(rt, c->title->r);
  100. if(c->title->environ!=H && c->title->environ->style!=H && rectXrect(r, rt)){
  101. drawelement(c->title, i, r, c->environ==c->title->environ, 0);
  102. r1.min.x = c->r.min.x;
  103. r1.min.y = c->title->r.max.y;
  104. s = c->title->environ->style;
  105. len = 0;
  106. switch(c->title->kind){
  107. case ETitle:
  108. font = lookupfont(s->titlefont);
  109. if(font != nil)
  110. len = 2+1+stringwidth(font, string2c(c->title->str));
  111. break;
  112. case EVertical:
  113. font = lookupfont(s->titlefont);
  114. if(font != nil)
  115. for(list=c->title->kids; list!=H; list=list->tail){
  116. e = *(Prefab_Element**)list->data;
  117. l = stringwidth(font, string2c(e->str));
  118. if(l > len)
  119. len = l;
  120. }
  121. len += 2+1;
  122. break;
  123. default:
  124. len = r1.min.x+2*Dx(c->r)/3;
  125. }
  126. r1.max.x = r1.min.x + len;
  127. r1.max.y = r1.min.y+1;
  128. draw(i, r1, edgecolor, nil, r.min);
  129. r.min.y = r1.max.y;
  130. }
  131. }
  132. if(c->contents!=H)
  133. drawelement(c->contents, i, r, c->environ==c->contents->environ, 0);
  134. edge(c->environ, i, c->r, DRECT(clipr));
  135. }
  136. void
  137. refreshcompound(Image *i, Rectangle r, void *ptr)
  138. {
  139. Prefab_Compound *c;
  140. c = ptr;
  141. if(c == nil)
  142. return;
  143. if(i == nil){ /* called from flushimage */
  144. i = lookupimage(c->image);
  145. if(i == nil)
  146. return;
  147. }
  148. redrawcompound(i, r, c);
  149. }
  150. void
  151. localrefreshcompound(Memimage *mi, Rectangle r, void *ptr)
  152. {
  153. Prefab_Compound *c;
  154. Image *i;
  155. USED(mi); /* can't do anything with this, but it's part of the memlayer interface */
  156. c = ptr;
  157. if(c == nil)
  158. return;
  159. i = lookupimage(c->image);
  160. if(i == nil)
  161. return;
  162. queuerefresh(i, r, refreshcompound, ptr);
  163. }
  164. void
  165. drawcompound(Prefab_Compound *c)
  166. {
  167. Image *i;
  168. if(c==H || c->image==H)
  169. return;
  170. i = lookupimage(c->image);
  171. redrawcompound(i, insetrect(IRECT(c->r), -1), c);
  172. if(i->display->local && i->refptr==nil)
  173. if(drawlsetrefresh(i->display->dataqid, i->id, localrefreshcompound, c) <= 0)
  174. fprint(2, "drawcompound: can't set refresh\n");
  175. i->refptr = c; /* can now be refreshed */
  176. }