Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

787 lines
17 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. UINT type;
  189. ULONG nItems = 0;
  190. PBYTE pClipBoardBuffer;
  191. if (pClipBoardBuffer = (PBYTE) ::GlobalLock(handle))
  192. {
  193. //
  194. // Count objects before we paste.
  195. //
  196. PBYTE pClipBuff = pClipBoardBuffer;
  197. length = ((PWB_OBJ)pClipBuff)->length;
  198. pClipBuff += sizeof(objectHeader);
  199. while(length)
  200. {
  201. nItems++;
  202. pClipBuff += length;
  203. length = ((PWB_OBJ)pClipBuff)->length;
  204. pClipBuff += sizeof(objectHeader);
  205. }
  206. TimeToGetGCCHandles(nItems);
  207. length = ((PWB_OBJ)pClipBoardBuffer)->length;
  208. type = ((PWB_OBJ)pClipBoardBuffer)->type;
  209. pClipBoardBuffer += sizeof(objectHeader);
  210. while(length)
  211. {
  212. if(type == TYPE_T126_ASN_OBJECT)
  213. {
  214. bResult = T126_MCSSendDataIndication(length, pClipBoardBuffer, g_MyMemberID, TRUE);
  215. }
  216. else if(type == TYPE_T126_DIB_OBJECT)
  217. {
  218. bResult = PasteDIB((LPBITMAPINFOHEADER)pClipBoardBuffer);
  219. }
  220. pClipBoardBuffer += length;
  221. length = ((PWB_OBJ)pClipBoardBuffer)->length;
  222. type = ((PWB_OBJ)pClipBoardBuffer)->type;
  223. pClipBoardBuffer += sizeof(objectHeader);
  224. }
  225. // Release the handle
  226. ::GlobalUnlock(handle);
  227. }
  228. }
  229. }
  230. break;
  231. }
  232. NoFormatData:
  233. ::CloseClipboard();
  234. NoOpenClip:
  235. return bResult;
  236. }
  237. //
  238. //
  239. // Function: Copy
  240. //
  241. // Purpose: Copy a graphic to the clipboard.
  242. //
  243. //
  244. BOOL WbMainWindow::CLP_Copy()
  245. {
  246. BOOL bResult = FALSE;
  247. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_Copy");
  248. //
  249. // We act according to the format of the selected graphic.
  250. //
  251. // For all formats we supply the Whiteboard private format (which is
  252. // just a copy of the flat representation of the graphic).
  253. //
  254. // We supply standard formats as follows.
  255. //
  256. // For bitmaps and all others we supply CF_DIB.
  257. //
  258. // For text graphics we supply CF_TEXT.
  259. //
  260. TRACE_MSG(("Rendering the graphic now"));
  261. // Have to empty the clipboard before rendering the formats.
  262. if (::OpenClipboard(m_hwnd))
  263. {
  264. // Get ownership of the clipboard
  265. ::EmptyClipboard();
  266. ::CloseClipboard();
  267. // Render the graphic
  268. bResult = CLP_RenderAllFormats();
  269. }
  270. return bResult;
  271. }
  272. //
  273. //
  274. // Function: RenderAllFormats
  275. //
  276. // Purpose: Render a graphic to the clipboard
  277. //
  278. //
  279. BOOL WbMainWindow::CLP_RenderAllFormats()
  280. {
  281. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAllFormats");
  282. BOOL bResult = FALSE;
  283. // Open the clipboard
  284. if (bResult = ::OpenClipboard(m_hwnd))
  285. {
  286. TRACE_DEBUG(("Rendering all formats of graphic"));
  287. // Render the private format
  288. bResult &= CLP_RenderPrivateFormat();
  289. // Text graphic
  290. bResult &= CLP_RenderAsText();
  291. // DIBs
  292. // bResult &= CLP_RenderAsImage();
  293. // Bitmaps
  294. bResult &= CLP_RenderAsBitmap();
  295. // Close the clipboard
  296. ::CloseClipboard();
  297. }
  298. return bResult;
  299. }
  300. //
  301. //
  302. // Function: CLP_RenderPrivateFormat
  303. //
  304. // Purpose: Render the private format of a graphic to the clipboard.
  305. // The clipboard should be open before this call is made.
  306. //
  307. //
  308. BOOL WbMainWindow::CLP_RenderPrivateFormat()
  309. {
  310. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderPrivateFormat");
  311. BOOL bResult = FALSE;
  312. LPBYTE pDest = NULL;
  313. HGLOBAL hMem = NULL;
  314. HGLOBAL hRealloc = NULL;
  315. WB_OBJ objectHeader;
  316. ULONG length = sizeof(objectHeader);
  317. BOOL bDoASN1CleanUp = FALSE;
  318. ULONG previousLength = 0;
  319. WBPOSITION pos;
  320. T126Obj * pObj;
  321. ASN1_BUF encodedPDU;
  322. pos = g_pCurrentWorkspace->GetHeadPosition();
  323. while(pos)
  324. {
  325. pObj = g_pCurrentWorkspace->GetNextObject(pos);
  326. if(pObj && pObj->WasSelectedLocally())
  327. {
  328. //
  329. // Get the encoded buffer
  330. //
  331. pObj->SetAllAttribs();
  332. pObj->SetViewState(unselected_chosen);
  333. pObj->GetEncodedCreatePDU(&encodedPDU);
  334. objectHeader.length = encodedPDU.length;
  335. if(pObj->GetType() == bitmapCreatePDU_chosen)
  336. {
  337. objectHeader.type = TYPE_T126_DIB_OBJECT;
  338. }
  339. else if(pObj->GetType() == drawingCreatePDU_chosen || pObj->GetType() == siNonStandardPDU_chosen)
  340. {
  341. objectHeader.type = TYPE_T126_ASN_OBJECT;
  342. bDoASN1CleanUp = TRUE;
  343. }
  344. length += encodedPDU.length + sizeof(objectHeader);
  345. if(pDest)
  346. {
  347. hRealloc = ::GlobalReAlloc(hMem, length, GMEM_MOVEABLE | GMEM_DDESHARE);
  348. if(!hRealloc)
  349. {
  350. goto bail;
  351. }
  352. hMem = hRealloc;
  353. }
  354. else
  355. {
  356. // Allocate memory for the clipboard data
  357. hMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, length);
  358. if(hMem == NULL)
  359. {
  360. goto bail;
  361. }
  362. }
  363. //
  364. // Get a pointer to the destination
  365. //
  366. pDest = (LPBYTE)::GlobalLock(hMem);
  367. //
  368. // Write the header
  369. //
  370. memcpy(pDest + previousLength, &objectHeader, sizeof(objectHeader));
  371. previousLength += sizeof(objectHeader);
  372. //
  373. // Copy the decoded data in the destination
  374. //
  375. memcpy(pDest + previousLength, encodedPDU.value, encodedPDU.length);
  376. previousLength += encodedPDU.length;
  377. //
  378. // Terminate the block with a 0
  379. //
  380. objectHeader.length = 0;
  381. memcpy(pDest + previousLength, &objectHeader, sizeof(objectHeader));
  382. //
  383. // Free the encoded data
  384. //
  385. if(bDoASN1CleanUp)
  386. {
  387. g_pCoder->Free(encodedPDU);
  388. bDoASN1CleanUp = FALSE;
  389. }
  390. }
  391. }
  392. // Release the memory
  393. ::GlobalUnlock(hMem);
  394. // Pass the data to the clipboard
  395. if (::SetClipboardData(g_ClipboardFormats[CLIPBOARD_PRIVATE], hMem))
  396. {
  397. TRACE_DEBUG(("Rendered data in Whiteboard format"));
  398. bResult = TRUE;
  399. }
  400. bail:
  401. if(bDoASN1CleanUp)
  402. {
  403. g_pCoder->Free(encodedPDU);
  404. }
  405. // If we failed to put the data into the clipboard, free the memory.
  406. // (If we did put it into the clipboard we must not free it).
  407. if (bResult == FALSE)
  408. {
  409. WARNING_OUT(("Render failed"));
  410. ::GlobalFree(hMem);
  411. }
  412. return bResult;
  413. }
  414. //
  415. //
  416. // Function: RenderAsText
  417. //
  418. // Purpose: Render the text format of a graphic to the clipboard.
  419. // The clipboard should be open before this call is made.
  420. // This member should only be called for text graphics.
  421. //
  422. //
  423. BOOL WbMainWindow::CLP_RenderAsText()
  424. {
  425. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsText");
  426. BOOL bResult = TRUE;
  427. WBPOSITION pos;
  428. T126Obj * pObj;
  429. pos = g_pCurrentWorkspace->GetHeadPosition();
  430. while(pos)
  431. {
  432. pObj = g_pCurrentWorkspace->GetNextObject(pos);
  433. if(pObj && pObj->WasSelectedLocally() && pObj->GraphicTool() == TOOLTYPE_TEXT)
  434. {
  435. // Get the total length of the clipboard format of the text
  436. StrArray& strText = ((TextObj*) pObj)->strTextArray;
  437. int iCount = strText.GetSize();
  438. int iIndex;
  439. DWORD dwLength = 0;
  440. for (iIndex = 0; iIndex < iCount; iIndex++)
  441. {
  442. // Length of string plus 2 for carriage return and line feed
  443. dwLength += lstrlen(strText[iIndex]) + 2;
  444. }
  445. // One more for the terminating NULL
  446. dwLength += 1;
  447. // Allocate memory for the clipboard data
  448. HANDLE hMem = ::GlobalAlloc(GHND, dwLength);
  449. if (hMem != NULL)
  450. {
  451. // Get a pointer to the memory
  452. LPSTR pDest = (LPSTR) ::GlobalLock(hMem);
  453. if (pDest != NULL)
  454. {
  455. // Write the graphic data to the allocated memory
  456. for (iIndex = 0; iIndex < iCount; iIndex++)
  457. {
  458. _tcscpy(pDest, strText[iIndex]);
  459. pDest += lstrlen(strText[iIndex]);
  460. // Add the carriage return and line feed
  461. *pDest++ = '\r';
  462. *pDest++ = '\n';
  463. }
  464. // Add the final NULL
  465. *pDest = '\0';
  466. // Release the memory
  467. ::GlobalUnlock(hMem);
  468. // Pass the data to the clipboard
  469. if (::SetClipboardData(CF_TEXT, hMem))
  470. {
  471. TRACE_DEBUG(("Rendered data in text format"));
  472. }
  473. else
  474. {
  475. bResult = FALSE;
  476. }
  477. }
  478. // If we failed to put the data into the clipboard, free the memory
  479. if (bResult == FALSE)
  480. {
  481. ::GlobalFree(hMem);
  482. }
  483. break; // JOSEF what about copying all the text objects in the clipboard
  484. }
  485. }
  486. }
  487. return bResult;
  488. }
  489. //
  490. // CLP_RenderAsBitmap()
  491. //
  492. // This draws all other graphics into a bitmap and pastes the DIB contents
  493. // onto the clipboard.
  494. //
  495. BOOL WbMainWindow::CLP_RenderAsBitmap()
  496. {
  497. BOOL bResult = FALSE;
  498. HDC hdcDisplay = NULL;
  499. HDC hdcMem = NULL;
  500. HBITMAP hBitmap = NULL;
  501. HBITMAP hOldBitmap = NULL;
  502. HPALETTE hPalette;
  503. RECT rcBounds = g_pDraw->m_selectorRect;
  504. POINT pt;
  505. LPBITMAPINFOHEADER lpbi;
  506. T126Obj * pObj = NULL;
  507. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsBitmap");
  508. //
  509. // First, draw this into a bitmap
  510. // Second, get the DIB bits of the bitmap
  511. //
  512. hdcDisplay = ::CreateDC("DISPLAY", NULL, NULL, NULL);
  513. if (!hdcDisplay)
  514. {
  515. ERROR_OUT(("Can't create DISPLAY dc"));
  516. goto AsBitmapDone;
  517. }
  518. hdcMem = ::CreateCompatibleDC(hdcDisplay);
  519. if (!hdcMem)
  520. {
  521. ERROR_OUT(("Can't create DISPLAY compatible dc"));
  522. goto AsBitmapDone;
  523. }
  524. hBitmap = ::CreateCompatibleBitmap(hdcDisplay,
  525. (rcBounds.right - rcBounds.left), (rcBounds.bottom - rcBounds.top));
  526. if (!hBitmap)
  527. {
  528. ERROR_OUT(("Can't create compatible bitmap"));
  529. goto AsBitmapDone;
  530. }
  531. hOldBitmap = SelectBitmap(hdcMem, hBitmap);
  532. if (!hOldBitmap)
  533. {
  534. ERROR_OUT(("Failed to select compatible bitmap"));
  535. goto AsBitmapDone;
  536. }
  537. ::SetMapMode(hdcMem, MM_ANISOTROPIC);
  538. ::SetWindowOrgEx(hdcMem, rcBounds.left,rcBounds.top, NULL);
  539. // Clear out bitmap with white background -- now that origin has been
  540. // altered, we can use drawing area coors.
  541. ::PatBlt(hdcMem, rcBounds.left, rcBounds.top, rcBounds.right - rcBounds.left,
  542. rcBounds.bottom - rcBounds.top, WHITENESS);
  543. WBPOSITION pos;
  544. pos = g_pCurrentWorkspace->GetHeadPosition();
  545. while(pos)
  546. {
  547. pObj = g_pCurrentWorkspace->GetNextObject(pos);
  548. if(pObj && pObj->WasSelectedLocally())
  549. {
  550. pObj->Draw(hdcMem);
  551. }
  552. }
  553. SelectBitmap(hdcMem, hOldBitmap);
  554. // Now get the dib bits...
  555. hPalette = CreateSystemPalette();
  556. lpbi = DIB_FromBitmap(hBitmap, hPalette, TRUE, FALSE);
  557. if (hPalette != NULL)
  558. ::DeletePalette(hPalette);
  559. // And put the handle on the clipboard
  560. if (lpbi != NULL)
  561. {
  562. if (::SetClipboardData(CF_DIB, (HGLOBAL)lpbi))
  563. {
  564. bResult = TRUE;
  565. }
  566. else
  567. {
  568. ::GlobalFree((HGLOBAL)lpbi);
  569. }
  570. }
  571. AsBitmapDone:
  572. if (hBitmap != NULL)
  573. ::DeleteBitmap(hBitmap);
  574. if (hdcMem != NULL)
  575. ::DeleteDC(hdcMem);
  576. if (hdcDisplay != NULL)
  577. ::DeleteDC(hdcDisplay);
  578. return(bResult);
  579. }
  580. //
  581. //
  582. // Function: AcceptableClipboardFormat
  583. //
  584. // Purpose: Return highest priority clipboard format if an acceptable
  585. // one is available, else return NULL.
  586. //
  587. //
  588. int WbMainWindow::CLP_AcceptableClipboardFormat(void)
  589. {
  590. // Look for any of the supported formats being available
  591. int iFormat = ::GetPriorityClipboardFormat((UINT *)g_ClipboardFormats, CLIPBOARD_ACCEPTABLE_FORMATS);
  592. if (iFormat == -1)
  593. {
  594. iFormat = 0;
  595. }
  596. return iFormat;
  597. }
  598. BOOL WbMainWindow::PasteDIB( LPBITMAPINFOHEADER lpbi)
  599. {
  600. BOOL bResult = FALSE;
  601. //
  602. // Create a bitmap object
  603. //
  604. BitmapObj* pDIB = NULL;
  605. DBG_SAVE_FILE_LINE
  606. pDIB = new BitmapObj(TOOLTYPE_FILLEDBOX);
  607. if(NULL == pDIB)
  608. {
  609. ERROR_OUT(("Failed to allocate new BitmapObj"));
  610. return FALSE;
  611. }
  612. pDIB->SetBitmapSize(lpbi->biWidth,lpbi->biHeight);
  613. RECT rect;
  614. // Calculate the bounding rectangle from the size of the bitmap
  615. rect.top = 0;
  616. rect.left = 0;
  617. rect.right = lpbi->biWidth;
  618. rect.bottom = lpbi->biHeight;
  619. pDIB->SetRect(&rect);
  620. pDIB->SetAnchorPoint(rect.left, rect.top);
  621. //
  622. // Make a copy of the clipboard data
  623. //
  624. pDIB->m_lpbiImage = DIB_Copy(lpbi);
  625. if(pDIB->m_lpbiImage!= NULL)
  626. {
  627. // Add the new bitmap
  628. AddCapturedImage(pDIB);
  629. bResult = TRUE;
  630. }
  631. else
  632. {
  633. delete pDIB;
  634. }
  635. return bResult;
  636. }