elistelement.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. #include <kernel.h>
  9. List*
  10. prefabwrap(void *elem)
  11. {
  12. List *l;
  13. Heap *h, *e;
  14. e = D2H(elem);
  15. h = nheap(sizeof(List) + sizeof(WORD*));
  16. h->t = &Tlist;
  17. Tlist.ref++;
  18. l = H2D(List*, h);
  19. l->tail = H;
  20. l->t = &Tptr;
  21. Tptr.ref++;
  22. e->ref++;
  23. *(WORD**)l->data = elem;
  24. return l;
  25. }
  26. static
  27. PElement*
  28. elistelement1(Prefab_Environ *e, Prefab_Element *elem, Prefab_Element *new, enum Elementtype kind)
  29. {
  30. int first;
  31. PElement *pelem;
  32. List *atom;
  33. if(badenviron(e, 0))
  34. return H;
  35. gchalt++;
  36. first = 0;
  37. if(new == H)
  38. atom = H;
  39. else
  40. atom = prefabwrap(new);
  41. if(elem == H){
  42. pelem = mkelement(e, kind);
  43. elem = &pelem->e;
  44. pelem->first = H;
  45. pelem->nkids = 0;
  46. }else
  47. pelem = (PElement*)elem;
  48. if(atom == H)
  49. goto Return;
  50. if(elem->kids != pelem->first)
  51. error("list Element has been modified externally");
  52. if(elem->kids == H){
  53. elem->kids = atom;
  54. pelem->first = atom;
  55. pelem->last = atom;
  56. pelem->vfirst = atom;
  57. pelem->vlast = atom;
  58. first = 1;
  59. }
  60. if(new->kind!=ESeparator && Dx(elem->r)==0){
  61. elem->r = new->r;
  62. pelem->drawpt.x = elem->r.min.x;
  63. pelem->drawpt.y = elem->r.min.y;
  64. }
  65. pelem->nkids++;
  66. if(first)
  67. goto Return;
  68. pelem->last->tail = atom;
  69. pelem->last = atom;
  70. pelem->vlast = atom;
  71. if(new->kind != ESeparator){
  72. if(kind == EVertical){
  73. elem->r.max.y += Dy(new->r);
  74. if(elem->r.min.x > new->r.min.x)
  75. elem->r.min.x = new->r.min.x;
  76. if(elem->r.max.x < new->r.max.x)
  77. elem->r.max.x = new->r.max.x;
  78. }else{
  79. elem->r.max.x += Dx(new->r);
  80. if(elem->r.min.y > new->r.min.y)
  81. elem->r.min.y = new->r.min.y;
  82. if(elem->r.max.y < new->r.max.y)
  83. elem->r.max.y = new->r.max.y;
  84. }
  85. }
  86. pelem->pkind = kind;
  87. Return:
  88. gchalt--;
  89. return pelem;
  90. }
  91. PElement*
  92. elistelement(Prefab_Environ *e, Prefab_Element *new, enum Elementtype kind)
  93. {
  94. return elistelement1(e, H, new, kind);
  95. }
  96. PElement*
  97. appendelist(Prefab_Element *elem, Prefab_Element *new)
  98. {
  99. if(elem->kind!=EVertical && elem->kind!=EHorizontal){
  100. kwerrstr("appendelist to non-list");
  101. return H;
  102. }
  103. return elistelement1(elem->environ, elem, new, elem->kind);
  104. }