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 ***********************************************************************************************/
01275 
01276 BOOL SGLibOil::FileExists(PathName *FileName)
01277 {
01278     return wxFile::Exists( PCTSTR(FileName->GetPath()) );
01279 
01280 #if 0
01281     CCDiskFile File;
01282     BOOL OldTEState = File.SetThrowExceptions(FALSE);
01283     BOOL OldREState = File.SetReportErrors(FALSE);
01284     BOOL Found = FALSE;
01285      
01286     // Open file - returns false if there was an error (file doesn't exist)
01287     Found = File.open(FileName->GetPath(), ios::in | ios::binary | ios::nocreate);
01288     if(Found) File.close();
01289         
01290     File.SetThrowExceptions(OldTEState);
01291     File.SetReportErrors(OldREState);
01292     Error::ClearError();
01293 
01294     return Found;
01295 #endif
01296 }
01297 
01298 /***********************************************************************************************
01299 
01300 >   static BOOL SGLibOil::DirExists(PathName *FileName)
01301 
01302     Author:     Luke Hart (Xara Group Ltd) <lukeh@xara.com>
01303     Created:    21/05/06
01304     Inputs:     File - Pointer to path and filename of dir
01305     Returns:    Returns true if the specified dir exists
01306     Purpose:    To find out whether a dir actually exists.
01307     Notes:
01308 
01309 ***********************************************************************************************/
01310 
01311 BOOL SGLibOil::DirExists( const PathName& FileName )
01312 {
01313     return wxDir::Exists( PCTSTR(FileName.GetPath()) );
01314 
01315 #if 0
01316     CCDiskFile File;
01317     BOOL OldTEState = File.SetThrowExceptions(FALSE);
01318     BOOL OldREState = File.SetReportErrors(FALSE);
01319     BOOL Found = FALSE;
01320      
01321     // Open file - returns false if there was an error (file doesn't exist)
01322     Found = File.open(FileName->GetPath(), ios::in | ios::binary | ios::nocreate);
01323     if(Found) File.close();
01324         
01325     File.SetThrowExceptions(OldTEState);
01326     File.SetReportErrors(OldREState);
01327     Error::ClearError();
01328 
01329     return Found;
01330 #endif
01331 }
01332 
01333 /***********************************************************************************************
01334 
01335 >   static INT32 SGLibOil::FileSize(PathName *FileName)
01336 
01337     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01338     Created:    28/3/95
01339     Inputs:     File - Pointer to path and filename of file
01340     Returns:    Returns true if the specified file exists
01341     Purpose:    To find out whether a file actually exists.
01342     Notes:
01343 
01344 ***********************************************************************************************/
01345 
01346 INT32 SGLibOil::FileSize(PathName *FileName)
01347 {
01348     PORTNOTETRACE("dialog","SGLibOil::FileSize - do nothing");
01349 #ifndef EXCLUDE_FROM_XARALX
01350     ERROR3IF(FileName == NULL, "SGLibOil::FileSize Filename should not be null");
01351     ERROR3IF(!FileName->IsValid(), "SGLibOil::FileSize given invalid path");
01352 
01353     INT32 FileSize = 0;
01354 
01355     // Unfortunately MFC seems to have a nasty bug which is less than useful
01356     // WRT reading file sizes of old files... We resort to good old c.
01357     FILE *FP = NULL;
01358     FP = _tfopen((const TCHAR *)FileName->GetPath(), "rb");
01359     if(FP != NULL)
01360     {
01361         fseek(FP,0,SEEK_END);
01362         FileSize = ftell(FP);
01363         fclose(FP);
01364     }
01365 
01366     return FileSize;
01367 #else   
01368     return 1;
01369 #endif
01370 }
01371 
01372 /***********************************************************************************************
01373 
01374 >   static BOOL SGLibOil::FileDelete(PathName *FileName)
01375 
01376     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01377     Created:    29/3/95
01378     Inputs:     File - Pointer to path and filename of file
01379     Returns:    Returns true if the specified file was deleted ok
01380     Purpose:    Delete a file - scarry !
01381     Notes:
01382 
01383 ***********************************************************************************************/
01384 
01385 BOOL SGLibOil::FileDelete(PathName *FileName)
01386 {
01387     PORTNOTETRACE("dialog","SGLibOil::FileDelete - do nothing");
01388 #ifndef EXCLUDE_FROM_XARALX
01389     ERROR3IF(FileName == NULL || !FileName->IsValid(), "SGLibOil::FileDelete given a dodgy FileName");
01390 
01391     // Check if it exists, if so, kill it...
01392     if( _taccess( (const TCHAR *)FileName->GetPath(), ios::in ) == 0 )
01393     {
01394 //      RemoveFile((TCHAR *)FileName->GetPath(), cmoVital | cmoForce);
01395         if(_tremove((const TCHAR *)FileName->GetPath()) == 0)
01396             return TRUE;
01397     }
01398 #endif
01399     return FALSE;
01400 }
01401 /***********************************************************************************************
01402 
01403 >   static UINT32 SGLibOil::FileModified(PathName *FileName);
01404 
01405     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01406     Created:    6/1/95
01407     Inputs:     FileName - Pointer to path and filename of file
01408     Returns:    Returns a numeric value relating the last time the file was modified.
01409                 Old files will always return a lesser number than new ones.
01410     Purpose:    Return numeric form of last modified time / date... for a file
01411 
01412 ***********************************************************************************************/
01413 
01414 UINT32 SGLibOil::FileModified(PathName *FileName)
01415 {
01416     PORTNOTETRACE("dialog","SGLibOil::FileModified - do nothing");
01417 #ifndef EXCLUDE_FROM_XARALX
01418     ERROR3IF(FileName == NULL, "SGLibOil::FileModified given a NULL FileName");
01419     ERROR3IF(!FileName->IsValid(), "SGLibOil::FileModified given invalid path");
01420 
01421     struct _tstat buf;
01422 
01423     INT32 Result = _tstat((const TCHAR *)FileName->GetPath(), &buf);
01424 
01425     if(Result != 0)
01426         return 0;
01427 
01428     // some files seem to have dates of -1, which is a long time in the future, or basically
01429     // random... We assume they haven't been modified recently...
01430     if(buf.st_mtime == -1)
01431         return 0;
01432 
01433     return (UINT32)buf.st_mtime;
01434 #else   
01435     return 1;
01436 #endif
01437 }
01438 
01439 /***********************************************************************************************
01440 
01441 >   static BOOL SGLibOil::LocateCDROMDrive(LibraryGallery *LG, SGLibType LibType, String_256 *DriveName,
01442                                     BOOL *OnXaraNet, String_256 *XaraMount, BOOL AdjustPressed = FALSE);
01443 
01444     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01445     Created:    6/4/95
01446     Inputs:     LG      - parent library gallery for function
01447                 LibType - the type of library we're looking for
01448                 AdjustPressed - Is 'adjust' held down ?
01449     Outputs:    DriveName will return a string such as "D:\" for the last valid CD drive it
01450                 found with any of the magic directories present.
01451 
01452                 OnXaraNet will return TRUE if we found a camelot CD mount was point
01453                 XaraMount will return the path of the dummy CD -> "g:\CD\"
01454 
01455     Returns:    Returns true if a CD Drive or Xara mount was found
01456     Purpose:    Looks for the Xara CD. At present we go through all their CDROM drives checking
01457                 for the existance of certain directories on the CDs... We also check the various
01458                 net points for the Xara CD test library...
01459 
01460     Notes:      The internal network drive matching code uses the serial number of the
01461                 drive itself. If we change the Xara CamelotCD mount point we'll need to
01462                 change the serial number stuff below...
01463 
01464 ***********************************************************************************************/
01465 
01466 BOOL SGLibOil::LocateCDROMDrive(LibraryGallery *LG, SGLibType LibType, String_256 *DriveName,
01467                                     BOOL *OnXaraNet, String_256 *XaraMount, BOOL AdjustPressed)
01468 {
01469 #if !defined(__WXMSW__)
01470     TRACE( _T("Warning - SGLibOil::FileModified called") );
01471     return FALSE;
01472 #else
01473     if(!LG || !DriveName || !OnXaraNet || !XaraMount)
01474     {
01475         ERROR3("SGLibOil::LocateCDROMDrive given null input stuff");
01476         return FALSE;
01477     }
01478 
01479     BOOL FoundCD = FALSE;
01480     BOOL FoundXara = FALSE;
01481     BOOL FoundProgramMount = FALSE;
01482 
01483     *OnXaraNet = FALSE;
01484 
01485     DWORD dwTemp;   
01486     const DWORD DriveStringBufferSize = 20480;
01487     TCHAR DriveStringBuffer[DriveStringBufferSize];
01488     TCHAR *lpszDriveStringBuffer = (TCHAR *)DriveStringBuffer;
01489     TCHAR RootPathName[] = { '?', ':', chPathSep, 0 };
01490 
01491     String_64 SlowJob(_R(IDS_LIBRARIES_FINDING_CD));
01492     BeginSlowJob(('z' - 'a'), FALSE, &SlowJob);
01493 
01494     DWORD dwDriveMask=GetLogicalDrives();
01495     DWORD dwRC=GetLogicalDriveStrings(DriveStringBufferSize, lpszDriveStringBuffer);
01496 
01497     //ERROR3IF(dwRC == 0, "SGLibOil::LocateCDROMDrive - RC == 0 (no worries, we can default to plan b !)");
01498     ERROR3IF(dwDriveMask == 0, "SGLibOil::LocateCDROMDrive - DriveMask == 0 - this means you haven't got any drives at all on your system !!!");
01499 
01500     if(dwRC == 0)
01501     {
01502         memset(DriveStringBuffer, 0, DriveStringBufferSize);
01503         INT32 i = 0;
01504         for(*RootPathName='a'; *RootPathName<='z'; (*RootPathName)++)
01505         {
01506             DriveStringBuffer[i] = *RootPathName;
01507             DriveStringBuffer[i + 1] = ':';
01508             DriveStringBuffer[i + 2] = chPathSep;
01509             DriveStringBuffer[i + 3] = 0;
01510             i += 4;             
01511         }
01512         
01513         dwRC = i;
01514         dwDriveMask = 0xffffffff;
01515     }
01516 
01517     if(dwRC != 0 && dwDriveMask != 0)
01518     {
01519         // Loop through all the drives
01520         for(*RootPathName='a'; *RootPathName<='z'; (*RootPathName)++)
01521         {
01522             if(!ContinueSlowJob(*RootPathName - 'a'))
01523             {
01524                 *RootPathName = 'z';
01525             }
01526             else
01527             {
01528                 dwTemp=dwDriveMask & 1;
01529                 dwDriveMask >>= 1;
01530                 if (dwTemp)
01531                 {
01532                     // finds out what sort of drive this is
01533                     dwRC=GetDriveType(RootPathName);
01534 
01535                     switch (dwRC)
01536                     {
01537                         case DRIVE_REMOTE:
01538 #ifdef SCANFORXARAMOUNT
01539                             {
01540                                 TRACEUSER( "Richard", wxT("The drive type for %s is remote\n"), lpszDriveStringBuffer);
01541 
01542                                 // See if we're on the Xara Net or not...
01543                                 String_256 FileSystemName;
01544                                 String_256 VolumeName;
01545                                 DWORD SerialNumber = 0;
01546                                 BOOL bRC;
01547                     
01548                                 bRC=GetVolumeInformation(RootPathName,
01549                                         (TCHAR *)VolumeName,
01550                                         255,
01551                                         &SerialNumber,
01552                                         NULL,
01553                                         NULL,
01554                                         (TCHAR *)FileSystemName,
01555                                         255);
01556                         
01557                                 if(bRC)
01558                                 {
01559                                     TRACEUSER( "Richard", wxT("%d - %s - %s\n"), SerialNumber, (TCHAR *)VolumeName, (TCHAR *)FileSystemName);                       
01560 
01561                                     BOOL FoundAPossibleMount = FALSE;
01562 
01563                                     // Programs mount
01564                                     if(    (SerialNumber    == (DWORD)0x589c1e6f)
01565                                         && (VolumeName      == (String_256)"")
01566                                         && (FileSystemName  == (String_256)"NTFS") )
01567                                     {
01568                                         FoundProgramMount = TRUE;
01569                                     }
01570 
01571                                     if(!AdjustPressed)
01572                                     {
01573                                         // \\jimpc\corelxra
01574                                         if(    (SerialNumber    == 0x6863b85e)
01575                                             && (VolumeName      == (String_256)"CORELXARA")
01576                                             && (FileSystemName  == (String_256)"CDFS") )
01577                                         {
01578                                             FoundAPossibleMount = TRUE;
01579                                         }
01580                                     }
01581 
01582                                     // \\earth\materials
01583                                     if(AdjustPressed)
01584                                     {
01585                                         if(    (SerialNumber    == 0xec29b7f6)
01586                                             && (VolumeName      == (String_256)"")
01587                                             && (FileSystemName  == (String_256)"NTFS") )
01588                                         {
01589                                             FoundAPossibleMount = TRUE;
01590                                         }
01591                                     }
01592 
01593                                     if(FoundAPossibleMount)
01594                                     {
01595                                         // OK, but are we the proper drive ?
01596                                         String_256 CDPath(lpszDriveStringBuffer);
01597                                         String_256 CheckPath(lpszDriveStringBuffer);
01598                                     
01599                                         if(AdjustPressed)
01600                                         {
01601                                             switch(LibType)
01602                                             {
01603                                                 case SGLib_ClipArt:
01604                                                 case SGLib_ClipArt_WebThemes:
01605                                                     CheckPath += TEXT("Graphics\\XaraSt~1");
01606                                                     break;
01607                                                 case SGLib_Font:
01608                                                     CheckPath += TEXT("Fonts");
01609                                                     break;
01610                                                 case SGLib_Texture:
01611                                                     CheckPath += TEXT("Graphics\\Fills");
01612                                                     break;
01613                                                 default:
01614                                                     CheckPath += TEXT("Fills\\Fabric");
01615                                                     break;
01616                                             }
01617                                         }
01618                                         else
01619                                             CheckPath += TEXT("Fills\\Fabric");
01620 
01621                                         if(_taccess((TCHAR *)CheckPath, ios::in ) == 0)
01622                                         {
01623                                             String_256 Drive(CDPath);
01624                                             SGLibOil::AppendSlashIfNotPresent(&Drive);
01625                                             *XaraMount = Drive;
01626                                             *OnXaraNet = TRUE;
01627                                             FoundXara = TRUE;
01628                                         }
01629                                     }
01630                                 }
01631                                 else
01632                                 {
01633                                     DWORD Problem = GetLastError();
01634                                     TRACEUSER( "Richard", wxT("GetVolumeInformation returned %d error"), Problem);
01635                                 }
01636                             }
01637 #endif
01638                             break;
01639 
01640                         case DRIVE_CDROM:
01641                             // Since autochangers seem to take a seemingly endless amount of time to swap through
01642                             // each disk, so I've added this check to see if we've already found the CD or not...
01643                             if(!FoundCD)
01644                             {
01645                                 String_256 CDPath(lpszDriveStringBuffer);
01646                                 String_256 LibDirName;                          
01647 PORTNOTE("dialog","Removed LibraryGallery usage")
01648 #ifndef EXCLUDE_FROM_XARALX
01649                                 LG->GetLibraryDirectoryName(&LibDirName);
01650 #endif
01651                                 CDPath += LibDirName;
01652 
01653                                 if( 0 == _taccess( (TCHAR *)CDPath, ios::in ) )
01654                                 {               
01655                                     FoundCD = TRUE;
01656                                     *DriveName = lpszDriveStringBuffer;
01657                                 }
01658 
01659                                 // Bodge for Viewer CD, which contains a hidden Fills directory
01660                                 // If this ever moves, the below code will need to be changed
01661                                 if(!FoundCD && LibType == SGLib_Texture)
01662                                 {
01663                                     CDPath = (String_256)lpszDriveStringBuffer;
01664                                     CDPath += TEXT("Clipart\\Clipart\\");
01665                                     CDPath += String_16(_R(IDS_LIBRARIES_XARAINFO_DIRNAME));
01666                                     CDPath += TEXT("\\");
01667                                     CDPath += String_16(_R(IDS_LIBRARIES_FILLS_DIRNAME));
01668                                     if(_taccess((TCHAR *)CDPath, ios::in ) == 0)
01669                                     {               
01670                                         FoundCD = TRUE;
01671                                         *DriveName = lpszDriveStringBuffer;
01672                                         *DriveName += TEXT("Clipart\\Clipart\\");
01673                                         *DriveName += String_16(_R(IDS_LIBRARIES_XARAINFO_DIRNAME));
01674                                         *DriveName += TEXT("\\");
01675                                     }                                   
01676                                 }
01677                             }
01678                             break;
01679 
01680                         case DRIVE_REMOVABLE:
01681                             TRACEUSER( "Richard", wxT("The drive type for %s is removable\n"), lpszDriveStringBuffer);
01682                             break;
01683     
01684                         case DRIVE_FIXED:
01685                             TRACEUSER( "Richard", wxT("The drive type for %s is fixed\n"), lpszDriveStringBuffer);
01686                             // Maybe we should be recursing through their hard drive looking for XaraInfo
01687                             // directories ? v2 probably...
01688                             break;
01689 
01690                         case DRIVE_RAMDISK:
01691                             TRACEUSER( "Richard", wxT("The drive type for %s is ramdisk\n"), lpszDriveStringBuffer);
01692                             break;
01693 
01694                         default:
01695                             break;
01696                     }
01697 
01698                     // Advance to next valid drive in system
01699                     lpszDriveStringBuffer = lpszDriveStringBuffer + camStrlen(lpszDriveStringBuffer) + 1;
01700                 }
01701             }
01702         }
01703     }
01704 
01705     EndSlowJob();
01706 
01707 #ifdef _DEBUG
01708     if(!FoundCD && !FoundXara && FoundProgramMount)
01709     {
01710         String_256 XaraMsg;
01711         XaraMsg = "You're connected to the Xara Net, but not the CamelotCD mount, so can't 'find' the library. ";
01712         ERROR3(XaraMsg);
01713     }
01714 #endif
01715 
01716     return (FoundCD || FoundXara);
01717 #endif
01718 }
01719 
01720 /***********************************************************************************************
01721 
01722 >   UINT32 CALLBACK SGLibOil::FileHook(HWND hDlg, UINT32 Msg, UINT32 wParam, INT32 lParam)
01723 
01724     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01725     Created:    2/4/95
01726 
01727     Inputs:     hDlg - HWND of the dialog box.
01728                 iMsg - UINT32 message number.
01729                 wParam - UINT32 parameter.
01730                 lParam - INT32 parameter.
01731  
01732     Returns:    Non-Zero or Zero, indicating if the common dialog should
01733                 SKIP the message (non-zero) or not (zero).  Don't confuse
01734                 with typical dialog box return values.
01735  
01736     Purpose:    Processes messages from the common File Open dialog.
01737                 Used to kill the get path dbox when OK is clicked.                  
01738                 Used for handling 'Generate' clicks.
01739     Notes:      
01740 
01741 ***********************************************************************************************/
01742 
01743 UINT32 CALLBACK SGLibOil::FileHook( wxWindow *pDlg, UINT32 Msg, UINT32 wParam, INT32 lParam )
01744 {
01745     PORTNOTETRACE("dialog","SGLibOil::FileHook - do nothing - window CB");
01746 #ifndef EXCLUDE_FROM_XARALX
01747     switch(Msg)
01748     {
01749         case WM_INITDIALOG:
01750             {           
01751 #ifdef STANDALONE
01752             // Remove the Help button on standalone builds...
01753             HWND hGadget = GetDlgItem((HWND)hDlg, (INT32)_R(IDC_LIBPATH_HELP_BUTTON));
01754             ShowWindow(hGadget, SW_HIDE);
01755 #endif
01756         
01757             // We need to apply the correct font if we are in DBCS land
01758             if (UnicodeManager::IsDBCSOS())
01759                 FontFactory::ApplyFontToWindow(hDlg, STOCKFONT_DIALOG);
01760             }
01761             return TRUE;
01762 
01763         case WM_COMMAND:
01764 
01765             switch(wParam)
01766             {
01767                 case _R(IDC_LIBPATH_HELP_BUTTON):
01768                     // Special check for the help button, and a bodgy way of invoking help for
01769                     // this dialog, which is a generic CFileDialog type with a custom template,
01770                     // and thus has no unique class-name.
01771                     _HelpUser(TEXT("SGalleryAddFolderDlg"));
01772                     return TRUE;
01773 
01774                 case IDOK:
01775                     // Close the dbox when Add pressed
01776                     PostMessage(GetParent(hDlg), WM_COMMAND, IDOK, (INT32)FALSE);
01777                     return FALSE;
01778 
01779                 case _R(IDC_LIBPATH_GENERATE):
01780                     // Since there's no way of getting the full pathname here, we simulate
01781                     // a click on 'OK' to close the dbox, and set a flag saying we've clicked
01782                     // 'Generate' instead, so the code after the DoModal can get the proper
01783                     // path, generate the index, and re-open the dbox. Talk about a bodge !         
01784                     SGLibOil::GenerateButtonClicked = TRUE;
01785                     PostMessage(hDlg, WM_COMMAND, IDOK, (INT32)FALSE);
01786                     return FALSE;
01787 
01788                 case _R(IDC_LIBPATH_SEARCH):
01789                     // Scan (Search) for some clipart
01790                     {
01791                         if(!SGLibOil::ParentLibraryGallery->ScanForLocation(SGLibOil::LibType,
01792                                                                             &SGLibOil::SearchDirectory))
01793                         {
01794                             // Keep the dialog open - don't change the path
01795                             INT32 ButtonPressed = InformWarning(_R(IDS_LIBRARY_BROWSING_CANT_FIND_LIBRARY), _R(IDS_OK));
01796                             Error::ClearError();
01797                             return FALSE;
01798                         }
01799 
01800                         DirPath Path(SGLibOil::SearchDirectory);
01801                         if(!Path.IsValid())
01802                         {
01803                             ERROR3("Scanned to path is invalid");
01804                             // Keep the dialog open - don't change the path
01805                             return FALSE;
01806                         }
01807 
01808                         // Remember the pathname and which button was clicked so we can update the dialog
01809                         SGLibOil::SearchButtonClicked = TRUE;
01810 
01811                         PostMessage(hDlg, WM_COMMAND, IDOK, (INT32)FALSE);
01812                         return FALSE;
01813                     }
01814 
01815                 default:
01816                     break;
01817             }
01818             break;
01819 
01820         default:
01821             return FALSE;
01822     }
01823 #endif
01824     return FALSE;
01825 }
01826 
01827 /***********************************************************************************************
01828 
01829 >   UINT32 CALLBACK SGLibOil::ExplorerFileHook(HWND hDlg, UINT32 Msg, UINT32 wParam, INT32 lParam)
01830 
01831     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01832     Created:    8/2/96
01833 
01834     Inputs:     hDlg - HWND of the dialog box.
01835                 iMsg - UINT32 message number.
01836                 wParam - UINT32 parameter.
01837                 lParam - INT32 parameter.
01838  
01839     Returns:    Non-Zero or Zero, indicating if the common dialog should
01840                 SKIP the message (non-zero) or not (zero).  Don't confuse
01841                 with typical dialog box return values.
01842  
01843     Purpose:    Processes messages from the Explorer version of the common File Open dialog.
01844                 Used to kill the get path dbox when OK is clicked, handling 'Generate' clicks,
01845                 and re-arranging the window's items...
01846 
01847 ***********************************************************************************************/
01848 
01849 #if _MFC_VER >= 0x400 
01850 UINT32 CALLBACK SGLibOil::ExplorerFileHook(HWND hDlg, UINT32 Msg, UINT32 wParam, INT32 lParam)
01851 {
01852 //  ERROR3("ExplorerFileHook called");
01853     static char szstr2[256];
01854 
01855     switch(Msg)
01856     {
01857         case WM_INITDIALOG:
01858         {           
01859 #ifdef STANDALONE
01860             // Remove the Help button on standalone builds...
01861             HWND hGadget = GetDlgItem((HWND)hDlg, (INT32)_R(IDC_LIBPATH_HELP_BUTTON));
01862             ShowWindow(hGadget, SW_HIDE);
01863 #endif
01864             CommDlg_OpenSave_HideControl(GetParent(hDlg), edt1); // name of current file
01865             CommDlg_OpenSave_HideControl(GetParent(hDlg), stc3); // label for edt1
01866             CommDlg_OpenSave_HideControl(GetParent(hDlg), cmb1); // file-types combo
01867             CommDlg_OpenSave_HideControl(GetParent(hDlg), stc2); // label for cmb1
01868             CommDlg_OpenSave_HideControl(GetParent(hDlg), chx1); // read-only checkbox
01869 
01870             CommDlg_OpenSave_HideControl(GetParent(hDlg), IDOK);
01871             CommDlg_OpenSave_HideControl(GetParent(hDlg), IDCANCEL);
01872 
01873             // drop down at top...
01874             //CommDlg_OpenSave_HideControl(GetParent(hDlg), cmb2);
01875             //HWND hGadget2 = GetDlgItem((HWND)GetParent(hDlg), (INT32)cmb2);
01876             //::MoveWindow(hGadget2, 6, 32+20, 90+50, 68, TRUE);
01877 
01878             CommDlg_OpenSave_HideControl(hDlg, _R(IDC_LIBPATH_ISLIBRARY));
01879             HWND hGadget2 = GetDlgItem((HWND)hDlg, (INT32)_R(IDC_LIBPATH_ISLIBRARY));
01880             ::MoveWindow(hGadget2, 212, 113+200, 200, 12, TRUE);
01881 
01882             // We need to apply the correct font if we are in DBCS land
01883             if (UnicodeManager::IsDBCSOS())
01884                 FontFactory::ApplyFontToWindow(hDlg, STOCKFONT_DIALOG);
01885 
01886             return TRUE;
01887         }
01888 
01889         case WM_NOTIFY:
01890             return ExplorerFileHookNotify(hDlg, (LPOFNOTIFY)lParam);
01891 
01892         case WM_COMMAND:
01893 
01894             switch(wParam)
01895             {
01896                 case _R(IDC_LIBPATH_HELP_BUTTON):
01897                     //ERROR3("CC Help button pressed");
01898                     // Special check for the help button, and a bodgy way of invoking help for
01899                     // this dialog, which is a generic CFileDialog type with a custom template,
01900                     // and thus has no unique class-name.
01901                     _HelpUser(TEXT("SGalleryAddFolderDlg"));
01902                     break;
01903 
01904                 case IDOK:
01905                 {
01906                     // Close the dbox when OK pressed
01907                     String_256 TmpPath;
01908                     INT32 Length = 0;
01909                     Length = CommDlg_OpenSave_GetFolderPath((HWND)GetParent(hDlg), (TCHAR *)TmpPath, 255);
01910                     if(Length > 0)
01911                     {
01912                         SGLibOil::BrowsePath = TmpPath;
01913                         ((TCHAR *)SGLibOil::BrowsePath)[Length] = (TCHAR)'\0x00';
01914                     }
01915 
01916                     PostMessage((HWND)GetParent(hDlg), WM_COMMAND, IDCANCEL, (INT32)FALSE);
01917                     break;
01918                 }
01919 
01920                 case IDCANCEL:
01921                     // Close the dbox when Cancel pressed
01922                     SGLibOil::BrowsePath = "";
01923                     PostMessage((HWND)GetParent(hDlg), WM_COMMAND, IDCANCEL, (INT32)FALSE);
01924                     break;
01925 
01926                 case _R(IDC_LIBPATH_GENERATE):
01927                 {
01928                     // Generate clicked, close the window, then re-open it later on...
01929                     SGLibOil::GenerateButtonClicked = TRUE;
01930                     String_256 TmpPath;
01931 
01932                     INT32 Length = 0;
01933                     Length = CommDlg_OpenSave_GetFolderPath((HWND)GetParent(hDlg), (TCHAR *)TmpPath, 255);
01934                     if(Length > 0)
01935                     {
01936                         SGLibOil::BrowsePath = TmpPath;
01937                         ((TCHAR *)SGLibOil::BrowsePath)[Length] = (TCHAR)'\0x00';
01938                     }
01939 
01940                     PostMessage((HWND)GetParent(hDlg), WM_COMMAND, IDCANCEL, (INT32)FALSE);
01941                     break;
01942                 }
01943 
01944                 case _R(IDC_LIBPATH_SEARCH):
01945                 {
01946                     // Scan (Search) for some clipart
01947     
01948                     if(!SGLibOil::ParentLibraryGallery->ScanForLocation(SGLibOil::LibType,
01949                                                                         &SGLibOil::SearchDirectory))
01950                     {
01951                         INT32 ButtonPressed = InformWarning(_R(IDS_LIBRARY_BROWSING_CANT_FIND_LIBRARY), _R(IDS_OK));
01952                         Error::ClearError();
01953                         return FALSE;
01954                     }
01955 
01956                     DirPath Path(SGLibOil::SearchDirectory);
01957                     if(!Path.IsValid())
01958                     {
01959                         ERROR3("Scanned to path is invalid");
01960                         // Keep the dialog open - don't change the path
01961                         return FALSE;
01962                     }
01963 
01964                     // Remember the pathname and which button was clicked so we can update the dialog
01965                     SGLibOil::SearchButtonClicked = TRUE;
01966 
01967                     PostMessage((HWND)GetParent(hDlg), WM_COMMAND, IDCANCEL, (INT32)FALSE);
01968                     return FALSE;
01969                 }
01970 
01971                 default:
01972                     break;
01973             }
01974             break;
01975 
01976         case WM_HELP:
01977             ERROR3("Context sensitive help clicked...");
01978             break;
01979 
01980         default:
01981             return FALSE;
01982     }
01983 
01984     return FALSE;
01985 }
01986 
01987 
01988 /***********************************************************************************************
01989 
01990 >   static BOOL SGLibOil::ExplorerFileHookNotify(HWND hDlg, LPOFNOTIFY pofn)
01991 
01992     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
01993     Created:    9/2/96
01994 
01995     Inputs:     hDlg - HWND of the dialog box.
01996                 pofn - pointer to notify structure
01997  
01998     Returns:    TRUE if ok...
01999  
02000     Purpose:    WM_NOTIFY is sent to the explorer hook - decode the various notify messages...
02001                 Only really used to keep the path field up to date and check for indexes when
02002                 changing folder...
02003 
02004 ***********************************************************************************************/
02005 
02006 BOOL SGLibOil::ExplorerFileHookNotify(HWND hDlg, LPOFNOTIFY pofn)
02007 {
02008     switch(pofn->hdr.code)
02009     {
02010         // The current selection has changed.
02011         case CDN_SELCHANGE:
02012             break;
02013 
02014         case CDN_FOLDERCHANGE:  // The current folder has changed.
02015         case CDN_INITDONE:      // or initialisation has finished
02016         {
02017             String_256 TmpPath;
02018             INT32 Length = 0;
02019             Length = CommDlg_OpenSave_GetFolderPath((HWND)GetParent(hDlg), (TCHAR *)TmpPath, 255);
02020             if(Length > 0)
02021             {
02022                 SGLibOil::BrowsePath = TmpPath;
02023                 
02024                 for(INT32 i=(Length-1); i<=255; i++)
02025                     ((TCHAR *)SGLibOil::BrowsePath)[i] = (TCHAR)0;
02026 
02027                 // Seems to be problems with this bit of code - the control gets random pants
02028                 // stuck at the end of the pathname randomly. Removing the truncated path stuff
02029                 // fixes it...
02030                 /*PathName BPath(SGLibOil::BrowsePath);
02031                 String_256 TruncatedPath;
02032                 TruncatedPath = BPath.GetTruncatedPath(100);
02033                 SetDlgItemText(hDlg, _R(IDC_LIBPATH_PATHNAME), (TCHAR *)TruncatedPath);*/
02034                 SetDlgItemText(hDlg, _R(IDC_LIBPATH_PATHNAME), (TCHAR *)BrowsePath);
02035 
02036                 if(SGLibOil::CheckForIndex(&SGLibOil::BrowsePath, SGLibOil::ParentLibraryGallery))
02037                     SetDlgItemText(hDlg, _R(IDC_LIBPATH_ISLIBRARY), (TCHAR *)String_256(_R(IDS_LIBPATH_INDEX_EXISTS)));
02038                 else
02039                     SetDlgItemText(hDlg, _R(IDC_LIBPATH_ISLIBRARY), (TCHAR *)String_256(_R(IDS_LIBPATH_INDEX_DOESNT_EXIST)));
02040             }
02041             break;
02042         }
02043 
02044         // The Help button has been clicked - this shouldn't happen because we've disabled the default
02045         // help button...
02046         case CDN_HELP:
02047             break;
02048 
02049         // The OK button has been clicked, er, but hang on, we haven't got an OK
02050         // button, so this should never get called !
02051         case CDN_FILEOK:
02052             break;
02053 
02054         // Received a sharing violation
02055         case CDN_SHAREVIOLATION:
02056             ERROR3("SGLibOil::ExplorerFileHookNotify got a share violation");
02057             break;
02058 
02059         // Received when the file type changes in the Files Of Type box
02060         case CDN_TYPECHANGE:
02061             break;
02062 
02063         // oops, we've missed one...
02064         default:
02065             break;
02066     }
02067 
02068     return TRUE;
02069 }
02070 
02071 /***********************************************************************************************
02072 
02073 >   static BOOL SGLibOil::CheckForIndex(String_256 *Path, LibraryGallery *ParentGallery)
02074 
02075     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02076     Created:    14/2/96
02077 
02078     Inputs:     Path            - Path to start looking from
02079                 ParentGallery   - Library gallery for the index we're interested in
02080 
02081     Returns:    TRUE if we find an index of the desired type in the given path, or the XaraInfo
02082                 subdirectory of the given path
02083 
02084     Purpose:    Check if an index exists in the given path...
02085 
02086     Notes:      We return TRUE if an index.txt is found as well as the normal XaraClip.txt, or
02087                 whatever. In an ideal world we should scan the index.txt for references to
02088                 indexes of the desired type... Perhaps we do, and I've not updated this comment...
02089 
02090 ***********************************************************************************************/
02091 
02092 BOOL SGLibOil::CheckForIndex(String_256 *Path, LibraryGallery *ParentGallery)
02093 {
02094     ERROR3IF(Path == NULL || ParentGallery == NULL, "SGLibOil::CheckForIndex given NULLs");
02095     
02096     String_256 OurPath(*Path);
02097     if(LibraryFile::TidyUpSubPath(&OurPath))
02098     {
02099         // Add a trailing backslash if there isn't one
02100         SGLibOil::AppendSlashIfNotPresent(&OurPath);
02101 
02102         OurPath += String_16(_R(IDS_LIBRARIES_XARAINFO_DIRNAME));
02103 
02104         PathName Index;
02105         String_256 IndexPath;
02106         
02107         // Check for the default index for this directory
02108         String_256 DefIndex;
02109         ParentGallery->GetDefaults(&DefIndex, NULL, NULL);
02110 
02111         IndexPath = OurPath;
02112         SGLibOil::AppendSlashIfNotPresent(&OurPath);
02113         IndexPath += DefIndex;
02114 
02115         Index.SetPathName(IndexPath);
02116         Error::ClearError();
02117         if(FileExists(&Index))
02118             return TRUE;
02119         
02120         // Check for the global index.txt file
02121         IndexPath = OurPath;
02122         SGLibOil::AppendSlashIfNotPresent(&IndexPath);
02123         IndexPath += String_256(_R(IDS_LIBRARIES_INDEX_FILENAME));
02124 
02125         Index.SetPathName(IndexPath);
02126         Error::ClearError();
02127         if(FileExists(&Index))
02128             return TRUE;
02129     }
02130 
02131     Error::ClearError();
02132     return FALSE;
02133 }
02134                     
02135 /***********************************************************************************************
02136 
02137 >   static BOOL SGLibOil::GenerateClicked(LibraryGallery *LG, PathName *GenDirectory)
02138 
02139     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02140     Created:    19/4/95
02141 
02142     Inputs:     LG      - required so we have access to the parent gallery's default indexey
02143                           values and stuff...
02144                 GenDirectory - contains a pathname for the location of the index file to
02145                           generate. We strip the filename bit off, but it should have a
02146                           filename anyhow...
02147     Returns:    TRUE if we generated an index ok
02148 
02149     Purpose:    Generate an index file in a given directory, go through all the various
02150                 checks with the user, etc. This function is intended to be called after a
02151                 click on the 'Generate' button in the browse dbox.
02152     Notes:      
02153 
02154 ***********************************************************************************************/
02155 
02156 BOOL SGLibOil::GenerateClicked(LibraryGallery *LG, PathName *GenDirectory)
02157 {
02158     if(GenDirectory == NULL || LG == NULL)
02159     {
02160         ERROR3("GenerateClicked given a null params");
02161         return FALSE;
02162     }
02163     
02164     if(!GenDirectory->IsValid())
02165     {
02166         ERROR3("GenerateClicked given an invalid path");
02167         return FALSE;
02168     }
02169 
02170     String_256 OurDirectory = GenDirectory->GetLocation();
02171 //  OurDirectory = DialogManager::GetStringGadgetValue(hDlg, stc1, NULL);
02172 
02173     if(OurDirectory.Sub((String_8)"...") != -1)
02174     {
02175         ERROR3("Sorry, pathname has been truncated, can't generate index");
02176         return FALSE;
02177     }
02178     else
02179     {
02180         if(OurDirectory.Length() > 1)
02181         {
02182             // Remove the xarainfo and trailing \'s if there are any
02183             LibraryFile::TidyUpSubPath(&OurDirectory);
02184 
02185             DirPath SubLibraryPath(OurDirectory);           
02186 
02187             // Bodge for A:, B:, etc...
02188 /*          BOOL RootDir = FALSE;
02189             if(OurDirectory.Length() == 2)
02190             {
02191                 RootDir = TRUE;
02192                 Error::ClearError();
02193             }*/
02194 
02195             if(SubLibraryPath.IsValid()/* || RootDir*/)
02196             {
02197                 // Get pathname of default sublib index and find out whether we can generate indexes, etc
02198                 String_256 IndexName;
02199                 String_256 IndexDesc;
02200                 BOOL CanGenerate = LG->CanCreateIndexes();      
02201 
02202                 if(LG->GetDefaults(&IndexName, &IndexDesc, NULL))
02203                 {
02204                     if(CanGenerate)
02205                     {
02206                         String_256 FullIndexPathStr(OurDirectory);
02207                         SGLibOil::AppendSlashIfNotPresent(&FullIndexPathStr);
02208                         FullIndexPathStr += String_16(_R(IDS_LIBRARIES_XARAINFO_DIRNAME));
02209                         FullIndexPathStr += TEXT("\\") + IndexName;
02210                         PathName FullIndexPath(FullIndexPathStr);
02211                         if(FullIndexPath.IsValid())
02212                         {
02213                             INT32 ButtonPressed = 0;
02214                             BOOL DoThumbnails = TRUE;
02215 
02216                             #if 0
02217                             if(SGLibOil::FileExists(&FullIndexPath))
02218                             {
02219                                 // Warn about existing index file
02220                                 ButtonPressed = InformWarning(_R(IDS_LIBRARY_OVERWRITE_INDEX_FILE), _R(IDS_GENERATE), _R(IDS_CANCEL));
02221                                 Error::ClearError();
02222                                 if(ButtonPressed == 2)
02223                                     return FALSE;
02224                             }
02225                             #endif
02226 
02227                             #if 0
02228                             // Ask if they want thumbnails or not
02229                             ButtonPressed = InformWarning(_R(IDS_WITH_THUMBNAILS_OR_NOT), _R(IDS_THUMBNAILS), _R(IDS_NOTHUMBNAILS), _R(IDS_CANCEL)/*, _R(IDS_HELP)*/);
02230                             Error::ClearError();
02231                             if(ButtonPressed > 2)
02232                                 return FALSE;
02233                             DoThumbnails = (ButtonPressed == 1);
02234                             #endif
02235                             
02236                             if(SGLibOil::FileExists(&FullIndexPath) && GenerateIndexFile::IsDirectoryReadOnly(&SubLibraryPath))
02237                             {
02238                                 // "Cannot update chosen folder because it is read only and already has an index."
02239                                 InformMessage(_R(IDS_LIBRARY_UPDATE_RO_WITH_INDEX), _R(IDS_CANCEL));
02240                                 Error::ClearError();
02241                                 return FALSE;
02242                             }
02243 
02244                             // Check they really want to generate the index - warn about disk usage
02245                             ButtonPressed = InformWarning(_R(IDS_LIBRARY_CHECK_INDEX_CREATE), _R(IDS_CREATE), _R(IDS_CANCEL)/*, _R(IDS_HELP)*/);
02246                             Error::ClearError();
02247                             if(ButtonPressed > 1)
02248                                 return FALSE;
02249                             DoThumbnails = TRUE;
02250 
02251                             // Generate an index...
02252                             String_64 Author("");
02253                             
02254                             BOOL ok = LibraryFile::GenerateDefaultIndex(&FullIndexPath, &SubLibraryPath, &Author, LibType, DoThumbnails);
02255                             if(FullIndexPathStr != FullIndexPath.GetPath())
02256                             {
02257                                 // The index location has changed - remote index...
02258                                 *GenDirectory = FullIndexPath.GetLocation(FALSE);
02259                                 SGLibOil::BrowsePath = GenDirectory->GetPath();
02260                             }
02261                             return ok;
02262                         }
02263                     }
02264                     else
02265                     {
02266                         ERROR3("You can't generate an index file for this type of library");
02267                     }
02268                 }
02269             }
02270             else
02271             {
02272                 ERROR3("Invalid pathname...");
02273             }
02274         }
02275     }
02276     return FALSE;
02277 }
02278 
02279 
02280 /**********************************************************************************************/
02281 
02282 // Static required for hook function
02283 SGLibType SGLibOil::LibType = SGLib_Blank;
02284 LibraryGallery *SGLibOil::ParentLibraryGallery = NULL;
02285 
02286 // Static containing the full path given by browsing
02287 String_256 SGLibOil::BrowsePath = "";
02288 
02289 // TRUE if the generate button was clicked in the browse dbox
02290 BOOL SGLibOil::GenerateButtonClicked = FALSE;
02291 
02292 // TRUE if the search button was clicked in the browse dbox
02293 BOOL SGLibOil::SearchButtonClicked = FALSE;
02294 
02295 // Directory located by the Search code
02296 String_256 SGLibOil::SearchDirectory = "";
02297 
02298 // Should we be using the explorer dialog ?
02299 BOOL SGLibOil::UseExplorerForAdd = FALSE;
02300 
02301 /***********************************************************************************************
02302 
02303 >   static BOOL SGLibOil::GetLibPath(LibraryGallery *LG, PathName *Path, BOOL CanGenerate,
02304                                                             SGLibType Type, BOOL *Updated = NULL)
02305     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02306     Created:    2/4/95
02307 
02308     Inputs:     LG - LibraryGallery for gallery which we're GetLibPath'ing...
02309                 Path points to the default path to start the dbox off with
02310                 CanGenerate should be TRUE if the dialog is to have a generate button
02311                 Type of library we're browsing for (used by generate if the button is hit)
02312     Outputs:    Path is updated with the resulting library path
02313                 Updated - if not null, returns true or false if the added item was updated or not...
02314     Returns:    TRUE if the outputpath has valid index file in XaraInfo on return
02315 
02316     Purpose:    Locate a library index by popping up a patched file open dialog and
02317                 letting the user scan through their directory tree. Also give them the
02318                 option to generate an index if none exists for the selected directory.
02319     Notes:      
02320 
02321 ***********************************************************************************************/
02322 
02323 BOOL SGLibOil::GetLibPath(LibraryGallery *LG, PathName *ThePath, BOOL CanGenerate, SGLibType Type,
02324                                                                                     BOOL *Updated)
02325 {
02326     if(ThePath == NULL || LG == NULL)
02327     {
02328         ERROR3("SGLibOil::GetLibPath given null params");
02329         return FALSE;
02330     }
02331 
02332     // Which window style should we use ?
02333     BOOL Explorer = FALSE;
02334 #if _MFC_VER >= 0x400 
02335 /*  if(IsWindows95() && SGLibOil::UseExplorerForAdd)
02336         Explorer = TRUE;*/
02337     if(CCamApp::IsNewWindowsUI())
02338         Explorer = TRUE;
02339 #endif
02340     
02341     if(Updated) *Updated = FALSE;
02342 
02343     SGLibOil::LibType = Type;
02344     SGLibOil::ParentLibraryGallery = LG;
02345 
02346     TCHAR Filter[] = "Library directories|TheIndex|||";   // This is never displayed
02347         
02348     DWORD CFileFlags = OFN_HIDEREADONLY | OFN_NOTESTFILECREATE |
02349                        OFN_ENABLEHOOK   | OFN_ENABLETEMPLATE;
02350 #if _MFC_VER >= 0x400 
02351     if(Explorer)
02352         CFileFlags |= OFN_EXPLORER;
02353 #endif
02354     
02355     CFileDialog BrowseFileDialog(TRUE,
02356                                  NULL,
02357                                  (const TCHAR *)ThePath->GetPath(),
02358                                  CFileFlags,
02359                                  (TCHAR *)Filter,
02360                                  NULL);
02361     
02362     String_256 InitialPath(ThePath->GetPath(TRUE));
02363 
02364     // This will contain the chosen path on return (provided they don't hit cancel)
02365     SGLibOil::BrowsePath = "";
02366 
02367     String_256 ExplorerBrowsePath;
02368 
02369     BrowseFileDialog.m_ofn.lStructSize = sizeof(OPENFILENAME);
02370     BrowseFileDialog.m_ofn.hwndOwner = NULL;
02371     BrowseFileDialog.m_ofn.hInstance = AfxGetResourceHandle();
02372     if(Explorer)
02373         BrowseFileDialog.m_ofn.lpstrFile = (TCHAR *)ExplorerBrowsePath;
02374     else
02375         BrowseFileDialog.m_ofn.lpstrFile = (TCHAR *)SGLibOil::BrowsePath;
02376 
02377     BrowseFileDialog.m_ofn.nMaxFile = 255;
02378     BrowseFileDialog.m_ofn.lpstrInitialDir = (TCHAR *)InitialPath;
02379     BrowseFileDialog.m_ofn.Flags = CFileFlags;
02380 
02381     String_64 DlgTitle(_R(IDS_LIBPATHDLG)/*Add new folder*/);
02382     BrowseFileDialog.m_ofn.lpstrTitle = (TCHAR *)DlgTitle;
02383 
02384     // Select our dialog template depending on the user's UI
02385 #if _MFC_VER >= 0x400 
02386     if(Explorer)
02387     {
02388         BrowseFileDialog.m_ofn.lpfnHook = (LPOFNHOOKPROC)SGLibOil::ExplorerFileHook;
02389         if(CanGenerate)
02390             BrowseFileDialog.m_ofn.lpTemplateName = MAKEINTRESOURCE(_R(IDD_LIBPATHGENDLG95));
02391         else
02392             BrowseFileDialog.m_ofn.lpTemplateName = MAKEINTRESOURCE(_R(IDD_LIBPATHDLG95));
02393     }
02394     else
02395 #endif
02396     {
02397         BrowseFileDialog.m_ofn.lpfnHook = (LPOFNHOOKPROC)SGLibOil::FileHook;
02398         if(CanGenerate)
02399             BrowseFileDialog.m_ofn.lpTemplateName = MAKEINTRESOURCE(_R(IDD_LIBPATHGENDLG));
02400         else
02401             BrowseFileDialog.m_ofn.lpTemplateName = MAKEINTRESOURCE(_R(IDD_LIBPATHDLG));
02402     }
02403 
02404     GenerateButtonClicked = FALSE;
02405     SearchButtonClicked = FALSE;
02406 
02407     // Keep popping the dbox up if generate is clicked
02408     BOOL Again = TRUE;
02409     while(Again)
02410     {
02411         // Keep Control Helper system informed
02412         ControlHelper::InformModalDialogOpened();
02413         
02414         INT32 Result = BrowseFileDialog.DoModal();
02415 
02416 //      ERROR3_PF(("Before... Path: %s", (TCHAR *)SGLibOil::BrowsePath));
02417 
02418         if(Explorer)
02419         {
02420             // This will be empty if cancel was pressed
02421             if(SGLibOil::BrowsePath.Length() > 0)
02422             {
02423                 // Add a trailing slash if it hasn't got one (usually, roots have 'em, but sub-dirs don't)
02424                 SGLibOil::AppendSlashIfNotPresent(&SGLibOil::BrowsePath);
02425 
02426                 SGLibOil::BrowsePath += TEXT("fish.wib"); // Required for later pathname nastyness, never displayed
02427             }
02428         }
02429 
02430 //      ERROR3_PF(("After... Path: %s, Result: %d", (TCHAR *)SGLibOil::BrowsePath, Result));
02431 
02432         // Keep Control Helper system informed
02433         ControlHelper::InformModalDialogClosed();               
02434 
02435         // Check that we have floating point exception handler in place
02436         // as we have just used a common dialog box and under win32s this might
02437         // have reset the floating point exception handler.
02438 PORTNOTE("dialog","Removed FixFPControlRegister usage - is it needed anymore?")
02439 #ifndef EXCLUDE_FROM_XARALX
02440         FixFPControlRegister();
02441 #endif
02442         
02443         // Close the browse box next time
02444         Again = FALSE;
02445 
02446         // The search / scan button in the dialog was clicked, SGLibOil::SearchDirectory contains
02447         // the location...
02448         if(SearchButtonClicked)
02449         {
02450             // We can't simply tell the dialog to change it's location whilst open, we have to
02451             // close it and reopen it - like the generate situation...
02452             SearchButtonClicked = FALSE;
02453 
02454             // Reopen the browse dbox
02455             Again = TRUE;       
02456 
02457             // Update the default path to be the one just selected
02458             BrowseFileDialog.m_ofn.lpstrInitialDir = SGLibOil::SearchDirectory;
02459         }
02460 
02461 
02462         // The generate button in the browse dialog was clicked... SGLibOil::BrowsePath contains
02463         // the currently selected path to generate an index for
02464         if(GenerateButtonClicked)
02465         {
02466             // Since the only way to return the full path is by a click on OK, we simulate
02467             // an OK click but flag a generate click as 
02468             GenerateButtonClicked = FALSE;
02469             PathName GenPath(SGLibOil::BrowsePath);
02470 
02471             if(GenPath.IsValid())
02472             {
02473                 // If there was a problem with the index file - non created, etc, reopen the browse dbox...
02474                 if(!GenerateClicked(LG, &GenPath))
02475                 {
02476                     // Reopen the browse dbox
02477                     Again = TRUE;
02478 
02479                     // Update the default path to be the one just selected
02480                     BrowseFileDialog.m_ofn.lpstrInitialDir = SGLibOil::BrowsePath;              
02481                 }
02482                 else
02483                 {
02484                     if(Updated) *Updated = TRUE;
02485                 }
02486             }
02487             else
02488             {
02489                 Error::ClearError();
02490                 Again = TRUE;
02491             }
02492         }
02493 
02494         if(Again)
02495         {
02496             // Clear the internal path so cancel works properly
02497             SGLibOil::BrowsePath = "";
02498 
02499             if(!(Explorer && SearchButtonClicked))
02500                 BrowseFileDialog.m_ofn.lpstrFile = (TCHAR *)SGLibOil::BrowsePath;
02501         }
02502     }
02503 
02504     if(SGLibOil::BrowsePath == (String_256)"")
02505     {
02506         Error::ClearError();
02507         return FALSE;
02508     }
02509     else
02510     {
02511         PathName Ret(SGLibOil::BrowsePath);
02512         if(Ret.IsValid())
02513         {
02514             // Normally we don't want the trailing backslash, if the path is invalid without
02515             // it then we do want it... ("C:" or "C:\")
02516             String_256 Location = Ret.GetLocation(FALSE);
02517             if(IsRootDirectory(&Location))
02518                 Location = Ret.GetLocation(TRUE);
02519 
02520             PathName PathForReturn(Location);
02521             *ThePath = PathForReturn;
02522         }
02523         else
02524         {
02525             ERROR3("SGLibOil::GetLibPath !Ret.IsValid()");
02526             Error::ClearError();    
02527             return FALSE;
02528         }
02529     }
02530 
02531     Error::ClearError();
02532 
02533 //  ERROR3_PF(("GetLibPath BrowsePath '%s'", (TCHAR *)SGLibOil::BrowsePath));
02534 //  String_256 RetPath(ThePath->GetPath());
02535 //  ERROR3_PF(("GetLibPath returning '%s'", (TCHAR *)RetPath));
02536 
02537     return TRUE;
02538 }
02539 
02540 #endif
02541 
02542 
02543 /***********************************************************************************************
02544 
02545 >   static BOOL SGLibOil::MakeSound(PathName *WaveFile)
02546 
02547     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02548     Created:    2/1/96
02549 
02550     Inputs:     WaveFile    - Full filename of .wav file
02551     Outputs:    
02552     Returns:    TRUE if played ok...
02553     
02554     Purpose:    Plays a wave file through the computer's sound system (if it has one)
02555 
02556 ***********************************************************************************************/
02557 
02558 BOOL SGLibOil::MakeSound(PathName *WaveFile)
02559 {
02560 #if defined(__WXMSW__)
02561     // Actually play the sound      
02562     String_256 File(WaveFile->GetPath());
02563     BOOL ok = PlaySound((TCHAR *)File, NULL, SND_ASYNC | SND_NODEFAULT | SND_NOWAIT | SND_FILENAME);
02564     if(!ok)
02565         ok = sndPlaySound((TCHAR *)File, SND_ASYNC | SND_NODEFAULT | SND_NOWAIT | SND_FILENAME);
02566 
02567     return ok;
02568 #else
02569     TRACE( wxT("Warning - SGLibOil::MakeSound called\n") );
02570     return TRUE;
02571 #endif
02572 }
02573 
02574 
02575 /***********************************************************************************************
02576 
02577 >   static BOOL SGLibOil::PlayRandomSample(String_256 *SampleString, String_256 *SubPath)
02578 
02579     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02580     Created:    2/1/96
02581 
02582     Inputs:     SampleString    - String such as "Fish.wav|fred.wav|C:\tmp.wav"
02583                 SubPath         - Path to append to file -> C:\animals
02584     Returns:    TRUE if item found and played ok...
02585     
02586     Purpose:    Plays a random wave file through the computer's sound system (if it has one)
02587 
02588 ***********************************************************************************************/
02589 
02590 BOOL SGLibOil::PlayRandomSample(String_256 *SampleString, String_256 *SubPath)
02591 {
02592 #if defined(__WXMSW__)
02593     String_256 SoundToUse(*SampleString);
02594 
02595     if(SoundToUse.Length() > 2)
02596     {
02597         // Pick a random sound from a line such as "Frog.wav|fish.wav|water.wav"
02598         INT32 Fields = SampleString->CountChar('|');
02599 
02600         if(Fields > 0)
02601         {
02602             INT32 Count = (rand()%(Fields+1))+1;
02603             String_256 TmpSoundToUse(SoundToUse);
02604 
02605             if(Count > 0)
02606             {
02607                 TCHAR *Start = (TCHAR *)*SampleString;
02608                 TCHAR *Finish = Start + SampleString->Length();
02609 
02610                 // char to look for
02611                 const TCHAR BAR = '|';
02612 
02613                 TCHAR Ch = *Start;
02614                 INT32 FieldCount = 1;
02615 
02616                 // scan through fields until we hit our baby
02617                 while(Count > FieldCount && Start < Finish)
02618                 {
02619                     if(Ch == 0) break;
02620                     if(Ch == BAR) FieldCount ++;
02621                     Start += sizeof(TCHAR);
02622                     Ch = *Start;
02623                 }
02624 
02625                 // Pointer to sound to use
02626                 if(Count == FieldCount)
02627                     TmpSoundToUse = Start;
02628             }
02629 
02630             // Strip any trailing sounds
02631             if(TmpSoundToUse.Sub(String_8(_T("|"))) != -1)
02632                 TmpSoundToUse.Left(&SoundToUse, TmpSoundToUse.Sub(String_8(_T("|"))));
02633             else
02634                 SoundToUse = TmpSoundToUse;
02635         }
02636 
02637         // Path for normal files is with the pictures
02638         if(SoundToUse.Sub(String_8(_T("\\"))) == -1)
02639         {
02640             String_256 File = *SubPath;
02641             SGLibOil::AppendSlashIfNotPresent(&File);
02642             File += SoundToUse;
02643             SoundToUse = File;
02644         }
02645 
02646         PathName SoundPath(SoundToUse);
02647         return SGLibOil::MakeSound(&SoundPath);
02648     }
02649     return FALSE;
02650 #else
02651     TRACE( wxT("Warning - SGLibOil::PlayRandomSample called\n") );
02652     return TRUE;
02653 #endif
02654 }
02655 
02656 
02657 /***********************************************************************************************
02658 
02659 >   static BOOL SGLibOil::IsRootDirectory(String_256 *Path)
02660 
02661     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02662     Created:    14/2/96
02663 
02664     Inputs:     Path    - Path string -> "A:\" or "C:\fred"
02665     Returns:    TRUE if the path describes a root directory -> "A:\" or "\\deepthought\materials",
02666                 "\\fred\fred\", etc...
02667     
02668     Purpose:    Checks if root directory or not...
02669 `
02670 ***********************************************************************************************/
02671 
02672 BOOL SGLibOil::IsRootDirectory(String_256 *Path)
02673 {
02674     TRACE( wxT("Warning - SGLibOil::PlayRandomSample called\n") );
02675 #if defined(__WXMSW__)
02676     ERROR3IF(Path == NULL, "SGLibOil::IsRootDirectory given a NULL string");
02677     if(Path == NULL)
02678         return FALSE;
02679 //  ERROR3_PF(("IsRootDirectory -> %s", (TCHAR *)*Path));
02680     
02681     // Remove trailing '\'s
02682     String_256 TmpPath(*Path);
02683     if(TmpPath[TmpPath.Length()-1] == _T('\\'))
02684         Path->Left(&TmpPath, Path->Length()-1);
02685 
02686     // Check for 'a:'s...
02687     if( TmpPath.Length() == 2 && TmpPath[1] == _T(':') )
02688         return TRUE;
02689 
02690 //  ERROR3_PF(("For %s, Sub = %d, Count = %d", (TCHAR *)TmpPath, TmpPath.Sub(String_8("\\\\"), 0, TCHAR('*')), TmpPath.CountChar('\\')));
02691     
02692     // Check if unc root dir
02693     if( ( TmpPath.Sub( String_8( wxT("\\\\") ), 0, wxT('*') ) == 0 && TmpPath.CountChar( wxT('\\') ) <= 3 ) )
02694     {
02695 //      ERROR3("UNC root");
02696         return TRUE;
02697     }
02698 
02699 //  ERROR3_PF(("%s is not a root", (TCHAR *)*Path));
02700     return FALSE;
02701 #else
02702     return FALSE;
02703 #endif
02704 }
02705 
02706 /***********************************************************************************************
02707 
02708 >   static BOOL SGLibOil::LoadSoundDefinition(CXaraFileRecordHandler *pXFileRecHandler,
02709                     CXaraFile * pCXFile, INT32 Tag, UINT32 Size, UINT32 RecordNumber);
02710 
02711     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02712     Created:    14/2/96
02713 
02714     Inputs:     pXFileRecHandler - The CXaraFileRecordHandler that is being used to provide read functions etc.
02715                 pCXFile - The CXaraFile that is being used to provide read functions etc.
02716                 Tag             - The tag of the record and hence the type of file being imported
02717                 Size            - The size of this record
02718                 RecordNumber    - The record number for this record
02719     Returns:    TRUE if the record was succesfully imported;
02720                 FALSE if not (e.g. out of memory)
02721     
02722 ***********************************************************************************************/
02723 
02724 BOOL SGLibOil::LoadSoundDefinition(CXaraFileRecordHandler *pXFileRecHandler, CXaraFile * pCXFile,
02725                                  INT32 Tag, UINT32 Size, UINT32 RecordNumber)
02726 {
02727     TRACE( wxT("Warning - SGLibOil::LoadSoundDefinition called\n") );
02728 #if defined(__WXMSW__)
02729     if(TmpSndName != NULL)
02730     {
02731         PathName TheFile(TmpSndName);
02732         FileDelete(&TheFile);
02733         TmpSndName = NULL;
02734     }
02735 
02736     // Create a temporary filename to use
02737     if(( TmpSndName = _ttmpnam( NULL ) ) != NULL )
02738     {
02739         UINT32 Size = pCXFile->GetCurrentRecordSize();
02740         CCFile *pRecordFile = pCXFile->GetCCFile();
02741 
02742         void *Buffer = CCMalloc(Size + 4);
02743     
02744         BOOL ok = FALSE;
02745 
02746         if(Buffer != NULL)
02747         {
02748             CCDiskFile File(1024, FALSE, TRUE);
02749  
02750             // Open file and check if it exists at the same time
02751             try
02752             {
02753                 // Read file into the buffer
02754                 pRecordFile->read(Buffer, Size);
02755 
02756                 // Write file from buffer into output file
02757                 PathName OutputPath(TmpSndName);
02758                 File.open(OutputPath, ios::out | ios::binary);
02759                 File.write(Buffer, Size);
02760                 if(File.isOpen())
02761                     File.close();
02762 
02763                 // File copied ok...
02764                 ok = TRUE;
02765             }       
02766             catch( CFileException )
02767             {
02768                 // File not copied ok... Clear the errors and fall though to alternative low-
02769                 // memory file copy... (this should be very rare !)
02770                 Error::ClearError();
02771             }
02772 
02773             CCFree(Buffer);
02774         }
02775 
02776         if(ok)
02777         {
02778             ok = PlaySound((TCHAR *)TmpSndName, NULL, SND_ASYNC | SND_NODEFAULT | SND_NOWAIT | SND_FILENAME);
02779             if(!ok)
02780                 ok = sndPlaySound((TCHAR *)TmpSndName, SND_ASYNC | SND_NODEFAULT | SND_NOWAIT | SND_FILENAME);      
02781         }
02782 /*      PathName TheFile(TmpSndName);
02783         FileDelete(&TheFile);*/
02784     }
02785     
02786     return TRUE;
02787 #else
02788     return FALSE;
02789 #endif
02790 }
02791 
02792 
02793 /***********************************************************************************************
02794 
02795 >   static BOOL SGLibOil::ExportWav(BaseCamelotFilter *pFilter)
02796 
02797     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02798     Created:    14/2/96
02799 
02800     Inputs:     pFilter     - Filter point to which we want the data streaming
02801     Returns:    TRUE if the record was succesfully exported;
02802                 FALSE if not
02803     
02804 ***********************************************************************************************/
02805 
02806 BOOL SGLibOil::ExportWav(BaseCamelotFilter *pFilter)
02807 {
02808 #if 0
02809     BOOL ok = TRUE;
02810     INT32 RecordNumber = pFilter->StartStreamedRecord(TAG_DEFINESOUND_WAV, CXF_UNKNOWN_SIZE);
02811 
02812     // If we had a problem starting the record up then exit now
02813     if (RecordNumber <= 0)
02814         return RecordNumber;
02815 
02816     PathName Source("C:\\sample.wav");  
02817     INT32 Size = SGLibOil::FileSize(&Source);
02818     void *Buffer = CCMalloc(Size + 4);
02819 
02820     if(Buffer != NULL)
02821     {
02822         CCDiskFile File(1024, FALSE, TRUE);
02823 
02824         // Open file and check if it exists at the same time
02825         TRY
02826         {
02827             // Read file into the buffer
02828             File.open(Source.GetPath(), ios::in | ios::binary | ios::nocreate);
02829             File.read(Buffer, Size);
02830             if(File.isOpen())
02831                 File.close();
02832 
02833             // Write file from buffer into output file
02834             //pOutput->write(Buffer, Size);
02835             for(INT32 i=0; i<Size; i++)
02836                 pFilter->Write(((BYTE *)Buffer)[i]);
02837         }       
02838 
02839         CATCH( CFileException, e)
02840         {
02841             // File not copied ok... Clear the errors and fall though to alternative low-
02842             // memory file copy... (this should be very rare !)
02843             Error::ClearError();
02844         }
02845         END_CATCH
02846 
02847         CCFree(Buffer);
02848     }
02849 
02850     // Ask for the record to be ended and hence items like the size in the record header
02851     // to be cleaned up and hence made correct
02852     if (ok) ok = pFilter->EndStreamedRecord();
02853 
02854     return ok;
02855 #else
02856     return FALSE;
02857 #endif
02858 }
02859 
02860 /***********************************************************************************************
02861 
02862 >   static void SGLibOil::AppendSlashIfNotPresent(String_256 *Str)
02863 
02864     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02865     Created:    15/2/96
02866 
02867     Inputs:     Str     - String to append slash to
02868     Outputs:    Str     - String with slash appended
02869   
02870     Purpose:    Checks if the string has a slash on the end, and appends one if not
02871 
02872 ***********************************************************************************************/
02873 
02874 void SGLibOil::AppendSlashIfNotPresent(String_256 *Str)
02875 {
02876     ERROR3IF(Str == NULL, "SGLibOil::AppendSlashIfNotPresent given a NULL string");
02877     if(Str == NULL)
02878         return;
02879 
02880     if(Str->Length() > 0)
02881         if( ((TCHAR *)*Str)[Str->Length()-1] != '/' )
02882             *Str += TEXT("/");
02883 }
02884 
02885 
02886 /***********************************************************************************************
02887 
02888 >   static DWORD SGLibOil::GetDriveSerialNumber(String_256 *PathStr)
02889 
02890     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com>
02891     Created:    17/7/96
02892 
02893     Inputs:     PathStr - Pathname string containing drive, etc
02894     Returns:    Serial number for given pathname's drive, or 0 if there were problems
02895   
02896     Purpose:    Obtains a serial number for the drive hosting the given pathname. Theoretically
02897                 CD's all contain unique serial numbers, so we can use this to check for new
02898                 CD's in the drive, etc...
02899 
02900 ***********************************************************************************************/
02901 
02902 DWORD SGLibOil::GetDriveSerialNumber(String_256 *PathStr)
02903 {
02904     TRACE( wxT("Warning - SGLibOil::GetDriveSerialNumber called\n") );
02905 #if defined(__WXMSW__)
02906     if(PathStr == NULL)
02907         return 0;
02908 
02909     TCHAR               Drive[MAX_PATH];
02910     BOOL                driveFound = FALSE;
02911 
02912     // Just for safety
02913     String_256 Path = *PathStr;
02914     const TCHAR *fn;
02915     fn = Path;
02916     BOOL BadCharacter = FALSE;
02917 
02918     // First check if there is a valid drive name or net drive name present
02919     // If the first character of the path is an alpha then assume drive and check if valid
02920     // and so of the form D:/
02921     // Otherwise, check for a UNC (Universal naming convention) form of drive of the form
02922     // //Deepthought 
02923     if (String::IsAlpha(*fn))           
02924         driveFound = getDrive(&fn, Drive);  // Parse the Drive 
02925     else 
02926         driveFound = getNetDrive(&fn, Drive, &BadCharacter);    //Parse as UNC or network drive
02927 
02928     if(driveFound && !BadCharacter)
02929     {
02930         String_256 FileSystemName;
02931         String_256 VolumeName;
02932         DWORD SerialNumber = 0;
02933         BOOL bRC = FALSE;
02934 
02935         bRC=GetVolumeInformation(Drive,
02936                 (TCHAR *)VolumeName,
02937                 255,
02938                 &SerialNumber,
02939                 NULL,
02940                 NULL,
02941                 (TCHAR *)FileSystemName,
02942                 255);
02943 
02944         if(bRC)
02945             return SerialNumber;
02946     }
02947 
02948     return 0;
02949 #else
02950     return 0x00BAD000;
02951 #endif
02952 }
02953 
02954 
02955 
02956 
02957 
02958 
02959 /********************************************************************************************
02960 
02961 >   TCHAR* InetUtils::GetStringField(UINT32 nIndex, UINT32 nCompositeStringID)
02962 
02963     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
02964     Created:    3/01/97
02965 
02966     Inputs:     nCompositeStringID - ID of the composite string
02967                     nIndex - relative position of the field within the composite string 
02968     Returns:     a pointer to a buffer containing the field, NULL
02969                     if the string is not valid/composite
02970 
02971     Purpose:    Allows string resource sharing
02972 
02973     Note:       The composite string is limited to 1024 characters
02974 
02975 ********************************************************************************************/
02976 
02977 namespace InetUtils {
02978 
02979 TCHAR* GetStringField( UINT32 nIndex, UINT32 nCompositeStringID )
02980 {
02981     PORTNOTETRACE("dialog","GetStringField - do nothing");
02982 #ifndef EXCLUDE_FROM_XARALX
02983     TCHAR rgtchBuff[1024];
02984     BOOL bLoad = ::LoadString(AfxGetResourceHandle(), nCompositeStringID, rgtchBuff, sizeof(rgtchBuff));
02985     ERROR3IF(!bLoad, "Failed to load string from resource");
02986     TCHAR* szField = _tcstok(rgtchBuff, _T("|"));
02987     for (UINT32 i = 0; i < nIndex && szField; i++)
02988         szField = _tcstok(NULL, _T("|"));
02989     return szField;
02990 #else
02991     return NULL;
02992 #endif
02993 }
02994 
02995 
02996 /********************************************************************************************
02997 
02998 >   void InetUtils::MakeURL(const String_256& rRelativePath, const String_256& rRootURL, String_256& rURL) 
02999 
03000     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
03001     Created:    15/12/96
03002 
03003     Params:     rRelativePath (in) - const reference to string holding a relative file path (no leading slash),
03004                         ex. "clipart\\drawings\\xarainfo\\xaraclip.txt"
03005                      rRootURL (in) - const reference to string holding the root clipart URL on our web site, 
03006                         currently "http://www.xara.com/"
03007                                         
03008     Returns:    URL of file on our site as a String_256 object. Note that this has no lvalue and should
03009                     only be used as an initializer for a local string.
03010 
03011     Purpose:    Allows us to obtain the URL of a file knowing its relative path (from the main clipart index
03012                         file) and the root URL. The URL is necessary to download the file. 
03013                      
03014 
03015 ********************************************************************************************/
03016 
03017 String_256 MakeURL(const String_256& rRelativePath, const String_256& rRootURL)
03018 {
03019     String_256 strURL = rRootURL;
03020     INT32 nCharCount = rRelativePath.Length();
03021     if (camStrstr( (const TCHAR *)strURL, _T("file://") ) )
03022         strURL += rRelativePath;
03023     else for (INT32 i = 0; i < nCharCount; i++)
03024     {
03025         // Walk down the relative path string, appending characters to the URL as we go along
03026         // Backslashes are converted to normal slashes
03027         if (rRelativePath[i] == _T('\\'))
03028             strURL += _T('/');
03029         else
03030             strURL += camTolower( rRelativePath[i] );
03031     }
03032     return strURL;
03033 }
03034 
03035 
03036 /***********************************************************************************************
03037 >   String_256 InetUtils::MakeLocalPath(const String_256& rRelPath)
03038     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
03039     Created:    17/12/96
03040     Params:     rRelPath (in) - reference to string containing a relative file path (no leading slash)
03041                 as read from a web clipart index file
03042     Returns:    A full local in the applicatoin's data folder eg if rRelPath is
03043                 "clipart\drawings\anatomy\baby.xar" then the function returns
03044                 "c:\documents and settings\jonathan\local settings\application data\xara\Cache\clipart\drawings\anatomy\baby.xar".
03045     Purpose:    Returns the expected location of a web clipart catalog file on the local machine,
03046                 having its relative path from the main index file. 
03047 ***********************************************************************************************/
03048 
03049 String_256 MakeLocalPath(const String_256& rRelPath)
03050 {
03051     String_256 strAppDataPath;
03052     GetAppDataPath(&strAppDataPath);
03053     if (strAppDataPath.IsEmpty()) // failed to get the path for some reason
03054         return strAppDataPath;
03055     PathNameEx appDataPath(strAppDataPath);
03056     String_256 strLocalPath = appDataPath.GetLocation(TRUE);
03057     strLocalPath += String_256(_R(IDS_CACHEPATH));
03058     strLocalPath += rRelPath;
03059     return strLocalPath;
03060 }
03061 
03062 
03063 /***********************************************************************************************
03064   > BOOL InetUtils::GetTempInetDir(String_256* pTempDir)
03065     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> (rewritten by Jonathan)
03066     Created:    1712/96 (rewritten 31 Jan 2001)
03067     Inputs:     pTempDir (out) - string returning the path to the OS temporary internet
03068     Returns:    TRUE if successful, FALSE otherwise
03069     Purpose:    Get path to the internet cache directory used to download web clipart files
03070 ***********************************************************************************************/
03071 BOOL GetTempInetDir(String_256* pTempDir)
03072 {
03073 #if defined(__WXMSW__)
03074     if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE | CSIDL_FLAG_CREATE,
03075                         NULL, 0, static_cast<TCHAR *>(*pTempDir))))
03076         return FALSE;
03077 #else
03078 #pragma error( "No equiverlent for SHGetFolderPath" )
03079 #endif
03080 
03081     *pTempDir += wxT("\\");
03082 
03083     return TRUE;
03084 }
03085 
03086 /********************************************************************************************
03087 >   BOOL GetAppDataPath(String_256* pPath)
03088     Author:     Jonathan_Payne (Xara Group Ltd) <camelotdev@xara.com>
03089     Created:    31/01/2001
03090     Inputs:     pPath   - String 256 to fill with path data
03091     Purpose:    Gets the app's data path eg "C:\ Documents And Settings\ Jonathan\
03092                 Local Settings\ Application Data\ Xara X\" (NOTE: includes slash at
03093                 end)
03094 ********************************************************************************************/
03095 BOOL GetAppDataPath(String_256* pPath)
03096 {
03097 #if defined(__WXMSW__)
03098     if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE,
03099                         NULL, 0, static_cast<TCHAR *>(*pPath))))
03100         return FALSE;
03101 #else
03102 #pragma error( "No equiverlent for SHGetFolderPath" )
03103 #endif
03104 
03105     *pPath += wxT("\\");
03106     *pPath += String_256(PRODUCT_MANUFACTURER); // PRODUCT_MANUFACTURER == "Xara"
03107     *pPath += wxT("\\");
03108     *pPath += String_256(PROGRAM_NAME); // PROGRAM_NAME == "Xara X" || "Xara X (debug)"
03109     *pPath += wxT("\\");
03110 
03111     return TRUE;
03112 }
03113 
03114 /********************************************************************************************
03115 >   BOOL GetAppCachePath(String_256* pPath)
03116     Author:     Jonathan_Payne (Xara Group Ltd) <camelotdev@xara.com>
03117     Created:    1/2/2001
03118     Inputs:     pPath   - String 256 to fill with path data
03119     Purpose:    Gets the app's data path eg "C:\ Documents And Settings\ Jonathan\
03120                 Local Settings\ Application Data\ Xara X\ Cache\" (NOTE: includes slash at
03121                 end)
03122 ********************************************************************************************/
03123 BOOL GetAppCachePath(String_256* pPath)
03124 {
03125     if (!GetAppDataPath(pPath))
03126         return FALSE;
03127 
03128     *pPath += String_256(_R(IDS_CACHEPATH)); // _R(IDS_CACHEPATH) == "Cache\\"
03129 
03130     return TRUE;
03131 }
03132 
03133 
03134 /***********************************************************************************************
03135 
03136 >   BOOL InetUtils::DeleteTree(const String_256& rPath)
03137 
03138     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
03139     Created:    1712/96
03140 
03141     Inputs:     reference to String_256 containing the path to the root directory
03142                     of the tree to be removed.
03143     Returns:    TRUE if successful, FALSE in case of total or partial failure (some 
03144                     of the files are locked etc.)
03145   
03146     Purpose:    remove a directory tree from the hard drive
03147 
03148   See also:     PathNameEx::RemoveRecursively()
03149     
03150 
03151 ***********************************************************************************************/
03152 
03153 BOOL DeleteDirectoryTree(const String_256& rPath)
03154 {
03155     PathNameEx dirPath(rPath);
03156     return dirPath.Remove();
03157 }}
03158 
03159 // <<webster
03160 
03161 

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