00001 // $Id: clipext.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 // External clipboard interface - classes for encapsulating clipboard data mappings 00099 // and for managing data transfers between the internal and external clipboards 00100 00101 #include "camtypes.h" 00102 00103 #include "stdafx.h" 00104 //#include "clipdlg.h" 00105 #include "clipext.h" 00106 #include "clipint.h" 00107 #include "clipmap.h" 00108 #include "natclipm.h" 00109 //#include "jason.h" 00110 00111 // **** TEMPORARY BODGE includes for crappy bitmap export 00112 //#include "ccobject.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 #include "grndbmp.h" 00115 #include "layer.h" 00116 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00117 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00118 #include "dlgview.h" 00119 #include "vstate.h" 00120 #include "wbitmap.h" 00121 00122 #include "mainfrm.h" 00123 #include "camvw.h" 00124 // **** 00125 00126 #if (_OLE_VER >= 0x200) 00127 #include "camdoc.h" 00128 #include "camelot.h" 00129 #include "srvritem.h" 00130 //#include "filters.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00131 #endif 00132 00133 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00134 00135 // --- Support for node types used in scanning the document tree for KeepClipboardOnExit 00136 #include "nodeblnd.h" 00137 #include "nodebmp.h" 00138 #include "bitmpinf.h" 00139 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00140 // --- 00141 00142 // --- OLE clipboard 00143 #if (_OLE_VER >= 0x200) 00144 #include "dataobj.h" 00145 #endif 00146 00147 //#include "richard2.h" // For resource strings 00148 //#include "justin3.h" 00149 //#include "mario.h" 00150 00151 CC_IMPLEMENT_MEMDUMP(ExternalClipboard, CC_CLASS_MEMDUMP) 00152 CC_IMPLEMENT_DYNCREATE(OpClipboardExport, Operation) 00153 CC_IMPLEMENT_DYNCREATE(OpClipboardImport, SelOperation) 00154 CC_IMPLEMENT_DYNAMIC(ClipboardView, View) 00155 CC_IMPLEMENT_DYNCREATE(PasteSpecialDlg, DialogOp) 00156 00157 00158 #define new CAM_DEBUG_NEW 00159 00160 00161 // define this symbol as 1 to enable paste-special behaviour (this makes a paste show 00162 // the paste-special dialogue box) or 0 to get "normal" simple paste behaviour. 00163 #if _DEBUG 00164 #define DO_PASTE_SPECIAL 1 00165 #else 00166 #define DO_PASTE_SPECIAL 1 00167 #endif 00168 00169 00170 // Statics ---------------------------------------------------------------------------------- 00171 ExternalClipboard* ExternalClipboard::pInstance = NULL; 00172 00173 // This value is the (rough) number of nodes in the clipboard tree before we think it's worth 00174 // asking the user about whether they want the clipboard contents retained on exit. This is 00175 // a very rough guide, mainly to eliminate this question when there is only trivial data 00176 // (a sentence or a couple of blobs) on the clipboard. 00177 // Note that this is not a strict node count. For example, blends and grad fill attributes 00178 // cause a large count to be added, as these nodes can produce much larger output in 00179 // standard clipboard formats such as WMF, while text characters cause a lower value. 00180 // Each other node generally adds about 10 to the value, so 2000 corresponds roughly 00181 // to 2000 characters, 200 nodes in the tree, or 10 grad-filled objects. 00182 const INT32 KeepClipboardThreshold = 4000; 00183 // ------------------------------------------------------------------------------------------ 00184 00185 00186 BOOL ExternalClipboard::m_fUpdateSystemClipboard = TRUE; 00187 00188 00189 /******************************************************************************************** 00190 Preference: DontExportCMXInIDataObject 00191 Section: OLE Local Server 00192 Range: 0 .. 1 (FALSE .. TRUE) 00193 Purpose: If TRUE then don't offer to render CorelXARA documents in Corel CMX format 00194 for transfer via the clipboard or drag'n'drop. Setting this pref. to TRUE 00195 overcomes a bug when embedding CorelXARA documents into CorelDRAW. By 00196 default this setting is TRUE. Making it FALSE will allow you to transfer 00197 CorelXARA documents to CorelDRAW via the clipboard or drag'n'drop in the 00198 CMX format, but embedding CorelXARA documents in CorelDRAW will no longer# 00199 work properly. 00200 ********************************************************************************************/ 00201 static BOOL fNoCMXDataExport = TRUE; 00202 00203 00204 /******************************************************************************************** 00205 00206 > ExternalClipboard::ExternalClipboard() 00207 00208 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00209 Created: 16/4/95 00210 00211 Purpose: constructor 00212 00213 ********************************************************************************************/ 00214 00215 ExternalClipboard::ExternalClipboard() 00216 { 00217 if (pInstance == NULL) 00218 pInstance = this; 00219 else 00220 { 00221 ERROR3("Oy! You can't have more than one instance of the ExternalClipboard!"); 00222 } 00223 00224 KeepFormatsOnExit = TRUE; 00225 00226 #if (_OLE_VER >= 0x200) 00227 m_fIgnoreChange = FALSE; 00228 #endif 00229 } 00230 00231 00232 00233 /******************************************************************************************** 00234 00235 > virtual ExternalClipboard::~ExternalClipboard() 00236 00237 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00238 Created: 16/4/95 00239 00240 Purpose: Destructor. Cleans up our lists and wotnot. 00241 00242 ********************************************************************************************/ 00243 00244 ExternalClipboard::~ExternalClipboard() 00245 { 00246 Mappings.DeleteAll(); 00247 00248 if (pInstance == this) 00249 pInstance = NULL; 00250 else 00251 { 00252 ERROR3("Oy! You can't have more than one instance of the ExternalClipboard!"); 00253 } 00254 } 00255 00256 00257 00258 /******************************************************************************************** 00259 00260 > static BOOL ExternalClipboard::Init(void) 00261 00262 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00263 Created: 16/4/95 00264 00265 Purpose: Initialises the ExternalClipboard ready for operation 00266 00267 SeeAlso: ExternalClipboard::Deinit 00268 00269 ********************************************************************************************/ 00270 00271 BOOL ExternalClipboard::Init(void) 00272 { 00273 if (!OpClipboardExport::Init()) 00274 return(FALSE); 00275 00276 if (!OpClipboardImport::Init()) 00277 return(FALSE); 00278 00279 if (!PasteSpecialDlg::Init()) 00280 return(FALSE); 00281 00282 ExternalClipboard *TheClipboard = new ExternalClipboard(); 00283 if (TheClipboard == NULL) 00284 return(FALSE); 00285 00286 00287 // **** !!!! DEBUG BODGE - add export mapping for text characters - ideally this 00288 // clipboard mapping should be provided by a proper text import/export filter, 00289 // but one does not exist yet. 00290 // Add a UNICODE filter - this only works under NT, as nobody else supports unicode 00291 BodgeUnicodeClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT, CF_UNICODETEXT); 00292 00293 // 8-bit text (windows implicitly converts between these for us) 00294 // The first one is the filter, while the second one is an 'alias' for import 00295 // which will make windows convert the OEMTEXT into TEXT and then we put this through 00296 // our normal TEXT mapping... 00297 BodgeTextClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT, CF_TEXT); 00298 BodgeTextClipMap::CreateAndRegister(CLIPMAP_IMPORTONLY, CF_OEMTEXT); 00299 00300 // Add bitmap/DIB import/export mappings 00301 // Note that if we export WMF and DIB, there is no need to bother with Bitmap 00302 // (Corel don't, probably because there is no way of getting a quality image via Bitmaps, 00303 // and also because some programs are stupid and corrupt the DIB by using the palette 00304 // which we supply for the Bitmap! Arrgh!) 00305 // BitmapClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT); 00306 BitmapClipMap::CreateAndRegister(CLIPMAP_IMPORTONLY); 00307 00308 DIBClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT); 00309 00310 // CMX import and export stuff to make commicating with Corel happier 00311 CMX16ClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT, ::RegisterClipboardFormat("Corel Presentation Exchange Data")); 00312 CMX32ClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT, ::RegisterClipboardFormat("Corel 32-bit Presentation Exchange Data")); 00313 00314 // native clipboard thing -- for OLE stuff 00315 // 00316 // this is export only (although functional code does exist for import) 00317 // as there are several technical problems with getting the native filter 00318 // to import into the clipboard document. See the comment near the 00319 // NativeClipMap::HandleImport() function for more details. 00320 NativeClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT /*CLIPMAP_EXPORTONLY*/, ::RegisterClipboardFormat("CorelXARA Document")); 00321 // NativeClipMap::CreateAndRegister(CLIPMAP_IMPORTEXPORT /*CLIPMAP_EXPORTONLY*/, ::RegisterClipboardFormat("XaraX Document")); 00322 00323 // Add a palette export mapping - used in conjunction with Bitmap exporter, it provides 00324 // the palette for the given bitmap. (not needed now we don't export BMPs) 00325 // PaletteClipMap::CreateAndRegister(); 00326 00327 #if FALSE 00328 // And add our Quark EPS import filter 00329 QuarkPictureClipMap::CreateAndRegister(); 00330 #endif 00331 00332 // Read the bug-fix preference for CMX. 00333 if (!GetApplication()->DeclareSection(TEXT("OLE Local Server"), 5) || 00334 !GetApplication()->DeclarePref(TEXT("OLE Local Server"), 00335 TEXT("DontExportCMXInIDataObject"), 00336 &fNoCMXDataExport, FALSE, TRUE)) 00337 { 00338 TRACEUSER( "JustinF", _T("Couldn't read CMX pref in ExternalClipboard::Init\n")); 00339 return FALSE; 00340 } 00341 00342 return(TRUE); 00343 } 00344 00345 00346 00347 /******************************************************************************************** 00348 00349 > static void ExternalClipboard::Deinit(void) 00350 00351 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00352 Created: 16/4/95 00353 00354 Purpose: De-Initialises the ExternalClipboard when you're shutting down 00355 00356 SeeAlso: ExternalClipboard::Init 00357 00358 ********************************************************************************************/ 00359 00360 void ExternalClipboard::Deinit(void) 00361 { 00362 if (pInstance != NULL) 00363 delete pInstance; 00364 pInstance = NULL; 00365 } 00366 00367 00368 00370 // 00371 // The OLE clipboard 00372 // 00373 00374 #if (_OLE_VER >= 0x200) 00375 00376 /******************************************************************************************** 00377 > void ExternalClipboard::SetRenderMemory(HGLOBAL hMem) 00378 00379 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00380 Created: 16/9/96 00381 Inputs: hMem --- the global memory to delay-render into, or null if 00382 the rendering functions themselves should allocate 00383 it. 00384 Purpose: Sets the memory that the delay-render functions will render into. 00385 SeeAlso: CCamDataSource::OnRenderGlobalData 00386 ********************************************************************************************/ 00387 00388 void ExternalClipboard::SetRenderMemory(HGLOBAL hMem) 00389 { 00390 // Record the handle and its size, if any. 00391 m_hMem = hMem; 00392 m_cbMemSize = (m_hMem != 0) ? ::GlobalSize(m_hMem) : 0; 00393 } 00394 00395 00396 00397 00398 /******************************************************************************************** 00399 > HGLOBAL ExternalClipboard::GetRenderMemory() const 00400 00401 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00402 Created: 16/9/96 00403 Returns: The global memory block that was delay-rendered into. 00404 Purpose: 00405 SeeAlso: ExternalClipboard::SetRenderMemory 00406 ********************************************************************************************/ 00407 00408 HGLOBAL ExternalClipboard::GetRenderMemory() const 00409 { 00410 return m_hMem; 00411 } 00412 00413 #endif 00414 00415 00416 00417 /******************************************************************************************** 00418 > BOOL ExternalClipboard::IsOurs() const 00419 00420 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00421 Created: 16/9/96 00422 Returns: TRUE if Camelot currently owns the clipboard, FALSE if it doesn't or the 00423 clipboard is empty. 00424 SeeAlso: COleDataSource::GetClipboardOwner; CWnd::GetClipboardOwner 00425 ********************************************************************************************/ 00426 00427 BOOL ExternalClipboard::IsOurs() const 00428 { 00429 #if (_OLE_VER >= 0x200) 00430 // OLE does it with data sources (but paste still does it with window handles). 00431 return CCamDataSource::GetClipboardOwner() != 0 || 00432 CWnd::GetClipboardOwner() == GetOwnerWindow(); 00433 #else 00434 // Windows does it with window handles. 00435 return CWnd::GetClipboardOwner() == GetOwnerWindow(); 00436 #endif 00437 } 00438 00439 00440 00442 00443 00444 00445 /******************************************************************************************** 00446 00447 > static void ExternalClipboard::PrepareForShutdown() 00448 00449 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00450 Created: 31/10/95 00451 00452 Purpose: Asks the user if they want to keep the clipboard content and renders the 00453 formats immeidately if they said yes. This is called on exit, BEFORE any 00454 windows close etc, so that the user is aware that Camelot is still running 00455 and that it is busy exporting the clipboard. 00456 00457 The user may not be asked at all (e.g. if we don't own the clipboard) 00458 00459 SeeAlso: ExternalClipboard::RenderAllFormats; ExternalClipboard::CheckKeepClipboardOnExit 00460 00461 ********************************************************************************************/ 00462 00463 BOOL fBodgeNoCMX = FALSE; 00464 00465 void ExternalClipboard::PrepareForShutdown() 00466 { 00467 // Is there a clipboard? 00468 if (InternalClipboard::IsEmpty(FALSE)) return; 00469 00470 ExternalClipboard* pClipboard = GetExternalClipboard(); 00471 if (pClipboard == NULL) return; 00472 00473 pClipboard->CheckKeepClipboardOnExit(); 00474 00475 #if (_OLE_VER >= 0x200) 00476 00477 if (pClipboard->KeepFormatsOnExit) 00478 { 00479 // Render all the clipboard formats now (except CMX cos it may crash if there's a 00480 // bitmap or a fractal about - doh-doh-double-doh?!?!?) 00481 // TRACEUSER( "JustinF", _T("Rendering clipboard formats now ...\n")); 00482 fBodgeNoCMX = TRUE; 00483 CCamDataSource::FlushClipboard(); 00484 fBodgeNoCMX = FALSE; 00485 } 00486 else 00487 { 00488 // Discard the clipboard contents now. 00489 // TRACEUSER( "JustinF", _T("Discarding clipboard formats ...\n")); 00490 COleDataSource* pSource = CCamDataSource::GetClipboardOwner(); 00491 if (pSource) pSource->Empty(); 00492 } 00493 00494 #else 00495 00496 // This member var. will have been set by someone calling CheckKeepClipboardOnExit() 00497 if (!pClipboard->KeepFormatsOnExit) 00498 { 00499 // They don't want to keep the clipboard formats, so wipe the clipboard. 00500 CWnd* pParent = GetOwnerWindow(); 00501 if (pParent->OpenClipboard() != NULL) 00502 { 00503 ::EmptyClipboard(); 00504 ::CloseClipboard(); 00505 } 00506 return; 00507 } 00508 00509 // They do want to keep the clipboard contents, so render all formats to it now 00510 pClipboard->RenderAllFormats(); 00511 00512 #endif 00513 00514 // And make sure that we ignore any further attempt to make us render formats 00515 pClipboard->KeepFormatsOnExit = FALSE; 00516 } 00517 00518 00519 00520 /******************************************************************************************** 00521 00522 > void ExternalClipboard::CheckKeepClipboardOnExit(void) 00523 00524 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00525 Created: 21/4/95 00526 00527 Purpose: Called once on exit to check if the user wants the contents of the clipboard 00528 to be available after camelot is gone. This is supposed to be done when 00529 RenderAllFormats is called, but this happens after the main frame window has 00530 departed, so we want someone to call this method sometime between the last 00531 document being closed and the main frame being removed. 00532 00533 It flags the user's choice, and this result will be used if/when we get 00534 a render-all-formats request. 00535 00536 The user may not be asked at all (e.g. if we don't own the clipboard) 00537 00538 SeeAlso: ExternalClipboard::RenderAllFormats 00539 00540 ********************************************************************************************/ 00541 00542 void ExternalClipboard::CheckKeepClipboardOnExit(void) 00543 { 00544 if (InternalClipboard::IsEmpty(FALSE)) // No clipboard! 00545 return; 00546 00547 // Do we own the clipboard? 00548 if (!IsOurs()) return; 00549 00550 // OK, Now let's determine just how complicated the data is. If it looks like it 00551 // will take an INT32 time or a lot of memory to leave it on the CB, then we'll 00552 // ask the user - if not, we'll just stay quiet about it and lump it all onto 00553 // the CB without asking permission. 00554 // This is done with a very rough guide: A node count of the clipboard content, 00555 // modified slightly to take account of the fact that blends and grad fills usually 00556 // cause a lot more output (in WMF format etc). 00557 Node *pRoot = InternalClipboard::GetInsertionLayer(); 00558 if (pRoot == NULL) 00559 { 00560 KeepFormatsOnExit = TRUE; 00561 return; 00562 } 00563 00564 Node *pNode = pRoot->FindFirstDepthFirst(); 00565 INT32 RoughNodeCount = 0; 00566 00567 while (pNode != NULL && RoughNodeCount < KeepClipboardThreshold) 00568 { 00569 if (pNode->IsAVisibleTextNode()) 00570 { 00571 RoughNodeCount += 1; // Text chars export small, so count as 1 00572 } 00573 else if (IS_A(pNode, NodeBlend)) 00574 { 00575 // Each blend step counts as another 8 00576 RoughNodeCount += 128 * (((NodeBlend *)pNode)->GetNumBlendSteps()); 00577 } 00578 else if (pNode->IsAnAttribute()) 00579 { 00580 // Each fill counts as 64 (in case it's a grad fill) 00581 if (pNode->IsKindOf(CC_RUNTIME_CLASS(AttrFillGeometry))) 00582 RoughNodeCount += 64; 00583 } 00584 else if (IS_A(pNode, NodeBitmap)) 00585 { 00586 // Add Bitmap memory size to the count 00587 // This will hit the threshold at about 128kB 00588 KernelBitmapRef *BmpRef = ((NodeBitmap*)pNode)->GetBitmapRef(); 00589 if (BmpRef != NULL) 00590 { 00591 KernelBitmap *KernelBmp = BmpRef->GetBitmap(); 00592 if (KernelBmp != NULL) 00593 { 00594 OILBitmap *OilBmp = KernelBmp->ActualBitmap; 00595 if (OilBmp != NULL) 00596 { 00597 BitmapInfo BmpInfo; 00598 OilBmp->GetInfo(&BmpInfo); 00599 RoughNodeCount += BmpInfo.MemoryUsed / 32; 00600 } 00601 } 00602 } 00603 00604 } 00605 else 00606 RoughNodeCount += 10; // All other nodes count as 10 00607 00608 pNode = pNode->FindNextDepthFirst(pRoot); 00609 } 00610 00611 // Default to saving the clipboard content on exit... 00612 KeepFormatsOnExit = TRUE; 00613 00614 if (RoughNodeCount >= KeepClipboardThreshold) 00615 { 00616 // It looks a bit complicated, so maybe we'd better ask the user if they want the 00617 // clipboard contents to stick around once Camelot has quit. 00618 INT32 ButtonPressed = AskQuestion(_R(IDS_CLIPBOARD_KEEPONQUIT), 00619 _R(IDS_CLIPBOARD_KEEP), _R(IDS_CLIPBOARD_DISCARD)); 00620 00621 // Then remember whether we should render all available formats to the clipboard 00622 KeepFormatsOnExit = (ButtonPressed == 1); 00623 } 00624 } 00625 00626 00627 /******************************************************************************************** 00628 00629 > static BOOL ExternalClipboard::CanImport(UINT32 WindowsFormat) 00630 00631 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00632 Created: 2/5/95 00633 00634 Inputs: WindowsFormat - the windows format (e.g. CF_ constant) which you wish to check 00635 00636 Returns: TRUE if it can import that data type 00637 00638 Purpose: Determines if there is an import mapping that can cope with the given format 00639 00640 ********************************************************************************************/ 00641 00642 BOOL ExternalClipboard::CanImport(UINT32 WindowsFormat) 00643 { 00644 if (pInstance == NULL) 00645 return(FALSE); 00646 00647 ClipboardMapping *Mapping = (ClipboardMapping *) pInstance->Mappings.GetHead(); 00648 while (Mapping != NULL) 00649 { 00650 if (Mapping->Type != CLIPMAP_EXPORTONLY && Mapping->ExternalDataType == WindowsFormat) 00651 return(TRUE); 00652 00653 Mapping = (ClipboardMapping *) pInstance->Mappings.GetNext(Mapping); 00654 } 00655 00656 return(FALSE); 00657 } 00658 00659 00660 00661 /******************************************************************************************** 00662 00663 > static void ExternalClipboard::RegisterDataType(ClipboardMapping *Mapping) 00664 00665 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00666 Created: 16/4/95 00667 00668 Inputs: TypeInfo - info describing the import/export mapping to add 00669 00670 Purpose: Called by filters to add import/export mappings to the external clipboard. 00671 Each mapping indicates which filter to call in order to convert data 00672 between a particular internal and external clipboard format. 00673 00674 Notes: The Mapping is NOW OWNED by the ExternalClipboard. DO NOT DELETE IT. 00675 00676 ********************************************************************************************/ 00677 00678 void ExternalClipboard::RegisterDataType(ClipboardMapping *Mapping) 00679 { 00680 ERROR3IF(Mapping == NULL, "Illegal NULL param"); 00681 00682 if (pInstance == NULL) 00683 { 00684 ERROR3("Attempt to register a clipboard mapping when there is no ExternalClipboard"); 00685 delete Mapping; 00686 return; 00687 } 00688 00689 List *TheList = &pInstance->Mappings; 00690 ClipboardMapping *Ptr = (ClipboardMapping *) TheList->GetHead(); 00691 00692 while (Ptr != NULL) 00693 { 00694 if (Ptr->Priority < Mapping->Priority) 00695 { 00696 TheList->InsertBefore(Ptr, Mapping); 00697 return; 00698 } 00699 00700 Ptr = (ClipboardMapping *) TheList->GetNext(Ptr); 00701 } 00702 00703 // Haven't found a lower-priority entry, so this one belongs at the tail 00704 TheList->AddTail(Mapping); 00705 } 00706 00707 00708 00709 /******************************************************************************************** 00710 00711 > static void ExternalClipboard::DescribeContents(String_64 *Result) 00712 00713 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00714 Created: 21/5/95 00715 00716 Outputs: Result will be returned with a string describing the current clipboard 00717 format. This may be the format of the internal clipboard (quickshape, 00718 line, etc) or could be from the external clipboard (metafile, text, bitmap) 00719 00720 If no special information can be given, or if the clipboard is empty, Result 00721 will contain an empty string 00722 00723 Purpose: To get the textual description of the clipboard format which will be pasted 00724 if a paste operation is to be applied now. 00725 00726 ********************************************************************************************/ 00727 00728 void ExternalClipboard::DescribeContents(String_64 *Result) 00729 { 00730 ERROR3IF(Result == NULL, "Illegal null param"); 00731 00732 // Ensure a safe return value 00733 *Result = TEXT(""); 00734 00735 if (pInstance == NULL) // There ain't no clipboard hereabouts, mac! 00736 return; 00737 00738 if (pInstance->IsOurs() || !InternalClipboard::IsEmpty(FALSE)) 00739 { 00740 // We own the clipboard, or have a cached result - Use the internal one 00741 ERROR3IF(InternalClipboard::IsEmpty(FALSE), 00742 "We own the clipboard but the internal clipboard is empty!!"); 00743 00744 InternalClipboard::DescribeContentsInternal(Result); 00745 return; 00746 } 00747 00748 if (GetOwnerWindow()->OpenClipboard() == NULL) 00749 return; // Can't open the clipboard 00750 00751 UINT32 ThisFormat = 0; 00752 UINT32 DefaultImportFormat = 0; 00753 INT32 NumExternalFormats = 0; 00754 BOOL IncludesTextFormat = FALSE; 00755 do 00756 { 00757 ThisFormat = EnumClipboardFormats(ThisFormat); 00758 if (ThisFormat != 0 && ExternalClipboard::CanImport(ThisFormat)) 00759 { 00760 // Bodge - text can be on the clipboard in 3 forms, but we only want to treat 00761 // it as a single format for the 'paste special' count 00762 if (ThisFormat == CF_TEXT || ThisFormat == CF_UNICODETEXT || ThisFormat == CF_OEMTEXT) 00763 { 00764 if (!IncludesTextFormat) 00765 NumExternalFormats++; 00766 00767 IncludesTextFormat = TRUE; 00768 } 00769 else 00770 NumExternalFormats++; 00771 00772 // Remember which format we will import by default 00773 if (DefaultImportFormat == 0) 00774 DefaultImportFormat = ThisFormat; 00775 } 00776 } while (ThisFormat != 0); 00777 00778 ::CloseClipboard(); 00779 00780 if (NumExternalFormats > 1) 00781 { 00782 // if there are 2 or more external formats, then we'll paste special ("Paste...") 00783 *Result = _R(IDS_CLIPFORMAT_ELIPSES); // TEXT("..."); 00784 } 00785 else 00786 { 00787 // There is no data, or only one format that we recognise. If there is something we 00788 // can paste, then lob its name on the end ("Paste blobby"), else leave result blank ("Paste") 00789 if (DefaultImportFormat != 0) 00790 GetExternalFormatName(DefaultImportFormat, Result); 00791 } 00792 } 00793 00794 00795 00796 /******************************************************************************************** 00797 00798 > static void ExternalClipboard::GetExternalFormatName(UINT32 ExternalFormat, String_64 *Result) 00799 00800 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00801 Created: 22/4/95 00802 00803 Inputs: ExternalFormat - A windows clipboard format ID (e.g. a CF_ constant) 00804 00805 Outputs: Result will be returned with a string describing this format 00806 00807 Purpose: To get the textual description of a clipboard format 00808 00809 Notes: Microsoft, being in a particularly helpful frame of mind, have 00810 given us a function that does not provide the names of the default 00811 (CF_ constant) clipboard formats. We must therefore recognise all the 00812 likely formats and provide our own names. Thanks, guys. 00813 00814 ********************************************************************************************/ 00815 00816 void ExternalClipboard::GetExternalFormatName(UINT32 ExternalFormat, String_64 *Result) 00817 { 00818 ERROR3IF(Result == NULL, "Illegal NULL param"); 00819 00820 if (ExternalFormat >= 0xC000 && ExternalFormat <= 0xFFFF) 00821 { 00822 GetClipboardFormatName(ExternalFormat, (LPTSTR)((TCHAR *)*Result), 63); 00823 if (*Result==String_64(_T("CorelXARA Document"))) 00824 *Result = String(_R(IDS_CLIPFORMAT_NATIVE)); 00825 } 00826 else 00827 { 00828 switch(ExternalFormat) 00829 { 00830 case CF_TEXT: 00831 *Result = String(_R(IDS_CLIPFORMAT_ATEXT)); 00832 break; 00833 00834 case CF_BITMAP: 00835 *Result = String(_R(IDS_CLIPFORMAT_BMP)); 00836 break; 00837 00838 case CF_METAFILEPICT: 00839 *Result = String(_R(IDS_CLIPFORMAT_WMF)); 00840 break; 00841 00842 // case CF_SYLK: 00843 // *Result = TEXT("Symbolic Link"); 00844 // break; 00845 00846 // case CF_DIF: 00847 // *Result = TEXT("Data Interchange Format"); 00848 // break; 00849 00850 case CF_TIFF: 00851 *Result = String(_R(IDS_CLIPFORMAT_TIFF)); 00852 break; 00853 00854 case CF_OEMTEXT: 00855 *Result = String(_R(IDS_CLIPFORMAT_ATEXT)); // Shares 'unformatted text' with CF_TEXT 00856 break; 00857 00858 case CF_DIB: 00859 *Result = String(_R(IDS_CLIPFORMAT_DIB)); 00860 break; 00861 00862 // case CF_PALETTE: 00863 // *Result = TEXT("Palette"); 00864 // break; 00865 00866 // case CF_PENDATA: 00867 // *Result = TEXT("Pen data"); 00868 // break; 00869 00870 // case CF_RIFF: 00871 // *Result = TEXT("RIFF data"); 00872 // break; 00873 00874 // case CF_WAVE: 00875 // *Result = TEXT("WAVE sound"); 00876 // break; 00877 00878 case CF_UNICODETEXT: 00879 *Result = String(_R(IDS_CLIPFORMAT_UTEXT)); 00880 break; 00881 00882 case CF_ENHMETAFILE: 00883 *Result = String(_R(IDS_CLIPFORMAT_EMF)); 00884 break; 00885 00886 default: 00887 *Result = String(_R(IDS_CLIPFORMAT_UNRECOGNISED_FORMAT)); // "Unrecognised format" 00888 TRACE( _T("WARNING: Unrecognised 'standard' windows clipboard format (%ld), %s,%ld\n"), 00889 (INT32)ExternalFormat, __FILE__, __LINE__); 00890 break; 00891 } 00892 } 00893 00894 00895 // If you want to hack a clipboard format, this little baby knows 00896 // how to dump it into the file c:\jason.tmp 00897 #if FALSE 00898 #if _DEBUG 00899 /* 00900 if (!camStrncmp((TCHAR *)(*Result), "QuarkXPress", 10)) // A Quack XPress clipboard format? 00901 { 00902 HANDLE Bob = GetClipboardData(ExternalFormat); 00903 char *buff = (char *) GlobalLock(Bob); 00904 00905 FILE *fp = _tfopen("c:\\jason.tmp", "wb"); 00906 size_t Size = (size_t)GlobalSize(Bob); 00907 fwrite(buff, 1, Size, fp); 00908 fclose(fp); 00909 00910 GlobalUnlock(Bob); 00911 00912 ERROR3("Quack XPress data detected and saved!"); 00913 } 00914 */ 00915 #endif 00916 #endif 00917 } 00918 00919 00920 00921 /******************************************************************************************** 00922 00923 > static BOOL ExternalClipboard::IsEmpty(void) 00924 00925 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00926 Created: 19/4/95 00927 00928 Returns: TRUE if the clipboard is ready to accept new data 00929 FALSE if the copy must be aborted 00930 00931 Purpose: To ready the clipboard for a cut/copy operation (copy data TO the clipboard). 00932 This will interact with the external clipboard in order to claim the global 00933 clipboard, and readies the clipboard for use. 00934 00935 Notes: After you have copied data to the clipboard, you MUST call CopyCompleted 00936 00937 Scope: protected (for friend class InternalClipboard only) 00938 00939 SeeAlso: ExternalClipboard::CopyCompleted; ExternalClipboard::PrepareForPaste 00940 00941 ********************************************************************************************/ 00942 00943 BOOL ExternalClipboard::IsEmpty(void) 00944 { 00945 BOOL IsEmpty = TRUE; 00946 00947 if (pInstance == NULL) 00948 return(TRUE); 00949 00950 CWnd *Parent = GetOwnerWindow(); 00951 if (Parent == NULL) return TRUE; 00952 00953 if (pInstance->IsOurs()) // We own the clipboard! Use the internal one 00954 { 00955 if (InternalClipboard::IsEmpty(FALSE)) 00956 { 00957 ERROR3("We own the clipboard but the internal clipboard is empty!!"); 00958 } 00959 else 00960 { 00961 ERROR3("Why are you asking the External clipboard if it's empty when the internal one isn't?"); 00962 } 00963 return(FALSE); 00964 } 00965 00966 if (Parent->OpenClipboard() == NULL) 00967 return(TRUE); // Can't open the clipboard, so we're empty 00968 00969 ClipboardMapping *Mapping; 00970 UINT32 ThisFormat = 0; // 0 makes EnumClipboardFormats start from the beginning 00971 do 00972 { 00973 ThisFormat = EnumClipboardFormats(ThisFormat); 00974 00975 if (ThisFormat != 0) 00976 { 00977 Mapping = (ClipboardMapping *) pInstance->Mappings.GetHead(); 00978 while (Mapping != NULL && IsEmpty) 00979 { 00980 // If this mapping is an import mapping and can handle this external format, 00981 // then we need look no further - there is importable data on the clipboard 00982 if (Mapping->Type != CLIPMAP_EXPORTONLY && Mapping->ExternalDataType == ThisFormat) 00983 IsEmpty = FALSE; 00984 00985 Mapping = (ClipboardMapping *) pInstance->Mappings.GetNext(Mapping); 00986 } 00987 } 00988 } while (ThisFormat != 0 && IsEmpty); 00989 00990 ::CloseClipboard(); 00991 return(IsEmpty); 00992 } 00993 00994 00995 00996 /******************************************************************************************** 00997 00998 > BOOL ExternalClipboard::PrepareForCopy(void) 00999 01000 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01001 Created: 19/4/95 01002 01003 Returns: TRUE if the clipboard is ready to accept new data 01004 FALSE if the copy must be aborted 01005 01006 Purpose: To ready the clipboard for a cut/copy operation (copy data TO the clipboard). 01007 This will interact with the external clipboard in order to claim the global 01008 clipboard, and readies the clipboard for use. 01009 01010 Notes: After you have copied data to the clipboard, you MUST call CopyCompleted 01011 01012 Scope: protected (for friend class InternalClipboard only) 01013 01014 SeeAlso: ExternalClipboard::CopyCompleted; ExternalClipboard::PrepareForPaste 01015 01016 ********************************************************************************************/ 01017 01018 BOOL ExternalClipboard::PrepareForCopy(void) 01019 { 01020 // Do nothing 01021 01022 return(TRUE); 01023 } 01024 01025 01026 01027 /******************************************************************************************** 01028 01029 > BOOL ExternalClipboard::CopyCompleted(void) 01030 01031 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01032 Created: 19/4/95 01033 01034 Returns: TRUE if all went well 01035 FALSE if the copy failed in some way 01036 01037 Purpose: Tells the ExternalClipboard that you have finished copying data to it. 01038 This interacts with the external clipboard in order to make the new data 01039 available to the outside world. 01040 01041 Notes: Before starting to copy data to the clipboard you MUST call PrepareForCopy 01042 01043 This is called AFTER have updated the internal clipboard. However, if we 01044 already own the Windows clipboard, Windows very kindly asks us to destroy 01045 our clipboard when we call EmptyClipboard. To avoid disembowling ourselves 01046 we thus have to check if we are the owner of the clipboard so that we only 01047 wipe the internal clipboard if someone else takes control of the 01048 external clipboard - see DestroyClipboard 01049 01050 Scope: protected (for friend class InternalClipboard only) 01051 01052 SeeAlso: ExternalClipboard::PrepareForCopy 01053 01054 ********************************************************************************************/ 01055 01056 BOOL ExternalClipboard::CopyCompleted(void) 01057 { 01058 // TRACEUSER( "JustinF", _T("In ExternalClipboard::CopyCompleted\n")); 01059 InternalClipboardFormat VectorFormat(CLIPTYPE_VECTOR); 01060 01061 ClipboardMapping *Mapping = (ClipboardMapping *) Mappings.GetHead(); 01062 while (Mapping != NULL) 01063 { 01064 // Mark all "vector" mappings available for export 01065 Mapping->Available = Mapping->GetInternalDataType()->IsSameFormat(VectorFormat); 01066 Mapping = (ClipboardMapping *) Mappings.GetNext(Mapping); 01067 } 01068 01069 // Scan the InternalClipboard document tree to determine which internal formats are available 01070 Node *pRoot = InternalClipboard::GetInsertionLayer(); 01071 Node *pNode = pRoot->FindFirstDepthFirst(); 01072 BOOL AllDone = FALSE; // Becomes TRUE when there is no need to continue the scan 01073 01074 while (pNode != NULL && !AllDone) 01075 { 01076 AllDone = TRUE; 01077 Mapping = (ClipboardMapping *) Mappings.GetHead(); 01078 while (Mapping != NULL) 01079 { 01080 if (!Mapping->Available && Mapping->Type != CLIPMAP_IMPORTONLY) 01081 { 01082 // Check if this mapping can be used on this node to provide another 01083 // output data format that was previously unavailable 01084 Mapping->Available = pNode->SupportsClipboardFormat(Mapping->GetInternalDataType()); 01085 if (!Mapping->Available) AllDone = FALSE; 01086 } 01087 01088 Mapping = (ClipboardMapping *) Mappings.GetNext(Mapping); 01089 } 01090 01091 pNode = pNode->FindNextDepthFirst(pRoot); 01092 } 01093 01094 01095 #if (_OLE_VER >= 0x200) 01096 01097 // Put the contents of the internal clipboard on the OLE clipboard, using the 01098 // associated CCamSrvrItem to do the hard stuff. 01099 01100 m_fIgnoreChange = TRUE; 01101 01102 // Only put stuff on the external clipboard if we are allowed to ... 01103 if (m_fUpdateSystemClipboard) 01104 { 01105 // If you have been using something like GIF construction set then this may 01106 // lock the clipboard. At this point, an exception will be thrown. This is an unknown 01107 // exception as far a Camelot is concerned and so is very bad. We should really stop 01108 // the main expection handler getting its claws on it and not knowing what to do with it. 01109 // Our exception handler can just pretend that nothing really happened. 01110 // Just mention to the user about the problem. 01111 TRY 01112 { 01113 // Get the oil form of the document and the associated server item 01114 CCamDoc * pCamDoc = InternalClipboard::Instance()->GetOilDoc(); 01115 CCamSrvrItem* pServer = NULL; 01116 if (pCamDoc != NULL) 01117 pServer = pCamDoc->GetEmbeddedItem(); 01118 // If that went well then ask it to copy the data to the clipboard 01119 if (pServer != NULL) 01120 pServer->CopyToClipboard(); 01121 } 01122 CATCH(COleException, e) // Handle all ole exceptions 01123 { 01124 // "e" contains information about the exception. 01125 TRACEUSER( "Neville", _T("ExternalClipboard::CopyCompleted exception handler\n")); 01126 01127 // Do nothing special, as all this means is that the external clipboard 01128 // has had a problem. Just report a generic error to the user so that they 01129 // know that something is not working correctly. 01130 InformError(_R(IDE_CLIPBOARDCOPYPROBLEM)); // There was a problem copying to the Windows clipboard 01131 } 01132 END_CATCH 01133 } 01134 01135 m_fIgnoreChange = FALSE; 01136 return TRUE; 01137 01138 #else 01139 01140 CWnd *Parent = GetOwnerWindow(); 01141 if (Parent->OpenClipboard() != NULL) 01142 { 01143 ::EmptyClipboard(); // Clear the windows clipboard 01144 01145 // Add all available export formats onto the clipboard 01146 Mapping = (ClipboardMapping *) Mappings.GetHead(); 01147 while (Mapping != NULL) 01148 { 01149 01150 #if FALSE 01151 #if _DEBUG 01152 TRACEUSER( "Jason", _T("Mapping %s available (for ICF %ld)\n"), 01153 Mapping->Available?"is":"NOT", (INT32)(Mapping->GetInternalDataType()->GetFormatID())); 01154 #endif 01155 #endif 01156 01157 if (Mapping->Available && Mapping->Type != CLIPMAP_IMPORTONLY) 01158 ::SetClipboardData(Mapping->ExternalDataType, NULL); 01159 01160 Mapping = (ClipboardMapping *) Mappings.GetNext(Mapping); 01161 } 01162 01163 ::CloseClipboard(); 01164 } 01165 // else another application/window has the clipboard open! 01166 01167 return(TRUE); 01168 01169 #endif 01170 } 01171 01172 01173 #if (_OLE_VER >= 0x200) 01174 01175 /******************************************************************************************** 01176 > void ExternalClipboard::DelayRenderData(CCamDataSource* pDataSource) 01177 01178 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01179 Created: 17/10/96 01180 Inputs: pDataSource --- the data source to render into 01181 Purpose: Delay-renders the old-style Camelot clipboard formats into the given 01182 data source. 01183 SeeAlso: CCamSrvrItem::OnRenderGlobalData; CCamDataSource 01184 ********************************************************************************************/ 01185 01186 void ExternalClipboard::DelayRenderData(CCamDataSource* pDataSource) 01187 { 01188 // JustinF says: bodge alert! We don't want to export *any* proprietary formats, such 01189 // as the native format or OLE embeddables, when this bodgey flag is FALSE. This finds 01190 // out the flag's value without changing it. 01191 BOOL fExportNative = CCamSrvrItem::RenderProprietaryFormats(TRUE); 01192 CCamSrvrItem::RenderProprietaryFormats(fExportNative); 01193 01194 // Tell the data source that we can render some static formats. 01195 for (ClipboardMapping* pMap = (ClipboardMapping*) pInstance->Mappings.GetHead(); 01196 pMap != 0; 01197 pMap = (ClipboardMapping*) pInstance->Mappings.GetNext(pMap)) 01198 { 01199 // JustinF says: bodge alert! We mustn't render CMX formats on shut-down because they 01200 // crash if the clipboard doc contains bitmaps or fractals. 01201 if (pMap->IS_KIND_OF(CMXClipMap) && (fBodgeNoCMX || fNoCMXDataExport)) 01202 { 01203 TRACEUSER( "JustinF", _T("Skipping CMX mapping at 0x%p\n"), (LPVOID) pMap); 01204 continue; 01205 } 01206 01207 // JustinF says: bodge alert! Don't render the native format if this flag is FALSE. 01208 if (pMap->IS_KIND_OF(NativeClipMap) && !fExportNative) 01209 { 01210 TRACEUSER( "JustinF", _T("Skipping native mapping at 0x%p\n"), (LPVOID) pMap); 01211 continue; 01212 } 01213 01214 // Can we export this format? 01215 if (pMap->Available && pMap->Type != CLIPMAP_IMPORTONLY) 01216 { 01217 // Yes, tell the data source to make this format available. 01218 pDataSource->DelayRenderData(pMap->ExternalDataType); 01219 /* TRACEUSER( "JustinF", _T("\t- added format 0x%X to COleDataSource at 0x%p\n"), 01220 (UINT32) pMap->ExternalDataType, (LPVOID) pSource); 01221 */ } 01222 } 01223 } 01224 01225 #endif 01226 01227 01228 01229 #if (_OLE_VER >= 0x200) 01230 01231 /******************************************************************************************** 01232 > static CLIPFORMAT ExternalClipboard::GetBestPasteFormat(COleDataObject* pDataObject) 01233 01234 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01235 Created: 11/10/96 01236 Inputs: pDataObject --- the data object containing the data to be queried 01237 Returns: The data format within the data object that is the most suitable for 01238 pasting, or zero if there isn't one. 01239 Purpose: Works out what we would paste from the given data object. 01240 SeeAlso: ExternalClipboard::PrepareForOlePaste 01241 ********************************************************************************************/ 01242 01243 CLIPFORMAT ExternalClipboard::GetBestPasteFormat(COleDataObject* pDataObject) 01244 { 01245 FORMATETC fmt; 01246 pDataObject->BeginEnumFormats(); 01247 while (pDataObject->GetNextFormat(&fmt)) 01248 { 01249 // Ask all the clipboard mappings if they can import this format. 01250 ClipboardMapping* pMap = (ClipboardMapping*) pInstance->Mappings.GetHead(); 01251 while (pMap) 01252 { 01253 // Can this mapping import this type of data? 01254 if (pMap->Type != CLIPMAP_EXPORTONLY && pMap->ExternalDataType == fmt.cfFormat) 01255 { 01256 // Yes it can. Check for implicit conversions between ANSI and Unicode text. 01257 if (pMap->ExternalDataType == pMap->RealExternalType || 01258 pDataObject->IsDataAvailable(pMap->RealExternalType)) 01259 { 01260 // We found a format. Return it. 01261 return pMap->RealExternalType; 01262 } 01263 } 01264 01265 // Consider the next mapping. 01266 pMap = (ClipboardMapping*) pInstance->Mappings.GetNext(pMap); 01267 } 01268 } 01269 01270 // No format is suitable, so sorry. 01271 return 0; 01272 } 01273 01274 01275 01276 /******************************************************************************************** 01277 > BOOL ExternalClipboard::PrepareForOlePaste(COleDataObject* pDataObject) 01278 01279 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01280 Created: 10/10/96 01281