getrect.c 3.0 KB

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