Source code of Windows XP (NT5)
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.

2325 lines
61 KiB

  1. /****************************** Module Header ******************************\
  2. *
  3. * Module Name: MetaRec.c
  4. *
  5. *
  6. * DESCRIPTIVE NAME: Metafile Recorder
  7. *
  8. * FUNCTION: Records GDI functions in memory and disk metafiles.
  9. *
  10. * PUBLIC ENTRY POINTS:
  11. * CloseMetaFile
  12. * CopyMetaFile
  13. * CreateMetaFile
  14. * GetMetaFileBits
  15. * SetMetaFileBits
  16. * PRIVATE ENTRY POINTS:
  17. * RecordParms
  18. * AttemptWrite
  19. * MarkMetaFile
  20. * RecordOther
  21. * RecordObject
  22. * ProbeSize
  23. * AddToTable
  24. *
  25. * History:
  26. * 02-Jul-1991 -by- John Colleran [johnc]
  27. * Combined From Win 3.1 and WLO 1.0 sources
  28. \***************************************************************************/
  29. #include <windows.h>
  30. #include <drivinit.h>
  31. #include "gdi16.h"
  32. #define SP_OUTOFDISK (-4) /* simply no disk to spool */
  33. extern HANDLE hStaticBitmap ; // MetaSup.c
  34. extern METACACHE MetaCache; // Meta.c
  35. extern HDC hScreenDC;
  36. WORD INTERNAL AddToTable(HANDLE hMF, HANDLE hObject, LPWORD position, BOOL bRealAdd);
  37. HANDLE INTERNAL AllocateSpaceForDIB (LPBITMAP, LPBYTE, LPWORD, LPDWORD);
  38. BOOL INTERNAL AttemptWrite(HANDLE, WORD, DWORD, BYTE huge *);
  39. BOOL INTERNAL CopyFile(LPSTR lpSFilename, LPSTR lpDFilename);
  40. LPWORD INTERNAL InitializeDIBHeader (LPBITMAPINFOHEADER, LPBITMAP, BYTE, WORD);
  41. VOID INTERNAL MarkMetaFile(HANDLE hMF);
  42. HANDLE INTERNAL ProbeSize(NPMETARECORDER pMF, DWORD dwLength);
  43. HANDLE hFirstMetaFile = 0; // Linked list of all open MetaFiles
  44. /****************************************************************************
  45. * *
  46. * RecordParms *
  47. * *
  48. * Parameters: 1.hMF handle to a metafile header. *
  49. * 2.The magic number of the function being recorded. *
  50. * 3.The number of parmmeter of the function (size of lpParm *
  51. * in words) *
  52. * 4.A long pointer to parameters stored in reverse order *
  53. * *
  54. ****************************************************************************/
  55. BOOL INTERNAL RecordParms(HANDLE hdc, WORD magic, DWORD count, LPWORD lpParm)
  56. {
  57. BOOL status = FALSE;
  58. DWORD i;
  59. DWORD dwLength;
  60. HPWORD hpwSpace;
  61. HPWORD hpHugeParm;
  62. LPWORD lpCache;
  63. HANDLE hSpace;
  64. WORD fileNumber;
  65. METARECORD recPair;
  66. HANDLE hMF;
  67. NPMETARECORDER npMF;
  68. dprintf( 6," RecordParms 0x%X", magic);
  69. hpHugeParm = (HPWORD)lpParm;
  70. // Validate the metafile handle
  71. if(npMF = (NPMETARECORDER)LocalLock(HANDLEFROMMETADC(hdc)))
  72. {
  73. if(npMF->metaDCHeader.ident != ID_METADC )
  74. {
  75. LocalUnlock(HANDLEFROMMETADC(hdc));
  76. ASSERTGDI( FALSE, "RecordParms: invalid metafile ID");
  77. return(FALSE);
  78. }
  79. }
  80. else
  81. {
  82. ASSERTGDI( FALSE, "RecordParms: invalid metafile");
  83. return(FALSE);
  84. }
  85. hMF = HANDLEFROMMETADC(hdc);
  86. if (!(npMF->recFlags & METAFILEFAILURE))
  87. {
  88. if (npMF->recordHeader.mtType == MEMORYMETAFILE)
  89. {
  90. if (hSpace = ProbeSize(npMF, dwLength = count + RECHDRSIZE / 2))
  91. {
  92. hpwSpace = (HPWORD) GlobalLock(hSpace);
  93. hpwSpace = (HPWORD) ((LPMETADATA) hpwSpace)->metaDataStuff;
  94. hpwSpace = hpwSpace + npMF->recFilePosition;
  95. // write length out at a pair of words because we
  96. // are not DWORD aligned, so we can't use "DWORD huge *"
  97. *hpwSpace++ = LOWORD(dwLength);
  98. *hpwSpace++ = HIWORD(dwLength);
  99. *hpwSpace++ = magic;
  100. for (i = 0; i < count; ++i)
  101. *hpwSpace++ = *hpHugeParm++;
  102. npMF->recFilePosition += dwLength;
  103. GlobalUnlock(hSpace);
  104. }
  105. else
  106. {
  107. goto Exit_RecordParms;
  108. }
  109. }
  110. else if (npMF->recordHeader.mtType == DISKMETAFILE)
  111. {
  112. dwLength = count + RECHDRSIZE / 2;
  113. if (npMF->recFileBuffer.fFixedDisk)
  114. {
  115. fileNumber = npMF->recFileNumber;
  116. }
  117. else
  118. {
  119. if ((fileNumber =
  120. OpenFile((LPSTR)npMF->recFileBuffer.szPathName,
  121. (LPOFSTRUCT)&(npMF->recFileBuffer),
  122. OF_PROMPT|OF_REOPEN|READ_WRITE))
  123. == -1)
  124. {
  125. goto Exit_RecordParms;
  126. }
  127. _llseek(fileNumber, (LONG) 0, 2);
  128. }
  129. if (hMF == MetaCache.hMF)
  130. {
  131. lpCache = (LPWORD) GlobalLock(MetaCache.hCache);
  132. if (dwLength + MetaCache.wCachePos >= MetaCache.wCacheSize)
  133. {
  134. if (!AttemptWrite(hdc,
  135. fileNumber,
  136. (DWORD)(MetaCache.wCachePos << 1),
  137. (BYTE huge *) lpCache))
  138. {
  139. MarkMetaFile(hMF);
  140. GlobalUnlock(MetaCache.hCache);
  141. goto Exit_RecordParms;
  142. }
  143. MetaCache.wCachePos = 0;
  144. if (dwLength >= MetaCache.wCacheSize)
  145. {
  146. GlobalUnlock(MetaCache.hCache);
  147. goto NOCACHE;
  148. }
  149. }
  150. lpCache += MetaCache.wCachePos;
  151. *((LPDWORD) lpCache)++ = dwLength;
  152. *lpCache++ = magic;
  153. for (i = 0; i < count; ++i)
  154. *lpCache++ = *lpParm++;
  155. MetaCache.wCachePos += dwLength;
  156. GlobalUnlock(MetaCache.hCache);
  157. }
  158. else
  159. {
  160. NOCACHE:
  161. recPair.rdSize = dwLength;
  162. recPair.rdFunction = magic;
  163. if (!AttemptWrite(hdc,
  164. fileNumber,
  165. (DWORD)RECHDRSIZE,
  166. (BYTE huge *) &recPair))
  167. {
  168. goto Exit_RecordParms;
  169. }
  170. if (count)
  171. {
  172. if (!AttemptWrite(hdc,
  173. fileNumber,
  174. (DWORD)(count * sizeof(WORD)),
  175. (BYTE huge *) lpParm))
  176. {
  177. goto Exit_RecordParms;
  178. }
  179. }
  180. }
  181. if (!(npMF->recFileBuffer.fFixedDisk))
  182. _lclose(fileNumber);
  183. }
  184. }
  185. if (npMF->recordHeader.mtMaxRecord < dwLength)
  186. npMF->recordHeader.mtMaxRecord = dwLength;
  187. npMF->recordHeader.mtSize += dwLength;
  188. status = TRUE;
  189. Exit_RecordParms:
  190. if (status == FALSE)
  191. {
  192. ASSERTGDI( FALSE, "RecordParms: failing");
  193. MarkMetaFile(hMF);
  194. }
  195. LocalUnlock(HANDLEFROMMETADC(hdc));
  196. return(status);
  197. } /* RecordParms */
  198. /***************************** Internal Function ***************************\
  199. * AttempWrite
  200. *
  201. * Tries to write data to a metafile disk file
  202. *
  203. * Returns TRUE iff the write was sucessful
  204. *
  205. *
  206. \***************************************************************************/
  207. BOOL INTERNAL AttemptWrite(hdc, fileNumber, dwBytes, lpData)
  208. HANDLE hdc;
  209. DWORD dwBytes;
  210. WORD fileNumber;
  211. HPBYTE lpData;
  212. {
  213. WORD cShort;
  214. WORD cbWritten;
  215. WORD cBytes;
  216. GdiLogFunc2( " AttemptWrite" );
  217. while(dwBytes > 0)
  218. {
  219. cBytes = (dwBytes > MAXFILECHUNK ? MAXFILECHUNK : (WORD) dwBytes);
  220. if ((cbWritten = _lwrite(fileNumber, (LPSTR)lpData, cBytes)) != cBytes)
  221. {
  222. cShort = cBytes - cbWritten;
  223. lpData += cbWritten;
  224. ASSERTGDI( 0, "Disk full?");
  225. // !!!!! handle disk full -- diskAvailable
  226. if( !IsMetaDC(hdc) )
  227. return(FALSE);
  228. }
  229. /* how many bytes are left? */
  230. dwBytes -= cBytes;
  231. lpData += cbWritten;
  232. }
  233. return(TRUE);
  234. }
  235. /***************************** Internal Function ***************************\
  236. * VOID INTERNAL MarkMetaFile(hmr)
  237. *
  238. * Marks a metafile as failed
  239. *
  240. * Effects:
  241. * Frees the metafile resources
  242. *
  243. \***************************************************************************/
  244. VOID INTERNAL MarkMetaFile(HANDLE hMF)
  245. {
  246. NPMETARECORDER npMF;
  247. GdiLogFunc2( " MarkMetaFile" );
  248. npMF = (NPMETARECORDER) NPFROMMETADC(hMF);
  249. npMF->recFlags |= METAFILEFAILURE;
  250. if (npMF->recordHeader.mtType == MEMORYMETAFILE)
  251. {
  252. if (npMF->hMetaData)
  253. GlobalFree(npMF->hMetaData);
  254. }
  255. else if (npMF->recordHeader.mtType == DISKMETAFILE)
  256. {
  257. if (npMF->recFileBuffer.fFixedDisk)
  258. _lclose(npMF->recFileNumber);
  259. OpenFile((LPSTR) npMF->recFileBuffer.szPathName,
  260. (LPOFSTRUCT) &(npMF->recFileBuffer),
  261. OF_PROMPT|OF_DELETE);
  262. }
  263. }
  264. /***************************** Internal Function **************************\
  265. * MakeLogPalette
  266. *
  267. * Records either CreatePalette or SetPaletteEntries
  268. *
  269. * Returns
  270. *
  271. *
  272. \***************************************************************************/
  273. WORD NEAR MakeLogPalette(HANDLE hMF, HANDLE hPal, WORD magic)
  274. {
  275. WORD cPalEntries;
  276. WORD status = 0xFFFF;
  277. HANDLE hSpace;
  278. WORD cbPalette;
  279. LPLOGPALETTE lpPalette;
  280. GdiLogFunc2( " MakeLogPalette" );
  281. cPalEntries = GetObject( hPal, 0, NULL );
  282. /* alloc memory and get the palette entries */
  283. if (hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,
  284. cbPalette = sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*(cPalEntries)))
  285. {
  286. lpPalette = (LPLOGPALETTE)GlobalLock(hSpace);
  287. lpPalette->palNumEntries = cPalEntries;
  288. GetPaletteEntries( hPal, 0, cPalEntries, lpPalette->palPalEntry);
  289. if (magic == (META_CREATEPALETTE & 255))
  290. {
  291. lpPalette->palVersion = 0x300;
  292. magic = META_CREATEPALETTE;
  293. }
  294. else if (magic == (META_SETPALENTRIES & 255))
  295. {
  296. lpPalette->palVersion = 0; /* really "starting index" */
  297. magic = META_SETPALENTRIES;
  298. }
  299. status = RecordParms(hMF, magic, (DWORD)cbPalette >> 1, (LPWORD)lpPalette);
  300. GlobalUnlock(hSpace);
  301. GlobalFree(hSpace);
  302. }
  303. return(status);
  304. }
  305. /****************************************************************************
  306. * *
  307. * Routine: RecordOther, records parameters for certain "hard functions" *
  308. * *
  309. * Parameters: 1. hMF handle to a metafile header. *
  310. * 2. The magic number of the function being recorded. *
  311. * 3. The number of parmmeter of the function (size of lpParm *
  312. * in words) *
  313. * 4. A long pointer to parameters stored in reverse order *
  314. * *
  315. ****************************************************************************/
  316. BOOL INTERNAL RecordOther(HDC hdc, WORD magic, WORD count, LPWORD lpParm)
  317. {
  318. NPMETARECORDER npMF;
  319. WORD buffer[5];
  320. WORD i;
  321. WORD status = FALSE;
  322. WORD iChar;
  323. WORD position;
  324. HANDLE hSpace = NULL;
  325. WORD iWords;
  326. LPWORD lpSpace;
  327. LPWORD lpTemp;
  328. HANDLE hMF;
  329. dprintf( 6," RecordOther 0x%X", magic);
  330. if ((hMF = GetPMetaFile(hdc)) != -1 )
  331. {
  332. // Handle functions with no DC.
  333. if( hMF == 0 )
  334. {
  335. HANDLE hmfSearch = hFirstMetaFile;
  336. // Play these records into all active metafiles
  337. while( hmfSearch )
  338. {
  339. npMF = (NPMETARECORDER)LocalLock( hmfSearch );
  340. if (!(npMF->recFlags & METAFILEFAILURE))
  341. {
  342. switch (magic & 255)
  343. {
  344. case (META_ANIMATEPALETTE & 255):
  345. {
  346. HANDLE hSpace;
  347. LPSTR lpSpace;
  348. LPSTR lpHolder;
  349. WORD SpaceSize;
  350. LPPALETTEENTRY lpColors;
  351. SpaceSize = 4 + (lpParm[2] * sizeof(PALETTEENTRY));
  352. if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG) SpaceSize)))
  353. {
  354. lpHolder = lpSpace = GlobalLock(hSpace);
  355. *((LPWORD)lpSpace)++ = lpParm[3];
  356. *((LPWORD)lpSpace)++ = lpParm[2];
  357. lpColors = (LPPALETTEENTRY)lpParm;
  358. for (i=0; i<lpParm[2]; i++)
  359. *((LPPALETTEENTRY)lpSpace)++ = *lpColors++;
  360. status = RecordParms(HMFFROMNPMF(npMF), magic, (DWORD)(SpaceSize >> 1),
  361. (LPWORD) lpHolder);
  362. GlobalUnlock(hSpace);
  363. GlobalFree(hSpace);
  364. }
  365. }
  366. break;
  367. case (META_RESIZEPALETTE & 255):
  368. {
  369. status = RecordParms(HMFFROMNPMF(npMF), magic, (DWORD)1, (LPWORD)&lpParm[0]);
  370. }
  371. break;
  372. case (META_DELETEOBJECT & 255):
  373. if (AddToTable(HMFFROMNPMF(npMF), *lpParm, (LPWORD) &position, FALSE) == 1)
  374. {
  375. status = RecordParms(HMFFROMNPMF(npMF), META_DELETEOBJECT, 1UL, &position);
  376. }
  377. break;
  378. } /* switch */
  379. }
  380. LocalUnlock( hmfSearch );
  381. hmfSearch = npMF->metaDCHeader.nextinchain;
  382. } /* while */
  383. }
  384. npMF = (NPMETARECORDER) NPFROMMETADC(hMF);
  385. if (!(npMF->recFlags & METAFILEFAILURE))
  386. {
  387. switch (magic & 255)
  388. {
  389. case (META_FRAMEREGION & 255):
  390. case (META_FILLREGION & 255):
  391. case (META_INVERTREGION & 255):
  392. case (META_PAINTREGION & 255):
  393. // Each region function has at least a region to record
  394. buffer[0] = RecordObject(hMF, magic, count, (LPWORD)&(lpParm[count-1]));
  395. /* Is there a brush too; FillRgn */
  396. if(count > 1 )
  397. buffer[1] = RecordObject(hMF, magic, count, (LPWORD)&(lpParm[count-2]));
  398. /* Are there are extents too; FrameRegion */
  399. if(count > 2)
  400. {
  401. buffer[2] = lpParm[0];
  402. buffer[3] = lpParm[1];
  403. }
  404. status = RecordParms(hMF, magic, (DWORD)count, (LPWORD)buffer);
  405. break;
  406. case (META_FLOODFILL & 255):
  407. buffer[0] = 0; // Regular FloodFill
  408. buffer[1] = lpParm[0];
  409. buffer[2] = lpParm[1];
  410. buffer[3] = lpParm[2];
  411. buffer[4] = lpParm[3];
  412. status = RecordParms(hMF, META_EXTFLOODFILL, (DWORD)count+1, (LPWORD)buffer);
  413. break;
  414. case (META_ESCAPE & 255):
  415. /* record the function number */
  416. {
  417. WORD iBytes;
  418. WORD count;
  419. char * pSpace;
  420. char * pTemp;
  421. LPSTR lpInData;
  422. LPEXTTEXTDATA lpTextData;
  423. WORD function;
  424. *((WORD FAR * FAR *) lpParm)++;
  425. lpInData = (LPSTR) *((WORD FAR * FAR *) lpParm)++;
  426. lpTextData = (LPEXTTEXTDATA) lpInData;
  427. count = iBytes = *lpParm++;
  428. function = *lpParm++;
  429. #ifdef OLDEXTTEXTOUT
  430. if (function == EXTTEXTOUT)
  431. {
  432. iBytes = (lpTextData->cch * (sizeof(WORD)+sizeof(char)))
  433. + 1 + sizeof(EXTTEXTDATA);
  434. }
  435. #endif
  436. if (!(pTemp = pSpace =
  437. (char *) LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (iBytes + (sizeof(WORD) * 2)))))
  438. return(FALSE);
  439. *((WORD *) pTemp)++ = function;
  440. *((WORD *) pTemp)++ = count;
  441. #ifdef OLDEXTTEXTOUT
  442. if (function != EXTTEXTOUT) {
  443. #endif
  444. for (i = 0; i < iBytes; ++i)
  445. *pTemp++ = *lpInData++;
  446. #ifdef OLDEXTTEXTOUT
  447. } else {
  448. *((WORD *) pTemp)++ = lpTextData->xPos;
  449. *((WORD *) pTemp)++ = lpTextData->yPos;
  450. *((WORD *) pTemp)++ = lpTextData->cch;
  451. *((RECT *) pTemp)++ = lpTextData->rcClip;
  452. for (i = 0; i < ((lpTextData->cch + 1) & ~1) ; ++i)
  453. *pTemp++ = lpTextData->lpString[i];
  454. for (i = 0; i < lpTextData->cch; ++i)
  455. *((WORD *) pTemp)++ = lpTextData->lpWidths[i];
  456. }
  457. #endif
  458. /* info block + 2 words for function and count */
  459. status = RecordParms(hMF, magic,
  460. (DWORD)((iBytes + 1) >> 1) + 2,
  461. (LPWORD) pSpace);
  462. LocalFree((HANDLE) pSpace);
  463. }
  464. break;
  465. case (META_POLYLINE & 255):
  466. case (META_POLYGON & 255):
  467. {
  468. WORD iPoints;
  469. WORD *pSpace;
  470. WORD *pTemp;
  471. LPWORD lpPoints;
  472. iPoints = *lpParm++;
  473. iWords = iPoints * 2;
  474. if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,
  475. (iPoints * sizeof(POINT)) + sizeof(WORD))))
  476. return(FALSE);
  477. lpPoints = *((WORD FAR * FAR *) lpParm)++;
  478. *pTemp++ = iPoints;
  479. for (i = 0; i < iWords; ++i)
  480. *pTemp++ = *lpPoints++;
  481. status = RecordParms(hMF, magic, (DWORD)iWords + 1, (LPWORD) pSpace);
  482. LocalFree((HANDLE) pSpace);
  483. }
  484. break;
  485. case (META_POLYPOLYGON & 255):
  486. {
  487. WORD iPoints;
  488. WORD iPolys;
  489. WORD *pSpace;
  490. WORD *pTemp;
  491. LPWORD lpPoints;
  492. LPWORD lpNumPoints;
  493. /* get the number of polygons */
  494. iPolys = *lpParm++;
  495. /* get the pointers to Points and NumPoints */
  496. lpNumPoints = *((WORD FAR * FAR *) lpParm)++;
  497. lpPoints = *((WORD FAR * FAR *) lpParm)++;
  498. /* count the total number of points */
  499. iPoints = 0 ;
  500. for (i=0; i<iPolys; i++)
  501. iPoints += *(lpNumPoints + i) ;
  502. /* allocate space needed for Points, NumPoints and Count */
  503. if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,
  504. (iPoints * sizeof(POINT)) +
  505. iPolys * sizeof(WORD) +
  506. sizeof(WORD))))
  507. return(FALSE);
  508. /* save the Count parameter */
  509. *pTemp++ = iPolys;
  510. /* now copy the NumPoints array*/
  511. for (i = 0; i < iPolys; ++i)
  512. *pTemp++ = *lpNumPoints++;
  513. /* finally copy the number of words in the Points array, remember
  514. the number of words there are double the number of points */
  515. iWords = iPoints * 2;
  516. for (i = 0; i < iWords; ++i)
  517. *pTemp++ = *lpPoints++;
  518. /* total number of words in the parameter list =
  519. iPoints*2(for Points) + iPolys(for NumPoints) + 1(for Count)
  520. and iWords has already iPoints*2 */
  521. iWords += iPolys + 1 ;
  522. /* finally record all the parameters */
  523. status = RecordParms(hMF, magic, (DWORD)iWords , (LPWORD) pSpace);
  524. LocalFree((HANDLE) pSpace);
  525. }
  526. break;
  527. #ifdef DEADCODE
  528. case (META_DRAWTEXT & 255):
  529. {
  530. WORD wFormat;
  531. WORD count;
  532. WORD *pSpace;
  533. WORD *pTemp;
  534. LPBYTE lpString;
  535. LPBYTE lpS;
  536. LPWORD lpRect;
  537. wFormat = *lpParm++;
  538. lpRect = *((WORD FAR * FAR *) lpParm)++;
  539. count = *lpParm++;
  540. lpString = (LPBYTE) *((WORD FAR * FAR *) lpParm)++;
  541. if(count == -1){ /* another null terminated string */
  542. lpS = lpString;
  543. for (count = 0 ; *lpS++ != 0; count++) ;
  544. }
  545. if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,
  546. count + 6 * sizeof(WORD))))
  547. return(FALSE);
  548. *pTemp++ = wFormat;
  549. *pTemp++ = count;
  550. for (i = 0; i < 4; ++i)
  551. *pTemp++ = *lpRect++;
  552. for (i = 0; i < count; ++i)
  553. *((BYTE *) pTemp)++ = *lpString++;
  554. count = (count + 1) >> 1;
  555. status = RecordParms(hMF, magic, (DWORD)count + 6, (LPWORD) pSpace);
  556. LocalFree((HANDLE) pSpace);
  557. }
  558. break;
  559. #endif
  560. case (META_EXTTEXTOUT & 255):
  561. {
  562. WORD iBytes;
  563. WORD count;
  564. WORD options;
  565. WORD *pTemp;
  566. WORD *pSpace;
  567. LPINT lpdx;
  568. LPWORD lpString;
  569. LPRECT lprt;
  570. WORD ii;
  571. lpdx = *((WORD FAR * FAR *) lpParm)++;
  572. count = iBytes = *lpParm++;
  573. lpString = (LPWORD) *((LPSTR FAR *) lpParm)++;
  574. lprt = (LPRECT) *((LPSTR FAR *) lpParm)++;
  575. options = *lpParm++;
  576. /* how much space do we need?
  577. ** room for the char string
  578. ** room for the 4 words that are the fixed parms
  579. ** if there is a dx array, we need room for it
  580. ** if the rectangle is being used, we need room for it
  581. ** and we need extra byte for eventual word roundoff
  582. */
  583. iBytes = (count * (((lpdx) ? sizeof(WORD) : 0)
  584. + sizeof(BYTE)))
  585. + ((options & (ETO_OPAQUE | ETO_CLIPPED))
  586. ? sizeof(RECT) : 0)
  587. + 1 + (sizeof(WORD) * 4);
  588. if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,iBytes)))
  589. return(FALSE);
  590. /* record YPos and XPos */
  591. *pTemp++ = *lpParm++;
  592. *pTemp++ = *lpParm++;
  593. *pTemp++ = count;
  594. *pTemp++ = options;
  595. /* if there's an opaquing rect copy it */
  596. if (options & (ETO_OPAQUE|ETO_CLIPPED))
  597. {
  598. *pTemp++ = lprt->left;
  599. *pTemp++ = lprt->top;
  600. *pTemp++ = lprt->right;
  601. *pTemp++ = lprt->bottom;
  602. }
  603. /* need to copy bytes because it may not be even */
  604. for (ii = 0; ii < count; ++ii)
  605. *((BYTE *)pTemp)++ = *((LPBYTE)lpString)++;
  606. if (count & 1) /* word align */
  607. *((BYTE *)pTemp)++;
  608. if (lpdx)
  609. for (ii = 0; ii < count; ++ii)
  610. *pTemp++ = *lpdx++;
  611. status = RecordParms(hMF, magic, (DWORD)iBytes >> 1,
  612. (LPWORD) pSpace);
  613. LocalFree((HANDLE)pSpace);
  614. }
  615. break;
  616. case (META_TEXTOUT & 255):
  617. {
  618. LPWORD lpString;
  619. WORD *pSpace;
  620. WORD *pTemp;
  621. POINT pt;
  622. iChar = *lpParm++;
  623. if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,
  624. iChar + (sizeof(WORD) * 4))))
  625. return(FALSE);
  626. *pTemp++ = iChar;
  627. lpString = (LPWORD) *((LPSTR FAR *) lpParm)++;
  628. for (i = 0; i < iChar; ++i)
  629. *((BYTE *)pTemp)++ = *((LPBYTE)lpString)++;
  630. if (iChar & 1) /* word align */
  631. *((BYTE *)pTemp)++;
  632. pt.y = *pTemp++ = *lpParm++;
  633. pt.x = *pTemp++ = *lpParm++;
  634. status = RecordParms(hMF, magic, (DWORD)((iChar + 1) >> 1) + 3,
  635. (LPWORD) pSpace);
  636. LocalFree((HANDLE) pSpace);
  637. }
  638. break;
  639. case (META_DIBBITBLT & 255):
  640. case (META_DIBSTRETCHBLT & 255):
  641. {
  642. LPBITMAPINFOHEADER lpDIBInfo ;
  643. DWORD iWords;
  644. DWORD iBits;
  645. WORD wColorTableSize ;
  646. BOOL bSame=FALSE;
  647. HANDLE hSpace=FALSE;
  648. HBITMAP hBitmap;
  649. HDC hSDC;
  650. BYTE bBitsPerPel ;
  651. BITMAP logBitmap;
  652. iWords = (WORD)count;
  653. hSDC = lpParm[iWords - 5];
  654. if (hMF == hSDC || hSDC == NULL)
  655. bSame = TRUE;
  656. else
  657. {
  658. WORD iParms;
  659. if( GetObjectType( (HANDLE)hSDC ) == OBJ_MEMDC)
  660. {
  661. HBITMAP hBitmap;
  662. hBitmap = GetCurrentObject( hSDC, OBJ_BITMAP );
  663. GetObject( hBitmap, sizeof(BITMAP), (LPSTR)&logBitmap);
  664. /* allocate space for the DIB header and bits */
  665. if (!(hSpace = AllocateSpaceForDIB (&logBitmap,
  666. &bBitsPerPel,
  667. &wColorTableSize,
  668. &iBits )))
  669. return (FALSE) ;
  670. lpTemp = lpSpace = (LPWORD) GlobalLock(hSpace);
  671. /*--------------------------------------------------------------------------**
  672. ** copy the parameters from the end of the list which is at the top of the **
  673. ** stack till the hSrcDC parameter,skip the hSrcDC parameter and copy the **
  674. ** rest of the parameters. ** **
  675. **--------------------------------------------------------------------------*/
  676. iParms = (magic == META_DIBBITBLT) ? 4 : 6;
  677. for (i = 0; i < iParms; ++i)
  678. *lpSpace++ = *lpParm++;
  679. /* skip the hSrcDC parameter and reduce parameter count */
  680. *lpParm++;
  681. iWords--;
  682. /* copy the rest of the parameters in the call */
  683. for ( ; i < (WORD)iWords; ++i)
  684. *lpSpace++ = *lpParm++;
  685. /* save the start of the bitmap info header field */
  686. lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace ;
  687. /* preapare the header and return lpSpace pointing to area
  688. for thr bits */
  689. lpSpace = InitializeDIBHeader (lpDIBInfo,
  690. &logBitmap, bBitsPerPel,wColorTableSize) ;
  691. /* lpSpace now points to the area to hold DIB bits */
  692. }
  693. else
  694. return(FALSE);
  695. }
  696. if (bSame)
  697. status = RecordParms(hMF, magic, (DWORD)count, lpParm);
  698. else
  699. {
  700. /* get the bits into the DIB */
  701. hBitmap = SelectObject (hSDC, hStaticBitmap) ;
  702. GetDIBits(hSDC, hBitmap, 0, logBitmap.bmHeight,
  703. (LPBYTE) lpSpace, (LPBITMAPINFO)lpDIBInfo, 0 ) ;
  704. SelectObject (hSDC,hBitmap) ;
  705. /* finally record the parameters into the file*/
  706. status = RecordParms(hMF, magic, (DWORD)(iWords
  707. + (iBits >> 1)) , (LPWORD) lpTemp ) ;
  708. if (hSpace)
  709. {
  710. GlobalUnlock(hSpace);
  711. GlobalFree(hSpace);
  712. }
  713. }
  714. }
  715. break;
  716. case (META_SETDIBTODEV & 255):
  717. {
  718. HANDLE hSpace;
  719. LPWORD lpSpace;
  720. LPWORD lpHolder;
  721. DWORD SpaceSize;
  722. WORD ColorSize;
  723. DWORD BitmapSize;
  724. LPBITMAPINFOHEADER lpBitmapInfo;
  725. HPWORD lpBits;
  726. WORD wUsage;
  727. LPBITMAPCOREHEADER lpBitmapCore; /* used for old DIBs */
  728. DWORD dwi;
  729. HPWORD lpHugeSpace;
  730. wUsage = *lpParm++;
  731. lpBitmapInfo = (LPBITMAPINFOHEADER) *((WORD FAR * FAR *) lpParm)++;
  732. lpBits = (WORD huge *) *((WORD FAR * FAR *) lpParm)++;
  733. /* old style DIB header */
  734. if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER))
  735. {
  736. lpBitmapCore = (LPBITMAPCOREHEADER)lpBitmapInfo;
  737. if (lpBitmapCore->bcBitCount == 24)
  738. ColorSize = 0;
  739. else
  740. ColorSize = (1 << lpBitmapCore->bcBitCount) *
  741. (wUsage == DIB_RGB_COLORS ?
  742. sizeof(RGBQUAD) :
  743. sizeof(WORD));
  744. /* bits per scanline */
  745. BitmapSize = lpBitmapCore->bcWidth *
  746. lpBitmapCore->bcBitCount;
  747. /* bytes per scanline (rounded to DWORD boundary) */
  748. BitmapSize = ((BitmapSize + 31) & (~31)) >> 3;
  749. /* bytes for the NumScans of the bitmap */
  750. BitmapSize *= lpParm[0];
  751. }
  752. /* new style DIB header */
  753. else
  754. {
  755. if (lpBitmapInfo->biClrUsed)
  756. {
  757. ColorSize = ((WORD)lpBitmapInfo->biClrUsed) *
  758. (wUsage == DIB_RGB_COLORS ?
  759. sizeof(RGBQUAD) :
  760. sizeof(WORD));
  761. }
  762. else if (lpBitmapInfo->biBitCount == 24)
  763. ColorSize = 0;
  764. else
  765. ColorSize = (1 << lpBitmapInfo->biBitCount) *
  766. (wUsage == DIB_RGB_COLORS ?
  767. sizeof(RGBQUAD) :
  768. sizeof(WORD));
  769. /* if biSizeImage is already there and we are
  770. ** getting a full image, there is no more work
  771. ** to be done.
  772. ** ****** what about partial RLEs? *****
  773. */
  774. if (!(BitmapSize = lpBitmapInfo->biSizeImage) ||
  775. (lpBitmapInfo->biHeight != lpParm[0]))
  776. {
  777. /* bits per scanline */
  778. BitmapSize = lpBitmapInfo->biWidth *
  779. lpBitmapInfo->biBitCount;
  780. /* bytes per scanline (rounded to DWORD boundary) */
  781. BitmapSize = ((BitmapSize + 31) & (~31)) >> 3;
  782. /* bytes for the NumScans of the bitmap */
  783. BitmapSize *= lpParm[0];
  784. }
  785. }
  786. SpaceSize = (DWORD)sizeof(BITMAPINFOHEADER) + (DWORD)ColorSize +
  787. (DWORD)BitmapSize +
  788. (DWORD)(9*sizeof(WORD));
  789. if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,SpaceSize)))
  790. {
  791. lpHolder = lpSpace = (LPWORD) GlobalLock(hSpace);
  792. /* copy over call parameters */
  793. *lpSpace++ = wUsage;
  794. for (i=0; i<8; i++)
  795. *lpSpace++ = *lpParm++;
  796. /* copy the bitmap header */
  797. if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER))
  798. {
  799. LPBITMAPINFOHEADER lpDIBInfo;
  800. lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace;
  801. lpDIBInfo->biSize = sizeof (BITMAPINFOHEADER);
  802. lpDIBInfo->biWidth = (DWORD)lpBitmapCore->bcWidth;
  803. lpDIBInfo->biHeight = (DWORD)lpBitmapCore->bcHeight;
  804. lpDIBInfo->biPlanes = lpBitmapCore->bcPlanes;
  805. lpDIBInfo->biBitCount = lpBitmapCore->bcBitCount;
  806. lpDIBInfo->biCompression = 0;
  807. lpDIBInfo->biSizeImage = 0;
  808. lpDIBInfo->biXPelsPerMeter = 0;
  809. lpDIBInfo->biYPelsPerMeter = 0;
  810. lpDIBInfo->biClrUsed = 0;
  811. lpDIBInfo->biClrImportant = 0;
  812. /* get lpSpace to point at color table location */
  813. ((LPBITMAPINFOHEADER)lpSpace)++;
  814. /* copy the color table */
  815. lpBitmapCore++; /* get to color table */
  816. if (wUsage == DIB_RGB_COLORS)
  817. {
  818. for (i=0; i< (ColorSize/(sizeof(RGBQUAD))); i++)
  819. {
  820. /* copy the triple */
  821. *((RGBTRIPLE FAR *)lpSpace)++ =
  822. *((RGBTRIPLE FAR *)lpBitmapCore)++;
  823. /* zero out reserved byte */
  824. *((LPBYTE)lpSpace)++ = 0;
  825. }
  826. }
  827. else
  828. {
  829. /* copy over indices */
  830. for (i=0; i< (ColorSize/2); i++)
  831. *lpSpace++ = *((LPWORD)lpBitmapCore)++;
  832. }
  833. }
  834. else
  835. {
  836. *((LPBITMAPINFOHEADER)lpSpace)++ = *lpBitmapInfo++;
  837. /* copy the color table */
  838. for (i=0; i< (ColorSize/2); i++)
  839. *lpSpace++ = *((LPWORD)lpBitmapInfo)++;
  840. }
  841. /* copy the actual bits */
  842. lpHugeSpace = (HPWORD) lpSpace;
  843. for (dwi=0; dwi < (BitmapSize/2); dwi++)
  844. *lpHugeSpace++ = *lpBits++;
  845. status = RecordParms(hMF, magic, (DWORD) (SpaceSize >> 1),
  846. (LPWORD) lpHolder);
  847. GlobalUnlock(hSpace);
  848. GlobalFree(hSpace);
  849. }
  850. }
  851. break;
  852. /* **** this should be combined with the above, but to eliminate possible
  853. ** **** breakage right before shipping, keep it separate.
  854. */
  855. case (META_STRETCHDIB & 255):
  856. {
  857. LPBITMAPINFOHEADER lpBitmapInfo;
  858. LPBITMAPCOREHEADER lpBitmapCore; /* used for old DIBs */
  859. HANDLE hSpace;
  860. LPWORD lpSpace;
  861. LPWORD lpHolder;
  862. DWORD SpaceSize;
  863. WORD ColorSize;
  864. DWORD BitmapSize;
  865. HPWORD lpBits;
  866. WORD wUsage;
  867. DWORD dwi;
  868. HPWORD lpHugeSpace;
  869. DWORD dwROP;
  870. dwROP = *((LPDWORD)lpParm)++;
  871. wUsage = *lpParm++;
  872. lpBitmapInfo = (LPBITMAPINFOHEADER) *((WORD FAR * FAR *) lpParm)++;
  873. lpBits = (HPWORD) *((WORD FAR * FAR *) lpParm)++;
  874. /* old style DIB header */
  875. if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER))
  876. {
  877. lpBitmapCore = (LPBITMAPCOREHEADER)lpBitmapInfo;
  878. if (lpBitmapCore->bcBitCount == 24)
  879. ColorSize = 0;
  880. else
  881. ColorSize = (1 << lpBitmapCore->bcBitCount) *
  882. (wUsage == DIB_RGB_COLORS ?
  883. sizeof(RGBQUAD) :
  884. sizeof(WORD));
  885. /* bits per scanline */
  886. BitmapSize = lpBitmapCore->bcWidth *
  887. lpBitmapCore->bcBitCount;
  888. /* bytes per scanline (rounded to DWORD boundary) */
  889. BitmapSize = ((BitmapSize + 31) & (~31)) >> 3;
  890. /* bytes for the height of the bitmap */
  891. BitmapSize *= lpBitmapCore->bcHeight;
  892. }
  893. /* new style DIB header */
  894. else
  895. {
  896. if (lpBitmapInfo->biClrUsed)
  897. {
  898. ColorSize = ((WORD)lpBitmapInfo->biClrUsed) *
  899. (wUsage == DIB_RGB_COLORS ?
  900. sizeof(RGBQUAD) :
  901. sizeof(WORD));
  902. }
  903. else if (lpBitmapInfo->biBitCount == 24)
  904. ColorSize = 0;
  905. else
  906. ColorSize = (1 << lpBitmapInfo->biBitCount) *
  907. (wUsage == DIB_RGB_COLORS ?
  908. sizeof(RGBQUAD) :
  909. sizeof(WORD));
  910. /* if biSizeImage is already there and we are
  911. ** getting a full image, there is no more work
  912. ** to be done.
  913. */
  914. if (!(BitmapSize = lpBitmapInfo->biSizeImage))
  915. {
  916. /* bits per scanline */
  917. BitmapSize = lpBitmapInfo->biWidth *
  918. lpBitmapInfo->biBitCount;
  919. /* bytes per scanline (rounded to DWORD boundary) */
  920. BitmapSize = ((BitmapSize + 31) & (~31)) >> 3;
  921. /* bytes for the height of the bitmap */
  922. BitmapSize *= (WORD)lpBitmapInfo->biHeight;
  923. }
  924. }
  925. SpaceSize = (DWORD)sizeof(BITMAPINFOHEADER) + (DWORD)ColorSize +
  926. (DWORD)BitmapSize +
  927. (DWORD)(11*sizeof(WORD));
  928. if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,SpaceSize)))
  929. {
  930. lpHolder = lpSpace = (LPWORD) GlobalLock(hSpace);
  931. /* copy over call parameters */
  932. *((LPDWORD)lpSpace)++ = dwROP;
  933. *lpSpace++ = wUsage;
  934. for (i=0; i<8; i++)
  935. *lpSpace++ = *lpParm++;
  936. /* copy the bitmap header */
  937. if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER))
  938. {
  939. LPBITMAPINFOHEADER lpDIBInfo;
  940. lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace;
  941. lpDIBInfo->biSize = sizeof (BITMAPINFOHEADER);
  942. lpDIBInfo->biWidth = (DWORD)lpBitmapCore->bcWidth;
  943. lpDIBInfo->biHeight = (DWORD)lpBitmapCore->bcHeight;
  944. lpDIBInfo->biPlanes = lpBitmapCore->bcPlanes;
  945. lpDIBInfo->biBitCount = lpBitmapCore->bcBitCount;
  946. lpDIBInfo->biCompression = 0;
  947. lpDIBInfo->biSizeImage = 0;
  948. lpDIBInfo->biXPelsPerMeter = 0;
  949. lpDIBInfo->biYPelsPerMeter = 0;
  950. lpDIBInfo->biClrUsed = 0;
  951. lpDIBInfo->biClrImportant = 0;
  952. /* get lpSpace to point at color table location */
  953. ((LPBITMAPINFOHEADER)lpSpace)++;
  954. /* copy the color table */
  955. lpBitmapCore++; /* get to color table */
  956. if (wUsage == DIB_RGB_COLORS)
  957. {
  958. for (i=0; i< (ColorSize/(sizeof(RGBQUAD))); i++)
  959. {
  960. /* copy the triple */
  961. *((RGBTRIPLE FAR *)lpSpace)++ =
  962. *((RGBTRIPLE FAR *)lpBitmapCore)++;
  963. /* zero out reserved byte */
  964. *((LPBYTE)lpSpace)++ = 0;
  965. }
  966. }
  967. else
  968. {
  969. /* copy over indices */
  970. for (i=0; i< (ColorSize/2); i++)
  971. *lpSpace++ = *((LPWORD)lpBitmapCore)++;
  972. }
  973. }
  974. else
  975. {
  976. *((LPBITMAPINFOHEADER)lpSpace)++ = *lpBitmapInfo++;
  977. /* copy the color table */
  978. for (i=0; i< (ColorSize/2); i++)
  979. *lpSpace++ = *((LPWORD)lpBitmapInfo)++;
  980. }
  981. /* copy the actual bits */
  982. lpHugeSpace = (HPWORD) lpSpace;
  983. for (dwi=0; dwi < (BitmapSize/2); dwi++)
  984. *lpHugeSpace++ = *lpBits++;
  985. status = RecordParms(hMF, magic, (DWORD) (SpaceSize >> 1),
  986. (LPWORD) lpHolder);
  987. GlobalUnlock(hSpace);
  988. GlobalFree(hSpace);
  989. }
  990. }
  991. break;
  992. case (META_REALIZEPALETTE & 255):
  993. {
  994. /* we need to see if the palette has changed since
  995. ** it was selected into the DC. if so, we need to
  996. ** adjust things with a SetPaletteEntries call
  997. */
  998. status = MakeLogPalette(hMF, npMF->recCurObjects[OBJ_PALETTE-1], META_SETPALENTRIES);
  999. if (status)
  1000. status = RecordParms(hMF, META_REALIZEPALETTE, (DWORD)0, (LPWORD) NULL);
  1001. }
  1002. break;
  1003. case (META_SELECTPALETTE & 255):
  1004. lpParm++; /* skip over fore/back flag */
  1005. npMF->recCurObjects[OBJ_PALETTE-1] = *lpParm; /* pal used in this DC */
  1006. if ((position = RecordObject(hMF, magic, count, lpParm)) != -1)
  1007. status = RecordParms(hMF, META_SELECTPALETTE, 1UL, &position);
  1008. break;
  1009. case (META_SELECTOBJECT & 255):
  1010. if (*lpParm)
  1011. {
  1012. if ((position = RecordObject(hMF, magic, count, lpParm)) == -1)
  1013. return(FALSE);
  1014. else
  1015. {
  1016. HANDLE hObject;
  1017. status = RecordParms(hMF, META_SELECTOBJECT, 1UL, &position);
  1018. /* maintain the new selection in the CurObject table */
  1019. hObject = *lpParm;
  1020. npMF->recCurObjects[GetObjectType(hObject)-1] = hObject;
  1021. }
  1022. }
  1023. break;
  1024. case (META_RESETDC & 255):
  1025. status = RecordParms( hMF, magic,
  1026. ((LPDEVMODE)lpParm)->dmSize +
  1027. ((LPDEVMODE)lpParm)->dmDriverExtra,
  1028. lpParm );
  1029. break;
  1030. case (META_STARTDOC & 255):
  1031. {
  1032. short iBytes;
  1033. LPSTR lpSpace;
  1034. LPSTR lpsz;
  1035. short n;
  1036. lpsz = (LPSTR)lpParm; // point to lpDoc
  1037. n = lstrlen((LPSTR)lpsz + 2) + 1;
  1038. iBytes = n + lstrlen((LPSTR)lpsz + 6) + 1;
  1039. lpSpace = (char *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,iBytes);
  1040. lstrcpy(lpSpace, (LPSTR)lpsz + 2);
  1041. lstrcpy(lpSpace + n + 1, lpsz + 6);
  1042. status = RecordParms(hMF, magic, (DWORD)(iBytes >> 1), (LPWORD)lpSpace);
  1043. LocalFree((HANDLE)(DWORD)lpSpace);
  1044. }
  1045. break;
  1046. }
  1047. return(status);
  1048. }
  1049. }
  1050. } /* RecordOther */
  1051. /***************************** Internal Function ***************************\
  1052. * RecordObject
  1053. *
  1054. * Records the use of an object by creating the object
  1055. *
  1056. * Returns: index of object in table
  1057. *
  1058. *
  1059. \***************************************************************************/
  1060. int INTERNAL RecordObject(HANDLE hMF, WORD magic, WORD count, LPWORD lpParm)
  1061. {
  1062. LPBITMAPINFOHEADER lpDIBInfo ;
  1063. WORD status;
  1064. WORD position;
  1065. HANDLE hObject;
  1066. WORD objType;
  1067. BYTE bBitsPerPel;
  1068. WORD wColorTableSize;
  1069. DWORD iBits ;
  1070. WORD i;
  1071. HANDLE hSpace = NULL ;
  1072. LPWORD lpSpace;
  1073. LPWORD lpTemp ;
  1074. BYTE objBuf[MAXOBJECTSIZE];
  1075. dprintf( 6," RecordObject 0x%X", magic);
  1076. hObject = *lpParm;
  1077. hMF = MAKEMETADC(hMF);
  1078. ASSERTGDI( IsMetaDC(hMF), "RecordObject: Expects only valid metafiles");
  1079. // Add the object to the metafiles list
  1080. if ((status = AddToTable(hMF, hObject, (LPWORD) &position, TRUE)) == -1)
  1081. return(status);
  1082. else if (status == FALSE)
  1083. {
  1084. objType = GetObjectAndType( hObject, objBuf );
  1085. switch (objType)
  1086. {
  1087. case OBJ_PEN:
  1088. status = RecordParms(hMF, META_CREATEPENINDIRECT,
  1089. (DWORD)((sizeof(LOGPEN) + 1) >> 1),
  1090. (LPWORD)objBuf );
  1091. break;
  1092. case OBJ_FONT:
  1093. /* size of LOGFONT adjusted based on the length of the facename */
  1094. status = RecordParms(hMF, META_CREATEFONTINDIRECT,
  1095. (DWORD)((1 + lstrlen((LPSTR) ((LPLOGFONT)objBuf)->lfFaceName) +
  1096. sizeof(LOGFONT) - LF_FACESIZE + 1) >> 1),
  1097. (LPWORD) objBuf);
  1098. break;
  1099. /*
  1100. !!! in win2, METACREATEREGION records contained an entire region object,
  1101. !!! including the full header. this header changed in win3.
  1102. !!!
  1103. !!! to remain compatible, the region records will be saved with the
  1104. !!! win2 header. here we save our region with a win2 header.
  1105. */
  1106. case OBJ_RGN:
  1107. {
  1108. LPWIN3REGION lpw3rgn = (LPWIN3REGION)NULL;
  1109. DWORD cbNTRgnData;
  1110. WORD sel;
  1111. DWORD curRectl = 0;
  1112. WORD cScans = 0;
  1113. WORD maxScanEntry = 0;
  1114. WORD curScanEntry;
  1115. WORD cbw3data;
  1116. LPRGNDATA lprgn = (LPRGNDATA)NULL;
  1117. LPRECTL lprcl;
  1118. LPSCAN lpScan;
  1119. status = FALSE; // just in case something goes wrong
  1120. // Get the NT Region Data
  1121. cbNTRgnData = GetRegionData( hObject, 0, NULL );
  1122. if (cbNTRgnData == 0)
  1123. break;
  1124. sel = GlobalAlloc( GMEM_FIXED, cbNTRgnData);
  1125. if (!sel)
  1126. break;
  1127. lprgn = (LPRGNDATA)MAKELONG(0, sel);
  1128. cbNTRgnData = GetRegionData( hObject, cbNTRgnData, lprgn );
  1129. if (cbNTRgnData == 0)
  1130. break;
  1131. lprcl = (LPRECTL)lprgn->Buffer;
  1132. // Create the Windows 3.x equivalent
  1133. // worst case is one scan for each rect
  1134. cbw3data = 2*sizeof(WIN3REGION) + (WORD)lprgn->rdh.nCount*sizeof(SCAN);
  1135. sel = GlobalAlloc( GMEM_FIXED, cbw3data);
  1136. if (!sel)
  1137. break;
  1138. lpw3rgn = (LPWIN3REGION)MAKELONG(0, sel);
  1139. GetRgnBox( hObject, &lpw3rgn->rcBounding );
  1140. cbw3data = sizeof(WIN3REGION) - sizeof(SCAN) + 2;
  1141. // visit all the rects
  1142. lpScan = lpw3rgn->aScans;
  1143. while(curRectl < lprgn->rdh.nCount)
  1144. {
  1145. LPWORD lpXEntry;
  1146. WORD cbScan;
  1147. curScanEntry = 0; // Current X pair in this scan
  1148. lpScan->scnPntTop = (WORD)lprcl[curRectl].yTop;
  1149. lpScan->scnPntBottom = (WORD)lprcl[curRectl].yBottom;
  1150. lpXEntry = lpScan->scnPntsX;
  1151. // handle rects on this scan
  1152. do
  1153. {
  1154. lpXEntry[curScanEntry + 0] = (WORD)lprcl[curRectl].xLeft;
  1155. lpXEntry[curScanEntry + 1] = (WORD)lprcl[curRectl].xRight;
  1156. curScanEntry += 2;
  1157. curRectl++;
  1158. } while ( (curRectl < lprgn->rdh.nCount)
  1159. && (lprcl[curRectl-1].yTop == lprcl[curRectl].yTop)
  1160. && (lprcl[curRectl-1].yBottom == lprcl[curRectl].yBottom)
  1161. );
  1162. lpScan->scnPntCnt = curScanEntry;
  1163. lpXEntry[curScanEntry] = curScanEntry; // Count also follows Xs
  1164. cScans++;
  1165. if (curScanEntry > maxScanEntry)
  1166. maxScanEntry = curScanEntry;
  1167. // account for each new scan + each X1 X2 Entry but the first
  1168. cbScan = sizeof(SCAN)-(sizeof(WORD)*2) + (curScanEntry*sizeof(WORD));
  1169. cbw3data += cbScan;
  1170. lpScan = (LPSCAN)(((LPBYTE)lpScan) + cbScan);
  1171. }
  1172. // Initialize the header
  1173. lpw3rgn->nextInChain = 0;
  1174. lpw3rgn->ObjType = 6; // old Windows OBJ_RGN identifier
  1175. lpw3rgn->ObjCount= 0x2F6;
  1176. lpw3rgn->cbRegion = cbw3data; // don't count type and next
  1177. lpw3rgn->cScans = cScans;
  1178. lpw3rgn->maxScan = maxScanEntry;
  1179. status = RecordParms(hMF, META_CREATEREGION,
  1180. cbw3data-1 >> 1, // Convert to count of words
  1181. (LPWORD) lpw3rgn);
  1182. GlobalFree( HIWORD(lprgn) );
  1183. GlobalFree( HIWORD(lpw3rgn) );
  1184. }
  1185. break;
  1186. case OBJ_BRUSH:
  1187. switch (((LPLOGBRUSH)objBuf)->lbStyle)
  1188. {
  1189. case BS_DIBPATTERN:
  1190. {
  1191. WORD cbDIBBits;
  1192. BITMAP logBitmap;
  1193. /* get the pattern DIB */
  1194. GetObject( (HANDLE)((LPLOGBRUSH)objBuf)->lbHatch, sizeof(BITMAP), (LPSTR)&logBitmap );
  1195. cbDIBBits = logBitmap.bmWidthBytes * logBitmap.bmHeight;
  1196. if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG)(cbDIBBits + 4))))
  1197. {
  1198. lpTemp = lpSpace = (LPWORD)GlobalLock (hSpace) ;
  1199. /* mark this as a DIB pattern brush */
  1200. *lpSpace++ = BS_DIBPATTERN;
  1201. /* set the usage word */
  1202. *lpSpace++ = (WORD)((LPLOGBRUSH)objBuf)->lbColor;
  1203. // lpPackedDIB = (LPWORD)GlobalLock(hPatBits);
  1204. /* copy the bits to the new buffer */
  1205. for (i = 0; i < (cbDIBBits >> 1); i++)
  1206. *lpSpace++ = *logBitmap.bmBits++;
  1207. status = RecordParms (hMF, META_DIBCREATEPATTERNBRUSH,
  1208. (DWORD)(cbDIBBits >> 1) + 2, (LPWORD)lpTemp);
  1209. /* release the allocated space */
  1210. GlobalUnlock (hSpace) ;
  1211. GlobalFree (hSpace) ;
  1212. }
  1213. }
  1214. break;
  1215. case BS_PATTERN:
  1216. {
  1217. BITMAP logBitmap;
  1218. if (GetObject((HANDLE)((LPLOGBRUSH)objBuf)->lbHatch, sizeof(logBitmap), (LPSTR)&logBitmap))
  1219. {
  1220. /* allocate space for the device independent bitmap */
  1221. if (hSpace = AllocateSpaceForDIB (&logBitmap,
  1222. (LPBYTE)&bBitsPerPel,
  1223. (LPWORD) &wColorTableSize ,
  1224. (LPDWORD) &iBits))
  1225. {
  1226. /* get a pointer to the allocated space */
  1227. lpTemp = lpSpace = (LPWORD) GlobalLock (hSpace) ;
  1228. /* mark this as a normal pattern brush */
  1229. *lpSpace++ = BS_PATTERN;
  1230. /* use RGB colors */
  1231. *lpSpace++ = DIB_RGB_COLORS;
  1232. /* this also will be a pointer to the DIB header */
  1233. lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace ;
  1234. /* prepare the header of the bitmap and get a pointer to the
  1235. start of the area which is to hold the bits */
  1236. lpSpace = InitializeDIBHeader (lpDIBInfo,
  1237. &logBitmap, bBitsPerPel, wColorTableSize);
  1238. /* convert the bits into the DIB format */
  1239. // !!! validate that the DC is ignored
  1240. GetDIBits (hScreenDC, (HBITMAP)((LPLOGBRUSH)objBuf)->lbHatch,
  1241. 0, logBitmap.bmHeight,
  1242. (LPSTR) lpSpace, (LPBITMAPINFO)lpDIBInfo,0) ;
  1243. /* now record the Header and Bits as parameters */
  1244. status = RecordParms (hMF, META_DIBCREATEPATTERNBRUSH,
  1245. (DWORD)(iBits >> 1) + 2, (LPWORD) lpTemp);
  1246. /* release the allocated space */
  1247. GlobalUnlock (hSpace) ;
  1248. GlobalFree (hSpace) ;
  1249. }
  1250. }
  1251. }
  1252. break;
  1253. default:
  1254. /* non-pattern brush */
  1255. status = RecordParms(hMF, META_CREATEBRUSHINDIRECT,
  1256. (DWORD)((sizeof(LOGBRUSH) + 1) >> 1),
  1257. (LPWORD)objBuf);
  1258. break;
  1259. } /* Brush Type switch */
  1260. break; /* Brush object case */
  1261. case OBJ_PALETTE:
  1262. status = MakeLogPalette(hMF, hObject, META_CREATEPALETTE);
  1263. break;
  1264. default:
  1265. ASSERTGDIW( 0, "unknown case RecordObject: %d", objType );
  1266. break;
  1267. }
  1268. // RecordObj10:
  1269. }
  1270. ASSERTGDI( status == TRUE, "RecordObject: Failing");
  1271. return ((status == TRUE) ? position : -1);
  1272. } /* RecordObject */
  1273. /***************************** Internal Function ***************************\
  1274. * ProbeSize
  1275. *
  1276. * Determines if there is sufficient space for metafiling the dwLength
  1277. * words into the memory metafile
  1278. *
  1279. * Returns: a global handle of where next metafile is to be recorded
  1280. * or FALSE if unable to allocate more memory
  1281. *
  1282. \***************************************************************************/
  1283. HANDLE INTERNAL ProbeSize(NPMETARECORDER npMF, DWORD dwLength)
  1284. {
  1285. DWORD nWords;
  1286. DWORD totalWords;
  1287. BOOL status = FALSE;
  1288. HANDLE hand;
  1289. GdiLogFunc3( " ProbeSize");
  1290. if (npMF->hMetaData == NULL)
  1291. {
  1292. nWords = ((DWORD)DATASIZE > dwLength) ? (DWORD)DATASIZE : dwLength;
  1293. totalWords = (nWords * sizeof(WORD)) + sizeof(METAHEADER);
  1294. if (npMF->hMetaData = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, totalWords))
  1295. {
  1296. npMF->sizeBuffer = nWords;
  1297. npMF->recFilePosition = 0;
  1298. status = TRUE;
  1299. }
  1300. }
  1301. else if(npMF->sizeBuffer < (npMF->recFilePosition + dwLength))
  1302. {
  1303. nWords = ((DWORD)DATASIZE > dwLength) ? (DWORD)DATASIZE : dwLength;
  1304. nWords += npMF->sizeBuffer;
  1305. totalWords = (nWords * sizeof(WORD)) + sizeof(METAHEADER);
  1306. if (hand = GlobalReAlloc(npMF->hMetaData, totalWords, GMEM_MOVEABLE))
  1307. {
  1308. npMF->hMetaData = hand;
  1309. npMF->sizeBuffer = nWords;
  1310. status = TRUE;
  1311. }
  1312. }
  1313. else
  1314. {
  1315. status = TRUE;
  1316. }
  1317. return ((status) ? npMF->hMetaData : NULL);
  1318. }
  1319. /***************************** Internal Function ***************************\
  1320. * AddToTable
  1321. *
  1322. * Add an object (brush, pen...) to a list of objects associated with the
  1323. * metafile.
  1324. *
  1325. *
  1326. *
  1327. * Returns: TRUE if object is already in table
  1328. * FALSE if object was just added to table
  1329. * -1 if failure
  1330. *
  1331. * Remarks
  1332. * bAdd is TRUE iff the object is being added otherwise it is being deleted
  1333. *
  1334. \***************************************************************************/
  1335. WORD INTERNAL AddToTable(HANDLE hMF, HANDLE hObject, LPWORD pPosition, BOOL bAdd)
  1336. {
  1337. NPMETARECORDER npMF;
  1338. WORD iEmptySpace = -1;
  1339. WORD i;
  1340. WORD status = -1;
  1341. HANDLE hTable;
  1342. OBJECTTABLE *pHandleTable;
  1343. GdiLogFunc2(" AddToTable");
  1344. if ((hMF = GetPMetaFile(hMF)) != -1 )
  1345. {
  1346. npMF = (NPMETARECORDER) LocalLock(hMF);
  1347. if (hTable = npMF->hObjectTable)
  1348. {
  1349. pHandleTable = (NPOBJECTTABLE) LMHtoP(hTable);
  1350. for (i = 0; i < npMF->recordHeader.mtNoObjects; ++i)
  1351. {
  1352. if (hObject == pHandleTable[i].objectCurHandle ) //!!!!! used to be check unique ID#
  1353. {
  1354. *pPosition = i;
  1355. status = TRUE;
  1356. // if we are doing a METADELETEOBJECT.
  1357. // delete object from table
  1358. if (!bAdd)
  1359. {
  1360. pHandleTable[i].objectIndex = NULL;
  1361. pHandleTable[i].objectCurHandle = NULL;
  1362. }
  1363. goto AddToTable10;
  1364. }
  1365. /* if the entry has been deleted, we want to add a new object
  1366. ** in its place. iEmptySpace will tell us where that place is.
  1367. */
  1368. else if ((pHandleTable[i].objectIndex == NULL) && (iEmptySpace == -1))
  1369. iEmptySpace = i;
  1370. }
  1371. }
  1372. if (bAdd)
  1373. {
  1374. // If there is no object table for this MetaFile then Allocate one.
  1375. if (hTable == NULL)
  1376. {
  1377. npMF->hObjectTable = hTable = LocalAlloc(LMEM_MOVEABLE, sizeof(OBJECTTABLE));
  1378. }
  1379. else if (iEmptySpace == -1)
  1380. hTable = LocalReAlloc(hTable, (npMF->recordHeader.mtNoObjects + 1)
  1381. * sizeof(OBJECTTABLE), LMEM_MOVEABLE);
  1382. if (hTable)
  1383. {
  1384. pHandleTable = (NPOBJECTTABLE) LMHtoP(hTable);
  1385. if (iEmptySpace == -1)
  1386. *pPosition = npMF->recordHeader.mtNoObjects++;
  1387. else
  1388. *pPosition = iEmptySpace;
  1389. pHandleTable[*pPosition].objectIndex = hObject; //!!!!! pObjHead->ilObjCount;
  1390. pHandleTable[*pPosition].objectCurHandle = hObject;
  1391. status = FALSE;
  1392. }
  1393. }
  1394. AddToTable10:;
  1395. LocalUnlock(hMF);
  1396. }
  1397. ASSERTGDI( status != -1, "AddToTable: Failing");
  1398. return(status);
  1399. }
  1400. #if 0 // this is going to gdi.dll
  1401. /***************************** Internal Function **************************\
  1402. * HDC GDIENTRY CreateMetaFile
  1403. *
  1404. * Creates a MetaFile DC
  1405. *
  1406. *
  1407. * Effects:
  1408. *
  1409. \***************************************************************************/
  1410. HDC GDIENTRY CreateMetaFile(LPSTR lpFileName)
  1411. {
  1412. BOOL status=FALSE;
  1413. GLOBALHANDLE hMF;
  1414. NPMETARECORDER npMF;
  1415. GdiLogFunc("CreateMetaFile");
  1416. if (hMF = LocalAlloc(LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof(METARECORDER)))
  1417. {
  1418. npMF = (NPMETARECORDER) LocalLock(hMF);
  1419. npMF->metaDCHeader.ilObjType = OBJ_METAFILE;
  1420. npMF->metaDCHeader.ident = ID_METADC;
  1421. npMF->recordHeader.mtHeaderSize = HEADERSIZE;
  1422. npMF->recordHeader.mtVersion = METAVERSION;
  1423. npMF->recordHeader.mtSize = HEADERSIZE;
  1424. if (lpFileName)
  1425. {
  1426. npMF->recordHeader.mtType = DISKMETAFILE;
  1427. if (((npMF->recFileNumber = OpenFile(lpFileName,
  1428. (LPOFSTRUCT) &(npMF->recFileBuffer),
  1429. OF_CREATE|READ_WRITE))
  1430. != -1)
  1431. && (_lwrite(npMF->recFileNumber, (LPSTR)npMF, sizeof(METAHEADER))
  1432. == sizeof(METAHEADER)))
  1433. {
  1434. status = TRUE;
  1435. }
  1436. if (npMF->recFileNumber != -1)
  1437. {
  1438. if (!(npMF->recFileBuffer.fFixedDisk))
  1439. _lclose(npMF->recFileNumber);
  1440. }
  1441. if (!MetaCache.hCache)
  1442. {
  1443. MetaCache.hCache = AllocBuffer(&MetaCache.wCacheSize);
  1444. MetaCache.wCacheSize >>= 1;
  1445. MetaCache.hMF = hMF;
  1446. MetaCache.wCachePos = 0;
  1447. }
  1448. }
  1449. else
  1450. {
  1451. npMF->recordHeader.mtType = MEMORYMETAFILE;
  1452. status = TRUE;
  1453. }
  1454. }
  1455. // If successfull then add the metafile to the linked list
  1456. if( status != FALSE )
  1457. {
  1458. if( hFirstMetaFile == 0 )
  1459. {
  1460. hFirstMetaFile = hMF;
  1461. }
  1462. else
  1463. {
  1464. npMF->metaDCHeader.nextinchain = hFirstMetaFile;
  1465. hFirstMetaFile = hMF;
  1466. }
  1467. LocalUnlock( hMF );
  1468. }
  1469. return ((status) ? MAKEMETADC(hMF) : FALSE);
  1470. }
  1471. /***************************** Internal Function **************************\
  1472. * HANDLE GDIENTRY CloseMetaFile
  1473. *
  1474. * The CloseMetaFile function closes the metafile device context and creates a
  1475. * metafile handle that can be used to play the metafile by using the
  1476. * PlayMetaFile function.
  1477. *
  1478. * Effects:
  1479. *
  1480. \***************************************************************************/
  1481. HANDLE GDIENTRY CloseMetaFile(HANDLE hdc)
  1482. {
  1483. BOOL status = FALSE;
  1484. HANDLE hMetaFile=NULL;
  1485. LPMETADATA lpMetaData;
  1486. LPMETAFILE lpMFNew;
  1487. WORD fileNumber;
  1488. NPMETARECORDER npMF;
  1489. DWORD metafileSize;
  1490. LPWORD lpCache;
  1491. HANDLE hMF;
  1492. HANDLE hMFSearch;
  1493. int rc;
  1494. GdiLogFunc("CloseMetaFile");
  1495. hMF = HANDLEFROMMETADC(hdc);
  1496. if (hMF && RecordParms(hMF, 0, (DWORD)0, (LONG)0))
  1497. {
  1498. npMF = (NPMETARECORDER)LocalLock(hMF);
  1499. if (!(npMF->recFlags & METAFILEFAILURE))
  1500. {
  1501. if (npMF->recordHeader.mtType == MEMORYMETAFILE)
  1502. {
  1503. lpMetaData = (LPMETADATA) GlobalLock(npMF->hMetaData);
  1504. lpMetaData->dataHeader = npMF->recordHeader;
  1505. metafileSize = (npMF->recordHeader.mtSize * sizeof(WORD))
  1506. + sizeof(METAHEADER);
  1507. GlobalUnlock(hMetaFile = npMF->hMetaData);
  1508. if (!(status = (BOOL) GlobalReAlloc(hMetaFile,
  1509. (LONG)metafileSize,
  1510. GMEM_MOVEABLE)))
  1511. GlobalFree(hMetaFile);
  1512. }
  1513. else
  1514. /* rewind the file and write the header out */
  1515. if (hMetaFile = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG) sizeof(METAFILE)))
  1516. {
  1517. lpMFNew = (LPMETAFILE) GlobalLock(hMetaFile);
  1518. lpMFNew->MetaFileHeader = npMF->recordHeader;
  1519. npMF->recordHeader.mtType = MEMORYMETAFILE;
  1520. if (npMF->recFileBuffer.fFixedDisk)
  1521. fileNumber = npMF->recFileNumber;
  1522. else
  1523. {
  1524. if ((fileNumber = OpenFile((LPSTR) npMF->recFileBuffer.szPathName,
  1525. (LPOFSTRUCT) &(npMF->recFileBuffer),
  1526. OF_PROMPT | OF_REOPEN | READ_WRITE))
  1527. == -1)
  1528. {
  1529. GlobalUnlock(hMetaFile);
  1530. GlobalFree(hMetaFile);
  1531. LocalUnlock(hMF);
  1532. if (MetaCache.hMF == hMF)
  1533. {
  1534. GlobalFree(MetaCache.hCache);
  1535. MetaCache.hCache = MetaCache.hMF = 0;
  1536. }
  1537. goto errCloseMetaFile;
  1538. }
  1539. }
  1540. if (MetaCache.hCache && MetaCache.hMF == hMF)
  1541. {
  1542. _llseek(fileNumber, (LONG) 0, 2);
  1543. lpCache = (LPWORD) GlobalLock(MetaCache.hCache);
  1544. rc = (MetaCache.wCachePos) ?
  1545. AttemptWrite(hMF,
  1546. fileNumber,
  1547. (DWORD)(MetaCache.wCachePos << 1),
  1548. (LPSTR) lpCache)
  1549. : TRUE;
  1550. GlobalUnlock(MetaCache.hCache);
  1551. GlobalFree(MetaCache.hCache);
  1552. MetaCache.hCache = MetaCache.hMF = 0;
  1553. if (!rc)
  1554. {
  1555. MarkMetaFile(hMF);
  1556. goto errCloseMetaFile;
  1557. }
  1558. }
  1559. _llseek(fileNumber, (LONG) 0, 0);
  1560. if(_lwrite(fileNumber, (LPSTR) (&npMF->recordHeader),
  1561. sizeof(METAHEADER)) == sizeof(METAHEADER))
  1562. {
  1563. status = TRUE;
  1564. }
  1565. lpMFNew->MetaFileBuffer = npMF->recFileBuffer;
  1566. _lclose(fileNumber);
  1567. GlobalUnlock(hMetaFile);
  1568. }
  1569. if (npMF->hObjectTable)
  1570. {
  1571. LocalFree((HANDLE) npMF->hObjectTable);
  1572. }
  1573. }
  1574. /* Remove the meta file from the list of active metafiles */
  1575. hMFSearch = hFirstMetaFile;
  1576. if( hFirstMetaFile == hMF )
  1577. {
  1578. hFirstMetaFile = npMF->metaDCHeader.nextinchain;
  1579. }
  1580. else
  1581. {
  1582. while( hMFSearch )
  1583. {
  1584. NPMETARECORDER npMFSearch;
  1585. HANDLE hNext;
  1586. npMFSearch = (NPMETARECORDER)LocalLock(hMFSearch);
  1587. hNext = npMFSearch->metaDCHeader.nextinchain;
  1588. if( hNext == hMF )
  1589. {
  1590. npMFSearch->metaDCHeader.nextinchain =
  1591. npMF->metaDCHeader.nextinchain;
  1592. }
  1593. else
  1594. {
  1595. hNext = npMFSearch->metaDCHeader.nextinchain;
  1596. }
  1597. LocalUnlock(hMFSearch);
  1598. hMFSearch = hNext;
  1599. }
  1600. }
  1601. LocalUnlock(hMF);
  1602. LocalFree(hMF);
  1603. }
  1604. errCloseMetaFile:
  1605. return ((status) ? hMetaFile : FALSE);
  1606. }
  1607. /***************************** Internal Function **************************\
  1608. * CopyMetaFile(hSrcMF, lpFileName)
  1609. *
  1610. * Copies the metafile (hSrcMF) to a new metafile with name lpFileName. The
  1611. * function then returns a handle to this new metafile if the function was
  1612. * successful.
  1613. *
  1614. * Retuns a handle to a new metafile, 0 iff failure
  1615. *
  1616. * IMPLEMENTATION:
  1617. * The source and target metafiles are checked to see if they are both memory
  1618. * metafile and if so a piece of global memory is allocated and the metafile
  1619. * is simply copied.
  1620. * If this is not the case CreateMetaFile is called with lpFileName and then
  1621. * records are pulled out of the source metafile (using GetEvent) and written
  1622. * into the destination metafile one at a time (using RecordParms).
  1623. *
  1624. * Lock the source
  1625. * if source is a memory metafile and the destination is a memory metafile
  1626. * alloc the same size global memory as the source
  1627. * copy the bits directly
  1628. * else
  1629. * get a metafile handle by calling CreateMetaFile
  1630. * while GetEvent returns records form the source
  1631. * record the record in the new metafile
  1632. *
  1633. * close the metafile
  1634. *
  1635. * return the new metafile handle
  1636. *
  1637. \***************************************************************************/
  1638. HANDLE GDIENTRY CopyMetaFile(HANDLE hSrcMF, LPSTR lpFileName)
  1639. {
  1640. DWORD i;
  1641. DWORD iBytes;
  1642. LPMETAFILE lpMF;
  1643. LPMETAFILE lpDstMF;
  1644. LPMETARECORD lpMR = NULL;
  1645. HANDLE hTempMF;
  1646. HANDLE hDstMF;
  1647. NPMETARECORDER pDstMF;
  1648. WORD state;
  1649. GdiLogFunc( "CopyMetaFile" );
  1650. if (!IsValidMetaFile(hSrcMF))
  1651. return NULL;
  1652. if (hSrcMF && (lpMF = (LPMETAFILE) GlobalLock(hSrcMF)))
  1653. {
  1654. state = (lpMF->MetaFileHeader.mtType == MEMORYMETAFILE) ? 0 : 2;
  1655. state |= (lpFileName) ? 1 : 0;
  1656. switch (state)
  1657. {
  1658. case 0: /* memory -> memory */
  1659. iBytes = GlobalSize(hSrcMF);
  1660. if (hDstMF = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, (DWORD) iBytes))
  1661. {
  1662. lpDstMF = (LPMETAFILE) GlobalLock(hDstMF);
  1663. iBytes = iBytes/2; /* get WORD count */
  1664. for (i = 0; i < iBytes; ++i)
  1665. *((WORD huge *) lpDstMF)++ = *((WORD huge *) lpMF)++;
  1666. GlobalUnlock(hDstMF);
  1667. }
  1668. break;
  1669. case 3: /* disk -> disk */
  1670. hDstMF = CopyFile(lpMF->MetaFileBuffer.szPathName,
  1671. lpFileName)
  1672. ? GetMetaFile(lpFileName) : NULL;
  1673. break;
  1674. case 1:
  1675. case 2:
  1676. if (hDstMF = CreateMetaFile(lpFileName))
  1677. {
  1678. while (lpMR = GetEvent(lpMF, lpMR, FALSE))
  1679. if (!RecordParms(hDstMF, lpMR->rdFunction,
  1680. lpMR->rdSize - 3,
  1681. (LPWORD) lpMR->rdParm))
  1682. {
  1683. MarkMetaFile(hDstMF);
  1684. LocalFree(hDstMF);
  1685. goto CopyMetaFile10;
  1686. }
  1687. pDstMF = (NPMETARECORDER) NPFROMMETADC(hDstMF);
  1688. pDstMF->recordHeader = lpMF->MetaFileHeader;
  1689. pDstMF->recordHeader.mtType = (lpFileName) ? DISKMETAFILE
  1690. : MEMORYMETAFILE;
  1691. hDstMF = (hTempMF = CloseMetaFile(hDstMF)) ? hTempMF : NULL;
  1692. }
  1693. break;
  1694. }
  1695. CopyMetaFile10:;
  1696. GlobalUnlock(hSrcMF);
  1697. }
  1698. return(hDstMF);
  1699. }
  1700. /***************************** Internal Function ***************************\
  1701. * HANDLE GDIENTRY GetMetaFileBits(HANDLE hMF)
  1702. *
  1703. * The GetMetaFileBits function returns a handle to a global memory block that
  1704. * contains the specified metafile as a collection of bits. The memory block
  1705. * can be used to determine the size of the metafile or to save the metafile as
  1706. * a file. The memory block should not be modified.
  1707. *
  1708. * Effects:
  1709. *
  1710. \***************************************************************************/
  1711. HANDLE GDIENTRY GetMetaFileBits(HANDLE hMF)
  1712. {
  1713. GdiLogFunc( "GetMetaFileBits");
  1714. /* 6/3/88 t-kensy: This code does nothing, except make sure hMF is valid
  1715. BOOL status = FALSE;
  1716. LPMETAFILE lpMF;
  1717. if (hMF && (lpMF = (LPMETAFILE) GlobalLock(hMF)))
  1718. {
  1719. if (lpMF->MetaFileHeader.mtType == MEMORYMETAFILE)
  1720. {
  1721. if (hMF = GlobalReAlloc(hMF, GlobalSize(hMF),
  1722. GLOBALMOVABLENONSHARED))
  1723. status = TRUE;
  1724. }
  1725. GlobalUnlock(hMF);
  1726. }
  1727. return(status ? hMF : status);
  1728. */
  1729. return (GlobalHandle(hMF) & 0xffff) ? hMF : FALSE;
  1730. }
  1731. /***************************** Internal Function **************************\
  1732. * HANDLE GDIENTRY SetMetaFileBits(HANDLE hMF)
  1733. *
  1734. *
  1735. *
  1736. * Effects:
  1737. *
  1738. \***************************************************************************/
  1739. HANDLE GDIENTRY SetMetaFileBits(HANDLE hBits)
  1740. {
  1741. GdiLogFunc( "SetMetaFileBits");
  1742. /* return (GlobalReAlloc(hBits, GlobalSize(hBits), GLOBALMOVABLE));*/
  1743. //---------------------------------------------------------------------------------
  1744. // We will make GDI take over the ownership of this memory block. This is
  1745. // done to help OLE, where either the server or the client could end while
  1746. // the other still had the handle to the memory block. This will prevent
  1747. // the block to dissapear after the creator exits. The strategy could be
  1748. // changed if this causes memory leaks with other application.
  1749. //
  1750. // Amit Chatterjee. 6/18/91.
  1751. //---------------------------------------------------------------------------------
  1752. return (GlobalReAlloc (hBits, 0L, GMEM_MODIFY | GMEM_DDESHARE)) ;
  1753. }
  1754. #endif // this is going to gdi.dll
  1755. /***************************** Internal Function **************************\
  1756. * CopyFile
  1757. *
  1758. *
  1759. * Returns TRUE iff success
  1760. *
  1761. *
  1762. \***************************************************************************/
  1763. BOOL INTERNAL CopyFile(LPSTR lpSFilename, LPSTR lpDFilename)
  1764. {
  1765. int ihSrc, ihDst, iBufferSize;
  1766. int iBytesRead;
  1767. OFSTRUCT ofStruct;
  1768. HANDLE hBuffer;
  1769. LPSTR lpBuffer;
  1770. BOOL fUnlink = FALSE;
  1771. GdiLogFunc3( "CopyFile");
  1772. /* Open the source file for reading */
  1773. if ((ihSrc = OpenFile(lpSFilename, &ofStruct, READ)) == -1)
  1774. goto CopyError10;
  1775. /* Open the destination file for writing */
  1776. if ((ihDst = OpenFile(lpDFilename, &ofStruct, OF_CREATE |
  1777. WRITE))
  1778. == -1)
  1779. goto CopyError20;
  1780. /* Get a buffer to transfer the file with */
  1781. if (!(hBuffer = AllocBuffer((LPWORD)&iBufferSize)))
  1782. goto CopyError30;
  1783. /* Lock the buffer and get a pointer to the storage */
  1784. if (!(lpBuffer = GlobalLock(hBuffer)))
  1785. goto CopyError40;
  1786. /* Copy the file, reading chunks at a time into the buffer */
  1787. do
  1788. {
  1789. if ((iBytesRead = _lread(ihSrc, lpBuffer, iBufferSize))
  1790. == -1)
  1791. goto CopyError40;
  1792. if (_lwrite(ihDst, lpBuffer, iBytesRead) != (WORD)iBytesRead)
  1793. goto CopyError40;
  1794. } while (iBytesRead == iBufferSize);
  1795. #ifdef FIREWALL
  1796. /* if we are able to read anything from the source file at this
  1797. * point, then something is wrong!
  1798. */
  1799. if (_lread(ihSrc, lpBuffer, iBufferSize))
  1800. {
  1801. fUnlink = TRUE;
  1802. goto CopyError40;
  1803. }
  1804. #endif
  1805. /* Everything's fine. Close up and exit successfully */
  1806. if (_lclose(ihSrc) == -1 || _lclose(ihDst) == -1)
  1807. goto CopyError40;
  1808. GlobalUnlock(hBuffer);
  1809. GlobalFree(hBuffer);
  1810. return TRUE;
  1811. /* Error exit points */
  1812. CopyError40:;
  1813. GlobalUnlock(hBuffer);
  1814. GlobalFree(hBuffer);
  1815. CopyError30:;
  1816. _lclose(ihDst);
  1817. if (fUnlink)
  1818. OpenFile(lpDFilename, &ofStruct, OF_DELETE);
  1819. CopyError20:;
  1820. _lclose(ihSrc);
  1821. CopyError10:;
  1822. return FALSE;
  1823. }
  1824. /***************************** Internal Function **************************\
  1825. * AllocateSpaceForDIB
  1826. *
  1827. * The following routine takes as input a device dependent bitmap structure
  1828. * and calculates the size needed to store the corresponding DIB structure
  1829. * including the DIB bits. It then proceeds to allocate space for it and
  1830. * returns a HANDLE to the caller (HANDLE could be NULL if allocation fails)
  1831. *
  1832. * Returns a global handle to memory or FALSE
  1833. *
  1834. \***************************************************************************/
  1835. HANDLE INTERNAL AllocateSpaceForDIB (lpBitmap, pbBitsPerPel, pwColorTableSize,
  1836. pdwcBits )
  1837. LPBITMAP lpBitmap ;
  1838. LPBYTE pbBitsPerPel ;
  1839. LPWORD pwColorTableSize;
  1840. LPDWORD pdwcBits ;
  1841. {
  1842. int InputPrecision ;
  1843. DWORD iBits ;
  1844. GdiLogFunc3( " AllocateSpaceForDIB");
  1845. /* calculate the number of bits per pel that we are going to have in
  1846. the DIB format. This value should correspond to the number of planes
  1847. and bits per pel in the device dependent bitmap format */
  1848. /* multiply the number of planes and the bits pel pel in the device
  1849. dependent bitmap */
  1850. InputPrecision = lpBitmap->bmPlanes * lpBitmap->bmBitsPixel ;
  1851. /* DIB precision should be more than or equal this precison, though
  1852. the limit is 24 bits per pel */
  1853. if (InputPrecision == 1)
  1854. {
  1855. *pbBitsPerPel = 1 ;
  1856. *pwColorTableSize = 2 * sizeof (RGBQUAD) ;
  1857. }
  1858. else if (InputPrecision <= 4)
  1859. {
  1860. *pbBitsPerPel = 4 ;
  1861. *pwColorTableSize = 16 * sizeof (RGBQUAD) ;
  1862. }
  1863. else if (InputPrecision <= 8)
  1864. {
  1865. *pbBitsPerPel = 8 ;
  1866. *pwColorTableSize = 256 * sizeof (RGBQUAD) ;
  1867. }
  1868. else
  1869. {
  1870. *pbBitsPerPel = 24 ;
  1871. *pwColorTableSize = 0 ;
  1872. }
  1873. /*--------------------------------------------------------------------------**
  1874. ** calulate the size of the DIB. Each scan line is going to be a mutiple of **
  1875. ** a DWORD. Also we shall need to allocate space for the color table. **
  1876. **--------------------------------------------------------------------------*/
  1877. /* get the number of bits we need for a scanline */
  1878. iBits = lpBitmap->bmWidth * (*pbBitsPerPel);
  1879. iBits = (iBits + 31) & (~31) ;
  1880. /* convert to number of bytes and get the size of the DIB */
  1881. iBits = (iBits >> 3) * lpBitmap->bmHeight ;
  1882. /* add the space needed for the color table */
  1883. iBits += *pwColorTableSize ;
  1884. /* add the size for the BITMAPINFOHeader */
  1885. iBits += sizeof(BITMAPINFOHEADER) ;
  1886. /* return back the value for iBits */
  1887. *pdwcBits = iBits ;
  1888. /* actually allocate about 100 bytes more for params */
  1889. iBits += 100 ;
  1890. /*--------------------------------------------------------------------------**
  1891. ** alocate space for the bitmap info header, the color table and the bits **
  1892. ** Return the value of the HANDLE. **
  1893. **--------------------------------------------------------------------------*/
  1894. return (GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG) iBits)) ;
  1895. }
  1896. /***************************** Internal Function **************************\
  1897. * InitializeDIBHeader
  1898. *
  1899. * This function takes as input a pointer to a BITMAPINFO header structure
  1900. * and a pointer to a device dependendent bitmap pointer together with the
  1901. * number of bitsperpel requested for the DIB and the color table size. It
  1902. * initializes the DIB header and returns a pointer pointing to the first
  1903. * word after the color table. **
  1904. *
  1905. \***************************************************************************/
  1906. LPWORD INTERNAL InitializeDIBHeader (lpDIBInfo, lpBitmap, bBitsPerPel, wColorTableSize)
  1907. LPBITMAPINFOHEADER lpDIBInfo ;
  1908. LPBITMAP lpBitmap ;
  1909. BYTE bBitsPerPel ;
  1910. WORD wColorTableSize ;
  1911. {
  1912. LPBYTE lpSpace ;
  1913. GdiLogFunc3( " InitializeDIBHeader");
  1914. /* Initialize the fields till the start of the color table */
  1915. lpDIBInfo->biSize = sizeof (BITMAPINFOHEADER) ;
  1916. lpDIBInfo->biWidth = (DWORD)lpBitmap->bmWidth ;
  1917. lpDIBInfo->biHeight = (DWORD)lpBitmap->bmHeight ;
  1918. lpDIBInfo->biPlanes = 1 ;
  1919. lpDIBInfo->biBitCount = (WORD) bBitsPerPel ;
  1920. lpDIBInfo->biCompression = 0;
  1921. lpDIBInfo->biSizeImage = 0;
  1922. lpDIBInfo->biXPelsPerMeter = 0;
  1923. lpDIBInfo->biYPelsPerMeter = 0;
  1924. lpDIBInfo->biClrUsed = 0;
  1925. lpDIBInfo->biClrImportant = 0;
  1926. /* take the pointer past the HEADER and cast it to a BYTE ptr */
  1927. lpDIBInfo ++ ;
  1928. lpSpace = (LPBYTE) lpDIBInfo ;
  1929. /* take the pointer past the color table structure */
  1930. lpSpace += wColorTableSize ;
  1931. /* return this pointer as a WORD pointer */
  1932. return ((LPWORD) lpSpace) ;
  1933. }