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.

965 lines
30 KiB

  1. /*
  2. * CLIPFILE.C - Windows Clipboard File I/O Routines
  3. *
  4. * Copyright 1985-92, Microsoft Corporation
  5. */
  6. /* NOTE:
  7. * When saving the contents of the clipboard we SetClipboardData(fmt, NULL)
  8. * to free up the memory associated with each clipboard format. Then
  9. * after we are done saving we take over as the clipboard owner. This
  10. * causes OWNERDRAW formats to be lost in the save process.
  11. */
  12. /*
  13. *
  14. * Touched by : Anas Jarrah
  15. * On Date : May 11/1992.
  16. * Revision remarks by Anas Jarrah ext #15201
  17. * This file has been changed to comply with the Unicode standard
  18. * Following is a quick overview of what I have done.
  19. *
  20. * Was Changed it into Remark
  21. * === =============== ======
  22. * CHAR TCHAR if it refers to a text elements
  23. * LPCHAR & LPSTR LPTSTR if it refers to text.
  24. * LPCHAR & LPSTR LPBYTE if it does not refer to text
  25. * "..." TEXT("...") compile time macro resolves it.
  26. * '...' TEXT('...') same
  27. * strlen CharStrLen compile time macro resolves it.
  28. * strcpy CharStrCpy compile time macro resolves it.
  29. * strcmp CharStrCmp compile time macro resolves it.
  30. * strcat CharStrCat compile time macro resolves it.
  31. * LoadResource LoadResource(A/W) NT compiles resource strings into
  32. * Unicode binaries
  33. * MOpenFile() MapOpenFile/MOpenFile Depending on whether Unicode is defined or not.
  34. * This is a temporary cluge, That has to be taken care of.
  35. *
  36. *
  37. */
  38. #include "clipbrd.h"
  39. #include "dib.h"
  40. #define ATTRDIRLIST 0xC010
  41. // Windows 3.1 programs were packed on byte boundaries.
  42. #pragma pack(1)
  43. // Windows 3.1 BITMAP struct - used to save Win 3.1 .CLP files
  44. typedef struct {
  45. WORD bmType;
  46. WORD bmWidth;
  47. WORD bmHeight;
  48. WORD bmWidthBytes;
  49. BYTE bmPlanes;
  50. BYTE bmBitsPixel;
  51. LPVOID bmBits;
  52. } WIN31BITMAP;
  53. #pragma pack()
  54. /* EXTERN data */
  55. extern BOOL fAnythingToRender;
  56. /* FORWARD procs */
  57. HBITMAP PASCAL BitmapToBitmap(HBITMAP, WORD, WORD);
  58. TCHAR szFileSpecifier[] = TEXT("*.CLP");
  59. TCHAR szFileName[MAX_PATH];
  60. BOOL fNTReadFileFormat;
  61. #ifdef JAPAN
  62. extern TCHAR szCaptionName[];
  63. #endif
  64. /* ofSaveStruct is required; Otherwise, the following bug will occur
  65. * When the contents of the clipboard are loaded from a file, the
  66. * ofStruct is used to open the file and the data handles assigned to
  67. * the clipboard are NULL because of DELAYED RENDERING; Delayed
  68. * rendering will be done by reading from the file (ofStruct). But,
  69. * now, if the contents are to be saved into another file, it should
  70. * use the same ofStruct, because data has to be obtained from this
  71. * file using delayed rendering; So, a temporary ofSaveStruct is used
  72. * to hold the saved file's info; Once the save is successful, the
  73. * contents of ofSaveStruct are copied onto ofStruct
  74. */
  75. /* the ofStruct and ofSaveStruct are replaced by szFileName and
  76. * szSaveFileName strings.
  77. */
  78. TCHAR szSaveFileName[MAX_PATH];
  79. BOOL fNTSaveFileFormat;
  80. /*
  81. * IsWriteable()
  82. *
  83. * Test if a clipboard format is writeable(i.e. if it makes sense to write it)
  84. * OWNERDRAW and others can't be written because we (CLIPBRD) will become the
  85. * owner when the files are reopened.
  86. */
  87. BOOL NEAR PASCAL IsWriteable(UINT Format)
  88. {
  89. /* Are the PRIVATEFIRST and PRIVATELAST things right? */
  90. if ((Format >= CF_PRIVATEFIRST && Format <= CF_PRIVATELAST) || Format == CF_OWNERDISPLAY)
  91. return(FALSE);
  92. if (!fNTSaveFileFormat &&
  93. (Format == CF_UNICODETEXT || Format == CF_ENHMETAFILE || Format == CF_DSPENHMETAFILE))
  94. return(FALSE);
  95. return(TRUE);
  96. }
  97. /*
  98. * ReadClipboardFromFile()
  99. *
  100. * Read in a clipboard file and register all the formats in delayed mode.
  101. * to render things for real reopen the file specified by szFileName (was ofStruct).
  102. *
  103. * NOTE:
  104. * This makes us the clipboard owner.
  105. *
  106. * Bug 14564: Changed return value to a short integer noting why the
  107. * reading failed.
  108. * Return Value: 0 Success
  109. * 1 Improper format
  110. * 2 OpenClipboard failed
  111. */
  112. #define READFILE_SUCCESS 0
  113. #define READFILE_IMPROPERFORMAT 1
  114. #define READFILE_OPENCLIPBRDFAIL 2
  115. short NEAR PASCAL ReadClipboardFromFile(HWND hwnd,INT fh)
  116. {
  117. register WORD i;
  118. FILEHEADER FileHeader;
  119. FORMATHEADER FormatHeader;
  120. /* Read the File Header */
  121. _lread(fh, (LPBYTE)&FileHeader, sizeof(FILEHEADER));
  122. /* Sanity check, make sure this is one of ours. */
  123. #ifndef JAPAN
  124. if (FileHeader.magic == CLP_NT_ID)
  125. fNTReadFileFormat = TRUE;
  126. else if (FileHeader.magic == CLP_ID)
  127. fNTReadFileFormat = FALSE;
  128. else
  129. return(READFILE_IMPROPERFORMAT);
  130. if (FileHeader.FormatCount > 100)
  131. return(READFILE_IMPROPERFORMAT);
  132. #else
  133. if (FileHeader.magic == CLP_NT_ID)
  134. fNTReadFileFormat = TRUE;
  135. else if (FileHeader.magic == CLP_ID)
  136. fNTReadFileFormat = FALSE;
  137. else
  138. goto improperformat;
  139. if (FileHeader.FormatCount > 100)
  140. {
  141. improperformat:
  142. TCHAR szOutMessage[BUFFERLEN];
  143. TCHAR szCapBuffer[SMALLBUFFERLEN];
  144. LoadStringW(hInst, IDS_NAME, szCapBuffer, SMALLBUFFERLEN);
  145. LoadStringW(hInst, IDS_ENOTVALIDFILE, szOutMessage, BUFFERLEN);
  146. MessageBox(hwnd, szOutMessage,szCapBuffer, MB_OK | MB_ICONEXCLAMATION);
  147. return(READFILE_IMPROPERFORMAT);
  148. }
  149. #endif
  150. /* We become the clipboard owner here! */
  151. if (!OpenClipboard(hwnd))
  152. return(READFILE_OPENCLIPBRDFAIL);
  153. EmptyClipboard();
  154. for (i=0; i < FileHeader.FormatCount; i++)
  155. {
  156. if (fNTReadFileFormat)
  157. _lread(fh, (LPBYTE)&(FormatHeader.FormatID), sizeof(FormatHeader.FormatID));
  158. else {
  159. FormatHeader.FormatID = 0; /* initialize the high WORD */
  160. _lread(fh, (LPBYTE)&(FormatHeader.FormatID), sizeof(WORD));
  161. }
  162. _lread(fh, (LPBYTE)&(FormatHeader.DataLen), sizeof(FormatHeader.DataLen));
  163. _lread(fh, (LPBYTE)&(FormatHeader.DataOffset), sizeof(FormatHeader.DataOffset));
  164. _lread(fh, (LPBYTE)&(FormatHeader.Name), sizeof(FormatHeader.Name));
  165. if (PRIVATE_FORMAT(FormatHeader.FormatID))
  166. FormatHeader.FormatID = (UINT)RegisterClipboardFormat(FormatHeader.Name);
  167. /* Delayed Render. */
  168. SetClipboardData(FormatHeader.FormatID, NULL);
  169. }
  170. /* Now, clipbrd viewer has something to render */
  171. if (FileHeader.FormatCount > 0)
  172. fAnythingToRender = TRUE;
  173. CloseClipboard();
  174. return(READFILE_SUCCESS);
  175. }
  176. /*
  177. * OpenClipboardFile()
  178. */
  179. void NEAR PASCAL OpenClipboardFile(HWND hwnd)
  180. {
  181. INT fh;
  182. lstrcpy(szFileName, TEXT(""));
  183. OFN.lpstrTitle = szOpenCaption;
  184. OFN.lpstrFile = szFileName;
  185. /* Added OFN_FILEMUSTEXIST. 4 March 1991 clarkc */
  186. /* Added OFN_HIDEREADONLY. Happy now, Patrick? :) 1 Oct 1992 a-mgates.*/
  187. OFN.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  188. /* All long pointers should be defined immediately before the call.
  189. * L.Raman - 2/12/91
  190. */
  191. OFN.lpstrDefExt = (LPTSTR)szDefExt;
  192. OFN.lpstrFilter = (LPTSTR)szFilterSpec;
  193. OFN.lpstrCustomFilter = (LPTSTR)szCustFilterSpec;
  194. fh = GetOpenFileName ((LPOPENFILENAME) &OFN);
  195. if (fh)
  196. {
  197. fh = (INT)CreateFile((LPCTSTR)szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  198. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  199. if (fh > 0)
  200. {
  201. short nReadError;
  202. if (ClearClipboard(hwnd))
  203. {
  204. if (nReadError = ReadClipboardFromFile(hwnd, fh))
  205. {
  206. TCHAR szErr[MSGMAX];
  207. LoadString (hInst, IDS_READERR + nReadError, szErr, MSGMAX);
  208. MessageBox(hwnd,szErr,szAppName,MB_OK | MB_ICONEXCLAMATION);
  209. }
  210. }
  211. _lclose(fh);
  212. }
  213. }
  214. /* On GetOpenFileName failure CommDlgExtendedError will return a value.*/
  215. if(CommDlgExtendedError())
  216. {
  217. MemErrorMessage();
  218. }
  219. }
  220. /*
  221. * WriteFormatBlock() -
  222. */
  223. DWORD NEAR PASCAL WriteFormatBlock(INT fh,DWORD offset,DWORD DataOffset,
  224. DWORD DataLen,UINT Format,LPSTR szName)
  225. {
  226. FORMATHEADER FormatHeader;
  227. DWORD dwBytesWritten = 0;
  228. FormatHeader.FormatID = Format;
  229. FormatHeader.DataLen = DataLen;
  230. FormatHeader.DataOffset = DataOffset;
  231. lstrcpy(FormatHeader.Name, szName);
  232. _llseek(fh, offset, 0);
  233. if (fNTSaveFileFormat)
  234. dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.FormatID), sizeof(FormatHeader.FormatID));
  235. else
  236. dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.FormatID), sizeof(WORD));
  237. dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.DataLen), sizeof(FormatHeader.DataLen));
  238. dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.DataOffset), sizeof(FormatHeader.DataOffset));
  239. dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.Name), sizeof(FormatHeader.Name));
  240. return(dwBytesWritten);
  241. }
  242. /*
  243. * lread() - Good ol' _lread that will handle >64k
  244. */
  245. #define MAXREAD ((LONG) (60L * 1024L))
  246. DWORD APIENTRY lread(INT hFile,void FAR *pBuffer,DWORD dwBytes)
  247. {
  248. DWORD dwByteCount = dwBytes;
  249. #ifdef WIN16
  250. BYTE huge *hpBuffer = pBuffer;
  251. while (dwByteCount > MAXREAD)
  252. {
  253. if (_lread(hFile, hpBuffer, (WORD)MAXREAD) != MAXREAD)
  254. return(0);
  255. dwByteCount -= MAXREAD;
  256. hpBuffer += MAXREAD;
  257. }
  258. #else
  259. BYTE FAR *hpBuffer = pBuffer;
  260. #endif
  261. if ((DWORD)_lread(hFile, hpBuffer, dwByteCount) != dwByteCount)
  262. return(0);
  263. return(dwBytes);
  264. }
  265. /*
  266. * lwrite() - Good ol' _lwrite that will handle >64k
  267. */
  268. DWORD APIENTRY lwrite(INT hFile,void FAR *pBuffer,DWORD dwBytes)
  269. {
  270. DWORD dwByteCount=dwBytes;
  271. #ifdef WIN16
  272. BYTE huge *hpBuffer = pBuffer;
  273. while (dwByteCount > MAXREAD)
  274. {
  275. if (_lwrite(hFile, (LPSTR)hpBuffer, (WORD)MAXREAD) != MAXREAD)
  276. return(0);
  277. dwByteCount -= MAXREAD;
  278. hpBuffer += MAXREAD;
  279. }
  280. #else
  281. BYTE FAR *hpBuffer = pBuffer;
  282. #endif
  283. if ((DWORD)_lwrite(hFile, (LPSTR)hpBuffer, dwByteCount) != dwByteCount)
  284. return(0);
  285. return(dwBytes);
  286. }
  287. /*
  288. * WriteDataBlock() -
  289. *
  290. * Returns:
  291. * # of bytes written to the output file
  292. *
  293. * NOTE: Write saves the name of a temp file in the clipboard for it's
  294. * own internal clipboard format. This file goes aways when Write
  295. * (or windows?) shuts down. Thus saving Write clipboards won't work
  296. * (should we special case hack this?)
  297. *
  298. */
  299. DWORD NEAR PASCAL WriteDataBlock(register INT hFile,LONG offset,UINT Format)
  300. {
  301. WORD wPalEntries;
  302. LPBYTE lpData;
  303. DWORD dwSize;
  304. BITMAP bitmap;
  305. HANDLE hMF;
  306. HANDLE hBitmap;
  307. HANDLE hLogPalette;
  308. register HANDLE hData;
  309. LPLOGPALETTE lpLogPalette;
  310. LPMETAFILEPICT lpMFP;
  311. HENHMETAFILE hEMF;
  312. WIN31BITMAP bmWin31;
  313. if (!(hData = GetClipboardData(Format)))
  314. return(0);
  315. if(_llseek(hFile, offset, 0) != (int)offset)
  316. return(0);
  317. /* We have to special case a few common formats but most things
  318. * get handled in the default case.
  319. */
  320. switch (Format)
  321. {
  322. case CF_ENHMETAFILE:
  323. hEMF = hData;
  324. dwSize = (DWORD) GetEnhMetaFileBits(hEMF, 0, NULL); /* Get data size */
  325. if (!(hData = GlobalAlloc(GHND, dwSize))) /* allocate mem for EMF bits */
  326. return(0);
  327. if (!(lpData = GlobalLock(hData)))
  328. return(0);
  329. if (!GetEnhMetaFileBits(hEMF, dwSize, (LPBYTE)lpData))
  330. return(0);
  331. dwSize = lwrite(hFile, lpData, dwSize);
  332. GlobalUnlock(hData);
  333. GlobalFree(hData);
  334. break;
  335. case CF_METAFILEPICT:
  336. if (!(lpMFP = (LPMETAFILEPICT)GlobalLock(hData))) /* get header */
  337. return(0);
  338. if (fNTSaveFileFormat)
  339. _lwrite(hFile, (LPBYTE)lpMFP, sizeof(METAFILEPICT)); /* write header */
  340. else {
  341. /* If we save the metafile in the Windows 3.1 .CLP file format
  342. we have to save the METAFILEPICT structure as a 16bit METAFILEPICT
  343. structure. This may cause loss of information if the
  344. hight half of the METAFILEPICT structure's fields are used.
  345. [pierrej 5/27/92] */
  346. _lwrite(hFile, (LPBYTE)&(lpMFP->mm), sizeof(WORD));
  347. _lwrite(hFile, (LPBYTE)&(lpMFP->xExt), sizeof(WORD));
  348. _lwrite(hFile, (LPBYTE)&(lpMFP->yExt), sizeof(WORD));
  349. _lwrite(hFile, (LPBYTE)&(lpMFP->hMF), sizeof(WORD));
  350. }
  351. hMF = lpMFP->hMF;
  352. GlobalUnlock(hData); /* unlock the header */
  353. /* A-MGates 9/15/92 - Converted this block to use */
  354. /* GetMetaFileBitsEx */
  355. /* Figure out how big a block we need */
  356. dwSize = GetMetaFileBitsEx(hMF, 0, NULL);
  357. if (0 == dwSize)
  358. {
  359. return(0);
  360. }
  361. hData = GlobalAlloc(GMEM_MOVEABLE, dwSize);
  362. if (!(lpData = GlobalLock(hData)))
  363. {
  364. return(0);
  365. }
  366. if (dwSize != GetMetaFileBitsEx(hMF, dwSize, lpData))
  367. {
  368. GlobalUnlock(hData);
  369. GlobalFree(hData);
  370. return(0);
  371. }
  372. dwSize = lwrite(hFile, lpData, dwSize); /* spit them out */
  373. GlobalUnlock(hData);
  374. GlobalFree(hData);
  375. if(dwSize)
  376. if (fNTSaveFileFormat)
  377. dwSize += sizeof(METAFILEPICT); /* we wrote this much data */
  378. else
  379. dwSize += SIZE_OF_WIN31_METAFILEPICT_STRUCT;
  380. break;
  381. case CF_BITMAP:
  382. // hBitmap = hData;
  383. /* Writing DDBs to disk is bad. Therefore, we */
  384. /* write an intelligent CF_DIB block instead. */
  385. /* A-MGATES 9/29/92 */
  386. Format = CF_DIB;
  387. hBitmap = DibFromBitmap((HBITMAP)hData, BI_RGB, 4, NULL);
  388. lpData = GlobalLock(hBitmap);
  389. // dwSize might be too big, but we can live with that.
  390. dwSize = GlobalSize(lpData);
  391. _lwrite(hFile, lpData, dwSize);
  392. GlobalUnlock(hBitmap);
  393. GlobalFree(hBitmap);
  394. break;
  395. #ifdef ICKYOLDCODE
  396. if (!fNTSaveFileFormat)
  397. hBitmap = BitmapToBitmap(hBitmap, 4, 1);
  398. GetObject(hBitmap, sizeof(BITMAP), (LPBYTE) &bitmap);
  399. dwSize = (DWORD)bitmap.bmWidthBytes * bitmap.bmHeight * bitmap.bmPlanes;
  400. if (!fNTSaveFileFormat)
  401. {
  402. // Round up to the nearest TWO bytes when saving to Win 3.1,
  403. // not the nearest four, which is what GetObject gives you.
  404. // Note: The WidthBytes calculation does not include
  405. // bmPlanes in the multiplication because it seems to represent
  406. // bytes in a given plane.
  407. bitmap.bmWidthBytes =
  408. ((bitmap.bmWidth * bitmap.bmBitsPixel)+ 15 ) >> 3;
  409. // ">> 3" == " / 8", except cheaper.
  410. if (bitmap.bmWidthBytes & 1)
  411. {
  412. bitmap.bmWidthBytes++;
  413. }
  414. }
  415. if (!(hData = GlobalAlloc(GHND, dwSize)))
  416. return(0);
  417. if (!(lpData = GlobalLock(hData)))
  418. {
  419. GlobalFree(hData);
  420. return(0);
  421. }
  422. GetBitmapBits(hBitmap, dwSize, lpData);
  423. if (fNTSaveFileFormat)
  424. _lwrite(hFile, (LPBYTE) & bitmap, sizeof(BITMAP));
  425. else {
  426. /* If we save the bitmap in the Windows 3.1 .CLP file format
  427. we have to save the BITMAP structure as a 16bit BITMAP
  428. structure. This may cause loss of information if the
  429. hight half of the BITMAP structure's fields are used.
  430. [pierrej 5/27/92] */
  431. bmWin31.bmType = bitmap.bmType;
  432. bmWin31.bmWidth = bitmap.bmWidth;
  433. bmWin31.bmHeight = bitmap.bmHeight;
  434. bmWin31.bmWidthBytes = bitmap.bmWidthBytes;
  435. bmWin31.bmPlanes = bitmap.bmPlanes;
  436. bmWin31.bmBitsPixel = bitmap.bmBitsPixel;
  437. bmWin31.bmBits = bitmap.bmBits;
  438. _lwrite(hFile, (LPBYTE) &bmWin31, sizeof(WIN31BITMAP));
  439. }
  440. dwSize = lwrite(hFile, lpData, dwSize);
  441. GlobalUnlock(hData);
  442. GlobalFree(hData);
  443. if(dwSize)
  444. if (fNTSaveFileFormat)
  445. dwSize += sizeof(BITMAP);
  446. else
  447. dwSize += sizeof(WIN31BITMAP);
  448. break;
  449. #endif
  450. case CF_PALETTE:
  451. /* Get the number of palette entries */
  452. GetObject(hData, sizeof(WORD), (LPBYTE)&wPalEntries);
  453. /* Allocate enough place to build the LOGPALETTE struct */
  454. dwSize = (DWORD)(sizeof(LOGPALETTE) + (LONG)wPalEntries * sizeof(PALETTEENTRY));
  455. if (!(hLogPalette = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, dwSize)))
  456. {
  457. dwSize = 0L;
  458. goto Palette_Error;
  459. }
  460. if (!(lpLogPalette = (LPLOGPALETTE)GlobalLock(hLogPalette)))
  461. {
  462. dwSize = 0L;
  463. goto Palette_Error;
  464. }
  465. lpLogPalette->palVersion = 0x300; /* Windows 3.00 */
  466. lpLogPalette->palNumEntries = wPalEntries;
  467. if (GetPaletteEntries(hData, 0, wPalEntries,
  468. (LPPALETTEENTRY)(lpLogPalette->palPalEntry)) == 0)
  469. {
  470. dwSize = 0L;
  471. goto Palette_Error;
  472. }
  473. /* Write the LOGPALETTE structure onto disk */
  474. dwSize = lwrite(hFile, (LPBYTE)lpLogPalette, dwSize);
  475. Palette_Error:
  476. if (lpLogPalette)
  477. GlobalUnlock(hLogPalette);
  478. if (hLogPalette)
  479. GlobalFree(hLogPalette);
  480. break;
  481. default:
  482. dwSize = GlobalSize(hData);
  483. if (0 ==(lpData = GlobalLock(hData)) )
  484. {
  485. return 0;
  486. }
  487. dwSize = _lwrite(hFile, lpData, dwSize);
  488. GlobalUnlock(hData);
  489. break;
  490. }
  491. /* Return the number of bytes written. */
  492. return(dwSize);
  493. }
  494. /* This function will return the number of clipboard formats compatible with
  495. the Windows 3.1 clipboard, this excludes CF_UNICODETEXT, CF_ENHMETAFILE and
  496. CF_DSPENHMETAFILE
  497. */
  498. int Count16BitClipboardFormats(void)
  499. {
  500. int iCount;
  501. iCount = CountClipboardFormats();
  502. if (IsClipboardFormatAvailable(CF_UNICODETEXT))
  503. iCount--;
  504. if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
  505. iCount--;
  506. if (IsClipboardFormatAvailable(CF_DSPENHMETAFILE))
  507. iCount--;
  508. return iCount;
  509. }
  510. /*
  511. * SaveClipboardData() - Writes a clipboard file.
  512. *
  513. * In:
  514. * hwnd handle of wnd that becomes the clipboard owner
  515. * szFileName file handle to read from
  516. *
  517. * NOTE:
  518. * When done we call ReadClipboardFromFile(). this makes us the
  519. * clipboard owner.
  520. */
  521. BOOL NEAR PASCAL SaveClipboardData(HWND hwnd,LPTSTR szLocalFileName)
  522. {
  523. INT fh;
  524. register UINT Format;
  525. DWORD HeaderPos;
  526. DWORD DataPos;
  527. DWORD datasize;
  528. BOOL fComplain;
  529. BOOL fDIBUsed;
  530. HCURSOR hCursor;
  531. FILEHEADER FileHeader;
  532. TCHAR szComplaint[BUFFERLEN];
  533. TCHAR szName[CCHFMTNAMEMAX];
  534. WORD wHeaderSize;
  535. UINT uiSizeHeaderToWrite;
  536. /* First open the clipboard */
  537. if (!OpenClipboard(hwndMain))
  538. return(FALSE);
  539. /* Open the file */
  540. fh = (INT)CreateFile((LPCTSTR)szLocalFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  541. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  542. if (fh == -1)
  543. {
  544. GetLastError();
  545. CloseClipboard();
  546. return(FALSE);
  547. }
  548. /* Fill out the file header structure */
  549. if (fNTSaveFileFormat) {
  550. FileHeader.magic = CLP_NT_ID; /* magic number to tag our files */
  551. uiSizeHeaderToWrite = (sizeof(UINT) + 2*sizeof(DWORD) + CCHFMTNAMEMAX*sizeof(TCHAR));
  552. } else {
  553. FileHeader.magic = CLP_ID; /* magic number to tag our files */
  554. uiSizeHeaderToWrite = (sizeof(WORD) + 2*sizeof(DWORD) + CCHFMTNAMEMAX*sizeof(TCHAR));
  555. }
  556. FileHeader.FormatCount = 0; /* dummy for now */
  557. /* Update HeaderPos and DataPos */
  558. HeaderPos = sizeof(FILEHEADER);
  559. /* This is the maximum number of formats that will be written. Potentially
  560. * some may fail and some space will be wasted.
  561. * In 32bit the number of bytes written to the disk isn't sizeof(FORMATHEADER)
  562. * because of DWORD alignment in the FORMATHEADER structure. Instead we write
  563. * the format headre structure one field at a time to remain compatible with
  564. * the 16bit Windows versions.
  565. */
  566. if (fNTSaveFileFormat)
  567. DataPos = HeaderPos + (uiSizeHeaderToWrite * CountClipboardFormats());
  568. else
  569. DataPos = HeaderPos + (uiSizeHeaderToWrite * Count16BitClipboardFormats());
  570. /* Now loop throught the data, one format at a time, and write out the data. */
  571. fComplain = FALSE;
  572. LoadString(hInst, IDS_FMTNOTSAV, szComplaint, BUFFERLEN);
  573. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  574. ShowCursor(TRUE);
  575. /* Enumerate all formats */
  576. Format = 0;
  577. fDIBUsed = FALSE;
  578. while ((Format = EnumClipboardFormats(Format)) != 0)
  579. {
  580. if (IsWriteable(Format))
  581. {
  582. // DO NOT write CF_BITMAP to disk. Transform to CF_DIB
  583. // and write that instead.
  584. if (CF_BITMAP == Format || CF_DIB == Format)
  585. {
  586. if (!fDIBUsed)
  587. {
  588. fDIBUsed = TRUE;
  589. }
  590. // If I've already done DIB, go on to the next format.
  591. else continue;
  592. }
  593. GetClipboardName((Format == CF_BITMAP ? CF_DIB : Format),
  594. szName, sizeof(szName));
  595. if ((datasize = WriteDataBlock(fh, DataPos, Format)) != 0)
  596. {
  597. /* Create a Format header and write it to the file */
  598. wHeaderSize = (WORD)WriteFormatBlock(fh,
  599. HeaderPos, DataPos, datasize,
  600. (Format == CF_BITMAP ? CF_DIB : Format),
  601. (LPTSTR)szName);
  602. if(wHeaderSize < uiSizeHeaderToWrite)
  603. {
  604. fComplain = TRUE;
  605. break;
  606. }
  607. HeaderPos += wHeaderSize;
  608. /* Update the data pos for the next block */
  609. DataPos += datasize;
  610. FileHeader.FormatCount++; /* this format has been written */
  611. }
  612. else
  613. {
  614. fComplain = TRUE;
  615. break;
  616. }
  617. }
  618. }
  619. ShowCursor(FALSE);
  620. SetCursor(hCursor);
  621. if (fComplain)
  622. {
  623. #ifdef JAPAN
  624. /* Use Japanese message for caption instead of app name */
  625. MessageBox(hwnd, szComplaint, szCaptionName, MB_OK | MB_ICONEXCLAMATION);
  626. #else
  627. MessageBox(hwnd, szComplaint, szAppName, MB_OK | MB_ICONEXCLAMATION);
  628. #endif
  629. CloseClipboard();
  630. _lclose(fh);
  631. return(FALSE);
  632. }
  633. CloseClipboard(); /* we are done looking at this */
  634. _llseek(fh, 0L, 0); /* move back to the start of file */
  635. /* Write the File Header with the correct number of formats written */
  636. _lwrite(fh, (LPBYTE) & FileHeader, sizeof(FILEHEADER));
  637. /* Now we open the clipboard and become the owner. this places
  638. * all the things we just saved in the clipboard (and throws out
  639. * those things we didn't save)
  640. */
  641. _llseek(fh, 0L, 0);
  642. /* ofStruct will be used for reopening the file */
  643. lstrcpy(szFileName, szSaveFileName);
  644. fNTReadFileFormat = fNTSaveFileFormat;
  645. ReadClipboardFromFile(hwndMain, fh);
  646. _lclose(fh);
  647. return(TRUE);
  648. }
  649. /*
  650. * SaveClipboardToFile() -
  651. */
  652. void NEAR PASCAL SaveClipboardToFile(HWND hwnd)
  653. {
  654. INT hFile;
  655. OFN.lpstrTitle = szSaveCaption;
  656. OFN.lpstrFile = szSaveFileName;
  657. szSaveFileName[0] = 0;
  658. OFN.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
  659. OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN;
  660. /* All long pointers should be defined immediately before the call. */
  661. OFN.lpstrDefExt = (LPTSTR)szDefExt;
  662. OFN.lpstrFilter = (LPTSTR)szFilterSpec;
  663. OFN.lpstrCustomFilter = NULL;
  664. OFN.lpfnHook = NULL;
  665. OFN.nFilterIndex = 1;
  666. hFile = GetSaveFileName ((LPOPENFILENAME) &OFN);
  667. if (hFile)
  668. {
  669. // The first filter listed is "NT Clipboard File". The second is
  670. // "Windows 3.1 Clipboard file".
  671. fNTSaveFileFormat = (1 == OFN.nFilterIndex);
  672. hFile = (INT)CreateFile((LPCTSTR)szSaveFileName, GENERIC_READ, FILE_SHARE_READ,
  673. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  674. if (hFile != -1)
  675. /* The file already exists and the user wants to
  676. * overwrite! Now, we have to check whether this
  677. * file is the most recently saved clip file;
  678. * If so, it will be used for delayed rendering; So,
  679. * before we overwrite this file we must read all data
  680. * from it thro RENDERALLFORMATS;
  681. * Fix for Bug #5602 --SANKAR-- 10-16-89
  682. */
  683. {
  684. CloseHandle((HANDLE)hFile);
  685. if (lstrcmp(szSaveFileName, szFileName) == 0)
  686. {
  687. SendMessage(hwndMain, WM_RENDERALLFORMATS, 0, 0L);
  688. }
  689. }
  690. if (!SaveClipboardData(hwnd, (LPTSTR)szSaveFileName))
  691. {
  692. /* If Failure, Delete the incomplete file */
  693. DeleteFile(szSaveFileName);
  694. }
  695. }
  696. }
  697. //
  698. // Purpose:
  699. // Convert an existing bitmap to the given number of planes and
  700. // bits/pixel.
  701. //
  702. // Parameters:
  703. // hBitmap - Handle to the existing bitmap.
  704. // wPlanes - Number of planes in the destination bitmap.
  705. // wBitCount - Number of bits/pel in the destination bitmap.
  706. //
  707. // Returns:
  708. // A handle to the converted bitmap.
  709. //
  710. ////////////////////////////////////////////////////////////////////////////
  711. HBITMAP PASCAL BitmapToBitmap(HBITMAP hBitmap, WORD wPlanes, WORD wBitCount)
  712. {
  713. BITMAP bm;
  714. BITMAPINFOHEADER BmpInfoHeader;
  715. HANDLE hDib, hBmp;
  716. LPBYTE lpDib, lpBits;
  717. DWORD dwLength, dwSize;
  718. int iColorTable;
  719. int iColorUsed;
  720. HDC hDC;
  721. /*
  722. ** Get the size of the bitmap. These values are used to setup the memory
  723. ** requirements for the DIB.
  724. */
  725. GetObject(hBitmap,sizeof(BITMAP),(LPSTR)&bm);
  726. if ((bm.bmBitsPixel == wBitCount) && (bm.bmPlanes == wPlanes))
  727. return hBitmap;
  728. #if 0
  729. dwSize = dwLength = (DWORD)(bm.bmWidthBytes+sizeof(WORD)) * bm.bmHeight * bm.bmPlanes;
  730. #else
  731. dwSize = dwLength = (DWORD)(((bm.bmWidth * wBitCount + 7)/8)*2 + 1)/2
  732. * wPlanes * bm.bmHeight;
  733. #endif
  734. switch(bm.bmBitsPixel * bm.bmPlanes)
  735. {
  736. case 1:
  737. iColorTable = sizeof(RGBQUAD) * 2;
  738. break;
  739. case 4:
  740. iColorTable = sizeof(RGBQUAD) * 16;
  741. break;
  742. case 8:
  743. iColorTable = sizeof(RGBQUAD) * 256;
  744. break;
  745. case 24:
  746. default:
  747. iColorTable = 0;
  748. break;
  749. }
  750. iColorUsed = iColorTable / sizeof(RGBQUAD);
  751. dwLength += (sizeof(BITMAPINFOHEADER) + iColorTable);
  752. /*
  753. ** Create the DIB. First, to the size of the bitmap. We will calculate
  754. ** the new memory requirements if DIB-Compression is desired.
  755. */
  756. if(hDib = GlobalAlloc(GHND,dwLength)) {
  757. if(lpDib = GlobalLock(hDib))
  758. {
  759. ((LPBITMAPINFOHEADER)lpDib)->biSize = sizeof(BITMAPINFOHEADER);
  760. ((LPBITMAPINFOHEADER)lpDib)->biWidth = bm.bmWidth;
  761. ((LPBITMAPINFOHEADER)lpDib)->biHeight = bm.bmHeight;
  762. ((LPBITMAPINFOHEADER)lpDib)->biPlanes = 1;
  763. ((LPBITMAPINFOHEADER)lpDib)->biBitCount = bm.bmBitsPixel*bm.bmPlanes;
  764. ((LPBITMAPINFOHEADER)lpDib)->biCompression = BI_RGB;
  765. ((LPBITMAPINFOHEADER)lpDib)->biSizeImage = 0;
  766. ((LPBITMAPINFOHEADER)lpDib)->biXPelsPerMeter = 0;
  767. ((LPBITMAPINFOHEADER)lpDib)->biYPelsPerMeter = 0;
  768. ((LPBITMAPINFOHEADER)lpDib)->biClrUsed = 0;
  769. ((LPBITMAPINFOHEADER)lpDib)->biClrImportant = 0;
  770. // Figure out where the bits go
  771. lpBits = (LPBYTE)lpDib+sizeof(BITMAPINFOHEADER)+iColorTable;
  772. hDC = GetDC(hwndMain);
  773. if (NULL != hDC)
  774. {
  775. if (bm.bmHeight == GetDIBits(hDC,hBitmap,0,
  776. bm.bmHeight,lpBits,(LPBITMAPINFO)lpDib,
  777. // DIB_PAL_INDICES))
  778. DIB_RGB_COLORS))
  779. {
  780. BmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
  781. BmpInfoHeader.biWidth = bm.bmWidth;
  782. BmpInfoHeader.biHeight = bm.bmHeight;
  783. BmpInfoHeader.biPlanes = wPlanes;
  784. BmpInfoHeader.biBitCount = wBitCount;
  785. BmpInfoHeader.biCompression = BI_RGB;
  786. BmpInfoHeader.biSizeImage = dwSize;
  787. BmpInfoHeader.biXPelsPerMeter = 0;
  788. BmpInfoHeader.biYPelsPerMeter = 0;
  789. BmpInfoHeader.biClrUsed = iColorUsed;
  790. BmpInfoHeader.biClrImportant = iColorUsed;
  791. hBmp = CreateDIBitmap(NULL, &BmpInfoHeader, CBM_INIT,
  792. lpBits, (LPBITMAPINFO)lpDib, DIB_RGB_COLORS);
  793. }
  794. ReleaseDC(hwndMain, hDC);
  795. }
  796. GlobalUnlock(hDib);
  797. }
  798. GlobalFree(hDib);
  799. }
  800. return(hBmp);
  801. }