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.

723 lines
22 KiB

  1. /*****************************************************************************
  2. *
  3. * regions - Entry points for Win32 to Win 16 converter
  4. *
  5. * Date: 7/1/91
  6. * Author: Jeffrey Newman (c-jeffn)
  7. *
  8. * Copyright 1991 Microsoft Corp
  9. *
  10. * NOTES:
  11. *
  12. When there are no embedded metafiles we need to do the following:
  13. 1] Read the metafile data from the Win32 metafile. This
  14. is done by the handler routines that in turn call these
  15. routines.
  16. 2] Translate the Win32 metafile data into Win16 metafile data.
  17. The region data for FillRgn, FrameRgn, InvertRgn, and PaintRgn
  18. are in record-time world coordinates. The region data for
  19. these region API's will have to be translated from record-time
  20. -world coordinates to play-time-page coordinates
  21. (XFORM_WORLD_TO_PAGE). The helperDC will be used for
  22. this transformation.
  23. The region data for SelectClipRgn and OffsetClipRgn are in
  24. record-time device coordinates. The region data for these
  25. APIs will be translated from record-time-device coordinates
  26. to play-time-device coordinates.
  27. 3] Emit a Win16 create region metafile record.
  28. 4] Select the newly created region into the metafile.
  29. 5] Do the region function (FillRegion, FrameRegion, ...).
  30. This means emit a FillRegion or FrameRegion drawing order
  31. into the Win16 metafile.
  32. 6] Emit a Delete Region drawing order.
  33. 7] Clean up all the memory resources used.
  34. When there are embedded metafiles things get a little more complicated.
  35. Most of the complications are hidden in PlayMetafile record processing.
  36. Items 1 thru 3 will be handled by the PlayMetafile Doer.
  37. 1] We need to keep the region from the previous DC level.
  38. This can be done by the helper DC (SaveDC). We will have to
  39. do a GetClipRgn and a SelectMetaRgn. A MetaRgn is the clip
  40. region from the previous level.
  41. 2] We will have to intersect any clip regions from the current
  42. level with any clip regions from the previous level. This can
  43. be done by the helper DC (using the hrgnMeta & ExtCombineRegion)
  44. 3] When we pop out from this level we will have to restore the
  45. previous saved region. This can be done by the helper DC.
  46. (RestoreDC).
  47. Since we do not know whether or not there will be an embedded metafile
  48. in the metafile we are currently processing we will always shadow
  49. the Clip Region call into the helper DC.
  50. *****************************************************************************/
  51. #include "precomp.h"
  52. #pragma hdrstop
  53. BOOL bEmitWin3Region(PLOCALDC pLocalDC, HRGN hrgn);
  54. #define MIN_RGN_COORD16 -30000
  55. #define MAX_RGN_COORD16 30000
  56. /***************************************************************************
  57. * DoDrawRgn
  58. *
  59. * CR1: This routine was added as part of the handle manager change.
  60. * I noticed that almost all of the Region Rendering code was
  61. * the same.
  62. **************************************************************************/
  63. BOOL APIENTRY DoDrawRgn
  64. (
  65. PLOCALDC pLocalDC,
  66. INT ihBrush,
  67. INT nWidth,
  68. INT nHeight,
  69. INT cRgnData,
  70. LPRGNDATA pRgnData,
  71. INT mrType
  72. )
  73. {
  74. BOOL b ;
  75. HRGN hrgn = (HRGN) 0;
  76. INT ihW16Rgn = -1,
  77. ihW16Brush = -1;
  78. b = FALSE ;
  79. // Translate the Win32 region data from Metafile-World to
  80. // Referencd-Page space.
  81. // This is done by ExtCreateRegion's xform. The returned region
  82. // is transformed.
  83. hrgn = ExtCreateRegion(&pLocalDC->xformRWorldToPPage, cRgnData,
  84. (LPRGNDATA) pRgnData);
  85. if (!hrgn)
  86. {
  87. RIP("MF3216: DoDrawRgn, ExtCreateRegion failed\n") ;
  88. goto error_exit ;
  89. }
  90. // Allocate a handle for the region.
  91. // This is different from a normal handle allocation, because
  92. // there is no region handle in Win32. We are using one of our
  93. // extra slots here.
  94. ihW16Rgn = iGetW16ObjectHandleSlot(pLocalDC, REALIZED_REGION) ;
  95. if (ihW16Rgn == -1)
  96. goto error_exit ;
  97. // Emit a Win16 create region record for the region.
  98. if (!bEmitWin3Region(pLocalDC, hrgn))
  99. {
  100. RIP("MF3216: DoDrawRgn, bEmitWin3Region failed\n") ;
  101. goto error_exit ;
  102. }
  103. // Translate the W32 Brush object index to a W16 Brush object index.
  104. if (ihBrush)
  105. {
  106. // Make sure that the W16 object exists. Stock brushes may not
  107. // have been created and iValidateHandle will take care of creating
  108. // them.
  109. ihW16Brush = iValidateHandle(pLocalDC, ihBrush) ;
  110. if (ihW16Brush == -1)
  111. goto error_exit ;
  112. }
  113. // Emit the Region Record depending upon the function type.
  114. switch (mrType)
  115. {
  116. case EMR_FILLRGN:
  117. if(ihW16Brush == -1)
  118. goto error_exit;
  119. b = bEmitWin16FillRgn(pLocalDC,
  120. LOWORD(ihW16Rgn),
  121. LOWORD(ihW16Brush)) ;
  122. break ;
  123. case EMR_FRAMERGN:
  124. nWidth = iMagnitudeXform (pLocalDC, nWidth, CX_MAG) ;
  125. nHeight = iMagnitudeXform (pLocalDC, nHeight, CY_MAG) ;
  126. if(ihW16Brush == -1)
  127. goto error_exit;
  128. b = bEmitWin16FrameRgn(pLocalDC,
  129. LOWORD(ihW16Rgn),
  130. LOWORD(ihW16Brush),
  131. LOWORD(nWidth),
  132. LOWORD(nHeight)) ;
  133. break ;
  134. case EMR_INVERTRGN:
  135. b = bEmitWin16InvertRgn(pLocalDC,
  136. LOWORD(ihW16Rgn)) ;
  137. break ;
  138. case EMR_PAINTRGN:
  139. b = bEmitWin16PaintRgn(pLocalDC,
  140. LOWORD(ihW16Rgn)) ;
  141. break ;
  142. default:
  143. RIP("MF3216: DoDrawRgn, unknown type\n") ;
  144. break ;
  145. }
  146. error_exit:
  147. // Delete the W16 Region Object.
  148. if (ihW16Rgn != -1)
  149. bDeleteW16Object(pLocalDC, ihW16Rgn) ;
  150. if (hrgn)
  151. DeleteObject(hrgn) ;
  152. return(b) ;
  153. }
  154. /***************************************************************************
  155. * ExtSelectClipRgn - Win32 to Win16 Metafile Converter Entry Point
  156. *
  157. * History:
  158. * Tue Apr 07 17:05:37 1992 -by- Hock San Lee [hockl]
  159. * Wrote it.
  160. **************************************************************************/
  161. BOOL WINAPI DoExtSelectClipRgn
  162. (
  163. PLOCALDC pLocalDC,
  164. INT cRgnData,
  165. LPRGNDATA pRgnData,
  166. INT iMode
  167. )
  168. {
  169. HANDLE hrgn;
  170. BOOL bRet;
  171. BOOL bNoClipRgn ;
  172. bNoClipRgn = bNoDCRgn(pLocalDC, DCRGN_CLIP);
  173. // Do it to the helper DC.
  174. if (cRgnData == 0) // default clipping
  175. {
  176. ASSERTGDI(iMode == RGN_COPY, "MF3216: DoExtSelectClipRgn: bad iMode\n");
  177. // No work if no previous clip region.
  178. if (bNoClipRgn)
  179. return(TRUE);
  180. bRet = (ExtSelectClipRgn(pLocalDC->hdcHelper, (HRGN)0, iMode) != ERROR);
  181. }
  182. else
  183. {
  184. // If there is no initial clip region and we are going to operate
  185. // on the initial clip region, we have to
  186. // create one. Otherwise, GDI will create some random default
  187. // clipping region for us!
  188. if (bNoClipRgn
  189. && (iMode == RGN_DIFF || iMode == RGN_XOR || iMode == RGN_OR))
  190. {
  191. HRGN hrgnDefault;
  192. if (!(hrgnDefault = CreateRectRgn((int) (SHORT) MINSHORT,
  193. (int) (SHORT) MINSHORT,
  194. (int) (SHORT) MAXSHORT,
  195. (int) (SHORT) MAXSHORT)))
  196. {
  197. ASSERTGDI(FALSE, "MF3216: CreateRectRgn failed");
  198. return(FALSE);
  199. }
  200. bRet = (ExtSelectClipRgn(pLocalDC->hdcHelper, hrgnDefault, RGN_COPY)
  201. != ERROR);
  202. ASSERTGDI(bRet, "MF3216: ExtSelectClipRgn failed");
  203. if (!DeleteObject(hrgnDefault))
  204. ASSERTGDI(FALSE, "MF3216: DeleteObject failed");
  205. if (!bRet)
  206. return(FALSE);
  207. }
  208. // Create a region from the region data passed in.
  209. if (!(hrgn = ExtCreateRegion((LPXFORM) NULL, cRgnData, pRgnData)))
  210. {
  211. RIP("MF3216: DoExtSelectClipRgn, Create region failed\n");
  212. return(FALSE);
  213. }
  214. bRet = (ExtSelectClipRgn(pLocalDC->hdcHelper, hrgn, iMode) != ERROR);
  215. ASSERTGDI(bRet, "MF3216: ExtSelectClipRgn failed\n");
  216. if (!DeleteObject(hrgn))
  217. RIP("MF3216: DeleteObject failed\n");
  218. }
  219. // dump the clip region data.
  220. if (bRet)
  221. return(bDumpDCClipping(pLocalDC));
  222. else
  223. return(FALSE);
  224. }
  225. /***************************************************************************
  226. * SetMetaRgn - Win32 to Win16 Metafile Converter Entry Point
  227. *
  228. * History:
  229. * Tue Apr 07 17:05:37 1992 -by- Hock San Lee [hockl]
  230. * Wrote it.
  231. **************************************************************************/
  232. BOOL WINAPI DoSetMetaRgn(PLOCALDC pLocalDC)
  233. {
  234. // No work if the clip region does not exist.
  235. if (bNoDCRgn(pLocalDC, DCRGN_CLIP))
  236. return(TRUE);
  237. // Do it to the helper DC.
  238. if (!SetMetaRgn(pLocalDC->hdcHelper))
  239. return(FALSE);
  240. // Dump the clip region data.
  241. return(bDumpDCClipping(pLocalDC));
  242. }
  243. /***************************************************************************
  244. * OffsetClipRgn - Win32 to Win16 Metafile Converter Entry Point
  245. *
  246. * History:
  247. * Tue Apr 07 17:05:37 1992 -by- Hock San Lee [hockl]
  248. * Wrote it.
  249. **************************************************************************/
  250. BOOL WINAPI DoOffsetClipRgn(PLOCALDC pLocalDC, INT x, INT y)
  251. {
  252. POINTL aptl[2];
  253. BOOL b;
  254. // Do it to the helper DC.
  255. if (!OffsetClipRgn(pLocalDC->hdcHelper, x, y))
  256. return(FALSE);
  257. // Dump region if the meta region exists.
  258. // We don't offset the meta region!
  259. if (!bNoDCRgn(pLocalDC, DCRGN_META))
  260. return(bDumpDCClipping(pLocalDC));
  261. // Translate the record-time world offsets to play-time page offsets.
  262. aptl[0].x = 0;
  263. aptl[0].y = 0;
  264. aptl[1].x = x;
  265. aptl[1].y = y;
  266. if (!bXformRWorldToPPage(pLocalDC, aptl, 2))
  267. return(FALSE);
  268. aptl[1].x -= aptl[0].x;
  269. aptl[1].y -= aptl[0].y;
  270. b = bEmitWin16OffsetClipRgn(pLocalDC, (SHORT) aptl[1].x, (SHORT) aptl[1].y);
  271. ASSERTGDI(b, "MF3216: DoOffsetClipRgn, bEmitWin16OffsetClipRgn failed\n");
  272. return(b) ;
  273. }
  274. /***************************************************************************
  275. * bNoDCRgn - Return TRUE if the dc clip region does not exist.
  276. * Otherwise, return FALSE.
  277. * This is TEMPORARY only. Get gdi to provide this functionality.
  278. **************************************************************************/
  279. BOOL bNoDCRgn(PLOCALDC pLocalDC, INT iType)
  280. {
  281. BOOL bRet = FALSE; // assume the dc region exists
  282. HRGN hrgnTmp;
  283. ASSERTGDI(iType == DCRGN_CLIP || iType == DCRGN_META,
  284. "MF3216: bNoDCRgn, bad iType\n");
  285. if (!(hrgnTmp = CreateRectRgn(0, 0, 0, 0)))
  286. {
  287. ASSERTGDI(FALSE, "MF3216: bNoDCRgn, CreateRectRgn failed\n");
  288. return(bRet);
  289. }
  290. switch (GetRandomRgn(pLocalDC->hdcHelper,
  291. hrgnTmp,
  292. iType == DCRGN_CLIP ? 1 : 2
  293. )
  294. )
  295. {
  296. case -1: // error
  297. ASSERTGDI(FALSE, "GetRandomRgn failed");
  298. break;
  299. case 0: // no dc region
  300. bRet = TRUE;
  301. break;
  302. case 1: // has dc region
  303. break;
  304. }
  305. if (!DeleteObject(hrgnTmp))
  306. ASSERTGDI(FALSE, "DeleteObject failed");
  307. return(bRet);
  308. }
  309. /***************************************************************************
  310. * bDumpDCClipping - Dump the DC clipping regions.
  311. *
  312. * History:
  313. * Tue Apr 07 17:05:37 1992 -by- Hock San Lee [hockl]
  314. * Wrote it.
  315. **************************************************************************/
  316. BOOL bDumpDCClipping(PLOCALDC pLocalDC)
  317. {
  318. BOOL bRet = FALSE; // assume failure
  319. HRGN hrgnRDev = (HRGN) 0;
  320. HRGN hrgnPPage = (HRGN) 0;
  321. HRGN hrgnPPageBounds = (HRGN) 0;
  322. LPRGNDATA lprgnRDev = (LPRGNDATA) NULL;
  323. LPRGNDATA lprgnPPage = (LPRGNDATA) NULL;
  324. DWORD cRgnData;
  325. INT i;
  326. INT nrcl;
  327. PRECTL prcl;
  328. RECTL rclPPage;
  329. // Since clipping region is not scalable in Win30, we do not emit
  330. // SelectClipRgn record. Instead, we set the clipping to the default, i.e.
  331. // no clipping, and then emit the scalable IntersectClipRect/ExcludeClipRect
  332. // records to exclude clipping region. This will allow the win30 metafiles
  333. // to be scalable.
  334. // First, emit a default clipping region.
  335. // On Win3.x, the META_SELECTCLIPREGION record only works if it has
  336. // a NULL handle. The Win3x metafile driver does not translate the
  337. // region handle at playback time!
  338. if (!bW16Emit1(pLocalDC, META_SELECTCLIPREGION, 0))
  339. goto ddcc_exit;
  340. // Now find the clip and meta regions to be excluded from the default
  341. // clipping region.
  342. if (!(hrgnRDev = CreateRectRgn(0, 0, 0, 0)))
  343. goto ddcc_exit;
  344. switch (GetRandomRgn(pLocalDC->hdcHelper, hrgnRDev, 3)) // meta and clip
  345. {
  346. case -1: // error
  347. ASSERTGDI(FALSE, "GetRandomRgn failed");
  348. goto ddcc_exit;
  349. case 0: // no clip region, we are done
  350. bRet = TRUE;
  351. goto ddcc_exit;
  352. case 1: // has clip region
  353. break;
  354. }
  355. // Get the clip region data.
  356. // First query the size of the buffer required to hold the clip region data.
  357. if (!(cRgnData = GetRegionData(hrgnRDev, 0, (LPRGNDATA) NULL)))
  358. goto ddcc_exit;
  359. // Allocate the memory for the clip region data buffer.
  360. if (!(lprgnRDev = (LPRGNDATA) LocalAlloc(LMEM_FIXED, cRgnData)))
  361. goto ddcc_exit;
  362. // Get clip region data.
  363. if (GetRegionData(hrgnRDev, cRgnData, lprgnRDev) != cRgnData)
  364. goto ddcc_exit;
  365. // Create the clip region in the playtime page space.
  366. if (!(hrgnPPage = ExtCreateRegion(&pLocalDC->xformRDevToPPage, cRgnData, lprgnRDev)))
  367. goto ddcc_exit;
  368. // Get the bounding box for the playtime clip region in page space.
  369. if (GetRgnBox(hrgnPPage, (LPRECT) &rclPPage) == ERROR)
  370. goto ddcc_exit;
  371. // Bound it to 16-bit.
  372. rclPPage.left = max(MIN_RGN_COORD16,rclPPage.left);
  373. rclPPage.top = max(MIN_RGN_COORD16,rclPPage.top);
  374. rclPPage.right = min(MAX_RGN_COORD16,rclPPage.right);
  375. rclPPage.bottom = min(MAX_RGN_COORD16,rclPPage.bottom);
  376. // Set the bounding box as the bounds for the clipping.
  377. if (!bEmitWin16IntersectClipRect(pLocalDC,
  378. (SHORT) rclPPage.left,
  379. (SHORT) rclPPage.top,
  380. (SHORT) rclPPage.right,
  381. (SHORT) rclPPage.bottom))
  382. goto ddcc_exit;
  383. // Create the bounding region.
  384. if (!(hrgnPPageBounds = CreateRectRgn(rclPPage.left,
  385. rclPPage.top,
  386. rclPPage.right,
  387. rclPPage.bottom)))
  388. goto ddcc_exit;
  389. // Exclude the regions in playtime page space.
  390. if (CombineRgn(hrgnPPage, hrgnPPageBounds, hrgnPPage, RGN_DIFF) == ERROR)
  391. goto ddcc_exit;
  392. // Finally, exclude the rectangles from the bounding box.
  393. if (!(cRgnData = GetRegionData(hrgnPPage, 0, (LPRGNDATA) NULL)))
  394. goto ddcc_exit;
  395. if (!(lprgnPPage = (LPRGNDATA) LocalAlloc(LMEM_FIXED, cRgnData)))
  396. goto ddcc_exit;
  397. if (GetRegionData(hrgnPPage, cRgnData, lprgnPPage) != cRgnData)
  398. goto ddcc_exit;
  399. // Get the number of rectangles in the transformed region.
  400. nrcl = lprgnPPage->rdh.nCount;
  401. prcl = (PRECTL) lprgnPPage->Buffer;
  402. // Emit a series of Exclude Clip Rectangle Metafile records.
  403. for (i = 0 ; i < nrcl; i++)
  404. {
  405. ASSERTGDI(prcl[i].left >= MIN_RGN_COORD16
  406. && prcl[i].top >= MIN_RGN_COORD16
  407. && prcl[i].right <= MAX_RGN_COORD16
  408. && prcl[i].bottom <= MAX_RGN_COORD16,
  409. "MF3216: bad coord");
  410. if (!bEmitWin16ExcludeClipRect(pLocalDC,
  411. (SHORT) prcl[i].left,
  412. (SHORT) prcl[i].top,
  413. (SHORT) prcl[i].right,
  414. (SHORT) prcl[i].bottom))
  415. goto ddcc_exit;
  416. }
  417. bRet = TRUE; // we are golden!
  418. // Cleanup all the resources used.
  419. ddcc_exit:
  420. if (hrgnRDev)
  421. DeleteObject(hrgnRDev);
  422. if (hrgnPPage)
  423. DeleteObject(hrgnPPage);
  424. if (hrgnPPageBounds)
  425. DeleteObject(hrgnPPageBounds);
  426. if (lprgnRDev)
  427. LocalFree(lprgnRDev);
  428. if (lprgnPPage)
  429. LocalFree(lprgnPPage);
  430. return(bRet) ;
  431. }
  432. /***************************************************************************
  433. * Emit a 16-bit CreateRegion record for the given region.
  434. *
  435. * This code is copied from the 16-bit metafile driver in gdi.
  436. *
  437. **************************************************************************/
  438. WIN3REGION w3rgnEmpty =
  439. {
  440. 0, // nextInChain
  441. 6, // ObjType
  442. 0x2F6, // ObjCount
  443. sizeof(WIN3REGION) - sizeof(SCAN) + 2,
  444. // cbRegion
  445. 0, // cScans
  446. 0, // maxScan
  447. {0,0,0,0}, // rcBounding
  448. {0,0,0,{0,0},0} // aScans[]
  449. };
  450. BOOL bEmitWin3Region(PLOCALDC pLocalDC, HRGN hrgn)
  451. {
  452. /*
  453. * in win2, METACREATEREGION records contained an entire region object,
  454. * including the full header. this header changed in win3.
  455. *
  456. * to remain compatible, the region records will be saved with the
  457. * win2 header. here we save our region with a win2 header.
  458. */
  459. PWIN3REGION lpw3rgn;
  460. DWORD cbNTRgnData;
  461. DWORD curRectl;
  462. WORD cScans;
  463. WORD maxScanEntry;
  464. WORD curScanEntry;
  465. DWORD cbw3data;
  466. PRGNDATA lprgn;
  467. LPRECT lprc;
  468. PSCAN lpScan;
  469. BOOL bRet;
  470. ASSERTGDI(hrgn, "MF3216: bEmitWin3Region, hrgn is NULL");
  471. // Get the NT Region Data
  472. cbNTRgnData = GetRegionData(hrgn, 0, NULL);
  473. if (cbNTRgnData == 0)
  474. return(FALSE);
  475. lprgn = (PRGNDATA) LocalAlloc(LMEM_FIXED, cbNTRgnData);
  476. if (!lprgn)
  477. return(FALSE);
  478. cbNTRgnData = GetRegionData(hrgn, cbNTRgnData, lprgn);
  479. if (cbNTRgnData == 0)
  480. {
  481. LocalFree((HANDLE) lprgn);
  482. return(FALSE);
  483. }
  484. // Handle the empty region.
  485. if (!lprgn->rdh.nCount)
  486. {
  487. bRet = bEmitWin16CreateRegion(pLocalDC, sizeof(WIN3REGION) - sizeof(SCAN), (PVOID) &w3rgnEmpty);
  488. LocalFree((HANDLE)lprgn);
  489. return(bRet);
  490. }
  491. lprc = (LPRECT)lprgn->Buffer;
  492. // Create the Windows 3.x equivalent
  493. // worst case is one scan for each rect
  494. cbw3data = 2*sizeof(WIN3REGION) + (WORD)lprgn->rdh.nCount*sizeof(SCAN);
  495. lpw3rgn = (PWIN3REGION)LocalAlloc(LMEM_FIXED, cbw3data);
  496. if (!lpw3rgn)
  497. {
  498. LocalFree((HANDLE) lprgn);
  499. return(FALSE);
  500. }
  501. // Grab the bounding rect.
  502. lpw3rgn->rcBounding.left = (SHORT)lprgn->rdh.rcBound.left;
  503. lpw3rgn->rcBounding.right = (SHORT)lprgn->rdh.rcBound.right;
  504. lpw3rgn->rcBounding.top = (SHORT)lprgn->rdh.rcBound.top;
  505. lpw3rgn->rcBounding.bottom = (SHORT)lprgn->rdh.rcBound.bottom;
  506. cbw3data = sizeof(WIN3REGION) - sizeof(SCAN) + 2;
  507. // visit all the rects
  508. curRectl = 0;
  509. cScans = 0;
  510. maxScanEntry = 0;
  511. lpScan = lpw3rgn->aScans;
  512. while(curRectl < lprgn->rdh.nCount)
  513. {
  514. LPWORD lpXEntry;
  515. DWORD cbScan;
  516. curScanEntry = 0; // Current X pair in this scan
  517. lpScan->scnPntTop = (WORD)lprc[curRectl].top;
  518. lpScan->scnPntBottom = (WORD)lprc[curRectl].bottom;
  519. lpXEntry = (LPWORD) lpScan->scnPntsX;
  520. // handle rects on this scan
  521. do
  522. {
  523. lpXEntry[curScanEntry + 0] = (WORD)lprc[curRectl].left;
  524. lpXEntry[curScanEntry + 1] = (WORD)lprc[curRectl].right;
  525. curScanEntry += 2;
  526. curRectl++;
  527. } while ((curRectl < lprgn->rdh.nCount)
  528. && (lprc[curRectl-1].top == lprc[curRectl].top)
  529. && (lprc[curRectl-1].bottom == lprc[curRectl].bottom)
  530. );
  531. lpScan->scnPntCnt = curScanEntry;
  532. lpXEntry[curScanEntry] = curScanEntry; // Count also follows Xs
  533. cScans++;
  534. if (curScanEntry > maxScanEntry)
  535. maxScanEntry = curScanEntry;
  536. // account for each new scan + each X1 X2 Entry but the first
  537. cbScan = sizeof(SCAN)-(sizeof(WORD)*2) + (curScanEntry*sizeof(WORD));
  538. cbw3data += cbScan;
  539. lpScan = (PSCAN)(((LPBYTE)lpScan) + cbScan);
  540. }
  541. // Initialize the header
  542. lpw3rgn->nextInChain = 0;
  543. lpw3rgn->ObjType = 6; // old Windows OBJ_RGN identifier
  544. lpw3rgn->ObjCount= 0x2F6; // any non-zero number
  545. lpw3rgn->cbRegion = (WORD)cbw3data; // don't count type and next
  546. lpw3rgn->cScans = cScans;
  547. lpw3rgn->maxScan = maxScanEntry;
  548. bRet = bEmitWin16CreateRegion(pLocalDC, cbw3data-2, (PVOID) lpw3rgn);
  549. if (LocalFree((HANDLE)lprgn))
  550. ASSERTGDI(FALSE, "bEmitWin3Region: LocalFree(lprgn) Failed\n");
  551. if (LocalFree((HANDLE)lpw3rgn))
  552. ASSERTGDI(FALSE, "bEmitWin3Region: LocalFree(lpw3rgn) Failed\n");
  553. return(bRet);
  554. }