getrect.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <thread.h>
  13. #include <cursor.h>
  14. #include <mouse.h>
  15. #define W Borderwidth
  16. static Image *tmp[4];
  17. static Image *red;
  18. static Cursor sweep={
  19. {-7, -7},
  20. {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,
  21. 0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7,
  22. 0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F,
  23. 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,},
  24. {0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02,
  25. 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2,
  26. 0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38,
  27. 0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,}
  28. };
  29. static
  30. void
  31. brects(Rectangle r, Rectangle rp[4])
  32. {
  33. if(Dx(r) < 2*W)
  34. r.max.x = r.min.x+2*W;
  35. if(Dy(r) < 2*W)
  36. r.max.y = r.min.y+2*W;
  37. rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W);
  38. rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y);
  39. rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W);
  40. rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W);
  41. }
  42. Rectangle
  43. getrect(int but, Mousectl *mc)
  44. {
  45. Rectangle r, rc;
  46. but = 1<<(but-1);
  47. setcursor(mc, &sweep);
  48. while(mc->buttons)
  49. readmouse(mc);
  50. while(!(mc->buttons & but)){
  51. readmouse(mc);
  52. if(mc->buttons & (7^but))
  53. goto Return;
  54. }
  55. r.min = mc->xy;
  56. r.max = mc->xy;
  57. do{
  58. rc = canonrect(r);
  59. drawgetrect(rc, 1);
  60. readmouse(mc);
  61. drawgetrect(rc, 0);
  62. r.max = mc->xy;
  63. }while(mc->buttons == but);
  64. Return:
  65. setcursor(mc, nil);
  66. if(mc->buttons & (7^but)){
  67. rc.min.x = rc.max.x = 0;
  68. rc.min.y = rc.max.y = 0;
  69. while(mc->buttons)
  70. readmouse(mc);
  71. }
  72. return rc;
  73. }
  74. static
  75. void
  76. freetmp(void)
  77. {
  78. freeimage(tmp[0]);
  79. freeimage(tmp[1]);
  80. freeimage(tmp[2]);
  81. freeimage(tmp[3]);
  82. freeimage(red);
  83. tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil;
  84. }
  85. static
  86. int
  87. max(int a, int b)
  88. {
  89. if(a > b)
  90. return a;
  91. return b;
  92. }
  93. void
  94. drawgetrect(Rectangle rc, int up)
  95. {
  96. int i;
  97. Rectangle r, rects[4];
  98. /*
  99. * BUG: if for some reason we have two of these going on at once
  100. * when we must grow the tmp buffers, we lose data. Also if tmp
  101. * is unallocated and we ask to restore the screen, it would be nice
  102. * to complain, but we silently make a mess.
  103. */
  104. if(up && tmp[0]!=nil)
  105. if(Dx(tmp[0]->r)<Dx(rc) || Dy(tmp[2]->r)<Dy(rc))
  106. freetmp();
  107. if(tmp[0] == 0){
  108. r = Rect(0, 0, max(Dx(display->screenimage->r), Dx(rc)), W);
  109. tmp[0] = allocimage(display, r, screen->chan, 0, -1);
  110. tmp[1] = allocimage(display, r, screen->chan, 0, -1);
  111. r = Rect(0, 0, W, max(Dy(display->screenimage->r), Dy(rc)));
  112. tmp[2] = allocimage(display, r, screen->chan, 0, -1);
  113. tmp[3] = allocimage(display, r, screen->chan, 0, -1);
  114. red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
  115. if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0){
  116. freetmp();
  117. drawerror(display, "getrect: allocimage failed");
  118. }
  119. }
  120. brects(rc, rects);
  121. if(!up){
  122. for(i=0; i<4; i++)
  123. draw(screen, rects[i], tmp[i], nil, ZP);
  124. return;
  125. }
  126. for(i=0; i<4; i++){
  127. draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min);
  128. draw(screen, rects[i], red, nil, ZP);
  129. }
  130. }