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.

1503 lines
37 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: region.c
  3. *
  4. * Client region support
  5. *
  6. * Created: 15-Jun-1995
  7. * Author: Mark Enstrom [marke]
  8. *
  9. * Copyright (c) 1995-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. void OrderRects(LPRECT lpR, int nRects)
  13. {
  14. RECT R;
  15. int i,j;
  16. //Sort Left to right
  17. for (i=0; i<nRects; i++){
  18. for (j=i+1; (j<nRects) && ((lpR+j)->top == (lpR+i)->top); j++){
  19. if (((lpR+j)->left < (lpR+i)->left)) {
  20. R = *(lpR+i);
  21. *(lpR+i) = *(lpR+j);
  22. *(lpR+j) = R;
  23. }
  24. }
  25. }
  26. }
  27. /******************************Public*Routine******************************\
  28. * MirrorRgnByWidth
  29. * Mirror a region (hrgn) according a specific width (cx)
  30. * hrgn : region to get mirrored.
  31. * cx : width used to mirror the region.
  32. * phrgn : If it is not NULL the hrgn will not be touched and the new mirrored
  33. region will be returned in phrgn
  34. * But if it is NULL the mirrored region will be copied to hrgn.
  35. *
  36. * WORRNING:
  37. * if phrng is not NULL it is the caller responsibility to free *phrgn latter.
  38. *
  39. * returns:
  40. * TRUE : if the region get mirrored
  41. * FALSE : otherwise.
  42. * See the comment about phrng.
  43. *
  44. \**************************************************************************/
  45. BOOL MirrorRgnByWidth(HRGN hrgn, int cx, HRGN *phrgn)
  46. {
  47. int nRects, i, nDataSize;
  48. HRGN hrgn2 = NULL;
  49. RECT *lpR;
  50. int Saveleft;
  51. RGNDATA *lpRgnData;
  52. BOOL bRet = FALSE;
  53. nDataSize = GetRegionData(hrgn, 0, NULL);
  54. if (nDataSize && (lpRgnData = (RGNDATA *)LocalAlloc(0, nDataSize * sizeof(DWORD)))) {
  55. if (GetRegionData(hrgn, nDataSize, lpRgnData)) {
  56. nRects = lpRgnData->rdh.nCount;
  57. lpR = (RECT *)lpRgnData->Buffer;
  58. Saveleft = lpRgnData->rdh.rcBound.left;
  59. lpRgnData->rdh.rcBound.left = cx - lpRgnData->rdh.rcBound.right;
  60. lpRgnData->rdh.rcBound.right = cx - Saveleft;
  61. for (i=0; i<nRects; i++){
  62. Saveleft = lpR->left;
  63. lpR->left = cx - lpR->right;
  64. lpR->right = cx - Saveleft;
  65. lpR++;
  66. }
  67. OrderRects((RECT *)lpRgnData->Buffer, nRects);
  68. hrgn2 = ExtCreateRegion(NULL, nDataSize, lpRgnData);
  69. if (hrgn2) {
  70. if (phrgn == NULL) {
  71. CombineRgn(hrgn, hrgn2, NULL, RGN_COPY);
  72. DeleteObject((HGDIOBJ)hrgn2);
  73. } else {
  74. *phrgn = hrgn2;
  75. }
  76. bRet = TRUE;
  77. }
  78. }
  79. //Free mem.
  80. LocalFree(lpRgnData);
  81. }
  82. return bRet;
  83. }
  84. BOOL
  85. WINAPI
  86. MirrorRgn(HWND hwnd, HRGN hrgn)
  87. {
  88. RECT rc;
  89. GetWindowRect(hwnd, &rc);
  90. rc.right -= rc.left;
  91. return MirrorRgnByWidth(hrgn, rc.right, NULL);
  92. }
  93. BOOL
  94. MirrorRgnDC(HDC hdc, HRGN hrgn, HRGN *phrgn)
  95. {
  96. FIXUP_HANDLE(hdc);
  97. if(!IS_ALTDC_TYPE(hdc))
  98. {
  99. PDC_ATTR pdcattr;
  100. PSHARED_GET_VALIDATE((PVOID)pdcattr,hdc,DC_TYPE);
  101. if (pdcattr) {
  102. return MirrorRgnByWidth(hrgn, NtGdiGetDeviceWidth(hdc), phrgn);
  103. }
  104. }
  105. return FALSE;
  106. }
  107. /******************************Public*Routine******************************\
  108. * iRectRelation
  109. *
  110. * returns:
  111. * CONTAINS where prcl1 contains prcl2
  112. * CONTAINED where prcl1 contained by prcl2
  113. * 0 - otherwise
  114. *
  115. * History:
  116. * 19-Nov-1993 -by- Eric Kutter [erick]
  117. * Wrote it.
  118. \**************************************************************************/
  119. int
  120. iRectRelation(
  121. PRECTL prcl1,
  122. PRECTL prcl2
  123. )
  124. {
  125. int iRet = 0;
  126. if ((prcl1->left <= prcl2->left) &&
  127. (prcl1->right >= prcl2->right) &&
  128. (prcl1->top <= prcl2->top) &&
  129. (prcl1->bottom >= prcl2->bottom))
  130. {
  131. iRet = CONTAINS;
  132. }
  133. else if (
  134. (prcl2->left <= prcl1->left) &&
  135. (prcl2->right >= prcl1->right) &&
  136. (prcl2->top <= prcl1->top) &&
  137. (prcl2->bottom >= prcl1->bottom))
  138. {
  139. iRet = CONTAINED;
  140. }
  141. else if (
  142. (prcl1->left >= prcl2->right) ||
  143. (prcl1->right <= prcl2->left) ||
  144. (prcl1->top >= prcl2->bottom) ||
  145. (prcl1->bottom <= prcl2->top))
  146. {
  147. iRet = DISJOINT;
  148. }
  149. return(iRet);
  150. }
  151. /******************************Public*Routine******************************\
  152. *
  153. * CreateRectRgn gets an hrgn with user-mode PRGNATTR pointer and
  154. * sets the type to SIMPLEREGION.
  155. *
  156. * Arguments:
  157. *
  158. * x1
  159. * y1
  160. * x2
  161. * y2
  162. *
  163. * Return Value:
  164. *
  165. * HRGN or NULL
  166. *
  167. * History:
  168. *
  169. * 15-Jun-1995 -by- Mark Enstrom [marke]
  170. *
  171. \**************************************************************************/
  172. #define MIN_REGION_COORD ((LONG) 0xF8000000)
  173. #define MAX_REGION_COORD ((LONG) 0x07FFFFFF)
  174. HRGN
  175. WINAPI
  176. CreateRectRgn(
  177. int x1,
  178. int y1,
  179. int x2,
  180. int y2
  181. )
  182. {
  183. //
  184. // get a region handle, allocate memory for the
  185. // region and associate handle with memory
  186. //
  187. PRGNATTR prRegion;
  188. HRGN hrgn;
  189. //
  190. // rectangle must be ordered
  191. //
  192. #if NOREORDER_RGN
  193. if ((x1 > x2) || (y1 > y2))
  194. {
  195. WARNING("CreateRectRgn called with badly ordered region");
  196. x1 = 0;
  197. x2 = 0;
  198. y1 = 0;
  199. y2 = 0;
  200. }
  201. #else
  202. if (x1 > x2)
  203. {
  204. int t = x1;
  205. x1 = x2;
  206. x2 = t;
  207. }
  208. if (y1 > y2)
  209. {
  210. int t = y1;
  211. y1 = y2;
  212. y2 = t;
  213. }
  214. #endif
  215. //
  216. // make sure ordered coordinates are legal
  217. //
  218. if ((x1 < MIN_REGION_COORD) ||
  219. (y1 < MIN_REGION_COORD) ||
  220. (x2 > MAX_REGION_COORD) ||
  221. (y2 > MAX_REGION_COORD))
  222. {
  223. GdiSetLastError(ERROR_INVALID_PARAMETER);
  224. return((HRGN) 0);
  225. }
  226. //
  227. // get a handle for the new region
  228. //
  229. hrgn = (HRGN)hGetPEBHandle(RegionHandle,0);
  230. if (hrgn == NULL)
  231. {
  232. hrgn = NtGdiCreateRectRgn(0,0,1,1);
  233. }
  234. PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
  235. if (prRegion)
  236. {
  237. if ((x1 == x2) || (y1 == y2))
  238. {
  239. prRegion->Flags = NULLREGION;
  240. prRegion->Rect.left = 0;
  241. prRegion->Rect.top = 0;
  242. prRegion->Rect.right = 0;
  243. prRegion->Rect.bottom = 0;
  244. }
  245. else
  246. {
  247. prRegion->Flags = SIMPLEREGION;
  248. //
  249. // assign region rectangle
  250. //
  251. prRegion->Rect.left = x1;
  252. prRegion->Rect.top = y1;
  253. prRegion->Rect.right = x2;
  254. prRegion->Rect.bottom = y2;
  255. }
  256. //
  257. // mark user-mode region as valid, not cached
  258. //
  259. prRegion->AttrFlags = ATTR_RGN_VALID | ATTR_RGN_DIRTY;
  260. }
  261. else
  262. {
  263. if (hrgn != NULL)
  264. {
  265. WARNING("Shared hrgn handle has no valid PRGNATTR");
  266. DeleteRegion(hrgn);
  267. hrgn = NULL;
  268. }
  269. }
  270. return(hrgn);
  271. }
  272. /******************************Public*Routine******************************\
  273. * CreateRectRgnIndirect *
  274. * *
  275. * Client side stub. *
  276. * *
  277. * Tue 04-Jun-1991 16:58:01 -by- Charles Whitmer [chuckwh] *
  278. * Wrote it. *
  279. \**************************************************************************/
  280. HRGN WINAPI CreateRectRgnIndirect(CONST RECT *prcl)
  281. {
  282. return
  283. CreateRectRgn
  284. (
  285. prcl->left,
  286. prcl->top,
  287. prcl->right,
  288. prcl->bottom
  289. );
  290. }
  291. /******************************Public*Routine******************************\
  292. *
  293. * The PtInRegion function determines whether the specified point is
  294. * inside the specified region.
  295. *
  296. * Arguments:
  297. *
  298. * hrgn - app region handle
  299. * x - point x
  300. * y - point y
  301. *
  302. * Return Value:
  303. *
  304. * If the specified point is in the region, the return value is TRUE.
  305. * If the function fails, the return value is FALSE.
  306. *
  307. * History:
  308. *
  309. * 21-Jun-1995 -by- Mark Enstrom [marke]
  310. *
  311. \**************************************************************************/
  312. BOOL
  313. WINAPI
  314. PtInRegion(
  315. HRGN hrgn,
  316. int x,
  317. int y
  318. )
  319. {
  320. BOOL bRet = FALSE;
  321. BOOL bUserMode = FALSE;
  322. PRECTL prcl;
  323. PRGNATTR prRegion;
  324. FIXUP_HANDLE(hrgn);
  325. PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
  326. if (prRegion != NULL)
  327. {
  328. if (prRegion->Flags == NULLREGION)
  329. {
  330. bRet = FALSE;
  331. bUserMode = TRUE;
  332. }
  333. else if (prRegion->Flags == SIMPLEREGION)
  334. {
  335. prcl = &prRegion->Rect;
  336. if ((x >= prcl->left) && (x < prcl->right) &&
  337. (y >= prcl->top) && (y < prcl->bottom))
  338. {
  339. bRet = TRUE;
  340. }
  341. bUserMode = TRUE;
  342. }
  343. }
  344. if (!bUserMode)
  345. {
  346. bRet = NtGdiPtInRegion(hrgn,x,y);
  347. }
  348. return(bRet);
  349. }
  350. /******************************Public*Routine******************************\
  351. *
  352. * The RectInRegion function determines whether any part of the specified
  353. * rectangle is within the boundaries of a region.
  354. *
  355. * Arguments:
  356. *
  357. * hrgn - app region handle
  358. * prcl - app rectangle
  359. *
  360. * Return Value:
  361. *
  362. * If any part of the specified rectangle lies within the boundaries
  363. * of the region, the return value is TRUE.
  364. *
  365. * If the function fails, the return value is FALSE.
  366. *
  367. * History:
  368. *
  369. * 21-Jun-1995 -by- Mark Enstrom [marke]
  370. *
  371. \**************************************************************************/
  372. BOOL
  373. WINAPI
  374. RectInRegion(
  375. HRGN hrgn,
  376. CONST RECT *prcl
  377. )
  378. {
  379. PRGNATTR prRegion;
  380. BOOL bRet = FALSE;
  381. RECTL TempRect;
  382. LONG iRelation;
  383. BOOL bUserMode = FALSE;
  384. FIXUP_HANDLE(hrgn);
  385. PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
  386. if (prRegion != NULL)
  387. {
  388. if (prRegion->Flags == NULLREGION)
  389. {
  390. bRet = FALSE;
  391. bUserMode = TRUE;
  392. }
  393. else if (prRegion->Flags == SIMPLEREGION)
  394. {
  395. TempRect = *((PRECTL)prcl);
  396. ORDER_PRECTL((&TempRect));
  397. iRelation = iRectRelation(&prRegion->Rect,&TempRect);
  398. if (iRelation != DISJOINT)
  399. {
  400. bRet = TRUE;
  401. }
  402. bUserMode = TRUE;
  403. }
  404. }
  405. if (!bUserMode)
  406. {
  407. bRet = NtGdiRectInRegion(hrgn, (PRECT)prcl);
  408. }
  409. return(bRet);
  410. }
  411. /******************************Public*Routine******************************\
  412. *
  413. * The CombineRgn function combines two regions and stores the result in
  414. * a third region. The two regions are combined according to the specified
  415. * mode.
  416. *
  417. * Arguments:
  418. *
  419. * hrgnDst - destination region
  420. * hrgnSrc1 - source region
  421. * hrgnSrc2 - source region
  422. * iMode - destination region
  423. *
  424. * Return Value:
  425. *
  426. * The resulting type of region or ERROR
  427. *
  428. * History:
  429. *
  430. * 21-Jun-1995 -by- Mark Enstrom [marke]
  431. *
  432. \**************************************************************************/
  433. int
  434. WINAPI
  435. CombineRgn(
  436. HRGN hrgnDst,
  437. HRGN hrgnSrc1,
  438. HRGN hrgnSrc2,
  439. int iMode
  440. )
  441. {
  442. LONG ResultComplexity = COMPLEXREGION;
  443. int iRet = ERROR;
  444. //
  445. // Check if this operation can be completed in user-mode.
  446. // hrgnDst must have a user mode RGNATTR. hrgnSrc1 must
  447. // also have a user mode RGNATTR. If iMode is not RGN_COPY
  448. // then hrgnSrc2 must have a user mode RGNATTR except for certain
  449. // combinations.
  450. //
  451. PRGNATTR prRegionDst;
  452. PRGNATTR prRegionSrc1;
  453. PRGNATTR prRegionSrc2;
  454. PRECTL prclRes;
  455. PRECTL prclSrc1;
  456. PRECTL prclSrc2;
  457. LONG ComplexSrc1;
  458. LONG ComplexSrc2;
  459. FIXUP_HANDLE(hrgnDst);
  460. FIXUP_HANDLE(hrgnSrc1);
  461. FIXUP_HANDLEZ(hrgnSrc2);
  462. PSHARED_GET_VALIDATE(prRegionDst,hrgnDst,RGN_TYPE);
  463. PSHARED_GET_VALIDATE(prRegionSrc1,hrgnSrc1,RGN_TYPE);
  464. if ((prRegionDst != (PRGNATTR)NULL) &&
  465. (prRegionSrc1 != (PRGNATTR)NULL))
  466. {
  467. //
  468. // region Src1 must me NULL or SIMPLE for current
  469. // user-mode optimizations. If Rect is the region
  470. // bounding box, then it will be possible for
  471. // some combinations with regionC to become
  472. // SIMPLE or NULL.
  473. //
  474. prclSrc1 = &prRegionSrc1->Rect;
  475. ComplexSrc1 = prRegionSrc1->Flags;
  476. if (ComplexSrc1 > SIMPLEREGION)
  477. {
  478. goto CombineRgnKernelMode;
  479. }
  480. if (iMode == RGN_COPY)
  481. {
  482. prclRes = prclSrc1;
  483. ResultComplexity = ComplexSrc1;
  484. }
  485. else
  486. {
  487. LONG iRelation;
  488. //
  489. // validate regionSrc2
  490. //
  491. PSHARED_GET_VALIDATE(prRegionSrc2,hrgnSrc2,RGN_TYPE);
  492. if (
  493. (prRegionSrc2 == (PRGNATTR)NULL) ||
  494. (prRegionSrc2->Flags > SIMPLEREGION)
  495. )
  496. {
  497. goto CombineRgnKernelMode;
  498. }
  499. prclSrc2 = &prRegionSrc2->Rect;
  500. ComplexSrc2 = prRegionSrc2->Flags;
  501. switch (iMode)
  502. {
  503. case RGN_AND:
  504. //
  505. // Creates the intersection of the two
  506. // combined regions.
  507. //
  508. if ((ComplexSrc1 == NULLREGION) ||
  509. (ComplexSrc2 == NULLREGION))
  510. {
  511. //
  512. // intersection with NULL is NULL
  513. //
  514. ResultComplexity = NULLREGION;
  515. }
  516. else
  517. {
  518. iRelation = iRectRelation(prclSrc1,prclSrc2);
  519. if (iRelation == DISJOINT)
  520. {
  521. ResultComplexity = NULLREGION;
  522. }
  523. else if (iRelation == CONTAINED)
  524. {
  525. //
  526. // Src1 is contained in Src2
  527. //
  528. ResultComplexity = SIMPLEREGION;
  529. prclRes = prclSrc1;
  530. }
  531. else if (iRelation == CONTAINS)
  532. {
  533. //
  534. // Src1 is contains Src2
  535. //
  536. ResultComplexity = SIMPLEREGION;
  537. prclRes = prclSrc2;
  538. }
  539. }
  540. break;
  541. case RGN_OR:
  542. case RGN_XOR:
  543. //
  544. // RGN_OR: Creates the union of two combined regions.
  545. // RGN_XOR: Creates the union of two combined regions
  546. // except for any overlapping areas.
  547. //
  548. if (ComplexSrc1 == NULLREGION)
  549. {
  550. if (ComplexSrc2 == NULLREGION)
  551. {
  552. ResultComplexity = NULLREGION;
  553. }
  554. else
  555. {
  556. ResultComplexity = SIMPLEREGION;
  557. prclRes = prclSrc2;
  558. }
  559. }
  560. else if (ComplexSrc2 == NULLREGION)
  561. {
  562. ResultComplexity = SIMPLEREGION;
  563. prclRes = prclSrc1;
  564. }
  565. else if (iMode == RGN_OR)
  566. {
  567. iRelation = iRectRelation(prclSrc1,prclSrc2);
  568. if (iRelation == CONTAINED)
  569. {
  570. //
  571. // Src1 contained in Src2
  572. //
  573. ResultComplexity = SIMPLEREGION;
  574. prclRes = prclSrc2;
  575. }
  576. else if (iRelation == CONTAINS)
  577. {
  578. //
  579. // Src1 contains Src2
  580. //
  581. ResultComplexity = SIMPLEREGION;
  582. prclRes = prclSrc1;
  583. }
  584. }
  585. break;
  586. case RGN_DIFF:
  587. //
  588. // Combines the parts of hrgnSrc1 that are not
  589. // part of hrgnSrc2.
  590. //
  591. if (ComplexSrc1 == NULLREGION)
  592. {
  593. ResultComplexity = NULLREGION;
  594. }
  595. else if (ComplexSrc2 == NULLREGION)
  596. {
  597. ResultComplexity = SIMPLEREGION;
  598. prclRes = prclSrc1;
  599. }
  600. else
  601. {
  602. iRelation = iRectRelation(prclSrc1,prclSrc2);
  603. if (iRelation == DISJOINT)
  604. {
  605. //
  606. // don't intersect so don't subtract anything
  607. //
  608. ResultComplexity = SIMPLEREGION;
  609. prclRes = prclSrc1;
  610. }
  611. else if (iRelation == CONTAINED)
  612. {
  613. ResultComplexity = NULLREGION;
  614. }
  615. }
  616. break;
  617. }
  618. }
  619. //
  620. // try to combine
  621. //
  622. if (ResultComplexity == NULLREGION)
  623. {
  624. if (SetRectRgn(hrgnDst,0,0,0,0))
  625. {
  626. iRet = NULLREGION;
  627. }
  628. }
  629. else if (ResultComplexity == SIMPLEREGION)
  630. {
  631. if (SetRectRgn(hrgnDst,
  632. prclRes->left,
  633. prclRes->top,
  634. prclRes->right,
  635. prclRes->bottom))
  636. {
  637. iRet = SIMPLEREGION;
  638. }
  639. }
  640. }
  641. if (ResultComplexity != COMPLEXREGION)
  642. {
  643. prRegionDst->AttrFlags |= ATTR_RGN_DIRTY;
  644. }
  645. CombineRgnKernelMode:
  646. if (ResultComplexity == COMPLEXREGION)
  647. {
  648. iRet = NtGdiCombineRgn(hrgnDst,hrgnSrc1,hrgnSrc2,iMode);
  649. }
  650. return(iRet);
  651. }
  652. /******************************Public*Routine******************************\
  653. *
  654. * OffsetRgn checks for user-mode region data, if it exits the the
  655. * rectregio is offset, otherwise the kernel is called
  656. *
  657. * Arguments:
  658. *
  659. * hrgn - app region handle
  660. * x - offset in x
  661. * y - offset in y
  662. *
  663. * Return Value:
  664. *
  665. *
  666. *
  667. * History:
  668. *
  669. * 21-Jun-1995 -by- Mark Enstrom [marke]
  670. *
  671. \**************************************************************************/
  672. int
  673. WINAPI
  674. OffsetRgn(
  675. HRGN hrgn,
  676. int x,
  677. int y
  678. )
  679. {
  680. int iRet;
  681. BOOL bClientRegion = FALSE;
  682. PRGNATTR prRegion;
  683. FIXUP_HANDLE(hrgn);
  684. PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
  685. if (prRegion != NULL)
  686. {
  687. iRet = prRegion->Flags;
  688. if (iRet == NULLREGION)
  689. {
  690. bClientRegion = TRUE;
  691. }
  692. else if (iRet == SIMPLEREGION)
  693. {
  694. RECTL rcl = prRegion->Rect;
  695. bClientRegion = TRUE;
  696. //
  697. // try to offset the region, check for overflow
  698. //
  699. if ( !((rcl.left >= rcl.right) ||
  700. (rcl.top >= rcl.bottom)))
  701. {
  702. rcl.left += x;
  703. rcl.top += y;
  704. rcl.right += x;
  705. rcl.bottom += y;
  706. if (VALID_SCRRC(rcl))
  707. {
  708. prRegion->Rect = rcl;
  709. prRegion->AttrFlags |= ATTR_RGN_DIRTY;
  710. }
  711. else
  712. {
  713. //
  714. // over/underflow
  715. //
  716. iRet = ERROR;
  717. }
  718. }
  719. }
  720. }
  721. if (!bClientRegion)
  722. {
  723. iRet = NtGdiOffsetRgn(hrgn,x,y);
  724. }
  725. return(iRet);
  726. }
  727. /******************************Public*Routine******************************\
  728. *
  729. * GetRgnBox tries to return user-mode rectregion data, otherwies
  730. * make kernel mode transition to get region data.
  731. *
  732. * Arguments:
  733. *
  734. * hrgn - app region handle
  735. * prcl - app rect pointer
  736. *
  737. * Return Value:
  738. *
  739. * region complexity, if the hrgn parameter does not identify a
  740. * valid region, the return value is zero.
  741. *
  742. * History:
  743. *
  744. * 21-Jun-1995 -by- Mark Enstrom [marke]
  745. *
  746. \**************************************************************************/
  747. int
  748. WINAPI
  749. GetRgnBox(
  750. HRGN hrgn,
  751. LPRECT prcl
  752. )
  753. {
  754. int iRet;
  755. BOOL bClientRegion = FALSE;
  756. //
  757. // check for user-mode region data
  758. //
  759. PRGNATTR prRegion;
  760. FIXUP_HANDLE(hrgn);
  761. PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
  762. if (prRegion != NULL)
  763. {
  764. iRet = prRegion->Flags;
  765. if (iRet == NULLREGION)
  766. {
  767. bClientRegion = TRUE;
  768. prcl->left = 0;
  769. prcl->top = 0;
  770. prcl->right = 0;
  771. prcl->bottom = 0;
  772. }
  773. else if (iRet == SIMPLEREGION)
  774. {
  775. bClientRegion = TRUE;
  776. prcl->left = prRegion->Rect.left;
  777. prcl->top = prRegion->Rect.top;
  778. prcl->right = prRegion->Rect.right;
  779. prcl->bottom = prRegion->Rect.bottom;
  780. }
  781. }
  782. if (!bClientRegion)
  783. {
  784. iRet = NtGdiGetRgnBox(hrgn, prcl);
  785. }
  786. return(iRet);
  787. }
  788. /******************************Public*Routine******************************\
  789. * PtVisible *
  790. * *
  791. * Client side stub. *
  792. * *
  793. * Thu 06-Jun-1991 00:58:46 -by- Charles Whitmer [chuckwh] *
  794. * Wrote it. *
  795. \**************************************************************************/
  796. BOOL
  797. WINAPI
  798. PtVisible(
  799. HDC hdc,
  800. int x,
  801. int y
  802. )
  803. {
  804. FIXUP_HANDLE(hdc);
  805. return(NtGdiPtVisible(hdc,x,y));
  806. }
  807. /******************************Public*Routine******************************\
  808. * RectVisible *
  809. * *
  810. * Client side stub. *
  811. * *
  812. * Thu 06-Jun-1991 00:58:46 -by- Charles Whitmer [chuckwh] *
  813. * Wrote it. *
  814. \**************************************************************************/
  815. BOOL
  816. WINAPI
  817. RectVisible(
  818. HDC hdc,
  819. CONST RECT *prcl
  820. )
  821. {
  822. FIXUP_HANDLE(hdc);
  823. return(NtGdiRectVisible(hdc,(LPRECT)prcl));
  824. }
  825. /******************************Public*Routine******************************\
  826. *
  827. * SetRectRgn checks for a user-mode portion of the region. If the
  828. * User-mode data is valid, the region is set to rect locally, otherwise
  829. * a kernel mode call is made to set the region
  830. *
  831. * Arguments:
  832. *
  833. * hrgn - app region handle
  834. * x1,y1,x2,y2 - app region data
  835. *
  836. * Return Value:
  837. *
  838. * BOOL status
  839. *
  840. \**************************************************************************/
  841. BOOL
  842. WINAPI
  843. SetRectRgn(
  844. HRGN hrgn,
  845. int x1,
  846. int y1,
  847. int x2,
  848. int y2
  849. )
  850. {
  851. BOOL bStatus;
  852. PRGNATTR prRegion;
  853. //
  854. // if hrgn has a user-mode rectregion, then set
  855. //
  856. FIXUP_HANDLE(hrgn);
  857. PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
  858. if (prRegion != NULL)
  859. {
  860. PRECTL prcl = &prRegion->Rect;
  861. if ((x1 == x2) || (y1 == y2))
  862. {
  863. prRegion->Flags = NULLREGION;
  864. prcl->left = 0;
  865. prcl->top = 0;
  866. prcl->right = 0;
  867. prcl->bottom = 0;
  868. }
  869. else
  870. {
  871. //
  872. // assign and order rectangle
  873. //
  874. prcl->left = x1;
  875. prcl->top = y1;
  876. prcl->right = x2;
  877. prcl->bottom = y2;
  878. ORDER_PRECTL(prcl);
  879. //
  880. // set region flag
  881. //
  882. prRegion->Flags = SIMPLEREGION;
  883. }
  884. prRegion->AttrFlags |= ATTR_RGN_DIRTY;
  885. bStatus = TRUE;
  886. }
  887. else
  888. {
  889. bStatus = NtGdiSetRectRgn(hrgn,x1,y1,x2,y2);
  890. }
  891. return(bStatus);
  892. }
  893. /******************************Public*Routine******************************\
  894. * GetRandomRgn
  895. *
  896. * Client side stub.
  897. *
  898. * 10-Mar-1992 -by- Donald Sidoroff [donalds]
  899. * Wrote it.
  900. \**************************************************************************/
  901. int APIENTRY GetRandomRgn(HDC hdc,HRGN hrgn,int iNum)
  902. {
  903. FIXUP_HANDLE(hdc);
  904. FIXUP_HANDLE(hrgn);
  905. return(NtGdiGetRandomRgn(hdc,hrgn,iNum));
  906. }
  907. /******************************Public*Routine******************************\
  908. * GetClipRgn *
  909. * *
  910. * Client side stub. *
  911. * *
  912. * Sat 08-Jun-1991 17:38:18 -by- Charles Whitmer [chuckwh] *
  913. * Wrote it. *
  914. \**************************************************************************/
  915. int WINAPI GetClipRgn(HDC hdc,HRGN hrgn)
  916. {
  917. BOOL bRet;
  918. FIXUP_HANDLE(hdc);
  919. FIXUP_HANDLE(hrgn);
  920. bRet = NtGdiGetRandomRgn(hdc, hrgn, 1);
  921. if (hrgn && MIRRORED_HDC(hdc)) {
  922. MirrorRgnDC(hdc, hrgn, NULL);
  923. }
  924. return(bRet);
  925. }
  926. /******************************Public*Routine******************************\
  927. * GetRegionData
  928. *
  929. * Download a region from the server
  930. *
  931. * History:
  932. * 29-Oct-1991 -by- Donald Sidoroff [donalds]
  933. * Wrote it.
  934. \**************************************************************************/
  935. DWORD
  936. WINAPI
  937. GetRegionData(
  938. HRGN hrgn,
  939. DWORD nCount,
  940. LPRGNDATA lpRgnData
  941. )
  942. {
  943. DWORD iRet;
  944. FIXUP_HANDLE(hrgn);
  945. //
  946. // If this is just an inquiry, pass over dummy parameters.
  947. //
  948. if (lpRgnData == (LPRGNDATA) NULL)
  949. {
  950. nCount = 0;
  951. }
  952. return(NtGdiGetRegionData(hrgn,nCount,lpRgnData));
  953. }
  954. /******************************Public*Routine******************************\
  955. *
  956. * Try to cache regions with user-mode rectregion defined
  957. *
  958. * Arguments:
  959. *
  960. * h - region handle
  961. *
  962. * Return Value:
  963. *
  964. * BOOL
  965. *
  966. * History:
  967. *
  968. * 21-Jun-1995 -by- Mark Enstrom [marke]
  969. *
  970. \**************************************************************************/
  971. BOOL
  972. DeleteRegion(
  973. HRGN hRgn
  974. )
  975. {
  976. PRGNATTR pRgnattr = NULL;
  977. BOOL bRet = FALSE;
  978. BEGIN_BATCH(BatchTypeDeleteRegion,BATCHDELETEREGION);
  979. PSHARED_GET_VALIDATE(pRgnattr,hRgn,RGN_TYPE);
  980. if (pRgnattr)
  981. {
  982. pBatch->hregion = hRgn;
  983. bRet = TRUE;
  984. }
  985. else
  986. {
  987. goto UNBATCHED_COMMAND;
  988. }
  989. COMPLETE_BATCH_COMMAND();
  990. UNBATCHED_COMMAND:
  991. //
  992. // All other cases
  993. //
  994. if (!bRet)
  995. {
  996. bRet = NtGdiDeleteObjectApp(hRgn);
  997. }
  998. return(bRet);
  999. }
  1000. /******************************Public*Routine******************************\
  1001. * SelectClipRgn
  1002. *
  1003. * Client side stub.
  1004. *
  1005. * History:
  1006. * 01-Nov-1991 12:53:47 -by- Donald Sidoroff [donalds]
  1007. * Now just call ExtSelectClipRgn
  1008. \**************************************************************************/
  1009. int META WINAPI SelectClipRgn(HDC hdc,HRGN hrgn)
  1010. {
  1011. return(ExtSelectClipRgn(hdc, hrgn, RGN_COPY));
  1012. }
  1013. /******************************Public*Routine******************************\
  1014. *
  1015. * The ExtSelectClipRgn function combines the specified region with the
  1016. * current clipping region by using the specified mode.
  1017. *
  1018. * Arguments:
  1019. *
  1020. * hdc - app DC handle
  1021. * hrgn - app region handle
  1022. * iMode - Select mode
  1023. *
  1024. * Return Value:
  1025. *
  1026. * If the function succeeds, the return value specifies the new clipping
  1027. * region's complexity and can be any one of the following values:
  1028. *
  1029. * Value Meaning
  1030. * NULLREGION Region is empty.
  1031. * SIMPLEREGION Region is a single rectangle.
  1032. * COMPLEXREGION Region is more than one rectangle.
  1033. * ERROR An error occurred
  1034. *
  1035. * History:
  1036. *
  1037. * 21-Jun-1995 -by- Mark Enstrom [marke]
  1038. *
  1039. \**************************************************************************/
  1040. int
  1041. META
  1042. WINAPI
  1043. ExtSelectClipRgn(
  1044. HDC hdc,
  1045. HRGN hrgn,
  1046. int iMode
  1047. )
  1048. {
  1049. int iRet = RGN_ERROR;
  1050. HRGN hrgnMirror = NULL;
  1051. FIXUP_HANDLE(hdc);
  1052. FIXUP_HANDLEZ(hrgn);
  1053. //
  1054. // Check Metafile
  1055. //
  1056. if (IS_ALTDC_TYPE(hdc))
  1057. {
  1058. PLDC pldc;
  1059. if (IS_METADC16_TYPE(hdc))
  1060. {
  1061. return(MF16_SelectClipRgn(hdc,hrgn,iMode));
  1062. }
  1063. DC_PLDC(hdc,pldc,iRet);
  1064. if (pldc->iType == LO_METADC)
  1065. {
  1066. if (!MF_ExtSelectClipRgn(hdc,hrgn,iMode))
  1067. {
  1068. return(iRet);
  1069. }
  1070. }
  1071. }
  1072. //
  1073. // Attempt to batch ExtSelectClipRgn:
  1074. //
  1075. // The DC_ATTR structure has a copy of the current vis region
  1076. // bounding rectangle, and the handle table has a flag indicating
  1077. // whether this region is valid.
  1078. //
  1079. // Calls can be batched when the iMode is RGN_COPY and either
  1080. // hrgn is NULL, or hrgn complexity is SIMPLE. (and the DC is not
  1081. // a DIBSECTION DC)
  1082. //
  1083. //
  1084. // FUTURE PERF:
  1085. //
  1086. // A check is made to determine if the region being selected
  1087. // is the same as the last selected region. In this case, only the
  1088. // correct return value needs to be calculated, no region changes
  1089. // are needed.
  1090. //
  1091. //
  1092. if (hrgn && MIRRORED_HDC(hdc)) {
  1093. if (MirrorRgnDC(hdc, hrgn, &hrgnMirror) && hrgnMirror) {
  1094. hrgn = hrgnMirror;
  1095. }
  1096. }
  1097. if (iMode == RGN_COPY)
  1098. {
  1099. //
  1100. // validate DC
  1101. //
  1102. BOOL bBatch = FALSE;
  1103. PRGNATTR prRegion = NULL;
  1104. PDC_ATTR pdca;
  1105. PENTRY pDCEntry;
  1106. PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
  1107. //
  1108. // check if call can be batched. DC must be valid,non-dibsection
  1109. // DC and there must be room on the batch and same batch DC
  1110. //
  1111. BEGIN_BATCH_HDC(hdc,pdca,BatchTypeSelectClip,BATCHSELECTCLIP);
  1112. pDCEntry = &pGdiSharedHandleTable[HANDLE_TO_INDEX(hdc)];
  1113. ASSERTGDI(pDCEntry,"pDCEntry must be valid when pdcattr is valid");
  1114. if (hrgn == NULL)
  1115. {
  1116. //
  1117. // deleting the clip region, so the return complexity
  1118. // will be the vis rgn complexity. Just batch the call.
  1119. //
  1120. if (!(pDCEntry->Flags & HMGR_ENTRY_INVALID_VIS))
  1121. {
  1122. bBatch = TRUE;
  1123. iRet = pdca->VisRectRegion.Flags;
  1124. }
  1125. }
  1126. else
  1127. {
  1128. PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
  1129. //
  1130. // pDCEntry must be valid because pdcattr is valid.
  1131. // In order to batch, the user-mode RectRegion must
  1132. // be valid and the complexity must be simple
  1133. //
  1134. if (
  1135. (prRegion) &&
  1136. (prRegion->Flags == SIMPLEREGION) &&
  1137. (!(prRegion->AttrFlags & ATTR_CACHED))
  1138. &&
  1139. !(pDCEntry->Flags & HMGR_ENTRY_INVALID_VIS)
  1140. )
  1141. {
  1142. //
  1143. // Batch the call.
  1144. //
  1145. bBatch = TRUE;
  1146. //
  1147. // if the new clip region intersects the DC vis region, the
  1148. // return value is SIMPLEREGION, otherwise it is NULLREGION
  1149. //
  1150. iRet = SIMPLEREGION;
  1151. if (
  1152. (pdca->VisRectRegion.Rect.left >= prRegion->Rect.right) ||
  1153. (pdca->VisRectRegion.Rect.top >= prRegion->Rect.bottom) ||
  1154. (pdca->VisRectRegion.Rect.right <= prRegion->Rect.left) ||
  1155. (pdca->VisRectRegion.Rect.bottom <= prRegion->Rect.top)
  1156. )
  1157. {
  1158. iRet = NULLREGION;
  1159. }
  1160. }
  1161. }
  1162. //
  1163. // if the call is to be batched, add to the batch
  1164. // and return
  1165. //
  1166. if (!bBatch)
  1167. {
  1168. goto UNBATCHED_COMMAND;
  1169. }
  1170. if (hrgn == NULL)
  1171. {
  1172. iMode |= REGION_NULL_HRGN;
  1173. }
  1174. else
  1175. {
  1176. pBatch->rclClip.left = prRegion->Rect.left;
  1177. pBatch->rclClip.top = prRegion->Rect.top;
  1178. pBatch->rclClip.right = prRegion->Rect.right;
  1179. pBatch->rclClip.bottom = prRegion->Rect.bottom;
  1180. }
  1181. pBatch->iMode = iMode;
  1182. COMPLETE_BATCH_COMMAND();
  1183. goto BATCHED_COMMAND;
  1184. }
  1185. //
  1186. // call kernel on fall-through and error cases
  1187. //
  1188. UNBATCHED_COMMAND:
  1189. iRet = NtGdiExtSelectClipRgn(hdc,hrgn,iMode);
  1190. BATCHED_COMMAND:
  1191. if (hrgnMirror) {
  1192. DeleteObject((HGDIOBJ)hrgnMirror);
  1193. }
  1194. return(iRet);
  1195. }
  1196. /******************************Public*Routine******************************\
  1197. * ExcludeClipRect *
  1198. * *
  1199. * Client side stub. *
  1200. * *
  1201. * History: *
  1202. * Thu 06-Jun-1991 23:10:01 -by- Charles Whitmer [chuckwh] *
  1203. * Wrote it. *
  1204. \**************************************************************************/
  1205. int
  1206. META WINAPI
  1207. ExcludeClipRect(
  1208. HDC hdc,
  1209. int x1,
  1210. int y1,
  1211. int x2,
  1212. int y2
  1213. )
  1214. {
  1215. int iRet = RGN_ERROR;
  1216. FIXUP_HANDLE(hdc);
  1217. if (IS_ALTDC_TYPE(hdc))
  1218. {
  1219. PLDC pldc;
  1220. if (IS_METADC16_TYPE(hdc))
  1221. return(MF16_RecordParms5(hdc,x1,y1,x2,y2,META_EXCLUDECLIPRECT));
  1222. DC_PLDC(hdc,pldc,iRet);
  1223. if (pldc->iType == LO_METADC)
  1224. {
  1225. if (!MF_AnyClipRect(hdc,x1,y1,x2,y2,EMR_EXCLUDECLIPRECT))
  1226. return(iRet);
  1227. }
  1228. }
  1229. return(NtGdiExcludeClipRect(hdc,x1,y1,x2,y2));
  1230. }
  1231. /******************************Public*Routine******************************\
  1232. * IntersectClipRect *
  1233. * *
  1234. * Client side stub. *
  1235. * *
  1236. * History: *
  1237. * Thu 06-Jun-1991 23:10:01 -by- Charles Whitmer [chuckwh] *
  1238. * Wrote it. *
  1239. \**************************************************************************/
  1240. int
  1241. META WINAPI
  1242. IntersectClipRect(
  1243. HDC hdc,
  1244. int x1,
  1245. int y1,
  1246. int x2,
  1247. int y2
  1248. )
  1249. {
  1250. int iRet = RGN_ERROR;
  1251. FIXUP_HANDLE(hdc);
  1252. if (IS_ALTDC_TYPE(hdc))
  1253. {
  1254. PLDC pldc;
  1255. if (IS_METADC16_TYPE(hdc))
  1256. return(MF16_RecordParms5(hdc,x1,y1,x2,y2,META_INTERSECTCLIPRECT));
  1257. DC_PLDC(hdc,pldc,iRet);
  1258. if (pldc->iType == LO_METADC)
  1259. {
  1260. if (!MF_AnyClipRect(hdc,x1,y1,x2,y2,EMR_INTERSECTCLIPRECT))
  1261. return(iRet);
  1262. }
  1263. }
  1264. return(NtGdiIntersectClipRect(hdc,x1,y1,x2,y2));
  1265. }