|
|
//
// CLPBD.CPP
// Clipboard Handling
//
// Copyright Microsoft 1998-
//
// PRECOMP
#include "precomp.h"
//
// NFC, SFR 5921. Maximum length of a string pasted from the clipboard.
// We impose this limit as our graphic object code cant
// handle more then this number of chars.
//
#define WB_MAX_TEXT_PASTE_LEN (INT_MAX-1)
//
//
// Function: Paste
//
// Purpose: Paste a format from the clipboard
//
//
BOOL WbMainWindow::CLP_Paste(void) { UINT length = 0; HANDLE handle = NULL; T126Obj* pGraphic = NULL; BOOL bResult = FALSE;
MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_Paste");
// Get the highest priority acceptable format in the clipboard
int iFormat = CLP_AcceptableClipboardFormat(); if (!iFormat) goto NoOpenClip;
TRACE_MSG(("Found acceptable format %d", iFormat));
// Open the clipboard
if (!::OpenClipboard(m_hwnd)) { WARNING_OUT(("CLP_Paste: can't open clipboard")); goto NoOpenClip; }
handle = ::GetClipboardData(iFormat); if (!handle) { WARNING_OUT(("CLP_Paste: can't get data for format %d", iFormat)); goto NoFormatData; }
switch (iFormat) { //
// Check the standard formats
//
case CF_DIB: { TRACE_MSG(("Pasting CF_DIB"));
// Lock the handle to get a pointer to the DIB
LPBITMAPINFOHEADER lpbi; lpbi = (LPBITMAPINFOHEADER) ::GlobalLock(handle); if (lpbi != NULL) { bResult= PasteDIB(lpbi);
// Release the memory
::GlobalUnlock(handle); }
} break;
//
// We have a metafile. Play it into a bitmap and then use the
// data.
//
case CF_ENHMETAFILE: { TRACE_MSG(("Pasting CF_ENHMETAFILE"));
HDC hDrawingDC; ENHMETAHEADER meta_header; HBITMAP hBitmap = NULL; HDC meta_dc = NULL; HBITMAP hSaveBitmap; HPEN hSavePen; HPALETTE hPalette; RECT meta_rect; LPBITMAPINFOHEADER lpbiNew; int tmp;
// We just need a DC compatible with the drawing area wnd
hDrawingDC = m_drawingArea.GetCachedDC();
// make a dc
meta_dc = ::CreateCompatibleDC(hDrawingDC); if (!meta_dc) goto CleanupMetaFile;
// figure out image size.
::GetEnhMetaFileHeader( (HENHMETAFILE)handle, sizeof( ENHMETAHEADER ), &meta_header ); meta_rect.left = meta_rect.top = 0;
meta_rect.right = ((meta_header.rclFrame.right - meta_header.rclFrame.left) * ::GetDeviceCaps(hDrawingDC, LOGPIXELSX ))/2540;
meta_rect.bottom = ((meta_header.rclFrame.bottom - meta_header.rclFrame.top) * ::GetDeviceCaps(hDrawingDC, LOGPIXELSY ))/2540;
// Normalize coords
if (meta_rect.right < meta_rect.left) { tmp = meta_rect.left; meta_rect.left = meta_rect.right; meta_rect.right = tmp; } if (meta_rect.bottom < meta_rect.top) { tmp = meta_rect.top; meta_rect.top = meta_rect.bottom; meta_rect.bottom = tmp; }
// make a place to play meta in
hBitmap = ::CreateCompatibleBitmap(hDrawingDC, meta_rect.right - meta_rect.left, meta_rect.bottom - meta_rect.top); if (!hBitmap) goto CleanupMetaFile;
hSaveBitmap = SelectBitmap(meta_dc, hBitmap);
// erase our paper
hSavePen = SelectPen(meta_dc, GetStockObject(NULL_PEN));
::Rectangle(meta_dc, meta_rect.left, meta_rect.top, meta_rect.right + 1, meta_rect.bottom + 1);
SelectPen(meta_dc, hSavePen);
// play the tape
::PlayEnhMetaFile(meta_dc, (HENHMETAFILE)handle, &meta_rect);
// unplug our new bitmap
SelectBitmap(meta_dc, hSaveBitmap);
// Check for a palette object in the clipboard
hPalette = (HPALETTE)::GetClipboardData(CF_PALETTE);
// Create a new DIB from the bitmap
lpbiNew = DIB_FromBitmap(hBitmap, hPalette, FALSE, FALSE);
if(lpbiNew != NULL) { bResult= PasteDIB(lpbiNew); }
CleanupMetaFile: // Free our temp intermediate bitmap
if (hBitmap != NULL) { DeleteBitmap(hBitmap); }
if (meta_dc != NULL) { ::DeleteDC(meta_dc); } } break;
case CF_TEXT: { LPSTR pData;
TRACE_DEBUG(("Pasting text"));
// Get a handle to the clipboard contents
pData = (LPSTR)::GlobalLock(handle);
if(pData) { // Create a text object to hold the data - get the font to
// use from the tool attributes group.
DBG_SAVE_FILE_LINE WbTextEditor* pPasteText = new WbTextEditor();
// Use the current font attributes
if (!pPasteText) { ERROR_OUT(("CF_TEXT handling; failed to allocate DCWbGraphicText object")); } else { pPasteText->SetFont(m_pCurrentTool->GetFont()); pPasteText->SetText(pData); RECT rcVis; m_drawingArea.GetVisibleRect(&rcVis); pPasteText->SetPenColor(RGB(0,0,0),TRUE); pPasteText->SetAnchorPoint(0, 0); pPasteText->MoveTo(rcVis.left, rcVis.top); pPasteText->Draw(); pPasteText->m_pEditBox = NULL;
// Add the new grabbed bitmap
pPasteText->SetAllAttribs(); pPasteText->AddToWorkspace(); bResult = TRUE; }
pGraphic = pPasteText; }
} break;
default: { if (iFormat == g_ClipboardFormats[CLIPBOARD_PRIVATE]) {
WB_OBJ objectHeader; UINT type; ULONG nItems = 0; PBYTE pClipBoardBuffer; if (pClipBoardBuffer = (PBYTE) ::GlobalLock(handle)) {
//
// Count objects before we paste.
//
PBYTE pClipBuff = pClipBoardBuffer; length = ((PWB_OBJ)pClipBuff)->length; pClipBuff += sizeof(objectHeader); while(length) { nItems++; pClipBuff += length; length = ((PWB_OBJ)pClipBuff)->length; pClipBuff += sizeof(objectHeader); }
TimeToGetGCCHandles(nItems);
length = ((PWB_OBJ)pClipBoardBuffer)->length; type = ((PWB_OBJ)pClipBoardBuffer)->type; pClipBoardBuffer += sizeof(objectHeader); while(length) { if(type == TYPE_T126_ASN_OBJECT) { bResult = T126_MCSSendDataIndication(length, pClipBoardBuffer, g_MyMemberID, TRUE); } else if(type == TYPE_T126_DIB_OBJECT) { bResult = PasteDIB((LPBITMAPINFOHEADER)pClipBoardBuffer); } pClipBoardBuffer += length; length = ((PWB_OBJ)pClipBoardBuffer)->length; type = ((PWB_OBJ)pClipBoardBuffer)->type; pClipBoardBuffer += sizeof(objectHeader); } // Release the handle
::GlobalUnlock(handle); } } } break; }
NoFormatData: ::CloseClipboard();
NoOpenClip: return bResult; }
//
//
// Function: Copy
//
// Purpose: Copy a graphic to the clipboard.
//
//
BOOL WbMainWindow::CLP_Copy() { BOOL bResult = FALSE;
MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_Copy");
//
// We act according to the format of the selected graphic.
//
// For all formats we supply the Whiteboard private format (which is
// just a copy of the flat representation of the graphic).
//
// We supply standard formats as follows.
//
// For bitmaps and all others we supply CF_DIB.
//
// For text graphics we supply CF_TEXT.
//
TRACE_MSG(("Rendering the graphic now"));
// Have to empty the clipboard before rendering the formats.
if (::OpenClipboard(m_hwnd)) { // Get ownership of the clipboard
::EmptyClipboard(); ::CloseClipboard();
// Render the graphic
bResult = CLP_RenderAllFormats(); }
return bResult; }
//
//
// Function: RenderAllFormats
//
// Purpose: Render a graphic to the clipboard
//
//
BOOL WbMainWindow::CLP_RenderAllFormats() { MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAllFormats"); BOOL bResult = FALSE;
// Open the clipboard
if (bResult = ::OpenClipboard(m_hwnd)) { TRACE_DEBUG(("Rendering all formats of graphic"));
// Render the private format
bResult &= CLP_RenderPrivateFormat();
// Text graphic
bResult &= CLP_RenderAsText();
// DIBs
// bResult &= CLP_RenderAsImage();
// Bitmaps
bResult &= CLP_RenderAsBitmap();
// Close the clipboard
::CloseClipboard(); }
return bResult; }
//
//
// Function: CLP_RenderPrivateFormat
//
// Purpose: Render the private format of a graphic to the clipboard.
// The clipboard should be open before this call is made.
//
//
BOOL WbMainWindow::CLP_RenderPrivateFormat() { MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderPrivateFormat");
BOOL bResult = FALSE; LPBYTE pDest = NULL; HGLOBAL hMem = NULL; HGLOBAL hRealloc = NULL; WB_OBJ objectHeader; ULONG length = sizeof(objectHeader); BOOL bDoASN1CleanUp = FALSE; ULONG previousLength = 0;
WBPOSITION pos; T126Obj * pObj; ASN1_BUF encodedPDU;
pos = g_pCurrentWorkspace->GetHeadPosition();
while(pos) { pObj = g_pCurrentWorkspace->GetNextObject(pos); if(pObj && pObj->WasSelectedLocally()) {
//
// Get the encoded buffer
//
pObj->SetAllAttribs(); pObj->SetViewState(unselected_chosen); pObj->GetEncodedCreatePDU(&encodedPDU); objectHeader.length = encodedPDU.length;
if(pObj->GetType() == bitmapCreatePDU_chosen) { objectHeader.type = TYPE_T126_DIB_OBJECT; } else if(pObj->GetType() == drawingCreatePDU_chosen || pObj->GetType() == siNonStandardPDU_chosen) { objectHeader.type = TYPE_T126_ASN_OBJECT; bDoASN1CleanUp = TRUE; } length += encodedPDU.length + sizeof(objectHeader);
if(pDest) { hRealloc = ::GlobalReAlloc(hMem, length, GMEM_MOVEABLE | GMEM_DDESHARE); if(!hRealloc) { goto bail; } hMem = hRealloc; } else { // Allocate memory for the clipboard data
hMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, length); if(hMem == NULL) { goto bail; } }
//
// Get a pointer to the destination
//
pDest = (LPBYTE)::GlobalLock(hMem);
//
// Write the header
//
memcpy(pDest + previousLength, &objectHeader, sizeof(objectHeader)); previousLength += sizeof(objectHeader);
//
// Copy the decoded data in the destination
//
memcpy(pDest + previousLength, encodedPDU.value, encodedPDU.length); previousLength += encodedPDU.length;
//
// Terminate the block with a 0
//
objectHeader.length = 0; memcpy(pDest + previousLength, &objectHeader, sizeof(objectHeader)); //
// Free the encoded data
//
if(bDoASN1CleanUp) { g_pCoder->Free(encodedPDU); bDoASN1CleanUp = FALSE; } } }
// Release the memory
::GlobalUnlock(hMem);
// Pass the data to the clipboard
if (::SetClipboardData(g_ClipboardFormats[CLIPBOARD_PRIVATE], hMem)) { TRACE_DEBUG(("Rendered data in Whiteboard format")); bResult = TRUE; }
bail:
if(bDoASN1CleanUp) { g_pCoder->Free(encodedPDU); }
// If we failed to put the data into the clipboard, free the memory.
// (If we did put it into the clipboard we must not free it).
if (bResult == FALSE) { WARNING_OUT(("Render failed")); ::GlobalFree(hMem); }
return bResult; }
//
//
// Function: RenderAsText
//
// Purpose: Render the text format of a graphic to the clipboard.
// The clipboard should be open before this call is made.
// This member should only be called for text graphics.
//
//
BOOL WbMainWindow::CLP_RenderAsText() { MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsText");
BOOL bResult = TRUE;
WBPOSITION pos;
T126Obj * pObj; pos = g_pCurrentWorkspace->GetHeadPosition(); while(pos) { pObj = g_pCurrentWorkspace->GetNextObject(pos); if(pObj && pObj->WasSelectedLocally() && pObj->GraphicTool() == TOOLTYPE_TEXT) {
// Get the total length of the clipboard format of the text
StrArray& strText = ((TextObj*) pObj)->strTextArray; int iCount = strText.GetSize(); int iIndex; DWORD dwLength = 0;
for (iIndex = 0; iIndex < iCount; iIndex++) { // Length of string plus 2 for carriage return and line feed
dwLength += lstrlen(strText[iIndex]) + 2; }
// One more for the terminating NULL
dwLength += 1;
// Allocate memory for the clipboard data
HANDLE hMem = ::GlobalAlloc(GHND, dwLength); if (hMem != NULL) { // Get a pointer to the memory
LPSTR pDest = (LPSTR) ::GlobalLock(hMem); if (pDest != NULL) { // Write the graphic data to the allocated memory
for (iIndex = 0; iIndex < iCount; iIndex++) { _tcscpy(pDest, strText[iIndex]); pDest += lstrlen(strText[iIndex]);
// Add the carriage return and line feed
*pDest++ = '\r'; *pDest++ = '\n'; }
// Add the final NULL
*pDest = '\0';
// Release the memory
::GlobalUnlock(hMem);
// Pass the data to the clipboard
if (::SetClipboardData(CF_TEXT, hMem)) { TRACE_DEBUG(("Rendered data in text format")); } else { bResult = FALSE; } }
// If we failed to put the data into the clipboard, free the memory
if (bResult == FALSE) { ::GlobalFree(hMem); }
break; // JOSEF what about copying all the text objects in the clipboard
}
} }
return bResult; }
//
// CLP_RenderAsBitmap()
//
// This draws all other graphics into a bitmap and pastes the DIB contents
// onto the clipboard.
//
BOOL WbMainWindow::CLP_RenderAsBitmap() { BOOL bResult = FALSE; HDC hdcDisplay = NULL; HDC hdcMem = NULL; HBITMAP hBitmap = NULL; HBITMAP hOldBitmap = NULL; HPALETTE hPalette; RECT rcBounds = g_pDraw->m_selectorRect; POINT pt; LPBITMAPINFOHEADER lpbi; T126Obj * pObj = NULL;
MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsBitmap");
//
// First, draw this into a bitmap
// Second, get the DIB bits of the bitmap
//
hdcDisplay = ::CreateDC("DISPLAY", NULL, NULL, NULL); if (!hdcDisplay) { ERROR_OUT(("Can't create DISPLAY dc")); goto AsBitmapDone; }
hdcMem = ::CreateCompatibleDC(hdcDisplay); if (!hdcMem) { ERROR_OUT(("Can't create DISPLAY compatible dc")); goto AsBitmapDone; }
hBitmap = ::CreateCompatibleBitmap(hdcDisplay, (rcBounds.right - rcBounds.left), (rcBounds.bottom - rcBounds.top)); if (!hBitmap) { ERROR_OUT(("Can't create compatible bitmap")); goto AsBitmapDone; }
hOldBitmap = SelectBitmap(hdcMem, hBitmap); if (!hOldBitmap) { ERROR_OUT(("Failed to select compatible bitmap")); goto AsBitmapDone; }
::SetMapMode(hdcMem, MM_ANISOTROPIC); ::SetWindowOrgEx(hdcMem, rcBounds.left,rcBounds.top, NULL);
// Clear out bitmap with white background -- now that origin has been
// altered, we can use drawing area coors.
::PatBlt(hdcMem, rcBounds.left, rcBounds.top, rcBounds.right - rcBounds.left, rcBounds.bottom - rcBounds.top, WHITENESS);
WBPOSITION pos;
pos = g_pCurrentWorkspace->GetHeadPosition();
while(pos) { pObj = g_pCurrentWorkspace->GetNextObject(pos);
if(pObj && pObj->WasSelectedLocally()) { pObj->Draw(hdcMem); } }
SelectBitmap(hdcMem, hOldBitmap);
// Now get the dib bits...
hPalette = CreateSystemPalette(); lpbi = DIB_FromBitmap(hBitmap, hPalette, TRUE, FALSE); if (hPalette != NULL) ::DeletePalette(hPalette);
// And put the handle on the clipboard
if (lpbi != NULL) { if (::SetClipboardData(CF_DIB, (HGLOBAL)lpbi)) { bResult = TRUE; } else { ::GlobalFree((HGLOBAL)lpbi); } }
AsBitmapDone: if (hBitmap != NULL) ::DeleteBitmap(hBitmap);
if (hdcMem != NULL) ::DeleteDC(hdcMem);
if (hdcDisplay != NULL) ::DeleteDC(hdcDisplay);
return(bResult); }
//
//
// Function: AcceptableClipboardFormat
//
// Purpose: Return highest priority clipboard format if an acceptable
// one is available, else return NULL.
//
//
int WbMainWindow::CLP_AcceptableClipboardFormat(void) { // Look for any of the supported formats being available
int iFormat = ::GetPriorityClipboardFormat((UINT *)g_ClipboardFormats, CLIPBOARD_ACCEPTABLE_FORMATS); if (iFormat == -1) { iFormat = 0; }
return iFormat; }
BOOL WbMainWindow::PasteDIB( LPBITMAPINFOHEADER lpbi) { BOOL bResult = FALSE; //
// Create a bitmap object
//
BitmapObj* pDIB = NULL; DBG_SAVE_FILE_LINE pDIB = new BitmapObj(TOOLTYPE_FILLEDBOX); if(NULL == pDIB) { ERROR_OUT(("Failed to allocate new BitmapObj")); return FALSE; } pDIB->SetBitmapSize(lpbi->biWidth,lpbi->biHeight);
RECT rect; // Calculate the bounding rectangle from the size of the bitmap
rect.top = 0; rect.left = 0; rect.right = lpbi->biWidth; rect.bottom = lpbi->biHeight; pDIB->SetRect(&rect); pDIB->SetAnchorPoint(rect.left, rect.top);
//
// Make a copy of the clipboard data
//
pDIB->m_lpbiImage = DIB_Copy(lpbi);
if(pDIB->m_lpbiImage!= NULL) { // Add the new bitmap
AddCapturedImage(pDIB); bResult = TRUE; } else { delete pDIB; }
return bResult; }
|