sgliboil.cpp

Go to the documentation of this file.
00001 // $Id: sgliboil.cpp 1664 2006-08-04 10:06:16Z gerry $
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 // SGLibOil.cpp - Library OIL code
00099 
00100 #include "camtypes.h"
00101 #include "sgliboil.h"
00102 
00103 //#include "app.h"      // For GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "galstr.h"
00105 //#include "pathname.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "sginit.h"
00107 //#include "sglcart.h"  // This .cpp file's corresponding header
00108 //#include "sglib.h"
00109 //#include "sgfonts.h"
00110 //#include "sgscan.h"       // Generate code with hourglass...
00111 //#include "sgscanf.h"      // Generate code with hourglass...
00112 //#include "thumb.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "ccdc.h"       // For render-into-dialogue support
00114 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 //#include "grnddib.h"
00116 //#include "galres.h"
00117 //#include "richard.h"
00118 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 //#include "oilfltrs.h"
00120 //#include "tim.h"
00121 //#include "nev.h"
00122 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 //#include "selop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 //#include "filedlgs.h"
00125 //#include "scrcamvw.h" // PageDropInfo
00126 //#include "resource.h" // _R(IDS_CANCEL)
00127 #include "dlgmgr.h"
00128 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00129 #include "oilbitmap.h"
00130 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00131 //#include "reshlpid.h"
00132 #include "progress.h"
00133 #include "helpuser.h"
00134 //#include "reshlpid.h"
00135 //#include "sgindgen.h"
00136 //#include "ctrlhelp.h"
00137 //#include "richard2.h"
00138 //#include "richard3.h"
00139 #include "camelot.h"
00140 #include "camdoc.h"
00141 #include "unicdman.h"
00142 //#include "fonts.h"
00143 //#include "camfiltr.h" // BaseCamelotFilter - version 2 native filter - in camtypes.h [AUTOMATICALLY REMOVED]
00144 #include "cxftags.h"    // TAG_DEFINEBITMAP_****
00145 #include "cxfile.h"     // CXF_UNKNOWN_SIZE
00146 //#include "cxfrech.h"  // CXaraFileRecordHandler - in camtypes.h [AUTOMATICALLY REMOVED]
00147 //#include "expcol.h"       // ExportedColours handling class
00148 //#include "cxfrec.h"       // CXaraFileRecord handler - in camtypes.h [AUTOMATICALLY REMOVED]
00149 //#include "webster.h"
00150 #include "pathnmex.h"
00151 //#include "docview.h"      // For DocView::GetCentreImportPosition - in camtypes.h [AUTOMATICALLY REMOVED]
00152 
00153 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00154 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00155 //#include "backgrnd.h" // OpBackground
00156 #include "nodebmp.h"    // OpCreateBitmapNode
00157 #include "product.h"    // PROGRAM_NAME macro
00158 
00159 //#include <io.h>           // for FileExists
00160 //#include <stdio.h>
00161 //#include <commdlg.h>  // For GetLibPath
00162 //#include <dlgs.h>
00163 //#include <stdlib.h>
00164 //#include <mmsystem.h>
00165 
00166 //#include <sys\stat.h> // FileModified
00167 
00168 #if defined(__WXMSW__)
00169 #include <shfolder.h>   // For SHGetFolderPath
00170 #endif
00171 
00172 extern void FixFPControlRegister(void);
00173 
00174 // Implement the dynamic class bits...
00175 PORTNOTE("dialog","Removed OpClipartImport")
00176 #ifndef EXCLUDE_FROM_XARALX
00177 CC_IMPLEMENT_DYNCREATE(OpClipartImport, SelOperation)
00178 #endif
00179 PORTNOTE("dialog","Removed OpBitmapImport")
00180 #ifndef EXCLUDE_FROM_XARALX
00181 CC_IMPLEMENT_DYNCREATE(OpBitmapImport, Operation)
00182 #endif
00183 CC_IMPLEMENT_DYNCREATE(SGLibOil, CCObject)
00184 
00185 // This line mustn't go before any CC_IMPLEMENT_... macros
00186 // Declare smart memory handling in Debug builds
00187 #define new CAM_DEBUG_NEW
00188 
00189 extern BOOL getDrive(const TCHAR**, TCHAR* drive);
00190 extern BOOL getNetDrive(const TCHAR**, TCHAR* drive, BOOL *BadCharacter);
00191 
00192 TCHAR *SGLibOil::TmpSndName = NULL;
00193 
00194 // Define or undefine this to enable / disable the checking of network drive serial numbers
00195 // for the inhouse 'FindCD' code... It's safe to leave in in release versions because it checks
00196 // serial numbers of drives, which are never the same... The code's never called if they aren't
00197 // connected to a network, or don't have their network mounts assigned to drive letters...
00198 #define SCANFORXARAMOUNT
00199 
00200 #if defined(__WXMSW__)
00201 const TCHAR             chPathSep = _T('\\');
00202 #else
00203 const TCHAR             chPathSep = _T('/');
00204 #endif
00205 
00206 PORTNOTE("dialog","Removed OpClipartImport impl.")
00207 #ifndef EXCLUDE_FROM_XARALX
00208 
00209 // Constructor for ClipartImportParam,
00210 // Makes sure the parameter defaults are sensible
00211 ClipartImportParam::ClipartImportParam()
00212 {
00213     File        = NULL;
00214     Import      = FALSE;
00215     Result      = FALSE;
00216     DropInfo    = NULL;
00217 }
00218 
00220 
00221 /******************************************************************************************
00222 
00223 >   OpClipartImport::OpClipartImport() : UndoableOperation()
00224 
00225     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00226     Created:    20/3/95
00227     Inputs:     -
00228     Outputs:    -
00229     Returns:    -
00230     Purpose:    OpClipartImport constructor (Creates an undoable operation)
00231     SeeAlso:
00232 
00233 ******************************************************************************************/
00234 
00235 OpClipartImport::OpClipartImport() : SelOperation()
00236 {
00237     OpFlags.HasOwnTimeIndicator = TRUE; // The OpMenuImport op has its own time indicator
00238 }       
00239 
00240 /********************************************************************************************
00241 
00242 >   OpClipartImport::~OpClipartImport() 
00243 
00244     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00245     Created:    20/3/95
00246     Inputs:     -
00247     Outputs:    -
00248     Returns:    -
00249     Purpose:    OpClipartImport destructor
00250     Errors:     -
00251     SeeAlso:    -
00252 
00253 ********************************************************************************************/
00254 
00255 OpClipartImport::~OpClipartImport()
00256 {
00257 }
00258 
00259 /******************************************************************************************
00260 
00261 >   BOOL OpClipartImport::Init()
00262 
00263     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00264     Created:    20/3/95
00265     Returns:    FALSE if it fails (due to lack of memory)
00266     Purpose:    Creates an OpDescriptor for an ClipartImport operation
00267     SeeAlso:
00268 
00269 ******************************************************************************************/
00270 
00271 BOOL OpClipartImport::Init()
00272 {  
00273     OpBitmapImport::Init();
00274     OpAsynchBitmapImport::Init();
00275 
00276     return RegisterOpDescriptor(
00277         0,                              // Tool ID
00278         _R(IDS_OPCLIPARTIMPORT),                // String resource ID
00279         CC_RUNTIME_CLASS(OpClipartImport),  // Runtime class
00280         OPTOKEN_OPCLIPARTIMPORT,            // Token string
00281         OpClipartImport::GetState,          // GetState function
00282         0,                              // Help ID
00283         0,                              // Bubble ID
00284         0,                              // Resource ID
00285         0                               // Control ID
00286 //  needs   'GREY_WHEN_NO_CURRENT_DOC'
00287     );
00288 }   
00289 
00290 /******************************************************************************************
00291 
00292 >   OpState OpClipartImport::GetState(String_256* pString, OpDescriptor* pOpDesc)
00293 
00294     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00295     Created:    20/3/95
00296     Purpose:    Returns the OpState of the OpClipartImport operation.
00297     SeeAlso:
00298 
00299 ******************************************************************************************/
00300 
00301 OpState OpClipartImport::GetState(String_256* pString, OpDescriptor* pOpDesc)
00302 {
00303     //OpState OpSt;
00304     OpState OpSt;
00305 
00306     return(OpSt);
00307 }
00308 
00309 /********************************************************************************************
00310 
00311 >   void OpClipartImport::Do(OpDescriptor*)
00312 
00313     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00314     Created:    20/3/95
00315     Inputs:     OpClipartImport (unused)
00316     Outputs:    -
00317     Returns:    -
00318     Purpose:    
00319     Errors:     Always fails because this Do doesn't.
00320     SeeAlso:    -
00321 
00322 ********************************************************************************************/
00323             
00324 void OpClipartImport::Do(OpDescriptor *NotUsed)
00325 {
00326     ERROR3("OpClipartImport does not provide a Do() function - Use DoWithParam");
00327     End();
00328 }
00329 
00330 /******************************************************************************************
00331 >   void OpClipartImport::DoWithParam(OpDescriptor* pOp, OpParam* pAlignParam)
00332 
00333     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com> (well, most of the code taken from tim's OpMenuImport)
00334     Created:    20/3/95
00335     Inputs:     pOp - OpDescriptor as for all Do() functions
00336                 Param - points to a handy ClipartImport structure which says which
00337                     file to import, etc...
00338     Outputs:    -
00339     Returns:    -
00340     Purpose:    Performs a clipart import / open depending on the parameters...
00341                 Imports overlay the clipart on the existing document,
00342                 Opens create a new page and import to that.
00343 
00344     SeeAlso:
00345 ******************************************************************************************/
00346 
00347 void OpClipartImport::DoWithParam(OpDescriptor* pOp, OpParam* pClipartImportParam)
00348 {
00349     ClipartImportParam *pInfo = (ClipartImportParam *) pClipartImportParam;
00350 
00351     if(pInfo == NULL)
00352     {
00353         ERROR3("OpClipartImport called with NULL info pointer");
00354         FailAndExecute(); 
00355         End();
00356         return;
00357     }
00358     else
00359     {
00360         if(pInfo->File == NULL)
00361         {
00362             ERROR3("OpClipartImport called with NULL file pointer");
00363             FailAndExecute(); 
00364             End();
00365             return;
00366         }
00367     }
00368 
00369     PathName Path = *(pInfo->File);
00370 
00371     if(!Path.IsValid())
00372     {
00373         ERROR3("Filename is invalid");
00374         //InformError(_R(IDT_IMPORT_NOTFOUND));
00375         FailAndExecute();
00376         End();
00377         return;
00378     }
00379 
00380     if(!pInfo->Import)
00381     {
00382         // Open / Load a file
00383         CCamApp        *pApp = AfxGetApp();
00384         BaseFileDialog::SelectedFilter = 0;
00385         
00386         String_256 OpenPath((const TCHAR *)Path.GetPath());
00387 //      Error::ClearError();
00388 
00389         // Open a document
00390         CCamDoc* pDoc = (CCamDoc*) pApp->OpenDocumentFile((TCHAR *)OpenPath);
00391 
00392         // Force the Ops 'Working Doc' to the selected one, in case the open
00393         // document thingy deleted the existing docs.
00394         if(pDoc != NULL) pOurDoc = Document::GetSelected();
00395         
00396         Document* pCurDoc = pDoc->GetKernelDoc();
00397 
00398         // And redraw the imported document
00399         //if(pCurDoc) pCurDoc->ForceRedraw();
00400 
00401     }
00402     else
00403     {
00404         // Can't import if no selected document (!)
00405         if(Document::GetSelected() == NULL)
00406         {
00407             ERROR3("No selected document");
00408             //InformError(_R(IDT_IMPORT_NOTFOUND));
00409             FailAndExecute();
00410             End();
00411             return;
00412         }
00413             
00414         // Import a file
00415         UINT32 SelFilter = FILTERID_GENERIC;
00416         BOOL LayersImport = FALSE;
00417         
00418         // Find the filter that the user chose
00419         Filter *pFilter = Filter::GetFirst();
00420 
00421         if(pFilter == NULL)
00422             return;
00423 
00424         while (pFilter != NULL)
00425         {
00426             if ((pFilter->GetFlags().CanImport) && (pFilter->FilterID == SelFilter))
00427                 // This is the filter!
00428                 break;
00429 
00430             // Try the next filter
00431             pFilter = Filter::GetNext(pFilter);
00432         }
00433 
00434         if (pFilter == NULL)
00435         {
00436             InformError(_R(IDT_CANT_FIND_FILTER));
00437             FailAndExecute(); 
00438             End();
00439             return;
00440         }
00441         else
00442         {
00443             // If this is not a filter family, check for compatibility before asking
00444             // filter to load the file.
00445             // This means the user has chosen an explicit filter to handle the import
00446             if (!pFilter->IS_KIND_OF(FilterFamily))
00447             {
00448                 UINT32 Size = 1024;
00449                 INT32 FileSize;
00450                 ADDR FilterBuf = pFilter->LoadInitialSegment(Path, &Size, &FileSize);
00451 
00452                 // If there has been a problem in the load initial segment then fail now.
00453                 if (FilterBuf == NULL)
00454                 {
00455                     // Tell the user about the problem and get out now while the goings good 
00456                     InformError();
00457                     FailAndExecute(); 
00458                     End();
00459                     return;
00460                 }
00461 
00462                 // Inform any filters that we are about to do a HowCompatible call.
00463                 // This would allow a set of filters which have common functionality hidden in a
00464                 // filter that cannot import and cannot export handle this call and hence set
00465                 // itself up. This would allow it to maybe cache a result which should only be
00466                 // checked by the first filter in the group. 
00467                 pFilter->PreHowCompatible();
00468         
00469                 // Change this to be less than 9 as the built in BMP filter returns 8 if it
00470                 // is not too sure about the file and would like the AccusoftBMp filter to 
00471                 // load the file if it is present.  
00472                 if (pFilter->HowCompatible(Path, FilterBuf, Size, FileSize) < 9)
00473                 {
00474                     // Not 100% happy with this file - ask for confirmation.
00475                     ErrorInfo Question;
00476                     Question.ErrorMsg = _R(IDT_IMPQUERY_NOTSURE);
00477                     Question.Button[0] = _R(IDB_IMPQUERY_IMPORT);
00478                     Question.Button[1] = _R(IDB_IMPQUERY_DONTIMPORT);
00479 
00480                     if (AskQuestion(&Question) != _R(IDB_IMPQUERY_IMPORT))
00481                     {
00482                         // User asked for this to be cancelled.
00483                         TRACEUSER( "Richard", wxT("Filter compatibility was less than 10\n") );
00484 
00485                         // Close the file, report the abort and finish.
00486                         CCFree(FilterBuf);
00487                         FailAndExecute();
00488                         InformMessage(_R(IDT_IMP_USERABORT));
00489                         End();
00490                         return;
00491                     }
00492                 }
00493 
00494                 // Get rid of initial file header
00495                 CCFree(FilterBuf);
00496             }
00497 
00498             // Start the selection operation
00499             if (DoStartSelOp(FALSE)) // We don't want to save the end selection status because 
00500                                      // it will be restored automatically when the operation is 
00501                                      // redone
00502             {
00503                 // First off, we have to try and open the file
00504                 CCDiskFile DiskFile(1024, FALSE, TRUE);
00505 
00506                 // Get pointer to current doc 'cos we'll need it several times...
00507                 //Document* pCurDoc = Document::GetCurrent();
00508                 Document* pCurDoc;
00509                 ImportPosition Pos;
00510 
00511                 if (pInfo->DropInfo)
00512                 {
00513                     // A specfic Import Position has been specified.
00514                     // Get the document, spread, and position to import at.
00515                     pCurDoc = pInfo->DropInfo->pDoc;
00516 
00517                     Pos.Position    = pInfo->DropInfo->DropPos;
00518                     Pos.pSpread     = pInfo->DropInfo->pSpread;
00519                 }
00520                 else
00521                 {
00522                     pCurDoc = Document::GetSelected();
00523                 }
00524 
00525                 if(pCurDoc == NULL)
00526                 {
00527                     ERROR3("OpClipartImport::DoWithParam retrieved NULL selected doc");
00528                     return;
00529                 }
00530 
00531                 TRY
00532                 {
00533                     if (!DiskFile.open(Path, ios::in | ios::binary))
00534                     {
00535                         // Failed to open the file...
00536                         TRACEUSER( "Richard", wxT("Failed to open file in ClipartImport Do") );
00537                         InformError(_R(IDT_IMPORT_NOTFOUND));
00538                         FailAndExecute();
00539                         End();
00540                         return;
00541                     }
00542 
00543                     // Import the file and see if Something went a bit wrong - tell the user what it was.
00544                     ImportPosition* ImportPos;
00545                     if (pInfo->DropInfo)
00546                         ImportPos = &Pos;   // Import at a specific point.
00547                     else
00548                     {
00549                         //Graham 15/7/97
00550                         //Otherwise, put the imported object in the centre of the view
00551                         //So get the current view
00552                         DocView* pDocView=DocView::GetCurrent();
00553 
00554                         //And find its centre import position
00555                         Pos=pDocView->GetCentreImportPosition();
00556 
00557                         ImportPos=&Pos;
00558                     }
00559 
00560 
00561 
00562                     if (!pFilter->DoImport(this, &DiskFile, pCurDoc, FALSE, ImportPos))
00563                     {
00564                         // Only tell them if not special user cancelled error message
00565                         if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00566                             InformError();
00567                         else
00568                             Error::ClearError();    // otherwise remove the error so it won't get reported
00569                         FailAndExecute();
00570                         End();
00571 
00572                         // close the file
00573                         if (DiskFile.isOpen())
00574                             DiskFile.close();
00575 
00576                         return;
00577                     }
00578 
00579                     // close the file
00580                     if (DiskFile.isOpen())
00581                         DiskFile.close();
00582 
00583                 }
00584 
00585                 // See if there was a file io error
00586                 CATCH(CFileException, e)
00587                 {
00588                     // Report the error if no one else did
00589                     if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00590                         InformError();
00591                     else
00592                         Error::ClearError();    // otherwise remove the error so it won't get reported
00593 
00594                     // Make sure that the file is closed
00595                     TRY
00596                     {
00597                         if (DiskFile.isOpen())
00598                             DiskFile.close();
00599                     }
00600                     CATCH(CFileException, e)
00601                     {
00602                         // Failed to close the file - not much we can do about it really
00603                     }
00604                     END_CATCH
00605 
00606                     // and fail
00607                     FailAndExecute();
00608                     End();
00609                     return;
00610                 }
00611                 END_CATCH
00612             }
00613         }
00614     }
00615         
00616     // grab the focus
00617     GetMainFrame()->SetActiveWindow();
00618     // Finished the operation
00619     End();
00620 }
00621 
00622 
00623 
00624 
00625 
00626 
00627 // Constructor for BitmapImportParam,
00628 // Makes sure the parameter defaults are sensible
00629 BitmapImportParam::BitmapImportParam()
00630 {
00631     File            = NULL;
00632     Result          = FALSE;
00633 
00634     pTargetDoc      = 0;
00635     TagObjectToFill = 0;
00636     TagObjectValid  = false;
00637     pObject         = 0;
00638     pObjectValid    = false;
00639 }
00640 
00642 
00643 /******************************************************************************************
00644 
00645 >   OpBitmapImport::OpBitmapImport() : UndoableOperation()
00646 
00647     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00648     Created:    20/3/95
00649     Inputs:     -
00650     Outputs:    -
00651     Returns:    -
00652     Purpose:    OpBitmapImport constructor (Creates an undoable operation)
00653     SeeAlso:
00654 
00655 ******************************************************************************************/
00656 
00657 OpBitmapImport::OpBitmapImport() : Operation()
00658 {
00659     OpFlags.HasOwnTimeIndicator = TRUE; // The OpMenuImport op has its own time indicator
00660 }       
00661 
00662 /********************************************************************************************
00663 
00664 >   OpBitmapImport::~OpBitmapImport() 
00665 
00666     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00667     Created:    20/3/95
00668     Inputs:     -
00669     Outputs:    -
00670     Returns:    -
00671     Purpose:    OpBitmapImport destructor
00672     Errors:     -
00673     SeeAlso:    -
00674 
00675 ********************************************************************************************/
00676 
00677 OpBitmapImport::~OpBitmapImport()
00678 {
00679 }
00680 
00681 /******************************************************************************************
00682 
00683 >   BOOL OpAlign::Init()
00684 
00685     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00686     Created:    20/3/95
00687     Returns:    FALSE if it fails (due to lack of memory)
00688     Purpose:    Creates an OpDescriptor for an BitmapImport operation
00689     SeeAlso:
00690 
00691 ******************************************************************************************/
00692 
00693 BOOL OpBitmapImport::Init()
00694 {
00695     return RegisterOpDescriptor(
00696         0,                              // Tool ID
00697         _R(IDS_OPCLIPARTIMPORT),                // String resource ID
00698         CC_RUNTIME_CLASS(OpBitmapImport),   // Runtime class
00699         OPTOKEN_OPBITMAPIMPORT,         // Token string
00700         OpBitmapImport::GetState,           // GetState function
00701         0,                              // Help ID
00702         0,                              // Bubble ID
00703         0,                              // Resource ID
00704         0                               // Control ID
00705 //  needs   'GREY_WHEN_NO_CURRENT_DOC'
00706     );
00707 }   
00708 
00709 /******************************************************************************************
00710 
00711 >   OpState OpBitmapImport::GetState(String_256* pString, OpDescriptor* pOpDesc)
00712 
00713     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00714     Created:    20/3/95
00715     Purpose:    Returns the OpState of the OpBitmapImport operation.
00716     SeeAlso:
00717 
00718 ******************************************************************************************/
00719 
00720 OpState OpBitmapImport::GetState(String_256* pString, OpDescriptor* pOpDesc)
00721 {
00722     //OpState OpSt;
00723     OpState OpSt;
00724 
00725     return(OpSt);
00726 }
00727 
00728 /********************************************************************************************
00729 
00730 >   void OpBitmapImport::Do(OpDescriptor*)
00731 
00732     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
00733     Created:    20/3/95
00734     Inputs:     OpBitmapImport (unused)
00735     Outputs:    -
00736     Returns:    -
00737     Purpose:    
00738     Errors:     Always fails because this Do doesn't.
00739     SeeAlso:    -
00740 
00741 ********************************************************************************************/
00742             
00743 void OpBitmapImport::Do(OpDescriptor *NotUsed)
00744 {
00745     ERROR3("OpBitmapImport does not provide a Do() function - Use DoWithParam");
00746     End();
00747 }
00748 
00749 /******************************************************************************************
00750 >   void OpBitmapImport::DoWithParam(OpDescriptor* pOp, OpParam* pAlignParam)
00751 
00752     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00753     Created:    9/4/95
00754     Inputs:     pOp - OpDescriptor as for all Do() functions
00755                 Param - points to a handy BitmapImport structure which says which
00756                     file to import, etc...
00757     Outputs:    -
00758     Returns:    -
00759     Purpose:    Performs a Bitmap import.
00760                 Returns a pointer to the imported bitmap, without creating any objects.
00761 
00762     SeeAlso:
00763 ******************************************************************************************/
00764 
00765 void OpBitmapImport::DoWithParam(OpDescriptor* pOp, OpParam* pBitmapImportParam)
00766 {
00767     BitmapImportParam *pInfo = (BitmapImportParam *) pBitmapImportParam;
00768     KernelBitmap* pBitmap = 0;
00769 
00770     if(pInfo == NULL)
00771     {
00772         ERROR3("OpBitmapImport called with NULL info pointer");
00773         FailAndExecute(); 
00774         End();
00775         return;
00776     }
00777     else
00778     {
00779         if(pInfo->File == NULL)
00780         {
00781             ERROR3("OpBitmapImport called with NULL file pointer");
00782             FailAndExecute(); 
00783             End();
00784             return;
00785         }
00786     }
00787 
00788     PathName Path = *(pInfo->File);
00789 
00790     if(!Path.IsValid())
00791     {
00792         ERROR3("Filename is invalid");
00793         //InformError(_R(IDT_IMPORT_NOTFOUND));
00794         FailAndExecute();
00795         End();
00796         return;
00797     }
00798 
00799     // Import a file
00800     UINT32 SelFilter = FILTERID_GENERIC;
00801     BOOL LayersImport = FALSE;
00802     
00803     // Find the filter that the user chose
00804     Filter *pFilter = Filter::GetFirst();
00805 
00806     if(pFilter == NULL)
00807         return;
00808 
00809     while (pFilter != NULL)
00810     {
00811         if ((pFilter->GetFlags().CanImport) && (pFilter->FilterID == SelFilter))
00812             // This is the filter!
00813             break;
00814 
00815         // Try the next filter
00816         pFilter = Filter::GetNext(pFilter);
00817     }
00818 
00819     if (pFilter == NULL)
00820     {
00821         InformError(_R(IDT_CANT_FIND_FILTER));
00822         FailAndExecute(); 
00823         End();
00824         return;
00825     }
00826     else
00827     {
00828         // If this is not a filter family, check for compatibility before asking
00829         // filter to load the file.
00830         // This means the user has chosen an explicit filter to handle the import
00831         if (!pFilter->IS_KIND_OF(FilterFamily))
00832         {
00833             UINT32 Size = 1024;
00834             INT32 FileSize;
00835             ADDR FilterBuf = pFilter->LoadInitialSegment(Path, &Size, &FileSize);
00836 
00837             // If there has been a problem in the load initial segment then fail now.
00838             if (FilterBuf == NULL)
00839             {
00840                 // Tell the user about the problem and get out now while the goings good 
00841                 InformError();
00842                 FailAndExecute(); 
00843                 End();
00844                 return;
00845             }
00846 
00847             // Inform any filters that we are about to do a HowCompatible call.
00848             // This would allow a set of filters which have common functionality hidden in a
00849             // filter that cannot import and cannot export handle this call and hence set
00850             // itself up. This would allow it to maybe cache a result which should only be
00851             // checked by the first filter in the group. 
00852             pFilter->PreHowCompatible();
00853     
00854             // Change this to be less than 9 as the built in BMP filter returns 8 if it
00855             // is not too sure about the file and would like the AccusoftBMp filter to 
00856             // load the file if it is present.  
00857             if (pFilter->HowCompatible(Path, FilterBuf, Size, FileSize) < 9)
00858             {
00859                 // Not 100% happy with this file - ask for confirmation.
00860                 ErrorInfo Question;
00861                 Question.ErrorMsg = _R(IDT_IMPQUERY_NOTSURE);
00862                 Question.Button[0] = _R(IDB_IMPQUERY_IMPORT);
00863                 Question.Button[1] = _R(IDB_IMPQUERY_DONTIMPORT);
00864 
00865                 if (AskQuestion(&Question) != _R(IDB_IMPQUERY_IMPORT))
00866                 {
00867                     // User asked for this to be cancelled.
00868                     TRACEUSER( "Richard", wxT("Filter compatibility was less than 10\n") );
00869 
00870                     // Close the file, report the abort and finish.
00871                     CCFree(FilterBuf);
00872                     FailAndExecute();
00873                     InformMessage(_R(IDT_IMP_USERABORT));
00874                     End();
00875                     return;
00876                 }
00877             }
00878 
00879             // Get rid of initial file header
00880             CCFree(FilterBuf);
00881         }
00882 
00883         // First off, we have to try and open the file
00884         CCDiskFile DiskFile(1024, FALSE, TRUE);
00885 
00886         TRY
00887         {
00888             if (!DiskFile.open(Path, ios::in | ios::binary))
00889             {
00890                 // Failed to open the file...
00891                 TRACEUSER( "Richard", wxT("Failed to open file in BitmapImport Do") );
00892                 InformError(_R(IDT_IMPORT_NOTFOUND));
00893                 FailAndExecute();
00894                 End();
00895                 return;
00896             }
00897 
00898             // Import the file and see if Something went a bit wrong - tell the user what it was.
00899             if (!pFilter->ImportBitmap(&DiskFile, &pBitmap))
00900             {
00901                 // Only tell them if not special user cancelled error message
00902                 if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00903                     InformError();
00904                 else
00905                     Error::ClearError();    // otherwise remove the error so it won't get reported
00906                 FailAndExecute();
00907                 End();
00908 
00909                 return;
00910             }
00911 
00912             // close the file
00913             if (DiskFile.isOpen())
00914                 DiskFile.close();
00915         }
00916 
00917         // See if there was a file io error
00918         CATCH(CFileException, e)
00919         {
00920             // Report the error if no one else did
00921             if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
00922                 InformError();
00923             else
00924                 Error::ClearError();    // otherwise remove the error so it won't get reported
00925 
00926             // Make sure that the file is closed
00927             TRY
00928             {
00929                 if (DiskFile.isOpen())
00930                     DiskFile.close();
00931             }
00932             CATCH(CFileException, e)
00933             {
00934                 // Failed to close the file - not much we can do about it really
00935             }
00936             END_CATCH
00937 
00938             // and fail
00939             FailAndExecute();
00940             End();
00941             return;
00942         }
00943         END_CATCH
00944     }
00945 
00946     // Should really check the return value of ApplyFill(...)
00947     ApplyFill(pInfo, pBitmap);
00948 
00949     // If we have created a bitmap and it hasn't been added to a list somewhere
00950     if (pBitmap && pBitmap->GetParentBitmapList() == NULL)
00951     {
00952         // Delete it
00953         delete pBitmap;
00954     }
00955 
00956     // grab the focus
00957     GetMainFrame()->SetActiveWindow();
00958 
00959     // Finished the operation
00960     End();
00961 }
00962 
00963 bool OpBitmapImport::ApplyFill(BitmapImportParam *pInfo, KernelBitmap* pBitmap)
00964 {
00965     // Check the document pointer points to the current document
00966     if (Document::GetCurrent() != pInfo->pTargetDoc || pInfo->pTargetDoc == 0)
00967     {
00968         // At the moment we cannot apply a fill to an object that is not in
00969         // the current document (the operations used in this function appear to
00970         // add the object to one documents tree and render the object on the other
00971         // document).
00972         ERROR3("Cannot apply fill when active document has changed");
00973         return false;
00974     }
00975 
00976     // Check the spread is valid
00977     if (!Document::SpreadBelongsToDoc(pInfo->pTargetDoc, pInfo->pSpread))
00978     {
00979         ERROR3("Trying to import a bitmap fill into a non-existent spread");
00980         return false;
00981     }
00982 
00983     // Everything looks OK, lets do the fill
00984     switch(pInfo->FillType)
00985     {
00986         // If you need to change ApplyToObject, you may need to change ApplyToObjectAsTrans
00987         case ApplyToObject:
00988         {
00989             NodeRenderableInk* pObjectToUse;
00990             if (pInfo->TagObjectValid)
00991             {
00992                 Node *pTreeRoot = pInfo->pTargetDoc->GetFirstNode()->FindFirstDepthFirst();
00993                 if (pTreeRoot) pTreeRoot = pTreeRoot->FindNext();
00994                 Node *pNode = pTreeRoot->FindFirstDepthFirst();
00995                 while ((pNode != NULL) && (pNode->GetTag() != pInfo->TagObjectToFill))
00996                     pNode = pNode->FindNextDepthFirst(pTreeRoot);
00997 
00998                 if (pNode == 0)
00999                     return false;
01000 
01001                 if (pNode->IsAnObject())
01002                     pObjectToUse = static_cast<NodeRenderableInk *>(pNode); // should use dynamic_cast but no RTTI available
01003                 else
01004                 {
01005                     ERROR3("It has the tag we saved but its type has changed.  This is odd");
01006                     return false;
01007                 }
01008             }
01009 
01010             AttrBitmapColourFill* Attrib = new AttrBitmapColourFill;
01011             if (Attrib == 0)
01012                 return false;
01013 
01014             Attrib->AttachBitmap(pBitmap);
01015 
01016             if (pInfo->TagObjectValid)
01017                 AttributeManager::ApplyAttribToNode(pObjectToUse, Attrib);
01018             else if (pInfo->pObjectValid)
01019                 AttributeManager::ApplyAttribToNode(pInfo->pObject, Attrib);
01020             else
01021                 AttributeManager::AttributeSelected(0, Attrib);
01022 
01023             return true;
01024         }
01025         // If you need to change ApplyToObjectAsTransp, you may need to change ApplyToObject
01026         case ApplyToObjectAsTransp:
01027         {
01028             NodeRenderableInk* pObjectToUse;
01029 
01030             if (pInfo->TagObjectValid)
01031             {
01032                 Node *pTreeRoot = pInfo->pTargetDoc->GetFirstNode()->FindFirstDepthFirst();
01033                 if (pTreeRoot) pTreeRoot = pTreeRoot->FindNext();
01034                 Node *pNode = pTreeRoot->FindFirstDepthFirst();
01035                 while ((pNode != NULL) && (pNode->GetTag() != pInfo->TagObjectToFill))
01036                     pNode = pNode->FindNextDepthFirst(pTreeRoot);
01037 
01038                 if (pNode == 0)
01039                     return false;
01040 
01041                 if (pNode->IsAnObject())
01042                     pObjectToUse = static_cast<NodeRenderableInk *>(pNode); // should use dynamic_cast but no RTTI available
01043                 else
01044                 {
01045                     ERROR3("It has the tag we saved but its type has changed.  This is odd");
01046                     return false;
01047                 }
01048             }
01049 
01050             pBitmap = NodeBitmap::CheckGreyscaleBitmap(pBitmap, _R(IDS_BMPGAL_MAKEGREY), _R(IDS_BMPGAL_DOGREY));
01051 
01052             AttributeManager::HaveAskedAboutContoneColours  = FALSE;
01053             AttributeManager::UserCancelledContoneColours   = FALSE;
01054 
01055             if (pBitmap == 0)
01056                 return false;
01057 
01058             // Fill colour selected so create a fill colour attribute
01059             NodeAttribute *Attrib = new AttrBitmapTranspFill;
01060             if (Attrib == 0)
01061                 return false;
01062 
01063             (static_cast<AttrBitmapTranspFill *>(Attrib))->AttachBitmap(pBitmap);
01064 
01065             if (pInfo->TagObjectValid)
01066                 AttributeManager::ApplyAttribToNode(pObjectToUse, Attrib);
01067             else if (pInfo->pObjectValid)
01068                 AttributeManager::ApplyAttribToNode(pInfo->pObject, Attrib);
01069             else
01070                 AttributeManager::AttributeSelected(0, Attrib);
01071 
01072             return true;
01073         }
01074         case SetBackground:
01075         {
01076             OpBackgroundParam Param;
01077             Param.pBitmap   = pBitmap;
01078             Param.pDoc      = pInfo->pTargetDoc;            
01079             Param.pSpread   = pInfo->pSpread;
01080             
01081             // Obtain a pointer to the op descriptor for the create operation 
01082             OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_BACKGROUND);
01083 
01084             // Invoke the operation, passing in our parameters
01085             pOpDesc->Invoke(&Param);
01086             return true;
01087         }
01088         case AddToPage:
01089         {
01090             PageDropInfo DropInfo;
01091 
01092             DropInfo.pDoc       = pInfo->pTargetDoc;
01093             DropInfo.pSpread    = pInfo->pSpread;
01094             DropInfo.DropPos    = pInfo->DropPos;
01095 
01096             // Obtain a pointer to the op descriptor for the create operation 
01097             OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpCreateNodeBitmap));
01098 
01099             // Invoke the operation, passing DocView and Pos as parameters
01100             OpDesc->Invoke(&OpParam((INT32)pBitmap,(INT32)&DropInfo));
01101             return true;
01102         }
01103         default:
01104         {
01105             ERROR3("Unknown fill type");
01106             return false;
01107         }
01108     }
01109 }
01110 
01111 #endif // wxCamelot port
01112 
01113 /***********************************************************************************************
01114 >   static BOOL SGLibOil::TidyUp(void)
01115 
01116     Purpose: Called by camelot de-init routines
01117 ***********************************************************************************************/
01118 
01119 BOOL SGLibOil::TidyUp(void)
01120 {
01121     if(TmpSndName != NULL)
01122     {
01123         PathName TheFile(TmpSndName);
01124         FileDelete(&TheFile);
01125         TmpSndName = NULL;
01126     }
01127     return TRUE;
01128 }
01129 
01130 /***********************************************************************************************
01131 
01132 >   static BOOL SGLibOil::FileCopy(PathName *Source, PathName *Destination)
01133 
01134     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01135     Created:    28/3/95
01136     Inputs:     Source - Source path to grab file from
01137                 Destination - Destination path to copy file to
01138     Returns:    Returns true if all was hunky dorey
01139     Purpose:    Copies a file from source to destination.
01140     Notes:      This function was deemed necessary as actually doing this sort of
01141                 thing in windows 3.1 is completely nasty, and completely incompatible
01142                 with NT's way...
01143           
01144 ***********************************************************************************************/
01145 
01146 BOOL SGLibOil::FileCopy(PathName *Source, PathName *Destination)
01147 {
01148     PORTNOTETRACE("dialog","SGLibOil::FileCopy - do nothing");
01149 #ifndef EXCLUDE_FROM_XARALX
01150     if(Source == NULL || Destination == NULL)
01151     {
01152         ERROR3("SGLibOil::FileCopy Source or Destination files should not be null");
01153         return FALSE;
01154     }
01155 
01156     if(!Destination->IsValid() || !Source->IsValid())
01157     {
01158         ERROR3("SGLibOil::FileCopy given invalid path");
01159         return FALSE;
01160     }
01161 
01162     if(FileExists(Destination))
01163     {
01164         ERROR3("SGLibOil::FileCopy destination file already exists");
01165         return FALSE;
01166     }
01167 
01168     if(!FileExists(Source))
01169     {
01170         ERROR3("SGLibOil::FileCopy source file doesn't exist");
01171         return FALSE;
01172     }
01173 
01174 // *************************
01175 
01176 //  return CopyFile((TCHAR *)Source->GetPath(), (TCHAR *)Destination->GetPath(), FALSE);
01177 
01178 // *************************
01179 
01180     INT32 Size = SGLibOil::FileSize(Source);
01181     void *Buffer = CCMalloc(Size + 4);
01182 
01183     if(Buffer != NULL)
01184     {
01185         CCDiskFile File(1024, FALSE, TRUE);
01186  
01187         // Open file and check if it exists at the same time
01188         try
01189         {
01190             // Read file into the buffer
01191             File.open( Source->GetPath(), ios::in | ios::binary );
01192             File.read( Buffer, Size );
01193             if(File.isOpen())
01194                 File.close();
01195 
01196             // Write file from buffer into output file
01197             File.open(Destination->GetPath(), ios::out | ios::binary);
01198             File.write(Buffer, Size);
01199             if(File.isOpen())
01200                 File.close();
01201 
01202             CCFree(Buffer);
01203 
01204             // File copied ok...
01205             return TRUE;
01206         }       
01207         catch( CFileException )
01208         {
01209             // File not copied ok... Clear the errors and fall though to alternative low-
01210             // memory file copy... (this should be very rare !)
01211             Error::ClearError();
01212         }
01213 
01214         CCFree(Buffer);
01215     }
01216 
01217 // *************************
01218 
01219     // Not enough memory available, do the copy the old, slow, byte by byte (ANSI) way...
01220 
01221     FILE               *FPin  = NULL;
01222     FILE               *FPout = NULL;
01223 
01224 #if defined(__WXMSW__)
01225     FPin  = _tfopen((const TCHAR *)Source->GetPath(), "rb");
01226     FPout = _tfopen((const TCHAR *)Destination->GetPath(), "wb");
01227 #else
01228     PSTR                pszSrc, pszDst;
01229     {
01230         size_t          cchTmp = camWcstombs( NULL, Source->GetPath(), 0 ) + 1;
01231         pszSrc = PSTR( alloca( cchTmp ) );
01232         camWcstombs( pszSrc, Source->GetPath(), cchTmp );
01233     }
01234     {
01235         size_t          cchTmp = camWcstombs( NULL, Destination->GetPath(), 0 ) + 1;
01236         pszDst = PSTR( alloca( cchTmp ) );
01237         camWcstombs( pszDst, Destination->GetPath(), cchTmp );
01238     }
01239 
01240     FPin  = fopen( pszSrc, "rb" );
01241     FPout = fopen( pszDst, "wb" );
01242 #endif
01243     
01244     if(FPin != NULL || FPout != NULL)
01245     {
01246         TCHAR C;
01247         while(!feof(FPin))
01248         {
01249             C = _fgettc(FPin);
01250             if(!feof(FPin)) _fputtc(C, FPout);
01251         }                       
01252         fclose(FPin);
01253         fclose(FPout);
01254         return TRUE;
01255     }
01256 
01257     if(FPin != NULL) fclose(FPin);
01258     if(FPout != NULL) fclose(FPout);
01259 #endif
01260     return FALSE;
01261 }
01262 
01263 /***********************************************************************************************
01264 
01265 >   static BOOL SGLibOil::FileExists(PathName *FileName)
01266 
01267     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01268     Created:    8/3/95
01269     Inputs:     File - Pointer to path and filename of file
01270     Returns:    Returns true if the specified file exists
01271     Purpose:    To find out whether a file actually exists.
01272     Notes:
01273 
01274 ********