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.

782 lines
16 KiB

  1. //
  2. // CLPBD.CPP
  3. // Clipboard Handling
  4. //
  5. // Copyright Microsoft 1998-
  6. //
  7. // PRECOMP
  8. #include "precomp.h"
  9. //
  10. // NFC, SFR 5921. Maximum length of a string pasted from the clipboard.
  11. // We impose this limit as our graphic object code cant
  12. // handle more then this number of chars.
  13. //
  14. #define WB_MAX_TEXT_PASTE_LEN (INT_MAX-1)
  15. //
  16. //
  17. // Function: Paste
  18. //
  19. // Purpose: Paste a format from the clipboard
  20. //
  21. //
  22. BOOL WbMainWindow::CLP_Paste(void)
  23. {
  24. UINT length = 0;
  25. HANDLE handle = NULL;
  26. T126Obj* pGraphic = NULL;
  27. BOOL bResult = FALSE;
  28. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_Paste");
  29. // Get the highest priority acceptable format in the clipboard
  30. int iFormat = CLP_AcceptableClipboardFormat();
  31. if (!iFormat)
  32. goto NoOpenClip;
  33. TRACE_MSG(("Found acceptable format %d", iFormat));
  34. // Open the clipboard
  35. if (!::OpenClipboard(m_hwnd))
  36. {
  37. WARNING_OUT(("CLP_Paste: can't open clipboard"));
  38. goto NoOpenClip;
  39. }
  40. handle = ::GetClipboardData(iFormat);
  41. if (!handle)
  42. {
  43. WARNING_OUT(("CLP_Paste: can't get data for format %d", iFormat));
  44. goto NoFormatData;
  45. }
  46. switch (iFormat)
  47. {
  48. //
  49. // Check the standard formats
  50. //
  51. case CF_DIB:
  52. {
  53. TRACE_MSG(("Pasting CF_DIB"));
  54. // Lock the handle to get a pointer to the DIB
  55. LPBITMAPINFOHEADER lpbi;
  56. lpbi = (LPBITMAPINFOHEADER) ::GlobalLock(handle);
  57. if (lpbi != NULL)
  58. {
  59. bResult= PasteDIB(lpbi);
  60. // Release the memory
  61. ::GlobalUnlock(handle);
  62. }
  63. }
  64. break;
  65. //
  66. // We have a metafile. Play it into a bitmap and then use the
  67. // data.
  68. //
  69. case CF_ENHMETAFILE:
  70. {
  71. TRACE_MSG(("Pasting CF_ENHMETAFILE"));
  72. HDC hDrawingDC;
  73. ENHMETAHEADER meta_header;
  74. HBITMAP hBitmap = NULL;
  75. HDC meta_dc = NULL;
  76. HBITMAP hSaveBitmap;
  77. HPEN hSavePen;
  78. HPALETTE hPalette;
  79. RECT meta_rect;
  80. LPBITMAPINFOHEADER lpbiNew;
  81. int tmp;
  82. // We just need a DC compatible with the drawing area wnd
  83. hDrawingDC = m_drawingArea.GetCachedDC();
  84. // make a dc
  85. meta_dc = ::CreateCompatibleDC(hDrawingDC);
  86. if (!meta_dc)
  87. goto CleanupMetaFile;
  88. // figure out image size.
  89. ::GetEnhMetaFileHeader( (HENHMETAFILE)handle,
  90. sizeof( ENHMETAHEADER ),
  91. &meta_header );
  92. meta_rect.left = meta_rect.top = 0;
  93. meta_rect.right = ((meta_header.rclFrame.right - meta_header.rclFrame.left)
  94. * ::GetDeviceCaps(hDrawingDC, LOGPIXELSX ))/2540;
  95. meta_rect.bottom = ((meta_header.rclFrame.bottom - meta_header.rclFrame.top)
  96. * ::GetDeviceCaps(hDrawingDC, LOGPIXELSY ))/2540;
  97. // Normalize coords
  98. if (meta_rect.right < meta_rect.left)
  99. {
  100. tmp = meta_rect.left;
  101. meta_rect.left = meta_rect.right;
  102. meta_rect.right = tmp;
  103. }
  104. if (meta_rect.bottom < meta_rect.top)
  105. {
  106. tmp = meta_rect.top;
  107. meta_rect.top = meta_rect.bottom;
  108. meta_rect.bottom = tmp;
  109. }
  110. // make a place to play meta in
  111. hBitmap = ::CreateCompatibleBitmap(hDrawingDC,
  112. meta_rect.right - meta_rect.left,
  113. meta_rect.bottom - meta_rect.top);
  114. if (!hBitmap)
  115. goto CleanupMetaFile;
  116. hSaveBitmap = SelectBitmap(meta_dc, hBitmap);
  117. // erase our paper
  118. hSavePen = SelectPen(meta_dc, GetStockObject(NULL_PEN));
  119. ::Rectangle(meta_dc, meta_rect.left, meta_rect.top,
  120. meta_rect.right + 1, meta_rect.bottom + 1);
  121. SelectPen(meta_dc, hSavePen);
  122. // play the tape
  123. ::PlayEnhMetaFile(meta_dc, (HENHMETAFILE)handle, &meta_rect);
  124. // unplug our new bitmap
  125. SelectBitmap(meta_dc, hSaveBitmap);
  126. // Check for a palette object in the clipboard
  127. hPalette = (HPALETTE)::GetClipboardData(CF_PALETTE);
  128. // Create a new DIB from the bitmap
  129. lpbiNew = DIB_FromBitmap(hBitmap, hPalette, FALSE, FALSE);
  130. if(lpbiNew != NULL)
  131. {
  132. bResult= PasteDIB(lpbiNew);
  133. }
  134. CleanupMetaFile:
  135. // Free our temp intermediate bitmap
  136. if (hBitmap != NULL)
  137. {
  138. DeleteBitmap(hBitmap);
  139. }
  140. if (meta_dc != NULL)
  141. {
  142. ::DeleteDC(meta_dc);
  143. }
  144. }
  145. break;
  146. case CF_TEXT:
  147. {
  148. LPSTR pData;
  149. TRACE_DEBUG(("Pasting text"));
  150. // Get a handle to the clipboard contents
  151. pData = (LPSTR)::GlobalLock(handle);
  152. if(pData)
  153. {
  154. // Create a text object to hold the data - get the font to
  155. // use from the tool attributes group.
  156. DBG_SAVE_FILE_LINE
  157. WbTextEditor* pPasteText = new WbTextEditor();
  158. // Use the current font attributes
  159. if (!pPasteText)
  160. {
  161. ERROR_OUT(("CF_TEXT handling; failed to allocate DCWbGraphicText object"));
  162. }
  163. else
  164. {
  165. pPasteText->SetFont(m_pCurrentTool->GetFont());
  166. pPasteText->SetText(pData);
  167. RECT rcVis;
  168. m_drawingArea.GetVisibleRect(&rcVis);
  169. pPasteText->SetPenColor(RGB(0,0,0),TRUE);
  170. pPasteText->SetAnchorPoint(0, 0);
  171. pPasteText->MoveTo(rcVis.left, rcVis.top);
  172. pPasteText->Draw();
  173. pPasteText->m_pEditBox = NULL;
  174. // Add the new grabbed bitmap
  175. pPasteText->SetAllAttribs();
  176. pPasteText->AddToWorkspace();
  177. bResult = TRUE;
  178. }
  179. pGraphic = pPasteText;
  180. }
  181. }
  182. break;
  183. default:
  184. {
  185. if (iFormat == g_ClipboardFormats[CLIPBOARD_PRIVATE])
  186. {
  187. WB_OBJ objectHeader;
  188. ULONG length;
  189. UINT type;
  190. ULONG nItems = 0;
  191. PBYTE pClipBoardBuffer;
  192. if (pClipBoardBuffer = (PBYTE) ::GlobalLock(handle))
  193. {
  194. //
  195. // Count objects before we paste.
  196. //
  197. PBYTE pClipBuff = pClipBoardBuffer;
  198. length = ((PWB_OBJ)pClipBuff)->length;
  199. pClipBuff += sizeof(objectHeader);
  200. while(length)
  201. {
  202. nItems++;
  203. pClipBuff += length;
  204. length = ((PWB_OBJ)pClipBuff)->length;
  205. pClipBuff += sizeof(objectHeader);
  206. }
  207. TimeToGetGCCHandles(nItems);
  208. length = ((PWB_OBJ)pClipBoardBuffer)->length;
  209. type = ((PWB_OBJ)pClipBoardBuffer)->type;
  210. pClipBoardBuffer += sizeof(objectHeader);
  211. while(length)
  212. {
  213. if(type == TYPE_T126_ASN_OBJECT)
  214. {
  215. bResult = T126_MCSSendDataIndication(length, pClipBoardBuffer, g_MyMemberID, TRUE);
  216. }
  217. else if(type == TYPE_T126_DIB_OBJECT)
  218. {
  219. bResult = PasteDIB((LPBITMAPINFOHEADER)pClipBoardBuffer);
  220. }
  221. pClipBoardBuffer += length;
  222. length = ((PWB_OBJ)pClipBoardBuffer)->length;
  223. type = ((PWB_OBJ)pClipBoardBuffer)->type;
  224. pClipBoardBuffer += sizeof(objectHeader);
  225. }
  226. // Release the handle
  227. ::GlobalUnlock(handle);
  228. }
  229. }
  230. }
  231. break;
  232. }
  233. NoFormatData:
  234. ::CloseClipboard();
  235. NoOpenClip:
  236. return bResult;
  237. }
  238. //
  239. //
  240. // Function: Copy
  241. //
  242. // Purpose: Copy a graphic to the clipboard.
  243. //
  244. //
  245. BOOL WbMainWindow::CLP_Copy()
  246. {
  247. BOOL bResult = FALSE;
  248. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_Copy");
  249. //
  250. // We act according to the format of the selected graphic.
  251. //
  252. // For all formats we supply the Whiteboard private format (which is
  253. // just a copy of the flat representation of the graphic).
  254. //
  255. // We supply standard formats as follows.
  256. //
  257. // For bitmaps and all others we supply CF_DIB.
  258. //
  259. // For text graphics we supply CF_TEXT.
  260. //
  261. TRACE_MSG(("Rendering the graphic now"));
  262. // Have to empty the clipboard before rendering the formats.
  263. if (::OpenClipboard(m_hwnd))
  264. {
  265. // Get ownership of the clipboard
  266. ::EmptyClipboard();
  267. ::CloseClipboard();
  268. // Render the graphic
  269. bResult = CLP_RenderAllFormats();
  270. }
  271. return bResult;
  272. }
  273. //
  274. //
  275. // Function: RenderAllFormats
  276. //
  277. // Purpose: Render a graphic to the clipboard
  278. //
  279. //
  280. BOOL WbMainWindow::CLP_RenderAllFormats()
  281. {
  282. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAllFormats");
  283. BOOL bResult = FALSE;
  284. // Open the clipboard
  285. if (bResult = ::OpenClipboard(m_hwnd))
  286. {
  287. TRACE_DEBUG(("Rendering all formats of graphic"));
  288. // Render the private format
  289. bResult &= CLP_RenderPrivateFormat();
  290. // Text graphic
  291. bResult &= CLP_RenderAsText();
  292. // DIBs
  293. // bResult &= CLP_RenderAsImage();
  294. // Bitmaps
  295. bResult &= CLP_RenderAsBitmap();
  296. // Close the clipboard
  297. ::CloseClipboard();
  298. }
  299. return bResult;
  300. }
  301. //
  302. //
  303. // Function: CLP_RenderPrivateFormat
  304. //
  305. // Purpose: Render the private format of a graphic to the clipboard.
  306. // The clipboard should be open before this call is made.
  307. //
  308. //
  309. BOOL WbMainWindow::CLP_RenderPrivateFormat()
  310. {
  311. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderPrivateFormat");
  312. BOOL bResult = FALSE;
  313. LPBYTE pDest = NULL;
  314. HGLOBAL hMem = NULL;
  315. HGLOBAL hRealloc = NULL;
  316. WB_OBJ objectHeader;
  317. ULONG length = sizeof(objectHeader);
  318. BOOL bDoASN1CleanUp = FALSE;
  319. ULONG previousLength = 0;
  320. WBPOSITION pos;
  321. T126Obj * pObj;
  322. ASN1_BUF encodedPDU;
  323. pos = g_pCurrentWorkspace->GetHeadPosition();
  324. while(pos)
  325. {
  326. pObj = g_pCurrentWorkspace->GetNextObject(pos);
  327. if(pObj && pObj->WasSelectedLocally())
  328. {
  329. //
  330. // Get the encoded buffer
  331. //
  332. pObj->SetAllAttribs();
  333. pObj->SetViewState(unselected_chosen);
  334. pObj->GetEncodedCreatePDU(&encodedPDU);
  335. objectHeader.length = encodedPDU.length;
  336. if(pObj->GetType() == bitmapCreatePDU_chosen)
  337. {
  338. objectHeader.type = TYPE_T126_DIB_OBJECT;
  339. }
  340. else if(pObj->GetType() == drawingCreatePDU_chosen || pObj->GetType() == siNonStandardPDU_chosen)
  341. {
  342. objectHeader.type = TYPE_T126_ASN_OBJECT;
  343. bDoASN1CleanUp = TRUE;
  344. }
  345. length += encodedPDU.length + sizeof(objectHeader);
  346. if(pDest)
  347. {
  348. hRealloc = ::GlobalReAlloc(hMem, length, GMEM_MOVEABLE | GMEM_DDESHARE);
  349. if(!hRealloc)
  350. {
  351. goto bail;
  352. }
  353. hMem = hRealloc;
  354. }
  355. else
  356. {
  357. // Allocate memory for the clipboard data
  358. hMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, length);
  359. if(hMem == NULL)
  360. {
  361. goto bail;
  362. }
  363. }
  364. //
  365. // Get a pointer to the destination
  366. //
  367. pDest = (LPBYTE)::GlobalLock(hMem);
  368. //
  369. // Write the header
  370. //
  371. memcpy(pDest + previousLength, &objectHeader, sizeof(objectHeader));
  372. previousLength += sizeof(objectHeader);
  373. //
  374. // Copy the decoded data in the destination
  375. //
  376. memcpy(pDest + previousLength, encodedPDU.value, encodedPDU.length);
  377. previousLength += encodedPDU.length;
  378. //
  379. // Terminate the block with a 0
  380. //
  381. objectHeader.length = 0;
  382. memcpy(pDest + previousLength, &objectHeader, sizeof(objectHeader));
  383. //
  384. // Free the encoded data
  385. //
  386. if(bDoASN1CleanUp)
  387. {
  388. g_pCoder->Free(encodedPDU);
  389. bDoASN1CleanUp = FALSE;
  390. }
  391. }
  392. }
  393. // Release the memory
  394. ::GlobalUnlock(hMem);
  395. // Pass the data to the clipboard
  396. if (::SetClipboardData(g_ClipboardFormats[CLIPBOARD_PRIVATE], hMem))
  397. {
  398. TRACE_DEBUG(("Rendered data in Whiteboard format"));
  399. bResult = TRUE;
  400. }
  401. bail:
  402. if(bDoASN1CleanUp)
  403. {
  404. g_pCoder->Free(encodedPDU);
  405. }
  406. // If we failed to put the data into the clipboard, free the memory.
  407. // (If we did put it into the clipboard we must not free it).
  408. if (bResult == FALSE)
  409. {
  410. WARNING_OUT(("Render failed"));
  411. ::GlobalFree(hMem);
  412. }
  413. return bResult;
  414. }
  415. //
  416. //
  417. // Function: RenderAsText
  418. //
  419. // Purpose: Render the text format of a graphic to the clipboard.
  420. // The clipboard should be open before this call is made.
  421. // This member should only be called for text graphics.
  422. //
  423. //
  424. BOOL WbMainWindow::CLP_RenderAsText()
  425. {
  426. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsText");
  427. BOOL bResult = TRUE;
  428. WBPOSITION pos;
  429. T126Obj * pObj;
  430. pos = g_pCurrentWorkspace->GetHeadPosition();
  431. while(pos)
  432. {
  433. pObj = g_pCurrentWorkspace->GetNextObject(pos);
  434. if(pObj && pObj->WasSelectedLocally() && pObj->GraphicTool() == TOOLTYPE_TEXT)
  435. {
  436. // Get the total length of the clipboard format of the text
  437. StrArray& strText = ((TextObj*) pObj)->strTextArray;
  438. int iCount = strText.GetSize();
  439. int iIndex;
  440. DWORD dwLength = 0;
  441. for (iIndex = 0; iIndex < iCount; iIndex++)
  442. {
  443. // Length of string plus 2 for carriage return and line feed
  444. dwLength += lstrlen(strText[iIndex]) + 2;
  445. }
  446. // One more for the terminating NULL
  447. dwLength += 1;
  448. // Allocate memory for the clipboard data
  449. HANDLE hMem = ::GlobalAlloc(GHND, dwLength);
  450. if (hMem != NULL)
  451. {
  452. // Get a pointer to the memory
  453. LPSTR pDest = (LPSTR) ::GlobalLock(hMem);
  454. if (pDest != NULL)
  455. {
  456. // Write the graphic data to the allocated memory
  457. for (iIndex = 0; iIndex < iCount; iIndex++)
  458. {
  459. _tcscpy(pDest, strText[iIndex]);
  460. pDest += lstrlen(strText[iIndex]);
  461. // Add the carriage return and line feed
  462. *pDest++ = '\r';
  463. *pDest++ = '\n';
  464. }
  465. // Add the final NULL
  466. *pDest = '\0';
  467. // Release the memory
  468. ::GlobalUnlock(hMem);
  469. // Pass the data to the clipboard
  470. if (::SetClipboardData(CF_TEXT, hMem))
  471. {
  472. TRACE_DEBUG(("Rendered data in text format"));
  473. }
  474. else
  475. {
  476. bResult = FALSE;
  477. }
  478. }
  479. // If we failed to put the data into the clipboard, free the memory
  480. if (bResult == FALSE)
  481. {
  482. ::GlobalFree(hMem);
  483. }
  484. break; // JOSEF what about copying all the text objects in the clipboard
  485. }
  486. }
  487. }
  488. return bResult;
  489. }
  490. //
  491. // CLP_RenderAsBitmap()
  492. //
  493. // This draws all other graphics into a bitmap and pastes the DIB contents
  494. // onto the clipboard.
  495. //
  496. BOOL WbMainWindow::CLP_RenderAsBitmap()
  497. {
  498. BOOL bResult = FALSE;
  499. HDC hdcDisplay = NULL;
  500. HDC hdcMem = NULL;
  501. HBITMAP hBitmap = NULL;
  502. HBITMAP hOldBitmap = NULL;
  503. HPALETTE hPalette;
  504. RECT rcBounds = g_pDraw->m_selectorRect;
  505. POINT pt;
  506. LPBITMAPINFOHEADER lpbi;
  507. T126Obj * pObj = NULL;
  508. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsBitmap");
  509. //
  510. // First, draw this into a bitmap
  511. // Second, get the DIB bits of the bitmap
  512. //
  513. hdcDisplay = ::CreateDC("DISPLAY", NULL, NULL, NULL);
  514. if (!hdcDisplay)
  515. {
  516. ERROR_OUT(("Can't create DISPLAY dc"));
  517. goto AsBitmapDone;
  518. }
  519. hdcMem = ::CreateCompatibleDC(hdcDisplay);
  520. if (!hdcMem)
  521. {
  522. ERROR_OUT(("Can't create DISPLAY compatible dc"));
  523. goto AsBitmapDone;
  524. }
  525. hBitmap = ::CreateCompatibleBitmap(hdcDisplay,
  526. (rcBounds.right - rcBounds.left), (rcBounds.bottom - rcBounds.top));
  527. if (!hBitmap)
  528. {
  529. ERROR_OUT(("Can't create compatible bitmap"));
  530. goto AsBitmapDone;
  531. }
  532. hOldBitmap = SelectBitmap(hdcMem, hBitmap);
  533. if (!hOldBitmap)
  534. {
  535. ERROR_OUT(("Failed to select compatible bitmap"));
  536. goto AsBitmapDone;
  537. }
  538. ::SetMapMode(hdcMem, MM_ANISOTROPIC);
  539. ::SetWindowOrgEx(hdcMem, rcBounds.left,rcBounds.top, NULL);
  540. // Clear out bitmap with white background -- now that origin has been
  541. // altered, we can use drawing area coors.
  542. ::PatBlt(hdcMem, rcBounds.left, rcBounds.top, rcBounds.right - rcBounds.left,
  543. rcBounds.bottom - rcBounds.top, WHITENESS);
  544. WBPOSITION pos;
  545. pos = g_pCurrentWorkspace->GetHeadPosition();
  546. while(pos)
  547. {
  548. pObj = g_pCurrentWorkspace->GetNextObject(pos);
  549. if(pObj && pObj->WasSelectedLocally())
  550. {
  551. pObj->Draw(hdcMem);
  552. }
  553. }
  554. SelectBitmap(hdcMem, hOldBitmap);
  555. // Now get the dib bits...
  556. hPalette = CreateSystemPalette();
  557. lpbi = DIB_FromBitmap(hBitmap, hPalette, TRUE, FALSE);
  558. if (hPalette != NULL)
  559. ::DeletePalette(hPalette);
  560. // And put the handle on the clipboard
  561. if (lpbi != NULL)
  562. {
  563. if (::SetClipboardData(CF_DIB, (HGLOBAL)lpbi))
  564. {
  565. bResult = TRUE;
  566. }
  567. else
  568. {
  569. ::GlobalFree((HGLOBAL)lpbi);
  570. }
  571. }
  572. AsBitmapDone:
  573. if (hBitmap != NULL)
  574. ::DeleteBitmap(hBitmap);
  575. if (hdcMem != NULL)
  576. ::DeleteDC(hdcMem);
  577. if (hdcDisplay != NULL)
  578. ::DeleteDC(hdcDisplay);
  579. return(bResult);
  580. }
  581. //
  582. //
  583. // Function: AcceptableClipboardFormat
  584. //
  585. // Purpose: Return highest priority clipboard format if an acceptable
  586. // one is available, else return NULL.
  587. //
  588. //
  589. int WbMainWindow::CLP_AcceptableClipboardFormat(void)
  590. {
  591. // Look for any of the supported formats being available
  592. int iFormat = ::GetPriorityClipboardFormat((UINT *)g_ClipboardFormats, CLIPBOARD_ACCEPTABLE_FORMATS);
  593. if (iFormat == -1)
  594. {
  595. iFormat = 0;
  596. }
  597. return iFormat;
  598. }
  599. BOOL WbMainWindow::PasteDIB( LPBITMAPINFOHEADER lpbi)
  600. {
  601. BOOL bResult = FALSE;
  602. //
  603. // Create a bitmap object
  604. //
  605. BitmapObj* pDIB = NULL;
  606. DBG_SAVE_FILE_LINE
  607. pDIB = new BitmapObj(TOOLTYPE_FILLEDBOX);
  608. pDIB->SetBitmapSize(lpbi->biWidth,lpbi->biHeight);
  609. RECT rect;
  610. // Calculate the bounding rectangle from the size of the bitmap
  611. rect.top = 0;
  612. rect.left = 0;
  613. rect.right = lpbi->biWidth;
  614. rect.bottom = lpbi->biHeight;
  615. pDIB->SetRect(&rect);
  616. pDIB->SetAnchorPoint(rect.left, rect.top);
  617. //
  618. // Make a copy of the clipboard data
  619. //
  620. pDIB->m_lpbiImage = DIB_Copy(lpbi);
  621. if(pDIB->m_lpbiImage!= NULL)
  622. {
  623. // Add the new bitmap
  624. AddCapturedImage(pDIB);
  625. bResult = TRUE;
  626. }
  627. else
  628. {
  629. delete pDIB;
  630. }
  631. return bResult;
  632. }