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