alloc.c 4.0 KB

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