alloc.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. Image*
  5. allocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val)
  6. {
  7. Image* i;
  8. i = _allocimage(nil, d, r, chan, repl, val, 0, 0);
  9. if (i)
  10. setmalloctag(i, getcallerpc(&d));
  11. return i;
  12. }
  13. Image*
  14. _allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong val, int screenid, int refresh)
  15. {
  16. uchar *a;
  17. char *err;
  18. Image *i;
  19. Rectangle clipr;
  20. int id;
  21. int depth;
  22. err = 0;
  23. i = 0;
  24. if(chan == 0){
  25. werrstr("bad channel descriptor");
  26. return nil;
  27. }
  28. depth = chantodepth(chan);
  29. if(depth == 0){
  30. err = "bad channel descriptor";
  31. Error:
  32. if(err)
  33. werrstr("allocimage: %s", err);
  34. else
  35. werrstr("allocimage: %r");
  36. free(i);
  37. return 0;
  38. }
  39. /* flush pending data so we don't get error allocating the image */
  40. flushimage(d, 0);
  41. a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);
  42. if(a == 0)
  43. goto Error;
  44. d->imageid++;
  45. id = d->imageid;
  46. a[0] = 'b';
  47. BPLONG(a+1, id);
  48. BPLONG(a+5, screenid);
  49. a[9] = refresh;
  50. BPLONG(a+10, chan);
  51. a[14] = repl;
  52. BPLONG(a+15, r.min.x);
  53. BPLONG(a+19, r.min.y);
  54. BPLONG(a+23, r.max.x);
  55. BPLONG(a+27, r.max.y);
  56. if(repl)
  57. /* huge but not infinite, so various offsets will leave it huge, not overflow */
  58. clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);
  59. else
  60. clipr = r;
  61. BPLONG(a+31, clipr.min.x);
  62. BPLONG(a+35, clipr.min.y);
  63. BPLONG(a+39, clipr.max.x);
  64. BPLONG(a+43, clipr.max.y);
  65. BPLONG(a+47, val);
  66. if(flushimage(d, 0) < 0)
  67. goto Error;
  68. if(ai)
  69. i = ai;
  70. else{
  71. i = malloc(sizeof(Image));
  72. if(i == nil){
  73. a = bufimage(d, 1+4);
  74. if(a){
  75. a[0] = 'f';
  76. BPLONG(a+1, id);
  77. flushimage(d, 0);
  78. }
  79. goto Error;
  80. }
  81. }
  82. i->display = d;
  83. i->id = id;
  84. i->depth = depth;
  85. i->chan = chan;
  86. i->r = r;
  87. i->clipr = clipr;
  88. i->repl = repl;
  89. i->screen = 0;
  90. i->next = 0;
  91. return i;
  92. }
  93. Image*
  94. namedimage(Display *d, char *name)
  95. {
  96. uchar *a;
  97. char *err, buf[12*12+1];
  98. Image *i;
  99. int id, n;
  100. ulong chan;
  101. err = 0;
  102. i = 0;
  103. n = strlen(name);
  104. if(n >= 256){
  105. err = "name too long";
  106. Error:
  107. if(err)
  108. werrstr("namedimage: %s", err);
  109. else
  110. werrstr("namedimage: %r");
  111. if(i)
  112. free(i);
  113. return 0;
  114. }
  115. /* flush pending data so we don't get error allocating the image */
  116. flushimage(d, 0);
  117. a = bufimage(d, 1+4+1+n);
  118. if(a == 0)
  119. goto Error;
  120. d->imageid++;
  121. id = d->imageid;
  122. a[0] = 'n';
  123. BPLONG(a+1, id);
  124. a[5] = n;
  125. memmove(a+6, name, n);
  126. if(flushimage(d, 0) < 0)
  127. goto Error;
  128. if(pread(d->ctlfd, buf, sizeof buf, 0) < 12*12)
  129. goto Error;
  130. buf[12*12] = '\0';
  131. i = malloc(sizeof(Image));
  132. if(i == nil){
  133. Error1:
  134. a = bufimage(d, 1+4);
  135. if(a){
  136. a[0] = 'f';
  137. BPLONG(a+1, id);
  138. flushimage(d, 0);
  139. }
  140. goto Error;
  141. }
  142. i->display = d;
  143. i->id = id;
  144. if((chan=strtochan(buf+2*12))==0){
  145. werrstr("bad channel '%.12s' from devdraw", buf+2*12);
  146. goto Error1;
  147. }
  148. i->chan = chan;
  149. i->depth = chantodepth(chan);
  150. i->repl = atoi(buf+3*12);
  151. i->r.min.x = atoi(buf+4*12);
  152. i->r.min.y = atoi(buf+5*12);
  153. i->r.max.x = atoi(buf+6*12);
  154. i->r.max.y = atoi(buf+7*12);
  155. i->clipr.min.x = atoi(buf+8*12);
  156. i->clipr.min.y = atoi(buf+9*12);
  157. i->clipr.max.x = atoi(buf+10*12);
  158. i->clipr.max.y = atoi(buf+11*12);
  159. i->screen = 0;
  160. i->next = 0;
  161. return i;
  162. }
  163. int
  164. nameimage(Image *i, char *name, int in)
  165. {
  166. uchar *a;
  167. int n;
  168. n = strlen(name);
  169. a = bufimage(i->display, 1+4+1+1+n);
  170. if(a == 0)
  171. return 0;
  172. a[0] = 'N';
  173. BPLONG(a+1, i->id);
  174. a[5] = in;
  175. a[6] = n;
  176. memmove(a+7, name, n);
  177. if(flushimage(i->display, 0) < 0)
  178. return 0;
  179. return 1;
  180. }
  181. int
  182. _freeimage1(Image *i)
  183. {
  184. uchar *a;
  185. Display *d;
  186. Image *w;
  187. if(i == 0 || i->display == 0)
  188. return 0;
  189. /* make sure no refresh events occur on this if we block in the write */
  190. d = i->display;
  191. /* flush pending data so we don't get error deleting the image */
  192. flushimage(d, 0);
  193. a = bufimage(d, 1+4);
  194. if(a == 0)
  195. return -1;
  196. a[0] = 'f';
  197. BPLONG(a+1, i->id);
  198. if(i->screen){
  199. w = d->windows;
  200. if(w == i)
  201. d->windows = i->next;
  202. else
  203. while(w){
  204. if(w->next == i){
  205. w->next = i->next;
  206. break;
  207. }
  208. w = w->next;
  209. }
  210. }
  211. if(flushimage(d, i->screen!=0) < 0)
  212. return -1;
  213. return 0;
  214. }
  215. int
  216. freeimage(Image *i)
  217. {
  218. int ret;
  219. ret = _freeimage1(i);
  220. free(i);
  221. return ret;
  222. }