Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

522 lines
14 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: rect.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains the various rectangle manipulation APIs.
  7. *
  8. * History:
  9. * 10-20-90 DarrinM Grabbed 'C' rect routines from Portable PM.
  10. \***************************************************************************/
  11. #ifdef _USERK_
  12. #define VALIDATERECT(prc, retval) UserAssert(prc)
  13. #else
  14. #define VALIDATERECT(prc, retval) if (prc == NULL) return retval
  15. #endif
  16. /***********************************************************************\
  17. * SetRect (API)
  18. *
  19. * This function fills a rectangle structure with the passed in coordinates.
  20. *
  21. * History:
  22. * 10-20-90 DarrinM Translated from PMese to Windowses.
  23. \***********************************************************************/
  24. BOOL APIENTRY SetRect(
  25. LPRECT prc,
  26. int left,
  27. int top,
  28. int right,
  29. int bottom)
  30. {
  31. VALIDATERECT(prc, FALSE);
  32. prc->left = left;
  33. prc->top = top;
  34. prc->right = right;
  35. prc->bottom = bottom;
  36. return TRUE;
  37. }
  38. /************************************************************************\
  39. * CopyInflateRect (API)
  40. *
  41. * This function copies the rect from prcSrc to prcDst, and inflates it.
  42. *
  43. * History:
  44. * 12-16-93 FritzS
  45. \************************************************************************/
  46. BOOL APIENTRY CopyInflateRect(
  47. LPRECT prcDst,
  48. CONST RECT *prcSrc,
  49. int cx, int cy)
  50. {
  51. prcDst->left = prcSrc->left - cx;
  52. prcDst->right = prcSrc->right + cx;
  53. prcDst->top = prcSrc->top - cy;
  54. prcDst->bottom = prcSrc->bottom + cy;
  55. return TRUE;
  56. }
  57. /************************************************************************\
  58. * CopyOffsetRect (API)
  59. *
  60. * This function copies the rect from prcSrc to prcDst, and offsets it.
  61. *
  62. * History:
  63. * 01-03-94 FritzS
  64. \************************************************************************/
  65. BOOL APIENTRY CopyOffsetRect(
  66. LPRECT prcDst,
  67. CONST RECT *prcSrc,
  68. int cx, int cy)
  69. {
  70. prcDst->left = prcSrc->left + cx;
  71. prcDst->right = prcSrc->right + cx;
  72. prcDst->top = prcSrc->top + cy;
  73. prcDst->bottom = prcSrc->bottom + cy;
  74. return TRUE;
  75. }
  76. /************************************************************************\
  77. * IsRectEmpty (API)
  78. *
  79. * This function returns TRUE if *prc is an empty rect, FALSE
  80. * otherwise. An empty rect is one that has no area: right is
  81. * less than or equal to left, bottom is less than or equal to top.
  82. *
  83. * Warning:
  84. * This function assumes that the rect is in device coordinates
  85. * mode where left and top coordinate are smaller than right and
  86. * bottom.
  87. *
  88. * History:
  89. * 10-20-90 DarrinM Translated from PMese to Windowses.
  90. \************************************************************************/
  91. BOOL APIENTRY IsRectEmpty(
  92. CONST RECT *prc)
  93. {
  94. VALIDATERECT(prc, TRUE);
  95. return ((prc->left >= prc->right) || (prc->top >= prc->bottom));
  96. }
  97. /***********************************************************************\
  98. * PtInRect (API)
  99. *
  100. * This function returns TRUE if *ppt falls inside of *prc.
  101. *
  102. * History:
  103. * 10-20-90 DarrinM Translated from PMese to Windowses.
  104. \************************************************************************/
  105. BOOL APIENTRY PtInRect(
  106. CONST RECT *prc,
  107. POINT pt)
  108. {
  109. VALIDATERECT(prc, FALSE);
  110. return ((pt.x >= prc->left) && (pt.x < prc->right) &&
  111. (pt.y >= prc->top) && (pt.y < prc->bottom));
  112. }
  113. /************************************************************************\
  114. * OffsetRect (API)
  115. *
  116. * This function offsets the coordinates of *prc by adding cx to
  117. * both the left and right coordinates, and cy to both the top and
  118. * bottom coordinates.
  119. *
  120. * History:
  121. * 10-20-90 DarrinM Translated from PMese to Windowses.
  122. \************************************************************************/
  123. BOOL APIENTRY OffsetRect(
  124. LPRECT prc,
  125. int cx,
  126. int cy)
  127. {
  128. VALIDATERECT(prc, FALSE);
  129. prc->left += cx;
  130. prc->right += cx;
  131. prc->bottom += cy;
  132. prc->top += cy;
  133. return TRUE;
  134. }
  135. /************************************************************************\
  136. * InflateRect (API)
  137. *
  138. * This function expands the given rect by cx horizantally and cy
  139. * vertically on all sides. If cx or cy are negative, the rect
  140. * is inset. cx is subtracted from the left and added to the right,
  141. * and cy is subtracted from the top and added to the bottom.
  142. *
  143. * History:
  144. * 10-20-90 DarrinM Translated from PMese to Windowses.
  145. \************************************************************************/
  146. BOOL APIENTRY InflateRect(
  147. LPRECT prc,
  148. int cx,
  149. int cy)
  150. {
  151. VALIDATERECT(prc, FALSE);
  152. prc->left -= cx;
  153. prc->right += cx;
  154. prc->top -= cy;
  155. prc->bottom += cy;
  156. return TRUE;
  157. }
  158. /************************************************************************\
  159. * IntersectRect (API)
  160. *
  161. * Calculates the intersection between *prcSrc1 and *prcSrc2,
  162. * returning the resulting rect in *prcDst. Returns TRUE if
  163. * *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no
  164. * intersection, an empty rect is returned in *prcDst
  165. *
  166. * History:
  167. * 10-20-90 DarrinM Translated from PMese to Windowses.
  168. \************************************************************************/
  169. BOOL APIENTRY IntersectRect(
  170. LPRECT prcDst,
  171. CONST RECT *prcSrc1,
  172. CONST RECT *prcSrc2)
  173. {
  174. VALIDATERECT(prcDst, FALSE);
  175. VALIDATERECT(prcSrc1, FALSE);
  176. VALIDATERECT(prcSrc2, FALSE);
  177. prcDst->left = max(prcSrc1->left, prcSrc2->left);
  178. prcDst->right = min(prcSrc1->right, prcSrc2->right);
  179. /*
  180. * check for empty rect
  181. */
  182. if (prcDst->left < prcDst->right) {
  183. prcDst->top = max(prcSrc1->top, prcSrc2->top);
  184. prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
  185. /*
  186. * check for empty rect
  187. */
  188. if (prcDst->top < prcDst->bottom) {
  189. return TRUE; // not empty
  190. }
  191. }
  192. /*
  193. * empty rect
  194. */
  195. SetRectEmpty(prcDst);
  196. return FALSE;
  197. }
  198. /********************************************************************\
  199. * UnionRect (API)
  200. *
  201. * This function calculates a rect that bounds *prcSrc1 and
  202. * *prcSrc2, returning the result in *prcDst. If either
  203. * *prcSrc1 or *prcSrc2 are empty, then the other rect is
  204. * returned. Returns TRUE if *prcDst is a non-empty rect,
  205. * FALSE otherwise.
  206. *
  207. * History:
  208. * 10-20-90 DarrinM Translated from PMese to Windowses.
  209. \*******************************************************************/
  210. BOOL APIENTRY UnionRect(
  211. LPRECT prcDst,
  212. CONST RECT *prcSrc1,
  213. CONST RECT *prcSrc2)
  214. {
  215. BOOL frc1Empty, frc2Empty;
  216. VALIDATERECT(prcDst, FALSE);
  217. VALIDATERECT(prcSrc1, FALSE);
  218. VALIDATERECT(prcSrc2, FALSE);
  219. frc1Empty = ((prcSrc1->left >= prcSrc1->right) ||
  220. (prcSrc1->top >= prcSrc1->bottom));
  221. frc2Empty = ((prcSrc2->left >= prcSrc2->right) ||
  222. (prcSrc2->top >= prcSrc2->bottom));
  223. if (frc1Empty && frc2Empty) {
  224. SetRectEmpty(prcDst);
  225. return FALSE;
  226. }
  227. if (frc1Empty) {
  228. *prcDst = *prcSrc2;
  229. return TRUE;
  230. }
  231. if (frc2Empty) {
  232. *prcDst = *prcSrc1;
  233. return TRUE;
  234. }
  235. /*
  236. * form the union of the two non-empty rects
  237. */
  238. prcDst->left = min(prcSrc1->left, prcSrc2->left);
  239. prcDst->top = min(prcSrc1->top, prcSrc2->top);
  240. prcDst->right = max(prcSrc1->right, prcSrc2->right);
  241. prcDst->bottom = max(prcSrc1->bottom, prcSrc2->bottom);
  242. return TRUE;
  243. }
  244. /********************************************************************\
  245. * EqualRect (API)
  246. *
  247. * This function returns TRUE if *prc1 and *prc2 are identical,
  248. * FALSE otherwise.
  249. *
  250. * History:
  251. * 10-20-90 DarrinM Translated from PMese to Windowses.
  252. \*****************************************************************/
  253. #undef EqualRect // don't let macro interfere with API
  254. BOOL APIENTRY EqualRect(
  255. CONST RECT *prc1,
  256. CONST RECT *prc2)
  257. {
  258. VALIDATERECT(prc1, FALSE);
  259. VALIDATERECT(prc2, FALSE);
  260. /*
  261. * Test equality only. This is what win31 does. win31 does not check to
  262. * see if the rectangles are "empty" first.
  263. */
  264. return RtlEqualMemory(prc1, prc2, sizeof(RECT));
  265. }
  266. /**********************************************************************\
  267. * SubtractRect (API)
  268. *
  269. * This function subtracts *prc2 from *prc1, returning the result in *prcDst
  270. * Returns FALSE if *lprDst is empty, TRUE otherwise.
  271. *
  272. * Warning:
  273. * Subtracting one rect from another may not always result in a
  274. * rectangular area; in this case SubtractRect will return *prc1 in
  275. * *prcDst. For this reason, SubractRect provides only an
  276. * approximation of subtraction. However, the area described by
  277. * *prcDst will always be greater than or equal to the "true" result
  278. * of the subtraction.
  279. *
  280. * History:
  281. * 10-20-90 DarrinM Translated from PMese to Windowsese.
  282. \**********************************************************************/
  283. BOOL APIENTRY SubtractRect(
  284. LPRECT prcDst,
  285. CONST RECT *prcSrc1,
  286. CONST RECT *prcSrc2)
  287. {
  288. int cSidesOut;
  289. BOOL fIntersect;
  290. RECT rcInt;
  291. VALIDATERECT(prcDst, FALSE);
  292. VALIDATERECT(prcSrc1, FALSE);
  293. VALIDATERECT(prcSrc2, FALSE);
  294. fIntersect = IntersectRect(&rcInt, prcSrc1, prcSrc2);
  295. /*
  296. * this is done after the intersection in case prcDst is the same
  297. * pointer as prcSrc2
  298. */
  299. *prcDst = *prcSrc1;
  300. if (fIntersect) {
  301. /*
  302. * exactly any 3 sides of prc2 must be outside prc1 to subtract
  303. */
  304. cSidesOut = 0;
  305. if (rcInt.left <= prcSrc1->left)
  306. cSidesOut++;
  307. if (rcInt.top <= prcSrc1->top)
  308. cSidesOut++;
  309. if (rcInt.right >= prcSrc1->right)
  310. cSidesOut++;
  311. if (rcInt.bottom >= prcSrc1->bottom)
  312. cSidesOut++;
  313. if (cSidesOut == 4) {
  314. /*
  315. * result is the empty rect
  316. */
  317. SetRectEmpty(prcDst);
  318. return FALSE;
  319. }
  320. if (cSidesOut == 3) {
  321. /*
  322. * subtract the intersecting rect
  323. */
  324. if (rcInt.left > prcSrc1->left)
  325. prcDst->right = rcInt.left;
  326. else if (rcInt.right < prcSrc1->right)
  327. prcDst->left = rcInt.right;
  328. else if (rcInt.top > prcSrc1->top)
  329. prcDst->bottom = rcInt.top;
  330. else if (rcInt.bottom < prcSrc1->bottom)
  331. prcDst->top = rcInt.bottom;
  332. }
  333. }
  334. if ((prcDst->left >= prcDst->right) || (prcDst->top >= prcDst->bottom))
  335. return FALSE;
  336. return TRUE;
  337. }
  338. /************************************************************************\
  339. * CopyRect (API)
  340. *
  341. * This function copies the rect from prcSrc to prcDst.
  342. *
  343. * History:
  344. * 10-20-90 DarrinM Translated from PMese to Windowses.
  345. \************************************************************************/
  346. #undef CopyRect // don't let macro interfere with API
  347. BOOL APIENTRY CopyRect(
  348. LPRECT prcDst,
  349. CONST RECT *prcSrc)
  350. {
  351. VALIDATERECT(prcDst, FALSE);
  352. VALIDATERECT(prcSrc, FALSE);
  353. *prcDst = *prcSrc;
  354. return TRUE;
  355. }
  356. /************************************************************************\
  357. * SetRectEmpty (API)
  358. *
  359. * This fuction sets *prc to an empty rect by setting each field to 0.
  360. * Equivalent to SetRect(prc, 0, 0, 0, 0).
  361. *
  362. * History:
  363. * 10-20-90 DarrinM Translated from PMese to Windowses.
  364. \************************************************************************/
  365. #undef SetRectEmpty // don't let macro interfere with API
  366. BOOL APIENTRY SetRectEmpty(
  367. LPRECT prc)
  368. {
  369. VALIDATERECT(prc, FALSE);
  370. RtlZeroMemory(prc, sizeof(RECT));
  371. return TRUE;
  372. }
  373. /***************************************************************************\
  374. * RECTFromSIZERECT
  375. *
  376. * This function converts a SIZERECT to a RECT.
  377. *
  378. * History:
  379. * 24-Sep-1996 adams Created.
  380. \***************************************************************************/
  381. void
  382. RECTFromSIZERECT(PRECT prc, PCSIZERECT psrc)
  383. {
  384. prc->left = psrc->x;
  385. prc->top = psrc->y;
  386. prc->right = psrc->x + psrc->cx;
  387. if (!(((prc->right < 0) == (psrc->x < 0))
  388. || ((prc->right < 0) == (psrc->cx < 0)))) {
  389. prc->right = prc->right < 0 ? INT_MAX : INT_MIN;
  390. }
  391. prc->bottom = psrc->y + psrc->cy;
  392. if (!(((prc->bottom < 0) == (psrc->y < 0))
  393. || ((prc->bottom < 0) == (psrc->cy < 0)))) {
  394. prc->bottom = prc->bottom < 0 ? INT_MAX : INT_MIN;
  395. }
  396. }
  397. /***************************************************************************\
  398. * SIZERECTFromRECT
  399. *
  400. * Converts a RECT to a SIZERECT.
  401. *
  402. * History:
  403. * 09-May-1997 adams Created.
  404. \***************************************************************************/
  405. void
  406. SIZERECTFromRECT(PSIZERECT psrc, LPCRECT prc)
  407. {
  408. psrc->x = prc->left;
  409. psrc->y = prc->top;
  410. psrc->cx = prc->right - prc->left;
  411. psrc->cy = prc->bottom - prc->top;
  412. }
  413. /***************************************************************************\
  414. * MirrorClientRect
  415. *
  416. * Mirror a rectangle using the client coordinates.
  417. *
  418. *
  419. * History:
  420. \***************************************************************************/
  421. void MirrorClientRect(PWND pwnd, LPRECT lprc)
  422. {
  423. int left, cx;
  424. cx = pwnd->rcClient.right - pwnd->rcClient.left;
  425. left = lprc->left;
  426. lprc->left = cx - lprc->right;
  427. lprc->right = cx - left;
  428. }
  429. /***************************************************************************\
  430. * MirrorWindowRect
  431. *
  432. * Mirror a rectangle using the window coordinates.
  433. *
  434. *
  435. * History:
  436. * 06-Jun-2000 JStall Created
  437. \***************************************************************************/
  438. void MirrorWindowRect(PWND pwnd, LPRECT lprc)
  439. {
  440. int left, cx;
  441. cx = pwnd->rcWindow.right - pwnd->rcWindow.left;
  442. left = lprc->left;
  443. lprc->left = cx - lprc->right;
  444. lprc->right = cx - left;
  445. }