clipmap.cpp

Go to the documentation of this file.
00001 // $Id: clipmap.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 /*
00102 */
00103 
00104 
00105 #include "camtypes.h"
00106 
00107 // -- clipboard includes
00108 #include "clipext.h"
00109 #include "clipint.h"
00110 #include "clipmap.h"
00111 
00112 // --- text includes  **** !!!! BODGE
00113 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 #include "layer.h"
00115 #include "nodetext.h"
00116 #include "nodetxtl.h"
00117 #include "nodetxts.h"
00118 #include "unicdman.h"
00119 
00120 // --- Bitmap Mapping includes
00121 #include "bitmpinf.h"
00122 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 //#include "jason.h"
00125 #include "nodebmp.h"
00126 #include "wbitmap.h"
00127 #include "scrcamvw.h"
00128 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00129 
00130 // ---
00131 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00132 //#include "filters.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00133 //#include "nev.h"
00134 
00135 #include "cmxifltr.h"
00136 
00137 // This class is defined in kernel\cliptype.h
00138 CC_IMPLEMENT_MEMDUMP(InternalClipboardFormat, CC_CLASS_MEMDUMP)
00139 
00140 CC_IMPLEMENT_DYNCREATE(ClipboardMapping, ListItem)
00141 
00142 CC_IMPLEMENT_DYNCREATE(BodgeTextClipMap, ClipboardMapping)
00143 CC_IMPLEMENT_DYNCREATE(BodgeUnicodeClipMap, ClipboardMapping)
00144 
00145 CC_IMPLEMENT_DYNAMIC(CMXClipMap, ClipboardMapping)
00146 CC_IMPLEMENT_DYNCREATE(CMX16ClipMap, CMXClipMap)
00147 CC_IMPLEMENT_DYNCREATE(CMX32ClipMap, CMXClipMap)
00148 
00149 #ifdef _DEBUG
00150 CC_IMPLEMENT_DYNCREATE(RTFClipMap, ClipboardMapping)
00151 #endif
00152 
00153 CC_IMPLEMENT_DYNCREATE(BitmapClipMap, ClipboardMapping)
00154 //CC_IMPLEMENT_DYNCREATE(PaletteClipMap, ClipboardMapping)
00155 CC_IMPLEMENT_DYNCREATE(DIBClipMap, ClipboardMapping)
00156 
00157 #if FALSE
00158 CC_IMPLEMENT_DYNCREATE(QuarkPictureClipMap, ClipboardMapping)
00159 #endif
00160 
00161 #define new CAM_DEBUG_NEW
00162 
00163 
00164 
00165 
00166 /********************************************************************************************
00167 
00168 >   ClipboardMapping::ClipboardMapping()
00169 
00170     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00171     Created:    16/4/95
00172 
00173     Purpose:    Constructor
00174 
00175     Notes:      DON'T call the constructor - call CreateAndRegister
00176 
00177     SeeAlso:    ClipboardMapping::CreateAndRegister
00178 
00179 ********************************************************************************************/
00180 
00181 ClipboardMapping::ClipboardMapping()
00182 {
00183     ERROR3("You can't directly construct an ClipboardMapping - Call CreateAndRegister");
00184 }
00185 
00186 
00187 
00188 /********************************************************************************************
00189 
00190 >   ClipboardMapping::~ClipboardMapping()
00191 
00192     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00193     Created:    16/4/95
00194 
00195     Purpose:    Destructor
00196 
00197 ********************************************************************************************/
00198 
00199 ClipboardMapping::~ClipboardMapping()
00200 {
00201     RemoveTempFile();
00202 }
00203 
00204 
00205 
00206 /********************************************************************************************
00207 
00208 >   ClipboardMapping::ClipboardMapping(ClipboardMappingType TheType, Filter *TheFilter,
00209                                         InternalClipboardFormat &TheInternalDataType,
00210                                         UINT32 TheExternalDataType,
00211                                         UINT32 ThePriority)
00212     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00213     Created:    16/4/95
00214 
00215     Inputs:     TheType - indicates import / export / import & export
00216 
00217                 TheFilter - The filter which can apply this conversion
00218 
00219                 TheInternalDatatType - A class defining the internal data type
00220                 (see cliptype.h)
00221 
00222                 TheExternalDataType - A Windows CF_ constant defining the external
00223                 clipboard data type which will be imported/exported.
00224 
00225                 ThePriority - An integer indicating the priority of this mapping.
00226                 The highest available priority mapping will be used in order to
00227                 retain as much information in the data as possible. See
00228                 docs\howtouse\ExtClip.doc for details of the existing mappings.
00229 
00230     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
00231                 manager. This mapping info describes a filter which is able to import
00232                 data from or export data to a windows clipboard in some way.
00233 
00234     Notes:      DON'T call the constructor - call CreateAndRegister
00235 
00236     SeeAlso:    ClipboardMapping::CreateAndRegister; InternalClipboardFormat
00237 
00238 ********************************************************************************************/
00239 
00240 ClipboardMapping::ClipboardMapping(ClipboardMappingType TheType, Filter *TheFilter,
00241                                     InternalClipboardFormat &TheInternalDataType,
00242                                     UINT32 TheExternalDataType,
00243                                     UINT32 ThePriority)
00244 {
00245     Type        = TheType;
00246     pFilter     = TheFilter;
00247 
00248     InternalDataType.SetFormatID(TheInternalDataType.GetFormatID());
00249     ExternalDataType = RealExternalType = TheExternalDataType;
00250 
00251     Priority    = ThePriority;
00252 
00253     Available   = FALSE;
00254 
00255     tempfilename = NULL;
00256 }
00257 
00258 
00259 
00261 //
00262 //  The OLE clipboard
00263 //
00264 
00265 #if (_OLE_VER >= 0x200)
00266 
00267 /********************************************************************************************
00268 >   void ClipboardMapping::SetRenderMemory(HGLOBAL hMem, DWORD cbMemSize)
00269 
00270     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00271     Created:    16/9/96
00272     Inputs:     hMem        ---     the global memory to delay-render into, or null if
00273                                     the rendering functions themselves should allocate
00274                                     it.
00275                 cbMemSize   ---     the size of the given memory block.
00276     Purpose:    Sets the memory that the delay-render functions will render into.
00277     SeeAlso:    ExternalClipboard::SetRenderMemory; OpClipboardExport::DoWithParam
00278 ********************************************************************************************/
00279 
00280 void ClipboardMapping::SetRenderMemory(HGLOBAL hMem, DWORD cbMemSize)
00281 {
00282     // Record the handle and its size.
00283     m_hMem = hMem;
00284     m_cbMemSize = cbMemSize;
00285 }
00286 
00287 #endif
00288 
00290 
00291 
00292 
00293 /********************************************************************************************
00294 
00295 >   static void ClipboardMapping::CreateAndRegister(ClipboardMappingType TheType, Filter *TheFilter,
00296                                                     InternalClipboardFormat &TheInternalDataType,
00297                                                     UINT32 TheExternalDataType,
00298                                                     UINT32 ThePriority)
00299     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00300     Created:    16/4/95
00301 
00302     Inputs:     TheType - indicates import / export / import & export
00303 
00304                 TheFilter - The filter which can apply this conversion
00305 
00306                 TheInternalDatatType - An object defining the internal data type
00307                 (see cliptype.h)
00308 
00309                 TheExternalDataType - A Windows CF_ constant defining the external
00310                 clipboard data type which will be imported/exported.
00311 
00312                 ThePriority - An integer indicating the priority of this mapping.
00313                 The highest available priority mapping will be used in order to
00314                 retain as much information in the data as possible. See
00315                 docs\howtouse\ExtClip.doc for details of the existing mappings.
00316 
00317     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
00318                 manager. This mapping info describes a filter which is able to import
00319                 data from or export data to a windows clipboard in some way.
00320 
00321     SeeAlso:    InternalClipboardFormat
00322 
00323 ********************************************************************************************/
00324 
00325 void ClipboardMapping::CreateAndRegister(ClipboardMappingType TheType, Filter *TheFilter,
00326                                          InternalClipboardFormat &TheInternalDataType,
00327                                          UINT32 TheExternalDataType,
00328                                          UINT32 ThePriority)
00329 {
00330     ClipboardMapping *Mapping = new ClipboardMapping(TheType, TheFilter,
00331                                                         TheInternalDataType, TheExternalDataType,
00332                                                         ThePriority);
00333     if (Mapping == NULL)
00334         InformError();
00335     else
00336         ExternalClipboard::RegisterDataType(Mapping);
00337 }
00338 
00339 
00340 
00341 /********************************************************************************************
00342 
00343 >   BOOL ClipboardMapping::ImportFromTempFile(TCHAR *filename, SelOperation *Caller,
00344                                                 InternalClipboard *Dest)
00345 
00346     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00347     Created:    20/4/95
00348 
00349     Inputs:     filename - the file name of the temporary scratch file to be loaded
00350                 Dest - the internal clipboard document to import into
00351 
00352 
00353     Purpose:    Internal helper function. Invokes pFilter::DoImport into the Dest doc,
00354                 using the given file as a source.
00355 
00356     Notes:      You must remove() the tem file yourself afterwards.
00357 
00358 ********************************************************************************************/
00359 
00360 BOOL ClipboardMapping::ImportFromTempFile(TCHAR *filename, SelOperation *Caller,
00361                                             InternalClipboard *Dest)
00362 {
00363     PathName FileToLoad(filename);
00364     
00365     CCLexFile* pFile = new CCDiskFile(1024, FALSE, TRUE);
00366 
00367     // See if we have a valid file
00368     if (pFile == NULL)
00369         return FALSE;
00370 
00371     // we have to try and open the file
00372     TRY
00373     {
00374         if (!((CCDiskFile*)pFile)->open(FileToLoad, ios::in | ios::binary))
00375         {
00376             // Failed to open the file...
00377             delete pFile;
00378             pFile = NULL;
00379             ERROR2RAW("Failed to open temp file for import into clipboard");
00380             return(FALSE);
00381         }
00382 
00383         // Found the Filter, so ask it to import the file please
00384 
00385         // Provide a current view for the filter to chomp on; We stack the current
00386         // view so that we do not corrupt it.
00387         View *OldCurrentView = View::GetCurrent();
00388         ClipboardView ImportView;
00389         if (!ImportView.Init())
00390         {
00391             delete pFile;
00392             pFile = NULL;
00393             return(FALSE);
00394         }
00395 
00396         ImportView.SetCurrent();
00397 
00398         if (!pFilter->DoImport(Caller, pFile, InternalClipboard::Instance()))
00399         {
00400             // Something went a bit wrong - tell the user what it was.
00401             // Only tell them if not special user cancelled error message
00402             if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00403                 InformError();
00404 
00405                 // If the file is open, then close it
00406             if (pFile->isOpen())
00407                 pFile->close();
00408 
00409             // and die a bit
00410             delete pFile;
00411             pFile = NULL;
00412 
00413             if (OldCurrentView != NULL)
00414                 OldCurrentView->SetCurrent();
00415             return FALSE;
00416         }
00417 
00418         if (OldCurrentView != NULL)
00419             OldCurrentView->SetCurrent();
00420 
00421         // If the file is open, then close it
00422         if (pFile->isOpen())
00423             pFile->close();
00424     }
00425 
00426     // See if there was a file I/O error
00427     CATCH(CFileException, e)
00428     {
00429         // Report the error if no one else did
00430         if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00431             InformError();
00432 
00433         // Make sure that the file is closed
00434         TRY
00435         {
00436             // Close the file
00437             if (pFile->isOpen())
00438                 pFile->close();
00439         }
00440         CATCH(CFileException, e)
00441         {
00442             // Not a lot we can do really...
00443         }
00444         END_CATCH
00445 
00446         // and fail
00447         delete pFile;
00448         pFile = NULL;
00449         return FALSE;
00450     }
00451     END_CATCH
00452 
00453     // Make sure that we have got rid of the file
00454     delete pFile;
00455 
00456     return(TRUE);
00457 }
00458 
00459 
00460 
00461 /********************************************************************************************
00462 
00463 >   virtual BOOL ClipboardMapping::HandleImport(SelOperation *Caller,
00464                                                 HANDLE ClipboardData,
00465                                                 InternalClipboard *Dest)
00466     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00467     Created:    20/4/95
00468 
00469     Inputs:     Caller - The operation within which this method is being called
00470                 ClipboardData - The result of calling GetClipboardData for your datatype
00471                 Dest - The InternalClipboard (document) to import the data into.
00472 
00473     Returns:    TRUE for success
00474 
00475     Purpose:    Calls the parent filter as appropriate to import the given data from
00476                 the external clipboard.
00477 
00478     Notes:      This base-class default treats the clipboard data as a file, and makes
00479                 the associated filter import it directly. (Note: It is currently
00480                 implemented by slaving a temp file to disc, in order to avoid CCMemFiles
00481                 which are not currently good enough for us to use)
00482 
00483 ********************************************************************************************/
00484 
00485 BOOL ClipboardMapping::HandleImport(SelOperation *Caller,
00486                                     HANDLE ClipboardData, InternalClipboard *Dest)
00487 {
00488     BOOL ok = TRUE;
00489 
00490     // ---
00491     // Get a scratch file - if TMP isn't set, this will try for c:\temp.
00492     // The filename will have XS as a prefix
00493     char *tempname = GetTempFileName(); //_ttempnam("C:\temp", "XS~");
00494     if (tempname == NULL)
00495     {
00496         ERROR3("Couldn't get a temp filename");
00497         return(FALSE);
00498     }
00499 
00500     PathName FullPath(tempname);
00501 
00502     // ---
00503     // Save the clipboard data into our tempfile
00504     OFSTRUCT OpenBuf;
00505     OpenBuf.cBytes = sizeof(OpenBuf);
00506     HFILE OutFile = OpenFile(tempname, &OpenBuf, OF_CREATE);
00507 
00508     // Did it work ok?
00509     if (OutFile == HFILE_ERROR)
00510     {
00511         ERROR2RAW("Import tempfile couldn't be opened");
00512         InformError();
00513         free(tempname);
00514         return(FALSE);
00515     }
00516 
00517     // And write it to the tempfile
00518     LPCSTR lpbuffer = (LPCSTR) GlobalLock(ClipboardData);
00519     if (lpbuffer != NULL)
00520     {
00521         DWORD DataSize = GlobalSize(ClipboardData);
00522 
00523         if (DataSize != 0)
00524         {
00525             UINT32 BytesWritten = _lwrite(OutFile, lpbuffer, DataSize);
00526 
00527             if (BytesWritten != DataSize)
00528             {
00529                 ERROR2RAW("Import tempfile save seems to have failed");
00530                 InformError();
00531                 ok = FALSE;
00532             }
00533         }
00534         else
00535         {
00536             ERROR3("No data in clipboard!");
00537             ok = FALSE;
00538         }
00539 
00540         GlobalUnlock(ClipboardData);
00541     }
00542     else
00543     {
00544         ERROR3("Clipboard memory chunk couldn't be locked!");
00545         ok = FALSE;
00546     }
00547 
00548     _lclose(OutFile);
00549 
00550 
00551     // ---
00552     // Now, import the temp file using our 'parent' filter
00553     if (ok)
00554         ok = ImportFromTempFile(tempname, Caller, InternalClipboard::Instance());
00555 
00556 
00557     // Delete the temp file, and deallocate the tempname memory
00558     _tremove(tempname);
00559     free(tempname);
00560     return(ok);
00561 }
00562 
00563 
00564 
00565 /********************************************************************************************
00566 
00567 >   BOOL ClipboardMapping::ExportToTempFile(TCHAR *filename, 
00568                                         Operation *Caller, InternalClipboard *Source)
00569 
00570     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00571     Created:    20/4/95
00572 
00573     Inputs:     filename - the file name of the temporary scratch file to be loaded
00574                 Caller   - the operation we're being called from 
00575                 Source   - the internal clipboard document to export from
00576 
00577     Returns:    TRUE if it succeeds. 
00578 
00579     Purpose:    Internal helper function. Invokes pFilter::DoExport from the Source doc,
00580                 using the given file as a destination.
00581 
00582     Notes:      You must delete the temp file afterwards - use 'remove()'
00583 
00584 ********************************************************************************************/
00585 
00586 BOOL ClipboardMapping::ExportToTempFile(TCHAR *filename, 
00587                                         Operation *Caller, InternalClipboard *Source)
00588 {
00589     // Provide a current view for the filter to chomp on; We stack the current
00590     // view so that we do not corrupt it.
00591     View *OldCurrentView = View::GetCurrent();
00592     ClipboardView ExportView;
00593     if (!ExportView.Init())
00594         return(FALSE);
00595 
00596     ExportView.SetCurrent();
00597 
00598     PathName FullPath(filename);
00599 
00600     // Try and open the temporary file
00601     CCDiskFile DiskFile(1024, FALSE, TRUE);
00602     BOOL AllOK = TRUE;
00603 
00604     TRY
00605     {
00606         if (!DiskFile.open(FullPath, ios::out | ios::binary))
00607         {
00608             if (OldCurrentView != NULL)
00609                 OldCurrentView->SetCurrent();
00610             return(FALSE);      // Failed to open the export file
00611         }
00612 
00613         // Tell the filter we would like a Preview Bitmap please
00614         if (pFilter->CanIncludePreviewBmp())
00615             pFilter->IncludePreviewBmp(TRUE);
00616 
00617         // Try and export the internal clipboard document
00618         if (!pFilter->DoExport(Caller, &DiskFile, &FullPath, InternalClipboard::Instance()))
00619         {
00620             // Something went a bit wrong - tell the user what it was.
00621             // Suppress the error if it was the 'user has cancelled one'
00622             if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00623             {
00624                 InformError();
00625                 // Caller should clean up the temp file
00626             }
00627             else
00628                 Error::ClearError();    // otherwise remove the error so it won't get reported
00629             
00630             // Set the error
00631             AllOK = FALSE;
00632         }
00633 
00634         // Close the file
00635         if (DiskFile.isOpen())
00636             DiskFile.close();
00637     }
00638 
00639     // See if there was a file io error
00640     CATCH(CFileException, e)
00641     {
00642         // Report the error if no one else did
00643         if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00644         {
00645             InformError();
00646         }
00647         else
00648             Error::ClearError();    // otherwise remove the error so it won't get reported
00649 
00650         // Make sure that the file is closed
00651         TRY
00652         {
00653             // Close that file
00654             if (DiskFile.isOpen())
00655                 DiskFile.close();
00656         }
00657         CATCH(CFileException, e)
00658         {
00659             // Not a lot we can do really...
00660         }
00661         END_CATCH
00662 
00663         // And restore the previous current view
00664         if (OldCurrentView != NULL)
00665             OldCurrentView->SetCurrent();
00666 
00667         return(FALSE);
00668     }
00669     END_CATCH
00670 
00671     // Tell the filter we would NOT like a Preview Bitmap ready for next time
00672     if (pFilter->CanIncludePreviewBmp())
00673         pFilter->IncludePreviewBmp(FALSE);
00674 
00675     // And restore the previous current view
00676     if (OldCurrentView != NULL)
00677         OldCurrentView->SetCurrent();
00678 
00679     return(TRUE);
00680 }
00681 
00682         
00683 /********************************************************************************************
00684 
00685 >   virtual BOOL ClipboardMapping::HandleExport(Operation *Caller,
00686                                                 InternalClipboard *Source)
00687 
00688     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00689     Created:    20/4/95
00690 
00691     Inputs:     Caller - the operation within which this method is being called
00692                 Source - the internal clipboard (document) to be exported
00693 
00694     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
00695                 the clipboard.
00696 
00697     Purpose:    Invokes this mapping for exporting
00698                 This takes the document tree of Source, and exports it to the external
00699                 (windows) clipboard. Usually this just involves calling Filter::DoExport
00700                 for the parent filter, and then returning the handle to the global memory
00701                 block to be placed onto the external clipboard.
00702 
00703     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
00704                 if you were dealing with it directly. You must adhere to all the Windows
00705                 rules for this - i.e. a global data block, unlocked, etc etc.
00706 
00707 ********************************************************************************************/
00708 
00709 HANDLE ClipboardMapping::HandleExport(Operation *Caller, InternalClipboard *Source)
00710 {
00711     ERROR3("Base class ClipboardMapping::HandleExport called");
00712 
00713 /*
00714     PathName FullPath;
00715 
00716     char *tempname = _ttempnam("C:\temp", "XS");
00717     if (tempname == NULL)
00718     {
00719         ERROR3("Couldn't get a temp filename");
00720         return(NULL);
00721     }
00722 
00723     if (!ExportToTempFile(tempname, Caller, Source))
00724     {
00725         remove(tempname);
00726         free(tempname);
00727         return(NULL);
00728     }
00729 
00730 
00731     // In the switch statement below, set this handle to the global mem handle
00732     // of the data you want to place on the clipboard. If you don't want to
00733     // put anything on, leave this handle NULL.
00734     HANDLE hGlobalMem = NULL;
00735 
00736 
00737     // **** !!!! Export the file
00738 
00739     // Delete the temp file, and return the result
00740     remove(tempname);
00741     free(tempname);
00742     return(hGlobalMem);
00743 */
00744     return(NULL);
00745 }
00746 
00747 
00748 
00749 /********************************************************************************************
00750 
00751 >   char *ClipboardMapping::GetTempFileName(void)
00752 
00753     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00754     Created:    29/4/95
00755 
00756     Returns:    NULL, or a a filename to be used as a temporary file
00757 
00758     Purpose:    Finds a temporary file
00759                 Remove it with ClipboardMapping::RemoveTempFile
00760 
00761     SeeAlso:    ClipboardMapping::RemoveTempFile
00762 
00763 ********************************************************************************************/
00764 
00765 char *ClipboardMapping::GetTempFileName(void)
00766 {
00767     RemoveTempFile();   // Try to ensure any previous tempfile is gone
00768 
00769     tempfilename = _ttempnam("C:\temp", "XS~");
00770 
00771     return(tempfilename);
00772 }
00773 
00774 
00775 
00776 /********************************************************************************************
00777 
00778 >   void ClipboardMapping::RemoveTempFile(void)
00779 
00780     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00781     Created:    29/4/95
00782 
00783     Purpose:    Removes the last temporary file 'allocated' with GetTempFilename
00784 
00785                 This function is automatically called when the clipboard is wiped,
00786                 as usually we had to leave the tempfile around while it was "on" the
00787                 clipboard.
00788 
00789     SeeAlso:    ClipboardMapping::GetTempFilename
00790 
00791 ********************************************************************************************/
00792 
00793 void ClipboardMapping::RemoveTempFile(void)
00794 {
00795     if (tempfilename != NULL)
00796     {
00797         _tremove(tempfilename);
00798         free(tempfilename);
00799         tempfilename = NULL;
00800     }
00801 }
00802 
00803 
00804 
00805 
00806 
00807 
00808 
00809 
00810 
00811 
00812 
00813 
00814 
00815 
00816 
00817 
00818 BodgeTextClipMap::BodgeTextClipMap()
00819 {
00820     ERROR3("Please don't press that button again");
00821 }
00822 
00823 
00824 /********************************************************************************************
00825 
00826 >   BodgeTextClipMap::BodgeTextClipMap(ClipboardMappingType TheType, UINT32 ClaimType = 0)
00827     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00828     Created:    16/4/95
00829 
00830     Inputs:     TheType - indicates import / export / import & export
00831 
00832                 ClaimType - specifies the text type that this mapping will claim from the
00833                 windows clipboard - that is, create 3 of these mappings, specifying
00834                 CF_TEXT, CF_UNICODETEXT, and CF_OEMTEXT, and they will all ask the
00835                 clipboard for UNICODE text when they actually go to import. This allows
00836                 us to detect the 3 implicitly-converted clipboard formats, and map them
00837                 all to UNICODE, i.e. use the UNICODE mapping for all 3 available formats.
00838                 If ClaimType == 0, UNICODE is assumed
00839 
00840     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
00841                 manager. This mapping info describes a filter which is able to import
00842                 data from or export data to a windows clipboard in some way.
00843 
00844     Notes:      DON'T call the constructor - call CreateAndRegister
00845 
00846     SeeAlso:    BodgeTextClipMap::CreateAndRegister
00847 
00848 ********************************************************************************************/
00849 
00850 BodgeTextClipMap::BodgeTextClipMap(ClipboardMappingType TheType, UINT32 ClaimType)
00851                 : ClipboardMapping(TheType, NULL, InternalClipboardFormat(CLIPTYPE_TEXT),
00852                                     CF_TEXT, 50)
00853 {
00854     if (ClaimType != 0)
00855         ExternalDataType = ClaimType;
00856 }
00857 
00858 
00859 
00860 /********************************************************************************************
00861 
00862 >   static void BodgeTextClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType = 0)
00863 
00864     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00865     Created:    16/4/95
00866 
00867     Inputs:     TheType - indicates import / export / import & export
00868 
00869                 ClaimType - specifies the text type that this mapping will claim from the
00870                 windows clipboard - that is, create 3 of these mappings, specifying
00871                 CF_TEXT, CF_UNICODETEXT, and CF_OEMTEXT, and they will all ask the
00872                 clipboard for UNICODE text when they actually go to import. This allows
00873                 us to detect the 3 implicitly-converted clipboard formats, and map them
00874                 all to UNICODE, i.e. use the UNICODE mapping for all 3 available formats.
00875                 If ClaimType == 0, UNICODE is assumed
00876 
00877     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
00878                 manager. This mapping info describes a filter which is able to import
00879                 data from or export data to a windows clipboard in some way.
00880 
00881 ********************************************************************************************/
00882 
00883 void BodgeTextClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType)
00884 {
00885     BodgeTextClipMap *Mapping = new BodgeTextClipMap(TheType, ClaimType);
00886     if (Mapping == NULL)
00887         InformError();
00888     else
00889         ExternalClipboard::RegisterDataType(Mapping);
00890 }
00891 
00892 
00893 
00894 /********************************************************************************************
00895 >   virtual BOOL BodgeTextClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData,
00896                                                 InternalClipboard *Dest)
00897     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00898     Created:    20/4/95
00899     Inputs:     Caller - The operation within which this method is being called
00900                 ClipboardData - The result of calling GetClipboardData for your datatype
00901                 Dest - The InternalClipboard (document) to import the data into.
00902     Returns:    TRUE for success
00903     Purpose:    Calls the parent filter as appropriate to import the given data from
00904                 the external clipboard.
00905                 This bodge mapping for text scans the docuemnt tree for text chars and
00906                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
00907 ********************************************************************************************/
00908 
00909 BOOL BodgeTextClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData, InternalClipboard *Dest)
00910 {
00911     char *buff=(char*)GlobalLock(ClipboardData);
00912     if (buff != NULL && buff[0] != 0)
00913     {
00914         // position arbitarily on clipboard - when pasted the clip contents are centered anyway
00915         TextStory* TheStory=TextStory::CreateFromChars(DocCoord(100,100), buff, NULL,
00916                                                        InternalClipboard::Instance(), NULL, TRUE);
00917 
00918         // Unlock the clipboard data, as we won't need it again
00919         GlobalUnlock(ClipboardData);
00920 
00921         if (TheStory!=NULL)
00922         {
00923             // OK, attach the new story to the clipboard document
00924             TheStory->AttachNode(InternalClipboard::GetInsertionLayer(), LASTCHILD);
00925             TheStory->NormaliseAttributes();
00926 
00927             // And make it reformat itself properly
00928             TheStory->FormatAndChildren(NULL,FALSE,FALSE);
00929             return(TRUE);
00930         }
00931 
00932         // We failed (no text story), so report and ensure the clipboard is 'clean'
00933         InformError();
00934         InternalClipboard::Clear();
00935     }
00936 
00937     // We failed
00938     return(FALSE);
00939 }
00940 
00941 //BOOL BodgeTextClipMap::HandleImport(SelOperation *Caller,
00942 //                                  HANDLE ClipboardData, InternalClipboard *Dest)
00943 //{
00944 //  char *buff = (char *) GlobalLock(ClipboardData);
00945 //  if (buff != NULL && buff[0] != 0)
00946 //  {
00947 //      DWORD Index = 0;
00948 //  
00949 //      TextStory *pStory = new TextStory(Dest->GetInsertionLayer(), LASTCHILD);
00950 //      if (pStory == NULL)
00951 //          goto Abort;
00952 //  
00953 //      // Lob in some default attributes (black fill, no line colour, line width = 250
00954 //      Node *pNode;
00955 //      FlatFillAttribute *pAttrFill = new FlatFillAttribute(DocColour(COLOUR_BLACK));
00956 //      if (pAttrFill == NULL)
00957 //          goto Abort;
00958 //      pNode = pAttrFill->MakeNode();
00959 //      if (pNode == NULL)
00960 //          goto Abort;
00961 //      pNode->AttachNode(pStory, LASTCHILD, FALSE);
00962 //  
00963 //      StrokeColourAttribute *pAttrLine = new StrokeColourAttribute(DocColour(COLOUR_TRANS));
00964 //      if (pAttrLine == NULL)
00965 //          goto Abort;
00966 //      pNode = pAttrLine->MakeNode();
00967 //      if (pNode == NULL)
00968 //          goto Abort;
00969 //      pNode->AttachNode(pStory, LASTCHILD, FALSE);
00970 //
00971 //      LineWidthAttribute *pAttrLineWidth = new LineWidthAttribute(250);
00972 //      if (pAttrLineWidth == NULL)
00973 //          goto Abort;
00974 //      pNode = pAttrLineWidth->MakeNode();
00975 //      if (pNode == NULL)
00976 //          goto Abort;
00977 //      pNode->AttachNode(pStory, LASTCHILD, FALSE);
00978 //  
00979 //      // Set the top left position for the text area - this doesn't matter because
00980 //      // the absolute position on the clipboard is ignored when we paste
00981 //      Matrix StoryMatrix(1000, 1000);
00982 //      pStory->SetStoryMatrix(StoryMatrix);
00983 //  
00984 //      TextLine *pLine = new TextLine(pStory, LASTCHILD);
00985 //      if (pLine == NULL)
00986 //          goto Abort;
00987 //  
00988 //      Node *pChar = NULL;
00989 //
00990 //      while(buff[Index] != 0)
00991 //      {
00992 //          if (buff[Index] == 0x0D)
00993 //          {
00994 //              if (buff[Index+1] == 0x0A)  // Skip LF if it's a CRLF pair
00995 //                  Index++;
00996 //  
00997 //              pChar = new EOLNode(pLine, LASTCHILD);
00998 //              if (pChar == NULL)
00999 //                  goto Abort;
01000 //  
01001 //              // Make sure if this is the last char exported, we don't leave
01002 //              // this next TextLine without an EOLNode in it!
01003 //              pChar = NULL;
01004 //
01005 //              pLine = new TextLine(pStory, LASTCHILD);
01006 //              if (pLine == NULL)
01007 //                  goto Abort;
01008 //          }
01009 //          else
01010 //          {
01011 //              // Ignore control chars like tabs and suchlike for now
01012 //              if (buff[Index] > 31)
01013 //              {
01014 //                  pChar = new TextChar(pLine, LASTCHILD, (WCHAR) buff[Index]);
01015 //                  if (pChar == NULL)
01016 //                      goto Abort;
01017 //              }
01018 //          }
01019 //          
01020 //          Index++;
01021 //      }
01022 //  
01023 //      if (pChar == NULL || !pChar->IsKindOf(CC_RUNTIME_CLASS(EOLNode)))
01024 //      {
01025 //          // no terminating newline, so add one
01026 //          pChar = new EOLNode(pLine, LASTCHILD);
01027 //          if (pChar == NULL)
01028 //              goto Abort;
01029 //      }
01030 //  
01031 //      // And lob a caret in, 'cos it seems to get upset if this isn't in there!
01032 //      pChar = new CaretNode(pChar, PREV);
01033 //      if (pChar == NULL)
01034 //          goto Abort;
01035 //  
01036 //      // And finally, format the text, else the chars all stack on top of each other!
01037 //      pStory->FormatAndChildren();
01038 //
01039 //      GlobalUnlock(ClipboardData);
01040 //      return(TRUE);
01041 //  }
01042 //
01043 //  return(FALSE);
01044 //
01045 //Abort:
01046 //  ERROR2RAW("Text import failed, probably due to lack of memory");
01047 //  InformError();
01048 //
01049 //  GlobalUnlock(ClipboardData);
01050 //  Dest->ClearClipboard(); // We failed, so ensure the doc is wiped
01051 //  return(FALSE);
01052 //}
01053 
01054         
01055 /********************************************************************************************
01056 
01057 >   virtual BOOL BodgeTextClipMap::HandleExport(Operation *Caller,
01058                                                 InternalClipboard *Source)
01059 
01060     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01061     Created:    20/4/95
01062 
01063     Inputs:     Caller - the operation within which this method is being called
01064                 Source - the internal clipboard (document) to be exported
01065 
01066     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
01067                 the clipboard.
01068 
01069     Purpose:    Invokes this mapping for exporting
01070                 This takes the document tree of Source, and exports it to the external
01071                 (windows) clipboard.
01072 
01073                 This bodge mapping for text scans the docuemnt tree for text chars and
01074                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
01075 
01076     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
01077                 if you were dealing with it directly. You must adhere to all the Windows
01078                 rules for this - i.e. a global data block, unlocked, etc etc.
01079 
01080 ********************************************************************************************/
01081 
01082 HANDLE BodgeTextClipMap::HandleExport(Operation *Caller, InternalClipboard *Source)
01083 {
01084     const DWORD Increment = 1024 * sizeof(char);
01085     DWORD CurrentSize   = 0;
01086     DWORD MaxSize       = Increment;
01087 
01088 #if (_OLE_VER >= 0x200)
01089 
01090     // If necessary allocate the memory.
01091     BOOL fDidAlloc = FALSE;
01092     HANDLE hGlobalMem = m_hMem;
01093     if (hGlobalMem)
01094     {
01095         // We have some already.  Set the size.
01096         MaxSize = m_cbMemSize;
01097     }
01098     else
01099     {
01100         // We don't have any, so try to allocate and remember that we did so.
01101         hGlobalMem = m_hMem = GlobalAlloc(GHND, MaxSize);
01102         if (!hGlobalMem) return 0;
01103         fDidAlloc = TRUE;
01104     }
01105 
01106 #else
01107 
01108     // Allocate a block of global memory to store the text
01109     HANDLE hGlobalMem = GlobalAlloc(GHND, MaxSize);
01110 
01111     if (hGlobalMem == NULL)
01112         return(NULL);
01113 
01114 #endif
01115 
01116     // Get a UNICODE text buffer
01117     char* buff = (char*) GlobalLock(hGlobalMem);
01118     if (buff == NULL)
01119     {
01120         return(NULL);
01121     }
01122 
01123     // Scan the entire document tree, and lob every TextChar we find into the export buffer
01124     // NOTE that the Global{Re}Alloc zeros memory, so we don't need to worry about 0-termination.
01125     Node *pSubtree = InternalClipboard::GetInsertionLayer();
01126     Node *pNode = pSubtree->FindFirstDepthFirst();
01127     while (pNode != NULL)
01128     {
01129         if (pNode->IsKindOf(CC_RUNTIME_CLASS(TextChar)) || pNode->IsKindOf(CC_RUNTIME_CLASS(EOLNode)))
01130         {
01131             if (pNode->IsKindOf(CC_RUNTIME_CLASS(TextChar)))
01132             {
01133                 UINT32 ComposedChar = UnicodeManager::UnicodeToMultiByte(((TextChar *) pNode)->GetUnicodeValue());
01134                 BYTE LeadByte = 0;
01135                 BYTE TrailByte = 0;
01136                 UnicodeManager::DecomposeMultiBytes(ComposedChar, &LeadByte, &TrailByte);
01137 
01138                 if (LeadByte != 0)
01139                     buff[CurrentSize++] = LeadByte;
01140 
01141                 buff[CurrentSize++] = TrailByte;
01142             }
01143             else
01144             {
01145                 if (!((EOLNode*)pNode)->IsVirtual())
01146                 {
01147                     buff[CurrentSize++] = (char) 0x0D;      // CRLF - newline
01148                     buff[CurrentSize++] = (char) 0x0A;
01149                 }
01150             }
01151 
01152             // Check if we've overrun the buffer - if so, we need to make the buffer bigger
01153             // (Allow 3 entries at the end (1 to guarantee we have a zero terminator, and 2 more
01154             // to allow room to fit the 2-char newline sequence in!)
01155             if ( (CurrentSize * sizeof(char)) >= MaxSize - 3)
01156             {
01157             #if (_OLE_VER >= 0x200)
01158                 // If we didn't allocate the block then we can't resize it.
01159                 if (!fDidAlloc) return 0;
01160                 m_hMem = 0;
01161             #endif
01162                 
01163                 GlobalUnlock(hGlobalMem);
01164 
01165                 MaxSize += Increment;
01166                 HANDLE hNewMem = GlobalReAlloc(hGlobalMem, MaxSize, GHND);
01167                 if (hNewMem == NULL)
01168                 {
01169                     GlobalFree(hGlobalMem);
01170                     return(NULL);
01171                 }
01172 
01173                 hGlobalMem = hNewMem;
01174                 buff = (char *)GlobalLock(hGlobalMem);
01175 
01176                 if (buff == NULL)
01177                 {
01178                     GlobalFree(hGlobalMem);
01179                     return(NULL);
01180                 }
01181 
01182             #if (_OLE_VER >= 0x200)
01183                 // Remember this block.
01184                 m_hMem = hNewMem;
01185             #endif
01186             }
01187         }
01188         pNode = pNode->FindNextDepthFirst(pSubtree);
01189     }
01190 
01191     // We must unlock the block before giving it to the clipboard
01192     GlobalUnlock(hGlobalMem);
01193 
01194     return(hGlobalMem);
01195 }
01196 
01197 
01198 
01199 
01200 
01201 
01202 
01203 
01204 
01205 
01206 BodgeUnicodeClipMap::BodgeUnicodeClipMap()
01207 {
01208     ERROR3("Please don't press that button again");
01209 }
01210 
01211 
01212 /********************************************************************************************
01213 
01214 >   BodgeUnicodeClipMap::BodgeUnicodeClipMap(ClipboardMappingType TheType, UINT32 ClaimType = 0)
01215     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01216     Created:    16/4/95
01217 
01218     Inputs:     TheType - indicates import / export / import & export
01219 
01220                 ClaimType - specifies the text type that this mapping will claim from the
01221                 windows clipboard - that is, create 3 of these mappings, specifying
01222                 CF_TEXT, CF_UNICODETEXT, and CF_OEMTEXT, and they will all ask the
01223                 clipboard for UNICODE text when they actually go to import. This allows
01224                 us to detect the 3 implicitly-converted clipboard formats, and map them
01225                 all to UNICODE, i.e. use the UNICODE mapping for all 3 available formats.
01226                 If ClaimType == 0, UNICODE is assumed
01227 
01228     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
01229                 manager. This mapping info describes a filter which is able to import
01230                 data from or export data to a windows clipboard in some way.
01231 
01232     Notes:      DON'T call the constructor - call CreateAndRegister
01233 
01234     SeeAlso:    BodgeUnicodeClipMap::CreateAndRegister
01235 
01236 ********************************************************************************************/
01237 
01238 BodgeUnicodeClipMap::BodgeUnicodeClipMap(ClipboardMappingType TheType, UINT32 ClaimType)
01239                 : ClipboardMapping(TheType, NULL, InternalClipboardFormat(CLIPTYPE_TEXT),
01240                                     CF_UNICODETEXT, 55)
01241 {
01242     if (ClaimType != 0)
01243         ExternalDataType = ClaimType;
01244 }
01245 
01246 
01247 
01248 /********************************************************************************************
01249 
01250 >   static void BodgeUnicodeClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType = 0)
01251 
01252     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01253     Created:    16/4/95
01254 
01255     Inputs:     TheType - indicates import / export / import & export
01256 
01257                 ClaimType - specifies the text type that this mapping will claim from the
01258                 windows clipboard - that is, create 3 of these mappings, specifying
01259                 CF_TEXT, CF_UNICODETEXT, and CF_OEMTEXT, and they will all ask the
01260                 clipboard for UNICODE text when they actually go to import. This allows
01261                 us to detect the 3 implicitly-converted clipboard formats, and map them
01262                 all to UNICODE, i.e. use the UNICODE mapping for all 3 available formats.
01263                 If ClaimType == 0, UNICODE is assumed
01264 
01265     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
01266                 manager. This mapping info describes a filter which is able to import
01267                 data from or export data to a windows clipboard in some way.
01268 
01269 ********************************************************************************************/
01270 
01271 void BodgeUnicodeClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType)
01272 {
01273     BodgeUnicodeClipMap *Mapping = new BodgeUnicodeClipMap(TheType, ClaimType);
01274     if (Mapping == NULL)
01275         InformError();
01276     else
01277         ExternalClipboard::RegisterDataType(Mapping);
01278 }
01279 
01280 
01281 
01282 /********************************************************************************************
01283 >   virtual BOOL BodgeUnicodeClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData,
01284                                                 InternalClipboard *Dest)
01285     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01286     Created:    20/4/95
01287     Inputs:     Caller - The operation within which this method is being called
01288                 ClipboardData - The result of calling GetClipboardData for your datatype
01289                 Dest - The InternalClipboard (document) to import the data into.
01290     Returns:    TRUE for success
01291     Purpose:    Calls the parent filter as appropriate to import the given data from
01292                 the external clipboard.
01293                 This bodge mapping for text scans the docuemnt tree for text chars and
01294                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
01295 ********************************************************************************************/
01296 
01297 BOOL BodgeUnicodeClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData, InternalClipboard *Dest)
01298 {
01299     WCHAR *buff=(WCHAR*)GlobalLock(ClipboardData);
01300     if (buff != NULL && buff[0] != 0)
01301     {
01302         // position arbitarily on clipboard - when pasted the clip contents are centered anyway
01303         TextStory* TheStory=TextStory::CreateFromChars(DocCoord(100,100), NULL, buff,
01304                                                        InternalClipboard::Instance(), NULL, TRUE);
01305 
01306         // Unlock the clipboard data, as we won't need it again
01307         GlobalUnlock(ClipboardData);
01308 
01309         if (TheStory!=NULL)
01310         {
01311             // OK, attach the new story to the clipboard document
01312             TheStory->AttachNode(InternalClipboard::GetInsertionLayer(), LASTCHILD);
01313             TheStory->NormaliseAttributes();
01314 
01315             // And make it reformat itself properly
01316             TheStory->FormatAndChildren(NULL,FALSE,FALSE);
01317             return(TRUE);
01318         }
01319 
01320         // We failed (no text story), so report and ensure the clipboard is 'clean'
01321         InformError();
01322         InternalClipboard::Clear();
01323     }
01324 
01325     // We failed
01326     return(FALSE);
01327 }
01328 
01329 
01330 //BOOL BodgeUnicodeClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData, InternalClipboard *Dest)
01331 //{
01332 //  WCHAR *buff = (WCHAR *) GlobalLock(ClipboardData);
01333 //  if (buff != NULL && buff[0] != 0)
01334 //  {
01335 //      DWORD Index = 0;
01336 //
01337 //      TextStory *pStory = new TextStory(Dest->GetInsertionLayer(), LASTCHILD);
01338 //      if (pStory == NULL)
01339 //          goto Abort;
01340 //
01341 //      // Lob in some default attributes (black fill, no line colour, line width = 250
01342 //      Node *pNode;
01343 //      FlatFillAttribute *pAttrFill = new FlatFillAttribute(DocColour(COLOUR_BLACK));
01344 //      if (pAttrFill == NULL)
01345 //          goto Abort;
01346 //      pNode = pAttrFill->MakeNode();
01347 //      if (pNode == NULL)
01348 //          goto Abort;
01349 //      pNode->AttachNode(pStory, LASTCHILD, FALSE);
01350 //
01351 //      StrokeColourAttribute *pAttrLine = new StrokeColourAttribute(DocColour(COLOUR_TRANS));
01352 //      if (pAttrLine == NULL)
01353 //          goto Abort;
01354 //      pNode = pAttrLine->MakeNode();
01355 //      if (pNode == NULL)
01356 //          goto Abort;
01357 //      pNode->AttachNode(pStory, LASTCHILD, FALSE);
01358 //
01359 //      LineWidthAttribute *pAttrLineWidth = new LineWidthAttribute(250);
01360 //      if (pAttrLineWidth == NULL)
01361 //          goto Abort;
01362 //      pNode = pAttrLineWidth->MakeNode();
01363 //      if (pNode == NULL)
01364 //          goto Abort;
01365 //      pNode->AttachNode(pStory, LASTCHILD, FALSE);
01366 //
01367 //      // Set the top left position for the text area - this doesn't matter because
01368 //      // the absolute position on the clipboard is ignored when we paste
01369 //      Matrix StoryMatrix(1000, 1000);
01370 //      pStory->SetStoryMatrix(StoryMatrix);
01371 //  
01372 //      TextLine *pLine = new TextLine(pStory, LASTCHILD);
01373 //      if (pLine == NULL)
01374 //          goto Abort;
01375 //
01376 //      Node *pChar = NULL;
01377 //
01378 //      while(buff[Index] != 0)
01379 //      {
01380 //          if (buff[Index] == 0x000D)
01381 //          {
01382 //              if (buff[Index+1] == 0x000A)    // Skip LF if it's a CRLF pair
01383 //                  Index++;
01384 //
01385 //              pChar = new EOLNode(pLine, LASTCHILD);
01386 //              if (pChar == NULL)
01387 //                  goto Abort;
01388 //
01389 //              // Make sure if this is the last char exported, we don't leave
01390 //              // this next TextLine without an EOLNode in it!
01391 //              pChar = NULL;
01392 //                          
01393 //              pLine = new TextLine(pStory, LASTCHILD);
01394 //              if (pLine == NULL)
01395 //                  goto Abort;
01396 //          }
01397 //          else
01398 //          {
01399 //              // Ignore control chars like tabs and suchlike for now
01400 //              if (buff[Index] > 31)
01401 //              {
01402 //                  pChar = new TextChar(pLine, LASTCHILD, buff[Index]);
01403 //                  if (pChar == NULL)
01404 //                      goto Abort;
01405 //              }
01406 //          }
01407 //          
01408 //          Index++;
01409 //      }
01410 //
01411 //      if (pChar == NULL || !pChar->IsKindOf(CC_RUNTIME_CLASS(EOLNode)))
01412 //      {
01413 //          // no terminating newline, so add one
01414 //          pChar = new EOLNode(pLine, LASTCHILD);
01415 //          if (pChar == NULL)
01416 //              goto Abort;
01417 //      }
01418 //
01419 //      // And lob a caret in, 'cos it seems to get upset if this isn't in there!
01420 //      pChar = new CaretNode(pChar, PREV);
01421 //      if (pChar == NULL)
01422 //          goto Abort;
01423 //
01424 //      // And finally, format the text, else the chars all stack on top of each other!
01425 //      pStory->FormatAndChildren();
01426 //
01427 //      GlobalUnlock(ClipboardData);
01428 //      return(TRUE);
01429 //  }
01430 //
01431 //  return(FALSE);
01432 //
01433 //Abort:
01434 //  ERROR2RAW("Text import failed, probably due to lack of memory");
01435 //  InformError();
01436 //
01437 //  GlobalUnlock(ClipboardData);
01438 //  Dest->ClearClipboard(); // We failed, so ensure the doc is wiped
01439 //  return(FALSE);
01440 //}
01441 
01442         
01443 /********************************************************************************************
01444 
01445 >   virtual BOOL BodgeUnicodeClipMap::HandleExport(Operation *Caller,
01446                                                 InternalClipboard *Source)
01447 
01448     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01449     Created:    20/4/95
01450 
01451     Inputs:     Caller - the operation within which this method is being called
01452                 Source - the internal clipboard (document) to be exported
01453 
01454     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
01455                 the clipboard.
01456 
01457     Purpose:    Invokes this mapping for exporting
01458                 This takes the document tree of Source, and exports it to the external
01459                 (windows) clipboard.
01460 
01461                 This bodge mapping for text scans the docuemnt tree for text chars and
01462                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
01463 
01464     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
01465                 if you were dealing with it directly. You must adhere to all the Windows
01466                 rules for this - i.e. a global data block, unlocked, etc etc.
01467 
01468 ********************************************************************************************/
01469 
01470 HANDLE BodgeUnicodeClipMap::HandleExport(Operation *Caller, InternalClipboard *Source)
01471 {
01472     const DWORD Increment = 1024 * sizeof(WCHAR);
01473     DWORD CurrentSize   = 0;
01474     DWORD MaxSize       = Increment;
01475 
01476 #if (_OLE_VER >= 0x200)
01477 
01478     // If necessary allocate the memory.
01479     BOOL fDidAlloc = FALSE;
01480     HANDLE hGlobalMem = m_hMem;
01481     if (hGlobalMem)
01482     {
01483         // We have some already.  Set the size.
01484         MaxSize = m_cbMemSize;
01485     }
01486     else
01487     {
01488         // We don't have any, so try to allocate and remember that we did so.
01489         hGlobalMem = m_hMem = GlobalAlloc(GHND, MaxSize);
01490         if (!hGlobalMem) return 0;
01491         fDidAlloc = TRUE;
01492     }
01493 
01494 #else
01495 
01496     // Allocate a block of global memory to store the text
01497     HANDLE hGlobalMem = GlobalAlloc(GHND, MaxSize);
01498 
01499     if (hGlobalMem == NULL)
01500         return(NULL);
01501 
01502 #endif
01503 
01504     // Get a UNICODE text buffer
01505     WCHAR *buff = (WCHAR *)GlobalLock(hGlobalMem);
01506     if (buff == NULL)
01507     {
01508         return(NULL);
01509     }
01510 
01511     // Scan the entire document tree, and lob every TextChar we find into the export buffer
01512     // NOTE that the Global{Re}Alloc zeros memory, so we don't need to worry about 0-termination.
01513     Node *pSubtree = InternalClipboard::GetInsertionLayer();
01514     Node *pNode = pSubtree->FindFirstDepthFirst();
01515     while (pNode != NULL)
01516     {
01517         if (pNode->IsKindOf(CC_RUNTIME_CLASS(TextChar)) || pNode->IsKindOf(CC_RUNTIME_CLASS(EOLNode)))
01518         {
01519             if (pNode->IsKindOf(CC_RUNTIME_CLASS(TextChar)))
01520             {
01521                 buff[CurrentSize] = ((TextChar *) pNode)->GetUnicodeValue();
01522                 CurrentSize++;
01523             }
01524             else
01525             {
01526                 buff[CurrentSize++] = 0x000D;       // CRLF - newline
01527                 buff[CurrentSize++] = 0x000A;
01528             }
01529 
01530             // Check if we've overrun the buffer - if so, we need to make the buffer bigger
01531             // (Allow 3 entries at the end (1 to guarantee we have a zero terminator, and 2 more
01532             // to allow room to fit the 2-char newline sequence in!)
01533             if ( (CurrentSize * sizeof(WCHAR)) >= MaxSize - 3)
01534             {
01535             #if (_OLE_VER >= 0x200)
01536                 // If we didn't allocate the block then we can't resize it.
01537                 if (!fDidAlloc) return 0;
01538                 m_hMem = 0;
01539             #endif
01540                 
01541                 GlobalUnlock(hGlobalMem);
01542 
01543                 MaxSize += Increment;
01544                 HANDLE hNewMem = GlobalReAlloc(hGlobalMem, MaxSize, GHND);
01545                 if (hNewMem == NULL)
01546                 {
01547                     GlobalFree(hGlobalMem);
01548                     return(NULL);
01549                 }
01550 
01551                 hGlobalMem = hNewMem;
01552                 buff = (WCHAR *)GlobalLock(hGlobalMem);
01553 
01554                 if (buff == NULL)
01555                 {
01556                     GlobalFree(hGlobalMem);
01557                     return(NULL);
01558                 }
01559 
01560             #if (_OLE_VER >= 0x200)
01561                 // Remember this block.
01562                 m_hMem = hNewMem;
01563             #endif
01564             }
01565         }
01566         pNode = pNode->FindNextDepthFirst(pSubtree);
01567     }
01568 
01569     // We must unlock the block before giving it to the clipboard
01570     GlobalUnlock(hGlobalMem);
01571 
01572     return(hGlobalMem);
01573 }
01574 
01575 BitmapClipMap::BitmapClipMap()
01576 {
01577     ERROR3("Please don't press that button again");
01578 }
01579 
01580 
01581 /********************************************************************************************
01582 
01583 >   BitmapClipMap::BitmapClipMap(ClipboardMappingType TheType, UINT32 ClaimType = 0)
01584 
01585     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01586     Created:    16/4/95
01587 
01588     Inputs:     TheType - indicates import / export / import & export
01589 
01590                 ClaimType - CF_DIB for straight import, CF_BITMAP for an alias
01591 
01592     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
01593                 manager. This mapping info describes a filter which is able to import
01594                 data from or export data to a windows clipboard in some way.
01595 
01596     Notes:      DON'T call the constructor - call CreateAndRegister
01597 
01598     SeeAlso:    BitmapClipMap::CreateAndRegister
01599 
01600 ********************************************************************************************/
01601 
01602 BitmapClipMap::BitmapClipMap(ClipboardMappingType TheType, UINT32 ClaimType)
01603                 : ClipboardMapping(TheType, NULL, InternalClipboardFormat(CLIPTYPE_BITMAP),
01604                                     CF_BITMAP, 75)
01605 {
01606     if (ClaimType != 0)
01607         ExternalDataType = ClaimType;
01608 }
01609 
01610 
01611 
01612 /********************************************************************************************
01613 
01614 >   static void BitmapClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType = 0)
01615 
01616     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01617     Created:    16/4/95
01618 
01619     Inputs:     TheType - indicates import / export / import & export
01620 
01621                 ClaimType - CF_DIB for straight import, CF_BITMAP for an alias
01622 
01623     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
01624                 manager. This mapping info describes a filter which is able to import
01625                 data from or export data to a windows clipboard in some way.
01626 
01627 ********************************************************************************************/
01628 
01629 void BitmapClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType)
01630 {
01631     BitmapClipMap *Mapping = new BitmapClipMap(TheType, ClaimType);
01632     if (Mapping == NULL)
01633         InformError();
01634     else
01635         ExternalClipboard::RegisterDataType(Mapping);
01636 }
01637 
01638 
01639 
01640 /********************************************************************************************
01641 
01642 >   static BOOL ConvertBMPToDIB(HBITMAP hSourceBmp, HPALETTE hSourcePal,
01643                                 BITMAPINFOHEADER **ResultHeader, LPBYTE *ResultBits)
01644 
01645     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01646     Created:    2/5/95
01647 
01648     Inputs:     hSourceBmp - The handle of the source bitmap GDI object
01649                 hSourcePal - NULL, or a handle of the palette to use
01650 
01651     Outputs:    ResultHeader - Will be NULL or point at the resulting DIB header
01652                 ResultBits   - Will be NULL or point at the resulting DIB body
01653 
01654     Returns:    TRUE for success
01655 
01656     Purpose:    Converts a Windows HBITMAP GDI DDB into a DIB
01657 
01658     Notes:      Both returned pointers will be NULL unless the return value is TRUE.
01659                 These pointers are CCMalloc'd blocks as used by other DIBUtil calls
01660                 and WBitmaps.
01661 
01662                 If hSourcePal is not supplied, a default palette will be used
01663 
01664     SeeAlso:    DibUtil::AloocDIB; DIBUtil::FreeDIB
01665 
01666 ********************************************************************************************/
01667 
01668 static BOOL ConvertBMPToDIB(HBITMAP hSourceBmp, HPALETTE hSourcePal,
01669                             LPBITMAPINFO *ResultHeader, LPBYTE *ResultBits)
01670 {
01671     ERROR3IF(hSourceBmp == NULL || ResultHeader == NULL ||
01672                 ResultBits == NULL, "Illegal NULL params");
01673 
01674     // Safe results if we fail
01675     *ResultHeader   = NULL;
01676     *ResultBits     = NULL;
01677     
01678     BITMAPINFOHEADER *Header;
01679     LPBYTE Bits;
01680 
01681     // See if we can get a palette from the clipboard - if not, grab a default one
01682     if (hSourcePal == NULL)
01683         hSourcePal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
01684 
01685     // Fill in the BITMAP info from the source bitmap
01686     BITMAP bm;
01687     GetObject(hSourceBmp, sizeof(bm), (LPSTR) &bm);
01688 
01689     UINT32 Depth = bm.bmPlanes * bm.bmBitsPixel;
01690     if (Depth > 8)      // DDBs can be 16bpp, but DIBs cannot -> convert it to 24bpp
01691         Depth = 24;
01692 
01693     INT32 PaletteSize = DIBUtil::CalcPaletteSize(Depth, FALSE);
01694 
01695     Header = (BITMAPINFOHEADER *) CCMalloc(sizeof(BITMAPINFOHEADER) + PaletteSize);
01696     if (Header == NULL)
01697         return(FALSE);      
01698 
01699     INT32 BitmapSize = DIBUtil::ScanlineSize(bm.bmWidth, Depth) * bm.bmHeight;
01700     if (BitmapSize == 0)    // Make sure we correctly handle zero width/height
01701         BitmapSize = 4;
01702 
01703     Header->biSize               = sizeof(BITMAPINFOHEADER);
01704     Header->biWidth              = bm.bmWidth;
01705     Header->biHeight             = bm.bmHeight;
01706     Header->biPlanes             = 1;
01707     Header->biBitCount           = Depth;
01708     Header->biCompression        = BI_RGB;
01709     Header->biSizeImage          = BitmapSize;
01710     Header->biXPelsPerMeter      = 0;
01711     Header->biYPelsPerMeter      = 0;
01712     Header->biClrUsed            = 0;
01713     Header->biClrImportant       = 0;
01714 
01715     // Add padding for Gavin rampancy etc
01716     BitmapSize += EXTRA_GAVIN_BYTES + DIBUtil::ScanlineSize(bm.bmWidth, Depth);
01717 
01718     Bits = (LPBYTE) CCMalloc(BitmapSize);
01719     if (Bits == NULL)
01720     {
01721         CCFree(Header);
01722         return(FALSE);
01723     }
01724 
01725     // Get a screen DC, and select in the palette
01726     HDC hDC = GetDC(NULL);
01727     if (Depth <= 8)
01728     {
01729         hSourcePal = SelectPalette(hDC, hSourcePal, FALSE);
01730         RealizePalette(hDC);
01731     }
01732 
01733     // Call GetDIBits to blit the bitmap data across
01734     INT32 result = GetDIBits(hDC, hSourceBmp,   0, (WORD)Header->biHeight,
01735                             Bits, (LPBITMAPINFO) Header, DIB_RGB_COLORS);
01736 
01737     // Restore the screen DC
01738     if (Depth <= 8)
01739         SelectPalette(hDC, hSourcePal, FALSE);
01740     ReleaseDC(NULL, hDC);
01741 
01742     // Result will be zero for failure, else the number of scanlines copied
01743     if (result == 0)
01744     {
01745         CCFree(Bits);
01746         CCFree(Header);
01747         return(FALSE);
01748     }
01749 
01750     if (Depth <= 8)
01751     {
01752         // If either of these fields are 0, they mean "The maximum number of colours"
01753         // and this doesn't export quite right, so we "fix" the value (eg 8bpp=>256 cols)
01754         if (Header->biClrUsed == 0)
01755             Header->biClrUsed = 1<<Depth;
01756 
01757         if (Header->biClrImportant == 0)
01758             Header->biClrImportant = 1<<Depth;
01759     }
01760 
01761     // And return successfully
01762     *ResultHeader   = (LPBITMAPINFO) Header;
01763     *ResultBits     = Bits;
01764     return(TRUE);
01765 }
01766 
01767 
01768 
01769 /********************************************************************************************
01770 
01771 >   virtual BOOL BitmapClipMap::HandleImport(SelOperation *Caller,
01772                                                 HANDLE ClipboardData,
01773                                                 InternalClipboard *Dest)
01774     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01775     Created:    20/4/95
01776 
01777     Inputs:     Caller - The operation within which this method is being called
01778                 ClipboardData - The result of calling GetClipboardData for your datatype
01779                 Dest - The InternalClipboard (document) to import the data into.
01780 
01781     Returns:    TRUE for success
01782 
01783     Purpose:    Calls the parent filter as appropriate to import the given data from
01784                 the external clipboard.
01785 
01786                 This bodge mapping for text scans the docuemnt tree for text chars and
01787                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
01788 
01789     SeeAlso:    DIBClipMap::HandleImport
01790 
01791 ********************************************************************************************/
01792 
01793 BOOL BitmapClipMap::HandleImport(SelOperation *Caller,
01794                                     HANDLE ClipboardData, InternalClipboard *Dest)
01795 {
01796     LPBYTE Bits = NULL;
01797     LPBITMAPINFO BmpInfo = NULL;
01798     WinBitmap *WinBmp = NULL;
01799     KernelBitmap *KernelBmp = NULL;
01800 //  NodeBitmap *pNode = NULL;
01801 
01802     // Try to retrieve the palette from the clipboard - if there is not one there,
01803     // we'll get a NULL, which ConvertBMPToDIB is quite happy with.
01804     HPALETTE hPalette = (HPALETTE) GetClipboardData(CF_PALETTE);
01805     if (!ConvertBMPToDIB((HBITMAP)ClipboardData, hPalette, /* TO */ &BmpInfo, &Bits))
01806         goto Abort;
01807 
01808     WinBmp = new WinBitmap(BmpInfo, Bits);
01809     if (WinBmp == NULL)
01810         goto Abort;
01811 
01812     KernelBmp = new KernelBitmap(WinBmp);
01813     if (KernelBmp == NULL)
01814         goto Abort;
01815 
01816 #if FALSE
01817 /*
01818     // And now, lob a bitmap node for it into the clipboard
01819     pNode = new NodeBitmap();
01820     if (pNode == NULL || pNode->GetBitmapRef() == NULL || !(pNode->SetUpPath(12,12)))
01821         goto Abort;
01822 
01823     // Attach this bitmap reference to the new bitmap, and put in the clipboard document
01824     pNode->GetBitmapRef()->Attach(KernelBmp, Dest);
01825 
01826     // And set up the node's bounds appropriately
01827     BitmapInfo Info;
01828     pNode->GetBitmap()->ActualBitmap->GetInfo(&Info);
01829 
01830     {
01831         DocRect BoundsRect;
01832         BoundsRect.lo.x = 0;
01833         BoundsRect.lo.y = 0;
01834         BoundsRect.hi.x = Info.RecommendedWidth/2;
01835         BoundsRect.hi.y = Info.RecommendedHeight/2;
01836 
01837         pNode->CreateShape(BoundsRect);
01838     }
01839 
01840     pNode->AttachNode(Dest->GetInsertionLayer(), LASTCHILD, FALSE);
01841 */
01842 #else
01843     {
01844         // Compile information on where to put the imported NodeBitmap
01845         PageDropInfo DropInfo;
01846 
01847         DropInfo.pDoc       = InternalClipboard::Instance();
01848         DropInfo.pDocView   = DocView::GetCurrent();
01849         DropInfo.pSpread    = InternalClipboard::Instance()->FindFirstSpread(); //GetInsertionLayer()->FindParent();
01850         DropInfo.DropPos    = DocCoord(100,100);        // Position is unimportant as it is centered when pasted
01851         DropInfo.TargetHit  = NO_TARGET;
01852         DropInfo.pObjectHit = NULL;
01853 
01854         // Invoke an Op to create a NodeBitmap for us
01855         OpDescriptor* OpCreateNodeBmp = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpCreateNodeBitmap));
01856         OpCreateNodeBmp->Invoke(&OpParam((INT32)KernelBmp,(INT32)&DropInfo));
01857     }
01858 #endif
01859 
01860     return(TRUE);
01861 
01862 Abort:
01863 //  ERROR2RAW("Bitmap import failed, probably due to lack of memory");
01864     InformError();
01865 
01866     if (KernelBmp != NULL)
01867         delete KernelBmp;
01868 
01869     if (WinBmp != NULL)
01870         delete WinBmp;
01871     else if (BmpInfo != NULL || Bits != NULL)
01872         FreeDIB(BmpInfo, Bits);
01873 
01874     InternalClipboard::Clear(); // We failed, so ensure the doc is wiped
01875 
01876     return(FALSE);
01877 }
01878 
01879 
01880 
01881 /********************************************************************************************
01882 
01883 >   static HPALETTE CreateBMPPalette(LPBITMAPINFOHEADER lpbi)
01884 
01885     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01886     Created:    3/5/95
01887 
01888     Inputs:     lpbi - A pointer to your DIB's header
01889 
01890     Returns:    NULL (failed, or no palette), or a windows handle of the GDI palette data
01891 
01892     Purpose:    Given a DIB, creates a GDI HPALETTE based on the DIB's palette.
01893                 If the DIB is 24 or 32 bit or whatever, this will return NULL, so it is a
01894                 quite normal return value.
01895 
01896 ********************************************************************************************/
01897 
01898 static HPALETTE CreateBMPPalette(LPBITMAPINFOHEADER lpbi)
01899 {
01900     ERROR3IF(lpbi == NULL, "Illegal NULL param");
01901 
01902     // Is it a windows DIB? If not, we can't get a palette out of it
01903     if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
01904         return NULL;
01905 
01906     // Get a pointer to the colour table and the number of colours in it
01907     RGBQUAD *pRGB = (RGBQUAD *)((LPSTR)lpbi + (WORD)lpbi->biSize);
01908     INT32 NumColours = DIBUtil::CalcPaletteSize(lpbi->biBitCount, lpbi->biCompression == BI_BITFIELDS) / sizeof(RGBQUAD);
01909 
01910     HPALETTE hpal = NULL;
01911 
01912     if (NumColours > 0)
01913     {
01914         // Allocate temporary memory
01915         LOGPALETTE *pPal = (LOGPALETTE *) LocalAlloc(LPTR, sizeof(LOGPALETTE) + NumColours * sizeof(PALETTEENTRY));
01916         if (pPal == NULL)
01917             return NULL;
01918 
01919         // Set up the LOGPALETTE structure, copying the pal entries across
01920         pPal->palNumEntries = NumColours;
01921         pPal->palVersion    = 0x300;        // Palette structure Windows version number
01922 
01923         for (INT32 i = 0; i < NumColours; i++)
01924         {
01925             pPal->palPalEntry[i].peRed   = pRGB[i].rgbRed;
01926             pPal->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
01927             pPal->palPalEntry[i].peBlue  = pRGB[i].rgbBlue;
01928             pPal->palPalEntry[i].peFlags = (BYTE)0;
01929         }
01930         hpal = CreatePalette(pPal);
01931         LocalFree((HANDLE)pPal);
01932     }
01933 
01934     return hpal;
01935 }
01936 
01937 
01938 
01939 /********************************************************************************************
01940 
01941 >   static KernelBitmap *FindBitmapToExport(InternalClipboard *Source)
01942 
01943     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01944     Created:    3/5/95
01945 
01946     Inputs:     Source - the internal clipboard (document) to be exported
01947 
01948     Returns:    NULL (if it failed), or a KernelBitmap to be exported
01949 
01950     Purpose:    Scans the clipboard for bitmap objects that can be exported, and
01951                 returns the first one found.
01952 
01953                 Used by the Bitmap, DIB, and Palette exporters to find the export data
01954 
01955 ********************************************************************************************/
01956 
01957 static KernelBitmap *FindBitmapToExport(InternalClipboard *Source)
01958 {
01959     KernelBitmap *KernelBmp = NULL;
01960 
01961     // Scan the entire document tree, looking for a bitmap to export
01962     Node *pSubtree = InternalClipboard::GetInsertionLayer();
01963     Node *pNode = pSubtree->FindFirstDepthFirst();
01964 
01965     while (pNode != NULL && KernelBmp == NULL)
01966     {
01967         // Is this node a NodeBitmap?
01968         if (pNode->IsAnObject() && pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeBitmap))
01969         {
01970             NodeBitmap* pNodeBmp = (NodeBitmap*)pNode;
01971             KernelBitmapRef *BmpRef = pNodeBmp->GetBitmapRef();
01972             if (BmpRef != NULL)
01973                 KernelBmp = BmpRef->GetBitmap();
01974         }
01975 /*
01976         // How about a bitmap fill?
01977         else if (pNode->IsAnAttribute())
01978         {
01979             if (((NodeAttribute*)pNode)->IsABitmapFill())
01980             {
01981                 // We've found either a Bitmap or Fractal fill
01982                 AttrFillGeometry* pBmpFill = (AttrFillGeometry*)pNode;
01983                 KernelBitmapRef *BmpRef = pBmpFill->GetBitmapRef();
01984                 if (BmpRef != NULL)
01985                     KernelBmp = BmpRef->GetBitmap();
01986             }
01987         }
01988 */
01989         pNode = pNode->FindNextDepthFirst(pSubtree);
01990     }
01991 
01992     return(KernelBmp);
01993 }
01994 
01995 
01996 
01997 /********************************************************************************************
01998 
01999 >   virtual BOOL BitmapClipMap::HandleExport(Operation *Caller,
02000                                                 InternalClipboard *Source)
02001 
02002     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02003     Created:    20/4/95
02004 
02005     Inputs:     Caller - the operation within which this method is being called
02006                 Source - the internal clipboard (document) to be exported
02007 
02008     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
02009                 the clipboard.
02010 
02011     Purpose:    Invokes this mapping for exporting
02012                 This takes the document tree of Source, and exports it to the external
02013                 (windows) clipboard.
02014 
02015                 This bodge mapping for text scans the docuemnt tree for text chars and
02016                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
02017 
02018     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
02019                 if you were dealing with it directly. You must adhere to all the Windows
02020                 rules for this - i.e. a global data block, unlocked, etc etc.
02021 
02022                 Note that when a bitmap is available on the clipabord, a palette will
02023                 also be available - see the SeeAlso
02024 
02025     SeeAlso:    PaletteClipMap::HandleExport; DIBClipMap::HandleExport
02026 
02027 ********************************************************************************************/
02028 
02029 HANDLE BitmapClipMap::HandleExport(Operation *Caller, InternalClipboard *Source)
02030 {
02031     ERROR3("Bitmap export is unsupported on the grounds that it won't work thanks to Windows");
02032     return(NULL);
02033 
02034 /*
02035     // Scan the entire document tree, looking for a bitmap to export
02036     KernelBitmap *KernelBmp = FindBitmapToExport(Source);
02037     if (KernelBmp == NULL)      // Didn't find a bitmap
02038         return(NULL);
02039 
02040     OILBitmap *pOilBitmap = KernelBmp->ActualBitmap;
02041     ERROR3IF(pOilBitmap == NULL, "Unattached kernel bitmap found!");
02042     WinBitmap* pWBitmap = (WinBitmap*)pOilBitmap;
02043     LPBITMAPINFO Info = pWBitmap->BMInfo;
02044     LPBYTE Bytes = pWBitmap->BMBytes;
02045     
02046     // Convert the DIB into GDI BITMAP format
02047     HDC hDCScreen = GetDC(NULL);
02048     HBITMAP hBitmap = NULL;
02049     if (hDCScreen != NULL)
02050     {
02051 //      HGDIOBJ OldPal = ::SelectObject(hDCScreen, CMainFrame::MainPalette.GetSafeHandle());
02052 //      RealizePalette(hDCScreen);
02053 
02054         HPALETTE hPal = CreateBMPPalette(&Info->bmiHeader);
02055         HPALETTE hOldPal = NULL;
02056         
02057 #if _DEBUG
02058         if (IsUserName("Jason"))
02059             ERROR3IF(hPal == NULL, "Couldn't create a palette for that image");
02060 #endif
02061 
02062         if (hPal != NULL)
02063         {
02064             hOldPal = SelectPalette(hDCScreen, hPal, FALSE);
02065             RealizePalette(hDCScreen);
02066         }
02067 
02068         hBitmap = CreateDIBitmap(hDCScreen, &Info->bmiHeader, CBM_INIT, Bytes, Info, DIB_RGB_COLORS);
02069         SetClipboardData(CF_PALETTE, hPal);
02070 
02071 //      if (OldPal != NULL)
02072 //          ::SelectObject(hDCScreen, OldPal);
02073         
02074 
02075         if (hPal != NULL)
02076         {
02077             SelectPalette(hDCScreen, hOldPal, FALSE);
02078             RealizePalette(hDCScreen);
02079         }
02080 
02081         ReleaseDC(NULL, hDCScreen);
02082     }
02083 
02084     // And return the bitmap handle, which is put on the clipboard for the CF_BITMAP data
02085     return((HANDLE) hBitmap);
02086  */
02087 /*
02088     // Scan the entire document tree, looking for a bitmap to export
02089     KernelBitmap *KernelBmp = FindBitmapToExport(Source);
02090     if (KernelBmp == NULL)      // Didn't find a bitmap
02091         return(NULL);
02092 
02093     OILBitmap *pOilBitmap = KernelBmp->ActualBitmap;
02094     ERROR3IF(pOilBitmap == NULL, "Unattached kernel bitmap found!");
02095     WinBitmap* pWBitmap = (WinBitmap*)pOilBitmap;
02096     LPBITMAPINFO Info = pWBitmap->BMInfo;
02097     LPBYTE Bytes = pWBitmap->BMBytes;
02098     
02099     // Convert the DIB into GDI BITMAP format
02100 //  HDC hDCScreen = GetDC(NULL);
02101     HBITMAP hBitmap = NULL;
02102 //  if (hDCScreen != NULL)
02103     {
02104 //      hBitmap = CreateDIBitmap(hDCScreen, &Info->bmiHeader, CBM_INIT, Bytes, Info, DIB_RGB_COLORS);
02105         hBitmap = CreateBitmap(Info->bmiHeader.biWidth, Info->bmiHeader.biHeight,
02106                                 1, Info->bmiHeader.biBitCount, NULL);//Bytes);
02107 
02108         // Copy the DIB bits into the bitmap
02109         SetDIBits(NULL, hBitmap, 0, Info->bmiHeader.biHeight, Bytes, Info, NULL);//DIB_RGB_COLORS);
02110 
02111         HPALETTE hPal = CreateBMPPalette(&Info->bmiHeader);
02112         SetClipboardData(CF_PALETTE, hPal);
02113 
02114 //      ReleaseDC(NULL, hDCScreen);
02115     }
02116 
02117     // And return the bitmap handle, which is put on the clipboard for the CF_BITMAP data
02118     return((HANDLE) hBitmap);
02119 */
02120 }
02121 
02122 
02123 
02124 
02125 
02126 
02127 
02128 
02129 
02130 #if FALSE
02131 
02132 // Palettes are only needed when exporting DDB Bitmaps, and we don't do this because they
02133 // almost never work. Also, fabbily, some programs out there stupidly use the palette we
02134 // supply with any DIB that we put on the clipboard (dang!) so it's generally a bad thing to
02135 // even try exporting a bitmap with palette.
02136 
02137 /********************************************************************************************
02138 
02139 //> PaletteClipMap::PaletteClipMap()
02140 
02141     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02142     Created:    16/4/95
02143 
02144     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
02145                 manager. This mapping info describes a filter which is able to export
02146                 palette data from bitmaps to a windows clipboard in CF_PALETTE format.
02147 
02148     Notes:      DON'T call the constructor - call CreateAndRegister
02149 
02150     SeeAlso:    PaletteClipMap::CreateAndRegister
02151 
02152 ********************************************************************************************/
02153 PaletteClipMap::PaletteClipMap()
02154                 : ClipboardMapping(CLIPMAP_EXPORTONLY, NULL,
02155                                     InternalClipboardFormat(CLIPTYPE_BITMAP),
02156                                     CF_PALETTE, 70)
02157 {
02158 }
02159 
02160 
02161 
02162 /********************************************************************************************
02163 
02164 //> static void PaletteClipMap::CreateAndRegister(void)
02165 
02166     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02167     Created:    3/5/95
02168 
02169     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
02170                 manager. This mapping info describes a filter which is able to export
02171                 data to a windows clipboard in CF_PALETTE format
02172 
02173 ********************************************************************************************/
02174 
02175 void PaletteClipMap::CreateAndRegister(void)
02176 {
02177     PaletteClipMap *Mapping = new PaletteClipMap();
02178     if (Mapping == NULL)
02179         InformError();
02180     else
02181         ExternalClipboard::RegisterDataType(Mapping);
02182 }
02183 
02184 
02185 
02186 /********************************************************************************************
02187 
02188 //> virtual BOOL PaletteClipMap::HandleExport(Operation *Caller,
02189                                                 InternalClipboard *Source)
02190 
02191     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02192     Created:    20/4/95
02193 
02194     Inputs:     Caller - the operation within which this method is being called
02195                 Source - the internal clipboard (document) to be exported
02196 
02197     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
02198                 the clipboard.
02199 
02200     Purpose:    Invokes this mapping for exporting
02201                 This takes the document tree of Source, and exports it to the external
02202                 (windows) clipboard.
02203 
02204                 This bodge mapping for text scans the docuemnt tree for text chars and
02205                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
02206 
02207     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
02208                 if you were dealing with it directly. You must adhere to all the Windows
02209                 rules for this - i.e. a global data block, unlocked, etc etc.
02210 
02211 ********************************************************************************************/
02212 
02213 HANDLE PaletteClipMap::HandleExport(Operation *Caller, InternalClipboard *Source)
02214 {
02215 ERROR3("Palette not exported\n");
02216 return(NULL);
02217 
02218 /*
02219     KernelBitmap *KernelBmp = FindBitmapToExport(Source);
02220     if (KernelBmp == NULL)      // Didn't find a bitmap
02221         return(NULL);
02222 
02223     OILBitmap *pOilBitmap = KernelBmp->ActualBitmap;
02224     ERROR3IF(pOilBitmap == NULL, "Unattached kernel bitmap found!");
02225     WinBitmap* pWBitmap = (WinBitmap*)pOilBitmap;
02226 
02227     // Generate a palette for the bitmap
02228     ERROR3IF(pWBitmap->BMInfo == NULL, "Incomplete winoil bitmap");
02229     HPALETTE hPal = CreateBMPPalette(&(pWBitmap->BMInfo->bmiHeader));
02230     if (hPal != NULL)
02231         return(hPal);
02232 
02233     // It failed (probably a 24 or 32 bpp BMP) so give them the mainframe's palette
02234     return(CMainFrame::MainPalette.GetSafeHandle());
02235 */
02236 }
02237 #endif
02238 
02239 
02240 
02241 
02242 
02243 
02244 
02245 
02246 
02247 
02248 
02249 DIBClipMap::DIBClipMap()
02250 {
02251     ERROR3("Please don't press that button again");
02252 }
02253 
02254 
02255 /********************************************************************************************
02256 
02257 >   DIBClipMap::DIBClipMap(ClipboardMappingType TheType, UINT32 ClaimType = 0)
02258 
02259     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02260     Created:    16/4/95
02261 
02262     Inputs:     TheType - indicates import / export / import & export
02263 
02264                 ClaimType - CF_DIB for straight import, CF_BITMAP for an alias
02265 
02266     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
02267                 manager. This mapping info describes a filter which is able to import
02268                 data from or export data to a windows clipboard in some way.
02269 
02270     Notes:      DON'T call the constructor - call CreateAndRegister
02271 
02272     SeeAlso:    DIBClipMap::CreateAndRegister
02273 
02274 ********************************************************************************************/
02275 
02276 DIBClipMap::DIBClipMap(ClipboardMappingType TheType, UINT32 ClaimType)
02277                 : ClipboardMapping(TheType, NULL, InternalClipboardFormat(CLIPTYPE_BITMAP),
02278                                     CF_DIB, 80)
02279 {
02280     if (ClaimType != 0)
02281         ExternalDataType = ClaimType;
02282 }
02283 
02284 
02285 
02286 /********************************************************************************************
02287 
02288 >   static void DIBClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType = 0)
02289 
02290     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02291     Created:    16/4/95
02292 
02293     Inputs:     TheType - indicates import / export / import & export
02294 
02295                 ClaimType - CF_DIB for straight import, CF_BITMAP for an alias
02296 
02297     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
02298                 manager. This mapping info describes a filter which is able to import
02299                 data from or export data to a windows clipboard in some way.
02300 
02301 ********************************************************************************************/
02302 
02303 void DIBClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType)
02304 {
02305     DIBClipMap *Mapping = new DIBClipMap(TheType, ClaimType);
02306     if (Mapping == NULL)
02307         InformError();
02308     else
02309         ExternalClipboard::RegisterDataType(Mapping);
02310 }
02311 
02312 
02313 
02314 /********************************************************************************************
02315 
02316 >   virtual BOOL DIBClipMap::HandleImport(SelOperation *Caller,
02317                                                 HANDLE ClipboardData,
02318                                                 InternalClipboard *Dest)
02319     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02320     Created:    20/4/95
02321 
02322     Inputs:     Caller - The operation within which this method is being called
02323                 ClipboardData - The result of calling GetClipboardData for your datatype
02324                 Dest - The InternalClipboard (document) to import the data into.
02325 
02326     Returns:    TRUE for success
02327 
02328     Purpose:    Calls the parent filter as appropriate to import the given data from
02329                 the external clipboard.
02330 
02331                 This bodge mapping for text scans the docuemnt tree for text chars and
02332                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
02333 
02334 ********************************************************************************************/
02335 
02336 BOOL DIBClipMap::HandleImport(SelOperation *Caller,
02337                                 HANDLE ClipboardData, InternalClipboard *Dest)
02338 {
02339     LPBYTE Bits = NULL;
02340     LPBITMAPINFO BmpInfo = NULL;
02341     WinBitmap *WinBmp = NULL;
02342     KernelBitmap *KernelBmp = NULL;
02343     CCMemFile MemFile;
02344 
02345     BITMAPINFO *buff = (BITMAPINFO *) GlobalLock(ClipboardData);
02346     if (buff != NULL)
02347     {
02348         String_64 ProgressMsg(_R(IDS_CLIPBOARD_IMPORTDIB));
02349         MemFile.open(buff, GlobalSize(ClipboardData), CCMemRead);
02350         if (!DIBUtil::ReadFromFile(&MemFile, &BmpInfo, &Bits, FALSE, &ProgressMsg))
02351             goto Abort;
02352 
02353         MemFile.close();
02354         GlobalUnlock(ClipboardData);
02355 
02356         WinBmp = new WinBitmap(BmpInfo, Bits);
02357         if (WinBmp == NULL)
02358             goto Abort;
02359 
02360         KernelBmp = new KernelBitmap(WinBmp);
02361         if (KernelBmp == NULL)
02362             goto Abort;
02363 
02364         // And now, lob a bitmap node for it into the clipboard
02365         NodeBitmap *pNode = new NodeBitmap();
02366         if (pNode == NULL || pNode->GetBitmapRef() == NULL || !(pNode->SetUpPath(12,12)))
02367             goto Abort;
02368 
02369         // Attach this bitmap reference to the new bitmap, and put in the clipboard document
02370         pNode->GetBitmapRef()->Attach(KernelBmp, InternalClipboard::Instance());
02371         if (pNode->GetBitmap() != KernelBmp)
02372         {
02373             // It didn't use the bitmap we gave it, so we can delete it
02374             delete KernelBmp;
02375         }
02376 
02377         // And set up the node's bounds appropriately
02378         BitmapInfo Info;
02379         pNode->GetBitmap()->ActualBitmap->GetInfo(&Info);
02380 
02381         DocRect BoundsRect;
02382         BoundsRect.lo.x = 0;
02383         BoundsRect.lo.y = 0;
02384         BoundsRect.hi.x = Info.RecommendedWidth/2;
02385         BoundsRect.hi.y = Info.RecommendedHeight/2;
02386 
02387         pNode->CreateShape(BoundsRect);
02388 
02389         // Apply the default bitmap attributes
02390         pNode->ApplyDefaultBitmapAttrs(NULL);
02391 
02392         pNode->AttachNode(InternalClipboard::GetInsertionLayer(), LASTCHILD, FALSE);
02393         return(TRUE);
02394     }
02395 
02396     return(FALSE);
02397 
02398 Abort:
02399 //  ERROR2RAW("Bitmap import failed, probably due to lack of memory");
02400 //  InformError();
02401 
02402     GlobalUnlock(ClipboardData);
02403 
02404     if (MemFile.isOpen())
02405         MemFile.close();
02406 
02407     if (KernelBmp != NULL)
02408         delete KernelBmp;
02409 
02410     if (WinBmp != NULL)
02411         delete WinBmp;
02412 /*  else if (BmpInfo != NULL || Bits != NULL)
02413         FreeDIB(BmpInfo, Bits);
02414 */
02415     InternalClipboard::Clear(); // We failed, so ensure the doc is wiped
02416     InformError();
02417     return(FALSE);
02418 }
02419 
02420 
02421         
02422 /********************************************************************************************
02423 
02424 >   virtual BOOL DIBClipMap::HandleExport(Operation *Caller,
02425                                                 InternalClipboard *Source)
02426 
02427     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02428     Created:    20/4/95
02429 
02430     Inputs:     Caller - the operation within which this method is being called
02431                 Source - the internal clipboard (document) to be exported
02432 
02433     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
02434                 the clipboard.
02435 
02436     Purpose:    Invokes this mapping for exporting
02437                 This takes the document tree of Source, and exports it to the external
02438                 (windows) clipboard.
02439 
02440                 This bodge mapping for text scans the docuemnt tree for text chars and
02441                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
02442 
02443     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
02444                 if you were dealing with it directly. You must adhere to all the Windows
02445                 rules for this - i.e. a global data block, unlocked, etc etc.
02446 
02447 ********************************************************************************************/
02448 
02449 HANDLE DIBClipMap::HandleExport(Operation *Caller, InternalClipboard *Source)
02450 {
02451     // Scan the entire document tree, looking for a bitmap to export
02452     KernelBitmap *KernelBmp = FindBitmapToExport(InternalClipboard::Instance());
02453     if (KernelBmp == NULL)      // Didn't find a bitmap
02454         return(NULL);
02455 
02456     OILBitmap *pOilBitmap = KernelBmp->ActualBitmap;
02457     ERROR3IF(pOilBitmap == NULL, "Unattached kernel bitmap found!");
02458     WinBitmap* pWBitmap = (WinBitmap*)pOilBitmap;
02459     LPBITMAPINFO Info = pWBitmap->BMInfo;
02460     LPBYTE Bytes = pWBitmap->BMBytes;
02461 
02462     ERROR3IF(Info->bmiHeader.biSizeImage == 0, "Bitmap data size is zero - I'm about to screw up the export");
02463 
02464     // Neville 14/10/97
02465     // Don't just use the number of colours in the colour depth. If we have set biClrUsed to
02466     // something between 0 and max number of colours for that colour depth then that is
02467     // the size of the palette that is expected. We set biClrUsed when exporting an
02468     // optimised palette with a user specified number of colours.
02469     // If we don't make sure that this matches the the destination program will skew the
02470     // bitmap. 
02471     UINT32 PalSize = DIBUtil::CalcPaletteSize(pWBitmap->GetBPP(), Info->bmiHeader.biCompression == BI_BITFIELDS,
02472         Info->bmiHeader.biClrUsed);
02473     DWORD HeaderSize = Info->bmiHeader.biSize + PalSize;
02474     DWORD BitmapSize = Info->bmiHeader.biSizeImage;
02475 
02476 #if (_OLE_VER >= 0x200)
02477 
02478     // Get the memory block's handle.
02479     BOOL fDidAlloc = FALSE;
02480     HANDLE hGlobalMem = m_hMem;
02481     if (!hGlobalMem)
02482     {
02483         // We don't have any memory, so try to allocate some and remember that we did so.
02484         fDidAlloc = TRUE;
02485         hGlobalMem = m_hMem = GlobalAlloc(GHND, HeaderSize + BitmapSize);
02486         if (hGlobalMem == NULL)
02487         {
02488             ERROR3("Couldn't get enough memory to export bitmap");
02489             return(NULL);
02490         }
02491     }
02492 
02493 #else
02494 
02495     // Allocate a block of global memory to store the DIB
02496     HANDLE hGlobalMem = GlobalAlloc(GHND, HeaderSize + BitmapSize);
02497 
02498     if (hGlobalMem == NULL)
02499     {
02500         ERROR3("Couldn't get enough memory to export bitmap");
02501         return(NULL);
02502     }
02503 
02504 #endif
02505 
02506     char* buff = (char*) GlobalLock(hGlobalMem);
02507     if (buff == NULL)
02508     {
02509         ERROR3("Couldn't get clipboard memory");
02510 #if (_OLE_VER >= 0x200)
02511         if (fDidAlloc) GlobalFree(hGlobalMem);
02512 #else
02513         GlobalFree(hGlobalMem);
02514 #endif
02515         return(NULL);
02516     }
02517 
02518     // Copy the DIB onto the clipboard (copy the header and body separately as they
02519     // may not lie in contiguous memory)
02520     memcpy(buff, Info, HeaderSize);
02521     memcpy(buff + HeaderSize, Bytes, BitmapSize);
02522 
02523     // We must unlock the block before giving it to the clipboard
02524     GlobalUnlock(hGlobalMem);
02525     return(hGlobalMem);
02526 }
02527 
02528 
02529 
02530 
02531 
02532 
02533 
02534 
02535 #if FALSE
02536 
02537 // Experimental code to attempt to load EPSF files copied from Quark XPress
02538 // It doesn't work very well, and it's highly specific, so not worth using.
02539 
02540 /********************************************************************************************
02541 
02542 >   QuarkPictureClipMap::QuarkPictureClipMap()
02543 
02544     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02545     Created:    16/4/95
02546 
02547     Inputs:     TheType - indicates import / export / import & export
02548 
02549                 ClaimType - CF_DIB for straight import, CF_BITMAP for an alias
02550 
02551     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
02552                 manager. This mapping info describes a filter which is able to import
02553                 data from or export data to a windows clipboard in some way.
02554 
02555     Notes:      DON'T call the constructor - call CreateAndRegister
02556 
02557     SeeAlso:    QuarkPictureClipMap::CreateAndRegister
02558 
02559 ********************************************************************************************/
02560 
02561 QuarkPictureClipMap::QuarkPictureClipMap()
02562 {
02563     ERROR3("Nope. Wrong constructor dude");
02564 }
02565 
02566 QuarkPictureClipMap::QuarkPictureClipMap(UINT32 MyFormat)
02567                 : ClipboardMapping(CLIPMAP_IMPORTONLY, NULL,
02568                                     InternalClipboardFormat(CLIPTYPE_VECTOR),
02569                                     MyFormat, 110)
02570 {
02571 }
02572 
02573 
02574 
02575 /********************************************************************************************
02576 
02577 >   static void QuarkPictureClipMap::CreateAndRegister(void)
02578 
02579     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02580     Created:    16/4/95
02581 
02582     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
02583                 manager. This mapping info describes a filter which is able to import
02584                 data from or export data to a windows clipboard in some way.
02585 
02586     Notes:      This also registers a custom clipboard format with Windows
02587 
02588 ********************************************************************************************/
02589 
02590 void QuarkPictureClipMap::CreateAndRegister(void)
02591 {
02592 #if _DEBUG
02593     // Register or determine the Format ID for the Quack XPress custom clipboard format
02594     UINT32 MyFormat = RegisterClipboardFormat("QuarkXPress Picture Data");
02595 
02596     if (MyFormat == 0)
02597     {
02598         ERROR3("Couldn't register QuarkXPress clipboard handler");
02599         return;
02600     }
02601 
02602     QuarkPictureClipMap *Mapping = new QuarkPictureClipMap(MyFormat);
02603     if (Mapping == NULL)
02604         InformError();
02605     else
02606         ExternalClipboard::RegisterDataType(Mapping);
02607 #endif
02608 }
02609 
02610 
02611 
02612 typedef struct
02613 {
02614     BYTE dunno1[2];         // Yep, I've really sussed their format now! ;-)
02615     char ID[4];
02616     BYTE dunno2[40];
02617     char Type[4];
02618     BYTE dunno3[28];
02619     char Pathname[260];     // Zero terminated, with a bit of crap on the end
02620 } QUACKDATA;
02621 
02622 
02623 /********************************************************************************************
02624 
02625 >   virtual BOOL QuarkPictureClipMap::HandleImport(SelOperation *Caller,
02626                                                 HANDLE ClipboardData,
02627                                                 InternalClipboard *Dest)
02628     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02629     Created:    20/4/95
02630 
02631     Inputs:     Caller - The operation within which this method is being called
02632                 ClipboardData - The result of calling GetClipboardData for your datatype
02633                 Dest - The InternalClipboard (document) to import the data into.
02634 
02635     Returns:    TRUE for success
02636 
02637     Purpose:    Calls the parent filter as appropriate to import the given data from
02638                 the external clipboard.
02639 
02640                 This bodge mapping for text scans the docuemnt tree for text chars and
02641                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
02642 
02643 ********************************************************************************************/
02644 
02645 BOOL QuarkPictureClipMap::HandleImport(SelOperation *Caller,
02646                                 HANDLE ClipboardData, InternalClipboard *Dest)
02647 {
02648 #if _DEBUG
02649     QUACKDATA *buff = (QUACKDATA *) GlobalLock(ClipboardData);
02650 
02651     if (buff != NULL)
02652     {
02653         if (IsUserName("Jason"))
02654         {
02655             FILE *fp = _tfopen("c:\\jason.tmp", "wb");
02656             size_t Size = (size_t)GlobalSize(ClipboardData);
02657             fwrite(buff, 1, Size, fp);
02658             fclose(fp);
02659         }
02660 
02661         if (camStrncmp(buff->ID, "XPR3", 4))
02662         {
02663             ERROR3("Not a Quark XPress 3 clipboard thingo");
02664             goto Abort;
02665         }
02666 
02667         if (camStrncmp(buff->Type, "EPSF", 4))
02668         {
02669             ERROR3("Doesn't appear to be EPSF");
02670             goto Abort;
02671         }
02672 
02673         // Attempt to load the EPS data from the given pathname - BODGE! ******* !!!!!!!!!!!
02674         CDocument* pDoc = AfxGetApp()->OpenDocumentFile(buff->Pathname);
02675 
02676         GlobalUnlock(ClipboardData);
02677         return(TRUE);
02678     }
02679 #endif
02680 
02681     return(FALSE);
02682 
02683 Abort:
02684     GlobalUnlock(ClipboardData);
02685     return(FALSE);
02686 }
02687 
02688 #endif
02689 
02690 
02691 #ifdef _DEBUG
02692 /********************************************************************************************
02693 >   RTFClipMap::RTFClipMap(ClipboardMappingType TheType, Filter *TheFilter,
02694                                         InternalClipboardFormat *TheInternalDataType,
02695                                         UINT32 TheExternalDataType,
02696                                         UINT32 ThePriority)
02697     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02698     Created:    13/12/95
02699     Inputs:     TheType - 1 (import), 2 (export), or 3 (import and export)
02700                 TheFilter - The filter which can apply this conversion
02701                 TheInternalDatatType - An object defining the internal data type
02702                 (see cliptype.h)
02703                 TheExternalDataType - A Windows CF_ constant defining the external
02704                 clipboard data type which will be imported/exported.
02705                 ThePriority - An integer indicating the priority of this mapping.
02706                 The highest available priority mapping will be used in order to
02707                 retain as much information in the data as possible. See
02708                 docs\howtouse\ExtClip.doc for details of the existing mappings.
02709     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
02710                 manager. This mapping info describes a filter which is able to import
02711                 data from or export data to a windows clipboard in some way.
02712     Notes:      DON'T call the constructor - call CreateAndRegister
02713     SeeAlso:    RTFClipMap::CreateAndRegister
02714 ********************************************************************************************/
02715 
02716 RTFClipMap::RTFClipMap(ClipboardMappingType TheType, Filter *TheFilter,
02717                                     InternalClipboardFormat &TheInternalDataType,
02718                                     UINT32 TheExternalDataType,
02719                                     UINT32 ThePriority)
02720                 : ClipboardMapping(TheType, TheFilter, TheInternalDataType,
02721                                     TheExternalDataType, ThePriority)
02722 {
02723 }
02724 
02725 
02726 
02727 /********************************************************************************************
02728 >   static void RTFClipMap::CreateAndRegister(ClipboardMappingType TheType, Filter *TheFilter,
02729                                                 InternalClipboardFormat &TheInternalDataType,
02730                                                 UINT32 TheExternalDataType,
02731                                                 UINT32 ThePriority)
02732     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02733     Created:    13/12/95
02734     Inputs:     ImportOrExport - TRUE == Import, FALSE == Export
02735 
02736                 TheFilter - The filter which can apply this conversion
02737 
02738                 TheInternalDatatType - An object defining the internal data type
02739                 (see cliptype.h)
02740 
02741                 TheExternalDataType - A Windows CF_ constant defining the external
02742                 clipboard data type which will be imported/exported.
02743 
02744                 ThePriority - An integer indicating the priority of this mapping.
02745                 The highest available priority mapping will be used in order to
02746                 retain as much information in the data as possible. See
02747                 docs\howtouse\ExtClip.doc for details of the existing mappings.
02748 
02749     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
02750                 manager. This mapping info describes a filter which is able to import
02751                 data from or export data to a windows clipboard in some way.
02752 ********************************************************************************************/
02753 void RTFClipMap::CreateAndRegister(ClipboardMappingType TheType, Filter *TheFilter,
02754                                         InternalClipboardFormat &TheInternalDataType,
02755                                         UINT32 TheExternalDataType,
02756                                         UINT32 ThePriority)
02757 {
02758     RTFClipMap *Mapping = new RTFClipMap(TheType, TheFilter,
02759                                                     TheInternalDataType,
02760                                                     TheExternalDataType,
02761                                                     ThePriority);
02762     if (Mapping == NULL)
02763         InformError();
02764     else
02765         ExternalClipboard::RegisterDataType(Mapping);
02766 }
02767 
02768 
02769 
02770 /********************************************************************************************
02771 >   virtual BOOL RTFClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData, InternalClipboard *Dest)
02772     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02773     Created:    13/12/95
02774     Inputs:     Caller - The operation within which this method is being called
02775                 ClipboardData - The result of calling GetClipboardData for your datatype
02776                 Dest - The InternalClipboard (document) to import the data into.
02777     Returns:    TRUE for success
02778     Purpose:    Calls the parent filter as appropriate to import the given data from
02779                 the external clipboard.
02780 ********************************************************************************************/
02781 BOOL RTFClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData, InternalClipboard *Dest)
02782 {
02783     CCMemFile MemFile;
02784     BOOL ok = TRUE;
02785 
02786     // Get a lock on the clipboard data
02787     BYTE* buff = (BYTE*) GlobalLock(ClipboardData);
02788     ERROR1IF(buff == NULL, FALSE, "_R(IDE_NOMORE_MEMORY)");
02789 
02790     // Provide a current view for the filter to chomp on; We stack the current
02791     // view so that we do not corrupt it.
02792     View *OldCurrentView = NULL;
02793     ClipboardView ImportView;
02794     if (ok)
02795         OldCurrentView = View::GetCurrent();
02796     if (ok)
02797         ok = ImportView.Init();
02798     if (ok)
02799         ImportView.SetCurrent();
02800 
02801     // Open a memfile onto that data
02802     if (ok)
02803         ok = MemFile.open(buff, GlobalSize(ClipboardData)-1, CCMemRead);
02804 
02805     // Attempt to import the file
02806     if (ok)
02807         ok = pFilter->DoImport(Caller, &MemFile, InternalClipboard::Instance());
02808 
02809     // Clean up behind messy importers
02810     if (MemFile.isOpen())
02811         MemFile.close();
02812 
02813     if (OldCurrentView != NULL)
02814         OldCurrentView->SetCurrent();
02815 
02816     GlobalUnlock(ClipboardData);
02817 
02818     return ok;
02819 }
02820 
02821 
02822         
02823 /********************************************************************************************
02824 >   virtual BOOL RTFClipMap::HandleExport(Operation *Caller,
02825                                                 InternalClipboard *Source)
02826     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02827     Created:    13/12/95
02828     Inputs:     Caller - the operation within which this method is being called
02829                 Source - the internal clipboard (document) to be exported
02830     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
02831                 the clipboard.
02832     Purpose:    Invokes this mapping for exporting
02833                 This takes the document tree of Source, and exports it to the external
02834                 (windows) clipboard. Usually this just involves calling Filter::DoExport
02835                 for the parent filter, and then returning the handle to the global memory
02836                 block to be placed onto the external clipboard.
02837     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
02838                 if you were dealing with it directly. You must adhere to all the Windows
02839                 rules for this - i.e. a global data block, unlocked, etc etc.
02840 ********************************************************************************************/
02841 HANDLE RTFClipMap::HandleExport(Operation *Caller, InternalClipboard *Source)
02842 {
02843     return NULL;
02844 }
02845 #endif
02846 
02847 
02848 
02849 /********************************************************************************************
02850 
02851 >   CMXClipMap::CMXClipMap(ClipboardMappingType TheType, UINT32 ClaimType = 0)
02852     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02853     Created:    04/09/96
02854 
02855     Inputs:     TheType - indicates import / export / import & export
02856 
02857                 ClaimType - specifies the text type that this mapping will claim from the
02858                 windows clipboard - that is, create 3 of these mappings, specifying
02859                 CF_TEXT, CF_UNICODETEXT, and CF_OEMTEXT, and they will all ask the
02860                 clipboard for UNICODE text when they actually go to import. This allows
02861                 us to detect the 3 implicitly-converted clipboard formats, and map them
02862                 all to UNICODE, i.e. use the UNICODE mapping for all 3 available formats.
02863                 If ClaimType == 0, UNICODE is assumed
02864 
02865     Purpose:    Constructs a clipboard mapping with the ExternalClipboard
02866                 manager. This mapping info describes a filter which is able to import
02867                 data from or export data to a windows clipboard in some way.
02868 
02869     Notes:      DON'T call the constructor - call CreateAndRegister
02870 
02871     SeeAlso:    BodgeTextClipMap::CreateAndRegister
02872 
02873 ********************************************************************************************/
02874 
02875 CMXClipMap::CMXClipMap(ClipboardMappingType TheType, UINT32 ClaimType, UINT32 nPriority)
02876                 : ClipboardMapping(TheType, NULL, InternalClipboardFormat(CLIPTYPE_VECTOR),
02877                     ClaimType, nPriority)
02878 {
02879     if (ClaimType != 0)
02880         ExternalDataType = ClaimType;
02881 }
02882 
02883 CMX16ClipMap::CMX16ClipMap()
02884 {
02885     ERROR3("Please don't press that button again");
02886 }
02887 
02888 CMX32ClipMap::CMX32ClipMap()
02889 {
02890     ERROR3("Please don't press that button again");
02891 }
02892 
02893 /********************************************************************************************
02894 
02895 >   static void CMXClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType = 0)
02896 
02897     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02898     Created:    04/09/96
02899 
02900     Inputs:     TheType - indicates import / export / import & export
02901 
02902                 ClaimType - specifies the text type that this mapping will claim from the
02903 
02904     Purpose:    Constructs and registers a clipboard mapping with the ExternalClipboard
02905                 manager. This mapping info describes a filter which is able to import
02906                 data from or export data to a windows clipboard in some way.
02907 
02908 ********************************************************************************************/
02909 
02910 void CMX16ClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType)
02911 {
02912     CMXClipMap *Mapping = new CMX16ClipMap(TheType, ClaimType, 120);
02913     if (Mapping == NULL)
02914         InformError();
02915     else
02916         ExternalClipboard::RegisterDataType(Mapping);
02917 }
02918 
02919 void CMX32ClipMap::CreateAndRegister(ClipboardMappingType TheType, UINT32 ClaimType)
02920 {
02921     // CMX32 should have a higher priority than CMX16!
02922     CMXClipMap *Mapping = new CMX32ClipMap(TheType, ClaimType, 121);
02923     if (Mapping == NULL)
02924         InformError();
02925     else
02926         ExternalClipboard::RegisterDataType(Mapping);
02927 }
02928 
02929 
02930 /********************************************************************************************
02931 
02932 >   virtual BOOL CMXClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData,
02933                                                 InternalClipboard *Dest)
02934     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02935     Created:    04/09/96
02936     Inputs:     Caller - The operation within which this method is being called
02937                 ClipboardData - The result of calling GetClipboardData for your datatype
02938                 Dest - The InternalClipboard (document) to import the data into.
02939     Returns:    TRUE for success
02940     Purpose:    Calls the parent filter as appropriate to import the given data from
02941                 the external clipboard.
02942                 This bodge mapping for text scans the docuemnt tree for text chars and
02943                 strips them out by hand. Styles and suchlike are lost. It's a bodge.
02944 ********************************************************************************************/
02945 
02946 BOOL CMXClipMap::HandleImport(SelOperation *Caller, HANDLE ClipboardData, InternalClipboard *Dest)
02947 {
02948     BOOL ok = FALSE;
02949 
02950     // Get a scratch file - if TMP isn't set, this will try for c:\temp.
02951     // The filename will have XS as a prefix
02952     char *tempname = GetTempFileName();
02953     if (tempname == NULL)
02954     {
02955         ERROR3("Couldn't get a temp filename");
02956         return(FALSE);
02957     }
02958 
02959     void *pMem = GlobalLock(ClipboardData);
02960     ok = (pMem != NULL);
02961 
02962     BOOL Layers = Filter::ImportWithLayers;
02963     Filter::ImportWithLayers = FALSE;
02964     pFilter = new CMXImportFilter;
02965     ok = (pFilter != NULL);
02966 
02967     CCDiskFile File;
02968     if(ok)
02969     {
02970         // get a file and write to it
02971         PathName pathname(tempname);
02972         if(!File.open(pathname, (ios::out | ios::binary)))
02973             ok = FALSE;     // error!
02974     }
02975 
02976     if(ok)
02977     {
02978         File.write(pMem, GlobalSize(ClipboardData));
02979 
02980         File.close();
02981     }
02982 
02983     GlobalUnlock(ClipboardData);
02984 
02985     if(ok)
02986     {
02987         ok = ImportFromTempFile(tempname, Caller, InternalClipboard::Instance());
02988     }
02989 
02990     RemoveTempFile();
02991 
02992     if(pFilter != NULL)
02993     {
02994         delete pFilter;
02995         pFilter = NULL;
02996     }
02997 
02998     Filter::ImportWithLayers = Layers;
02999 
03000     return(ok);
03001 
03002 
03003 /*  char *buff=(char*)GlobalLock(ClipboardData);
03004     if (buff != NULL && buff[0] != 0)
03005     {
03006         // get a filter to play with
03007         CMXImportFilter *pFilter = new CMXImportFilter;
03008         BOOL ok = (pFilter != NULL);
03009 
03010         // Provide a current view for the filter to chomp on; We stack the current
03011         // view so that we do not corrupt it.
03012         View *OldCurrentView = View::GetCurrent();
03013         ClipboardView ImportView;
03014         if(!ImportView.Init())
03015         {
03016             ok = FALSE;
03017         }
03018         else
03019         {
03020             ImportView.SetCurrent();
03021         }
03022 
03023         // position arbitarily on clipboard - when pasted the clip contents are centered anyway
03024         if(ok)
03025         {
03026             // make a memfile based on this thingy
03027             CCMemFile File(buff, GlobalSize(ClipboardData), CCMemRead, TRUE, TRUE);
03028 
03029             // run it through the filter
03030             ok = pFilter->DoImport(Caller, &File, Dest);
03031 
03032             if(File.isOpen())
03033                 File.close();
03034 
03035             if (OldCurrentView != NULL)
03036                 OldCurrentView->SetCurrent();
03037         }
03038 
03039         // Unlock the clipboard data, as we won't need it again
03040         GlobalUnlock(ClipboardData);
03041 
03042         if(ok)
03043             return TRUE;
03044 
03045         // We failed (no text story), so report and ensure the clipboard is 'clean'
03046         InformError();
03047         Dest->ClearClipboard();
03048     }
03049 
03050     // We failed
03051     return FALSE;*/
03052 }
03053 
03054 
03055 
03056 
03057 /********************************************************************************************
03058 
03059 >   virtual BOOL CMXClipMap::HandleExport(Operation *Caller,
03060                                                 InternalClipboard *Source)
03061 
03062     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03063     Created:    04/09/96
03064 
03065     Inputs:     Caller - the operation within which this method is being called
03066                 Source - the internal clipboard (document) to be exported
03067 
03068     Returns:    NULL (if it failed), or a windows handle of the data to be placed on
03069                 the clipboard.
03070 
03071     Purpose:    Invokes this mapping for exporting
03072                 This takes the document tree of Source, and exports it to the external
03073                 (windows) clipboard. Usually this just involves calling Filter::DoExport
03074                 for the parent filter, and then returning the handle to the global memory
03075                 block to be placed onto the external clipboard.
03076 
03077     Notes:      The returned handle should be the thing you'd pass to SetClipboardData
03078                 if you were dealing with it directly. You must adhere to all the Windows
03079                 rules for this - i.e. a global data block, unlocked, etc etc.
03080 
03081 ********************************************************************************************/
03082 
03083 HANDLE CMXClipMap::HandleExport(Operation *Caller, InternalClipboard *Source)
03084 {
03085     char *tempname = GetTempFileName(); //_ttempnam("C:\temp", "XS");
03086     if (tempname == NULL)
03087     {
03088         ERROR3("Couldn't get a temp filename");
03089         return(FALSE);
03090     }
03091 
03092 
03093     // make a new disk file of this name
03094     CCDiskFile File;
03095     PathName pathname(tempname);
03096     if(!File.open(pathname, (ios::in | ios::out | ios::binary)))
03097         return 0;       // error!
03098     
03099     // get a filter to export the thingy to
03100     CMXFilter* pFilter = CreateExportFilter();
03101     BOOL ok = (pFilter != NULL);
03102 
03103     if(ok)
03104     {
03105         // tell the filter not to do non clipboardy thing
03106         pFilter->SetIsDoingClipboardExport(TRUE);
03107 
03109         //
03110         // JustinF says: this is a ultra-late bodge so that we can render OLE presentation
03111         // data in CMX format.  The only app that requires this is CorelDRAW.  We are
03112         // tricking the CMX exporter to work with any kernel Document rather than only
03113         // the internal clipboard document.
03114         //
03115 
03116 // WEBSTER - markn 12/2/97
03117 #if (_OLE_VER >= 0x200)
03118         ok = pFilter->DoExport(Caller, &File, &pathname, m_pDoc, TRUE);
03119 #else
03120         // export to the file
03121         ok = pFilter->DoExport(Caller, &File, &pathname, InternalClipboard::Instance());
03122 #endif
03123 
03124         // reset clipboardy flag
03125         pFilter->SetIsDoingClipboardExport(FALSE);
03126     }
03127 
03128     delete pFilter;
03129 
03130     void* pMem;
03131     INT32 FileSize;
03132     HANDLE hGlobalMem;
03133 
03134     if (ok)
03135     {
03136         // find out how big the file is
03137         FileSize = File.Size();
03138 
03139     #if (_OLE_VER >= 0x200)
03140     
03141         // Is memory already allocated?
03142         if ((hGlobalMem = m_hMem) != 0)
03143         {
03144             // Is the file too big?
03145             if (UINT32(FileSize) > m_cbMemSize) return 0;
03146         }
03147         else
03148         {
03149             // No.  Allocate some.
03150             hGlobalMem = m_hMem = GlobalAlloc(GHND, FileSize);
03151         }
03152 
03153     #else
03154         
03155         // copy the file into the global block
03156         pMem = GlobalLock(hGlobalMem);
03157     
03158     #endif
03159 
03160         // Lock the block.
03161         pMem = GlobalLock(hGlobalMem);
03162         ok = (pMem != 0);
03163     }
03164 
03165     
03166     if (ok)
03167     {
03168         // seek to beginning of file
03169         File.seekIn(0);
03170 
03171         // load data..
03172         File.read(pMem, FileSize);
03173     }
03174 
03175     // close the file
03176     if(File.isOpen())
03177         File.close();
03178 
03179     // get rid of the temp file
03180     RemoveTempFile();
03181 
03182     // We must unlock the block before giving it to the clipboard
03183     GlobalUnlock(hGlobalMem);
03184 
03185     return hGlobalMem;
03186 }

Generated on Sat Nov 10 03:48:16 2007 for Camelot by  doxygen 1.4.4