inetop.cpp

Go to the documentation of this file.
00001 // $Id: inetop.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 #include "camtypes.h"
00099 #include "sgliboil.h"
00100 
00101 //#include "app.h"       - in camtypes.h [AUTOMATICALLY REMOVED]
00102 //#include "galstr.h"
00103 #include "sglcart.h"
00104 #include "sgfonts.h"
00105 #include "sglib.h"
00106 //#include "sgscan.h"        - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "sgscanf.h"    
00108 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "selop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "filedlgs.h"
00112 //#include "resource.h" // _R(IDS_CANCEL)
00113 #include "camdoc.h"
00114 //#include "webster.h"
00115 //#include "richard.h"
00116 #include "pathnmex.h"
00117 #include "inetop.h"
00118 #include "sglbase.h"
00119 #include "progress.h"
00120 #include "sglfills.h"
00121 #include "backgrnd.h"
00122 
00123 #include <io.h>         // for FileExists
00124 #include <stdio.h>
00125 #include <stdlib.h>
00126 
00127 using namespace InetUtils;
00128 
00129 CC_IMPLEMENT_DYNCREATE(DownloadOp, Operation)
00130 CC_IMPLEMENT_DYNCREATE(OpAsynchClipartImport, OpClipartImport)
00131 CC_IMPLEMENT_DYNCREATE(OpAddWebFolders, Operation)
00132 CC_IMPLEMENT_DYNCREATE(OpAddWebLibrary, Operation)
00133 CC_IMPLEMENT_DYNCREATE(OpThumbDownload, Operation)
00134 CC_IMPLEMENT_DYNCREATE(OpAsynchFontInstall, DownloadOp)
00135 CC_IMPLEMENT_DYNCREATE(OpAsynchBitmapImport, DownloadOp)
00136 
00137 
00138 #define new CAM_DEBUG_NEW
00139 
00140 void* DownloadOpParam::pAllocatedMemory;
00141 
00142 DownloadOpParam::DownloadOpParam()
00143 {
00144 #ifdef _DEBUG
00145     if ((void*) this != pAllocatedMemory)
00146         ERROR3("DownloadOpParam-derived objects should be allocated using the new operator");
00147     pAllocatedMemory = NULL;
00148 #endif
00149     // default to clipart download parameters
00150     type = TYPE_CLIPART;
00151     priority = AsynchDownload::PRIORITY_HIGH;
00152     bHasProgressDlg = TRUE;
00153     strDescription = _T("");
00154 }
00155 
00156 /********************************************************************************************
00157 
00158 >   DownloadOp::~DownloadOp() 
00159 
00160     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00161     Created:    3/04/97
00162     Inputs:     -
00163     Outputs:    -
00164     Returns:    -
00165     Purpose:    DownloadOp constructor
00166     Errors:     -
00167     SeeAlso:    -
00168 
00169 ********************************************************************************************/
00170 DownloadOp::DownloadOp()
00171 {
00172     pParam = NULL;
00173     m_hDownload = 0;
00174     m_nPercentageCompleted = 0;
00175     OpFlags.HasOwnTimeIndicator = TRUE;
00176 //  GetApplication()->RegisterIdleProcessor(IDLEPRIORITY_LOW, this); // start the polling loop
00177 }       
00178 
00179 /********************************************************************************************
00180 
00181 >   DownloadOp::~DownloadOp() 
00182 
00183     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00184     Created:    4/04/97
00185     Inputs:     -
00186     Outputs:    -
00187     Returns:    -
00188     Purpose:    DownloadOp destructor
00189     Errors:     -
00190     SeeAlso:    -
00191 
00192 ********************************************************************************************/
00193 
00194 DownloadOp::~DownloadOp()
00195 {
00196     GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_LOW, this); // end polling loop
00197     if (pParam)
00198         delete pParam;
00199 }
00200 
00201 /******************************************************************************************
00202 
00203 >   BOOL DownloadOp::Init()
00204 
00205     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00206     Created:    4/04/97
00207     Returns:    FALSE if it fails (due to lack of memory)
00208     Purpose:    Creates an OpDescriptor for a DownloadOp
00209     SeeAlso:
00210 
00211 ******************************************************************************************/
00212 
00213 
00214 BOOL DownloadOp::Init()
00215 {  
00216     return RegisterOpDescriptor(
00217         0,                              // Tool ID
00218         _R(IDS_OPDOWNLOAD),             // String resource ID
00219         CC_RUNTIME_CLASS(DownloadOp),   // Runtime class
00220         OPTOKEN_OPDOWNLOAD,         // Token string
00221         DownloadOp::GetState,           // GetState function
00222         0,                              // Help ID
00223         0,                              // Bubble ID
00224         0,                              // Resource ID
00225         0                               // Control ID
00226     );
00227 }   
00228 
00229 /******************************************************************************************
00230 
00231 >   OpState DownloadOp::GetState(String_256* pString, OpDescriptor* pOpDesc)
00232 
00233     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00234     Created:    4/04/97
00235     Purpose:    Returns the OpState of the DownloadOp operation.
00236     SeeAlso:
00237 
00238 ******************************************************************************************/
00239 
00240 OpState DownloadOp::GetState(String_256* pString, OpDescriptor* pOpDesc)
00241 {
00242     OpState OpSt;
00243     return(OpSt);
00244 }
00245 
00246 
00247 
00248 /********************************************************************************************
00249 
00250 >   void DownloadOp::Do(OpDescriptor*)
00251 
00252     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00253     Created:    20/1/97
00254     Inputs:     OpDescriptor* (unused)
00255     Outputs:    -
00256     Returns:    -
00257     Purpose:    
00258     Errors:     Always fails - should not be called
00259     SeeAlso:    -
00260 
00261 ******************************************************************************************/
00262         
00263 void DownloadOp::Do(OpDescriptor *NotUsed)
00264 {
00265     ERROR3("This operation does not provide a Do() function - Use DoWithParam");
00266     End();
00267 }
00268 
00269 
00270 /******************************************************************************************
00271 >   void DownloadOp::DoWithParam(OpDescriptor* pOp, OpParam* pDownloadOpParam)
00272 
00273     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00274     Created:    7/01/97
00275     Inputs:     pOp - OpDescriptor as for all Do() functions
00276                 pDownloadOpParam - pointer to  DownloadOpParam structure . This structure
00277                     must be created on the heap as it should not be destroyed when it goes
00278                     out of scope.
00279     Outputs:    -  none
00280                         Note that this function returns immediately after starting the download.
00281     Returns:    -
00282     Purpose:    Request a download with the parameters passed in pDownloadOpParam
00283 
00284 ******************************************************************************************/
00285 
00286 void DownloadOp::DoWithParam(OpDescriptor* pOp, OpParam* pDownloadOpParam)
00287 {
00288     DownloadOpParam *pInfo = (DownloadOpParam*) pDownloadOpParam;
00289     if (pInfo == NULL)
00290     {
00291         ERROR3("DoWithParam called with invalid pointer");
00292         goto FAIL;
00293     }
00294     else
00295     {
00296         if (!pInfo->file.IsValid() || pInfo->strURL.IsEmpty())
00297         {
00298             ERROR3("Invalid file path or URL");
00299             goto FAIL;
00300         }
00301         // Register the file for download
00302         DOWNLOADINFO downloadInfo;
00303         downloadInfo.strURL = pInfo->strURL;
00304         downloadInfo.strLocalFile = (String_256) pInfo->file.GetPath();
00305         downloadInfo.nFileType = pInfo->type;
00306         downloadInfo.nPriority = pInfo->priority;
00307         downloadInfo.strDescription = pInfo->strDescription;
00308         downloadInfo.bHasProgressDlg = TRUE;
00309 
00310         // NEW! Tell this downloader that we can handle status messages
00311         // (We don't use Idle event polling)
00312         downloadInfo.hwndNotifyWindow = GetMainFrame()->GetSafeHwnd();
00313         downloadInfo.lNotifyToken = (INT32)this;
00314 
00315         m_hDownload = InternetManager::RegisterDownload(&downloadInfo);
00316         if (!m_hDownload || m_hDownload == (DOWNLOAD_HANDLE) INVALID_HANDLE_VALUE)
00317         {
00318             ERROR3("Failed to register download");
00319             goto FAIL;
00320         }
00321         pParam = pInfo;
00322         if (pInfo->Output)
00323             *(pInfo->Output) = TRUE;
00324     }
00325     return;
00326 
00327 FAIL:
00328         if (pInfo->Output)
00329             *(pInfo->Output) = FALSE;
00330         FailAndDiscard(); 
00331         End();
00332 }
00333 
00334 /********************************************************************************************
00335 
00336 >   void DownloadOp::End()
00337 
00338     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00339     Created:    21/01/97
00340     Inputs:     -
00341     Outputs:    -
00342     Returns:    -
00343     Purpose:    overrides Operation::End() to avoid having an ERROR2 (caused
00344                     by Document::GetSelectedSpread() returning NULL) go off when
00345                     Camelot exits while a download is still in progress 
00346                 
00347     Errors:     -
00348     SeeAlso:    Operation::End()
00349 
00350 ********************************************************************************************/
00351 
00352 void DownloadOp::End()
00353 {
00354     if (m_hDownload)
00355         InternetManager::UnregisterDownload(m_hDownload);
00356     if (Document::GetSelectedSpread())
00357         Operation::End();
00358     else
00359         EndOp();
00360 }   
00361 
00362 
00363 
00364 
00365 /******************************************************************************************
00366 >   virtual BOOL DownloadOp::OnIdleEvent()
00367 
00368     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00369     Created:    7/01/97
00370     Inputs:     -
00371     Outputs:    - 
00372                         
00373     Returns:    - TRUE if we want to continue polling, FALSE otherwise
00374     Purpose:    - idle time polling loop; continues until either the download completes
00375                         or the operation is terminated on receiving a death message.
00376                         The appropriate functions are called according to the state of the download
00377                         on completion (succeeded/aborted/failed)
00378 
00379 ******************************************************************************************/
00380 
00381 BOOL DownloadOp::OnIdleEvent()
00382 {
00383 //ERROR2(FALSE, "DownloadOp::OnIdleEvent should no longer be called!!!");
00384     INT32 nPercentageCompleted = 0;
00385     ERROR2IF(!pParam, FALSE, "Unexpected NULL pointer");
00386     switch (InternetManager::GetDownloadState(m_hDownload))
00387     {
00388         case AsynchDownload::STATE_PENDING:
00389             // check the percentage downloaded so far
00390             nPercentageCompleted = InternetManager::GetPercentageDownloaded(m_hDownload);
00391             ERROR3IF(nPercentageCompleted == -1, "Invalid download handle");
00392             if (nPercentageCompleted != m_nPercentageCompleted) // we made some progress
00393             {
00394                 m_nPercentageCompleted = nPercentageCompleted;
00395                 OnDownloadProgress(nPercentageCompleted);
00396             }
00397             // download pending, so we continue polling
00398             return TRUE;
00399         case AsynchDownload::STATE_SUCCEEDED:
00400             // file has transferred successfully, we call OnDownloadSuccess() to process it
00401             OnDownloadSuccess();
00402             SucceedAndDiscard();
00403             End();
00404             return FALSE;
00405         case AsynchDownload::STATE_FAILED:
00406             OnDownloadFail();
00407             break;
00408         case AsynchDownload::STATE_ABORTED:
00409             OnDownloadAbort();
00410             break;
00411         default:
00412             ERROR3("Error or unrecognized state");
00413     }
00414     FailAndDiscard();
00415     End();
00416     return FALSE;
00417 }
00418 
00419 
00420 
00421 
00422 /******************************************************************************************
00423 >   virtual void DownloadOp::OnDownloadSuccess()
00424 
00425     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00426     Created:    7/01/97
00427     Inputs:     -
00428     Outputs:    - 
00429                         
00430     Returns:    - 
00431     Purpose:    - This function is called if the file download completes successfully
00432                     so that we can process it or take some other action. Derived classes 
00433                     should override this function - the current implementation does nothing. 
00434 
00435 ******************************************************************************************/
00436 
00437 void DownloadOp::OnDownloadSuccess()
00438 {
00439 }
00440 
00441 /******************************************************************************************
00442 >   virtual void DownloadOp::OnDownloadFail()
00443 
00444     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00445     Created:    7/01/97
00446     Inputs:     -
00447     Outputs:    - 
00448                         
00449     Returns:    - 
00450     Purpose:    - This function is called if the file download fails. The current implemention
00451                     simply outputs an error message based on the file type declared in DownloadOpParam.
00452                     If you want something more sophisticated override this function in your class.
00453 
00454 ******************************************************************************************/
00455 
00456 void DownloadOp::OnDownloadFail()
00457 {
00458         String_256 strTemp;
00459         strTemp.MakeMsg(_R(IDS_DOWNLOADFAILED), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GALLERY_DESCRIPTIONS)), (TCHAR*) pParam->strDescription);
00460         Error::SetError(0, strTemp, 0);
00461         InformError();
00462 }
00463 
00464 
00465 /******************************************************************************************
00466 >   virtual void DownloadOp::OnDownloadAbort()
00467 
00468     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00469     Created:    7/01/97
00470     Inputs:     -
00471     Outputs:    - 
00472                         
00473     Returns:    - 
00474     Purpose:    - This function is called if the file download is cancelled by the user.
00475                         Derived classes should override this function if some specific action
00476                         is required in this case. 
00477 
00478 ******************************************************************************************/
00479 
00480 void DownloadOp::OnDownloadAbort()
00481 {
00482 }
00483 
00484 
00485 
00486 
00487 /******************************************************************************************
00488 >   virtual void DownloadOp::OnDownloadPending()
00489 
00490     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00491     Created:    04/05/2004
00492     Inputs:     -
00493     Outputs:    - 
00494                         
00495     Returns:    - 
00496     Purpose:    - This function is called if the file download is just in the process of working.
00497                         Derived classes should override this function if some specific action
00498                         is required in this case. 
00499 
00500 ******************************************************************************************/
00501 
00502 void DownloadOp::OnDownloadPending()
00503 {
00504     // check the percentage downloaded so far
00505     INT32 nPercentageCompleted = 0;
00506     nPercentageCompleted = InternetManager::GetPercentageDownloaded(m_hDownload);
00507 //  ERROR3IF(nPercentageCompleted == -1, "Invalid download handle");
00508     if (nPercentageCompleted != -1)
00509     {
00510         if (nPercentageCompleted != m_nPercentageCompleted) // we made some progress
00511         {
00512             m_nPercentageCompleted = nPercentageCompleted;
00513             OnDownloadProgress(nPercentageCompleted);
00514         }
00515     }
00516 }
00517 
00518 
00519 
00520 
00521 // Asynchonous clipart import
00523 
00524 
00525 AsynchClipartImportParam::AsynchClipartImportParam()
00526 {
00527     Import      = FALSE;
00528     bDropped = FALSE;
00529 }
00530 
00531 AsynchClipartImportParam::~AsynchClipartImportParam()
00532 {
00533 }
00534 
00535 
00536 OpAsynchClipartImport::OpAsynchClipartImport()
00537 {
00538     pParam = NULL;
00539     m_hDownload = 0;
00540     m_pTargetDoc = NULL;
00541     m_pCurrentSelDoc = NULL;
00542     GetApplication()->RegisterIdleProcessor(IDLEPRIORITY_LOW, this);
00543 }       
00544 
00545 /********************************************************************************************
00546 
00547 >   OpAsynchClipartImport::~OpAsynchClipartImport() 
00548 
00549     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00550     Created:    20/12/96
00551     Inputs:     -
00552     Outputs:    -
00553     Returns:    -
00554     Purpose:    OpAsynchClipartImport destructor
00555     Errors:     -
00556     SeeAlso:    -
00557 
00558 ********************************************************************************************/
00559 
00560 OpAsynchClipartImport::~OpAsynchClipartImport()
00561 {
00562     GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_LOW, this);
00563     if (pParam)
00564         delete pParam;
00565 }
00566 
00567 /******************************************************************************************
00568 
00569 >   BOOL OpAsynchClipartImport::Init()
00570 
00571     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00572     Created:    4/01/97
00573     Returns:    FALSE if it fails (due to lack of memory)
00574     Purpose:    Creates an OpDescriptor for an AsynchClipartImport operation
00575     SeeAlso:
00576 
00577 ******************************************************************************************/
00578 
00579 
00580 BOOL OpAsynchClipartImport::Init()
00581 {  
00582     return RegisterOpDescriptor(
00583         0,                              // Tool ID
00584         _R(IDS_OPASYNCHCLIPARTIMPORT),              // String resource ID
00585         CC_RUNTIME_CLASS(OpAsynchClipartImport),    // Runtime class
00586         OPTOKEN_OPASYNCHCLIPARTIMPORT,          // Token string
00587         OpAsynchClipartImport::GetState,            // GetState function
00588         0,                              // Help ID
00589         0,                              // Bubble ID
00590         0,                              // Resource ID
00591         0                               // Control ID
00592     );
00593 }   
00594 
00595 /******************************************************************************************
00596 
00597 >   OpState OpAsynchClipartImport::GetState(String_256* pString, OpDescriptor* pOpDesc)
00598 
00599     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00600     Created:    20/3/95
00601     Purpose:    Returns the OpState of the OpAsynchClipartImport operation.
00602     SeeAlso:
00603 
00604 ******************************************************************************************/
00605 
00606 OpState OpAsynchClipartImport::GetState(String_256* pString, OpDescriptor* pOpDesc)
00607 {
00608     OpState OpSt;
00609     return(OpSt);
00610 }
00611 
00612 
00613 /******************************************************************************************
00614 
00615 >   BOOL OpAsynchClipartImport::OnDocChangingMsg(Document* pChangingDoc, DocChangingMsg::DocState State)
00616 
00617     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00618     Created:    12/01/97
00619     Returns:    - 
00620     Purpose:    Notifies us if the document we intend to import into is about to be destroyed,
00621                     in which case we should abort the operation
00622     SeeAlso:    MessageHandler::OnDocChangingMsg()
00623 
00624 ******************************************************************************************/
00625 
00626 BOOL OpAsynchClipartImport::OnDocChangingMsg(Document* pChangingDoc, DocChangingMsg::DocState State)
00627 {
00628     if (pChangingDoc == m_pTargetDoc && State == DocChangingMsg::ABOUTTODIE)
00629     {
00630         // We end the operation, but don't abort the clipart download - it's up to the user to do that
00631         FailAndExecute(); 
00632         End();
00633     }
00634     return TRUE;
00635 }
00636 
00637 
00638 /********************************************************************************************
00639 
00640 >   void OpAsynchClipartImport::Do(OpDescriptor*)
00641 
00642     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00643     Created:    20/1/97
00644     Inputs:     OpClipartImport (unused)
00645     Outputs:    -
00646     Returns:    -
00647     Purpose:    
00648     Errors:     Always fails - should not be called
00649     SeeAlso:    -
00650 
00651 ******************************************************************************************/
00652         
00653 void OpAsynchClipartImport::Do(OpDescriptor *NotUsed)
00654 {
00655     ERROR3("OpAsynchClipartImport does not provide a Do() function - Use DoWithParam");
00656     End();
00657 }
00658 
00659 /******************************************************************************************
00660 >   void OpAsynchClipartImport::DoWithParam(OpDescriptor* pOp, OpParam* pClipartImportParam)
00661 
00662     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00663     Created:    7/01/97
00664     Inputs:     pOp - OpDescriptor as for all Do() functions
00665                 pClipartImportParam - pointer to  AsynchClipartImport structure . This structure
00666                     must be created on the heap as it should not be destroyed when it goes
00667                     out of scope.
00668     Outputs:    -  none
00669                         Note that this function returns immediately after starting the download, so its success is not relevant to the outcome
00670                         of the actual clipart import operation, which will be done on the idle loop if the download
00671                         eventually succeeds. In case of failure, however, the user will be informed that the download - and
00672                         clipart import - cannot be started.
00673     Returns:    -
00674     Purpose:    Performs an asynch clipart import / open depending on the parameters
00675     Notes:      In case the downloads succeeds, the actual clipart import will be done
00676                     on the idle loop in order to avoid reentering the import code (potentially messy)
00677                     in case of multiple symultaneous downloads
00678     SeeAlso: OpClipartImport, OpAsynchClipartImport::OnIdleEvent()
00679 
00680 ******************************************************************************************/
00681 
00682 void OpAsynchClipartImport::DoWithParam(OpDescriptor* pOp, OpParam* pClipartImportParam)
00683 {
00684     AsynchClipartImportParam *pInfo = (AsynchClipartImportParam*) pClipartImportParam;
00685 
00686     if(pInfo == NULL)
00687     {
00688         ERROR3("OpAsynchClipartImport called with NULL info pointer");
00689         goto FAIL;
00690     }
00691     else
00692     {
00693         if (!pInfo->File.IsValid() || pInfo->strURL.IsEmpty())
00694         {
00695             ERROR3("Invalid file path or URL");
00696             goto FAIL;
00697         }
00698         // Remember the document pointer
00699         m_pTargetDoc = Document::GetSelected();
00700         m_pCurrentSelDoc = Document::GetSelected(); // target and selected are the same at this stage
00701         // Register the file for download
00702         DOWNLOADINFO downloadInfo;
00703         downloadInfo.strURL = pInfo->strURL;
00704         downloadInfo.strLocalFile = (String_256) pInfo->File.GetPath();
00705         downloadInfo.nFileType = TYPE_CLIPART;
00706         downloadInfo.nPriority = AsynchDownload::PRIORITY_HIGH;
00707         downloadInfo.strDescription = pInfo->strDescription;
00708         downloadInfo.bHasProgressDlg = TRUE;
00709         downloadInfo.hwndNotifyWindow = 0;
00710         downloadInfo.lNotifyToken = 0;
00711         m_hDownload = InternetManager::RegisterDownload(&downloadInfo);
00712         if (!m_hDownload || m_hDownload == (DOWNLOAD_HANDLE) INVALID_HANDLE_VALUE)
00713         {
00714             ERROR3("Failed to register download");
00715             goto FAIL;
00716         }
00717         pParam = pInfo;
00718     }
00719     return;
00720 
00721 FAIL:
00722         FailAndExecute(); 
00723         End();
00724 }
00725 
00726 /********************************************************************************************
00727 
00728 >   void OpAsynchClipartImport::End()
00729 
00730     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00731     Created:    21/01/97
00732     Inputs:     -
00733     Outputs:    -
00734     Returns:    -
00735     Purpose:    overwrites Operation::End() to avoid having an ERROR2 (caused
00736                     by Document::GetSelectedSpread() returning NULL) go off when
00737                     Webster exits while an asynch clipart import is still in progress 
00738                 
00739     Errors:     -
00740     SeeAlso:    Operation::End()
00741 
00742 ********************************************************************************************/
00743 
00744 void OpAsynchClipartImport::End()
00745 {
00746     if (Document::GetSelectedSpread())
00747         Operation::End();
00748     else
00749         EndOp();
00750 }   
00751 
00752 
00753 
00754 
00755 /******************************************************************************************
00756 >   virtual BOOL OpAsynchClipartImport::OnIdleEvent()
00757 
00758     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00759     Created:    7/01/97
00760     Inputs:     -
00761     Outputs:    - 
00762                         
00763     Returns:    - TRUE if we want to continue polling, FALSE otherwise
00764     Purpose:    - idle time polling loop; continues until either the download completes
00765                         or the operation is terminated on receiving a death message.
00766                         Different actions are taken according to the state of the download
00767                         on completion (succeeded/aborted/failed)
00768 
00769 ******************************************************************************************/
00770 
00771 BOOL OpAsynchClipartImport::OnIdleEvent()
00772 {
00773     ERROR2IF(!pParam, FALSE, "Unexpected NULL pointer");
00774     switch (InternetManager::GetDownloadState(m_hDownload))
00775     {
00776         case AsynchDownload::STATE_PENDING:
00777             // download pending, so we continue polling
00778             return TRUE;
00779 
00780         case AsynchDownload::STATE_SUCCEEDED:
00781         {
00782             // file has transferred successfully, so we can proceed with a synchronous import/open operation
00783             if (pParam->Import)
00784             {
00785                 if (m_pTargetDoc != Document::GetSelected())
00786                 {
00787                     m_pCurrentSelDoc = Document::GetSelected();
00788                     Document::SetSelectedViewAndSpread(m_pTargetDoc);
00789                     // If the target document is not selected yet we keep on polling until it is  
00790                     if (m_pTargetDoc != Document::GetSelected()) 
00791                         return TRUE;
00792                 }
00793                 OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpClipartImport));
00794                 if (pOpDesc != NULL)
00795                 {
00796                     ClipartImportParam Param;
00797                     // Set up the parameters which we require to import the clipart
00798                     Param.File = &(pParam->File);
00799                     Param.Import = pParam->Import;
00800                     Param.Result = TRUE;
00801                     if (pParam->bDropped) // if the file has been dropped on the page, get positioning informatiom
00802                         Param.DropInfo =  &(pParam->DropInfo);
00803                     pOpDesc->Invoke((OpParam*) &Param);
00804                     BOOL ok = Param.Result;
00805                     if (!ok)
00806                     {
00807                         ERROR3("LibClipartSGallery::ImportClipart - Problem importing file");
00808                     }
00809                 }
00810                 if (m_pCurrentSelDoc != m_pTargetDoc)
00811                     Document::SetSelectedViewAndSpread(m_pCurrentSelDoc);
00812             }
00813             else // open the file as new document
00814             {
00815                 CWinApp* pApp = AfxGetApp();
00816                 BaseFileDialog::SelectedFilter = 0;
00817                 // Open a document
00818                 CCamDoc* pDoc = (CCamDoc*) pApp->OpenDocumentFile((TCHAR*) String_256(pParam->File.GetPath()));
00819                 // And redraw the imported document
00820                 if(pDoc) pDoc->GetKernelDoc()->ForceRedraw();
00821             }
00822             if (LibFillsSGallery::ThisGallery)
00823                 LibFillsSGallery::ThisGallery->SelectionHasChanged();
00824             SucceedAndDiscard();
00825             End();
00826             return FALSE;
00827         }
00828 
00829         case AsynchDownload::STATE_FAILED:
00830         {
00831             String_256 strTemp;
00832             strTemp.MakeMsg(_R(IDS_DOWNLOADFAILED), (TCHAR*) (String_256) GetStringField((UINT32) SGLib_ClipArt, _R(IDS_GALLERY_DESCRIPTIONS)), (TCHAR*) pParam->strDescription);
00833             Error::SetError(0, strTemp, 0);
00834             InformError();
00835             goto FAIL;
00836         }
00837 
00838         case AsynchDownload::STATE_ABORTED:
00839         {
00840             // no errror message as this state is the result of a user cancel
00841             goto FAIL;
00842         }
00843 
00844         default:
00845             ERROR3("Error or unrecognized state");
00846             goto FAIL;
00847     }
00848 
00849 FAIL:
00850     FailAndDiscard();
00851     End();
00852     return FALSE;
00853 }
00854             
00855 
00856 
00857 
00858 // OpAddWebFolders
00860 
00861 BOOL OpAddWebFolders::Success[8];
00862 
00863 
00864 OpAddWebFolders::OpAddWebFolders()
00865 {
00866     pParam = NULL;
00867     GetApplication()->RegisterIdleProcessor(IDLEPRIORITY_LOW, this);
00868     OpFlags.HasOwnTimeIndicator = TRUE;
00869     m_hDownload = 0;
00870 }       
00871 
00872 /********************************************************************************************
00873 
00874 >   OpAddWebFolders::~OpAddWebFolders() 
00875 
00876     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00877     Created:    20/12/96
00878     Inputs:     -
00879     Outputs:    -
00880     Returns:    -
00881     Purpose:    OpAddWebFolders destructor
00882     Errors:     -
00883     SeeAlso:    -
00884 
00885 ********************************************************************************************/
00886 
00887 OpAddWebFolders::~OpAddWebFolders()
00888 {
00889     GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_LOW, this);
00890     if (pParam)
00891         delete pParam;
00892 }
00893 
00894 /******************************************************************************************
00895 
00896 >   BOOL OpAddWebFolders::Init()
00897 
00898     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00899     Created:    20/12/96
00900     Returns:    FALSE if it fails (due to lack of memory)
00901     Purpose:    Creates an OpDescriptor for an OpAddWebFolders operation
00902     SeeAlso:
00903 
00904 ******************************************************************************************/
00905 
00906 BOOL OpAddWebFolders::Init()
00907 {  
00908     return RegisterOpDescriptor(
00909         0,                              // Tool ID
00910         _R(IDS_OPADDWEBFOLDERS),                // String resource ID
00911         CC_RUNTIME_CLASS(OpAddWebFolders),  // Runtime class
00912         OPTOKEN_OPADDWEBFOLDERS,            // Token string
00913         OpAddWebFolders::GetState,          // GetState function
00914         0,                              // Help ID
00915         0,                              // Bubble ID
00916         0,                              // Resource ID
00917         0                               // Control ID
00918     );
00919 }   
00920 
00921 /******************************************************************************************
00922 
00923 >   OpState OpAddWebFolders::GetState(String_256* pString, OpDescriptor* pOpDesc)
00924 
00925     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00926     Created:    20/12/96
00927     Purpose:    Returns the OpState of the OpAddWebFolders operation.
00928     SeeAlso:
00929 
00930 ******************************************************************************************/
00931 
00932 OpState OpAddWebFolders::GetState(String_256* pString, OpDescriptor* pOpDesc)
00933 {
00934     OpState OpSt;
00935     return(OpSt);
00936 }
00937 
00938 /********************************************************************************************
00939 
00940 >   void OpAddWebFolders::Do(OpDescriptor*)
00941 
00942     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
00943     Created:    20/3/95
00944     Inputs:     OpAddWebFolders (unused)
00945     Outputs:    -
00946     Returns:    -
00947     Purpose:    
00948     Errors:     Always fails - should not be called
00949     SeeAlso:    -
00950 
00951 ********************************************************************************************/
00952             
00953 void OpAddWebFolders::Do(OpDescriptor *NotUsed)
00954 {
00955     ERROR3("OpAddWebFolders does not provide a Do() function - Use DoWithParam");
00956     End();
00957 }
00958 
00959 /******************************************************************************************
00960 >   void OpAddWebFolders::DoWithParam(OpDescriptor* pOp, OpParam* pAddWebFoldersParam)
00961 
00962     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
00963     Created:    7/01/97
00964     Inputs:     pOp - OpDescriptor as for all Do() functions
00965                     pAddWebFoldersParam - pointer to  AddWebFoldersParam structure
00966     Outputs:    - none
00967     Returns:    -
00968     Purpose:    attempts to download asynchronously the main web clipart index file, and if this succeeds
00969                     it goes on to parse it and launch separate downloads for each of the catalog files referenced
00970                     by the index
00971     
00972 
00973 ******************************************************************************************/
00974 
00975 void OpAddWebFolders::DoWithParam(OpDescriptor* pOp, OpParam* pAddWebFoldersParam)
00976 {
00977     AddWebFoldersParam *pInfo = (AddWebFoldersParam*) pAddWebFoldersParam;
00978     if (pInfo == NULL)
00979     {
00980         ERROR3("OpAddWebFolders called with NULL info pointer");
00981         goto FAIL;
00982     }
00983     else
00984     {
00985         if (!pInfo->localFile.IsValid() || pInfo->strURL.IsEmpty() || !pInfo->pLibGal)
00986         {
00987             ERROR3("OpAddWebFolders: invalid parameters");
00988             goto FAIL;
00989         }
00990         // Register the file for download
00991         DOWNLOADINFO downloadInfo;
00992         downloadInfo.strURL = pInfo->strURL;
00993         downloadInfo.strLocalFile = (String_256) pInfo->localFile.GetPath();
00994         downloadInfo.nFileType = TYPE_CATALOG;
00995         downloadInfo.nPriority = AsynchDownload::PRIORITY_NORMAL;
00996         downloadInfo.bHasProgressDlg = TRUE;
00997         downloadInfo.hwndNotifyWindow = 0;
00998         downloadInfo.lNotifyToken = 0;
00999         m_hDownload = InternetManager::RegisterDownload(&downloadInfo);
01000         if (!m_hDownload || m_hDownload == (DOWNLOAD_HANDLE) INVALID_HANDLE_VALUE)
01001         {
01002             InformError(_R(IDS_CATALOGDOWNLOADFAILED), _R(IDS_OK));
01003             goto FAIL;
01004         }
01005         pParam = pInfo;
01006     }
01007     // Make some optimistic assumptions...
01008     Success[pParam->type] = TRUE; 
01009     return;
01010 
01011 FAIL:
01012     Success[pParam->type] = FALSE; 
01013     FailAndExecute(); 
01014     End();
01015 }
01016 
01017 /******************************************************************************************
01018 >   virtual BOOL OpAddWebFolders::OnDeathMsg()
01019 
01020     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
01021     Created:    7/01/97
01022     Inputs:     -
01023     Outputs:    - 
01024                         
01025     Returns:    - always TRUE
01026     Purpose:    - aborts the download (so that we won't leak resources) 
01027                         and ends the op on Webster exit
01028 
01029 ******************************************************************************************/
01030 BOOL OpAddWebFolders::OnDeathMsg()
01031 {
01032     InternetManager::UnregisterDownload(m_hDownload);
01033     End();
01034     return TRUE;
01035 }
01036 
01037 
01038 
01039 /******************************************************************************************
01040 >   virtual BOOL OpAddWebFolders::OnIdleEvent()
01041 
01042     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
01043     Created:    7/01/97
01044     Inputs:     -
01045     Outputs:    - 
01046                         
01047     Returns:    - TRUE if we want to continue polling, FALSE otherwise
01048     Purpose:    - idle time polling loop; continues until either the download completes
01049                         or the operation is terminated on receiving a death message.
01050                         Different actions are taken according to the state of the download
01051                         on completion (succeeded/aborted/failed)
01052 
01053 ******************************************************************************************/
01054 
01055 BOOL OpAddWebFolders::OnIdleEvent()
01056 {
01057     ERROR2IF(!pParam, FALSE, "Unexpected NULL pointer");
01058     CCDiskFile mainIndex;
01059     switch (InternetManager::GetDownloadState(m_hDownload))
01060     {
01061         case AsynchDownload::STATE_PENDING:
01062             // download pending, so we continue polling
01063             return TRUE;
01064 
01065         case AsynchDownload::STATE_SUCCEEDED:
01066         {
01067             // file has transferred successfully, so we can go on and parse it
01068             if (!mainIndex.open(pParam->localFile,ios::in))
01069             {
01070                 // I/O error - no need to inform the user as CCDiskFile is error reporting by default
01071                 goto FAIL;
01072             }
01073             if (!mainIndex.InitLexer())
01074             {
01075                 String_256 strErrorMsg;
01076                 if (pParam->type == SGLib_ClipArt || pParam->type == SGLib_ClipArt_WebThemes)
01077                     strErrorMsg = _T("Failed to parse web clipart index file - web folders cannot be updated");
01078                 else if (pParam->type == SGLib_Font)
01079                     strErrorMsg = _T("Failed to parse web fonts index file - web folders cannot be updated");
01080                 ERROR2(FALSE,strErrorMsg); 
01081                 goto FAIL;
01082             }
01083             LexTokenType tokType = TOKEN_EOL;   
01084             // Initialise lexing routines, and aspects of the lexer
01085             mainIndex.SetDelimiters("\r\n");            // Set token delimiting characters
01086             mainIndex.SetCommentMarker('#');            // Set comment marker char
01087             mainIndex.SetWhitespace("\t");          // Set whitespace chars
01088             const TCHAR* TokenBuf = mainIndex.GetTokenBuf();    // Token buffer remains constant until lexer deinitialisation
01089             String_256 strFolderName("");
01090             String_256 strRelativePath("");
01091             String_256 strRootURL("");
01092             INT32 nFieldOffset = 0;
01093             INT32 nRecords = 0;
01094             while (tokType != TOKEN_EOF)
01095             {   
01096                 mainIndex.GetToken();
01097                 tokType = mainIndex.GetTokenType();
01098                 if (tokType == TOKEN_NORMAL)
01099                 {
01100                     switch (nFieldOffset)
01101                     {
01102                         case 0: // first field
01103                             strFolderName = TokenBuf;
01104                             break;
01105                         case 1: // second field
01106                             strRelativePath = TokenBuf;
01107                             break;
01108                         case 2: // third field
01109                             strRootURL = TokenBuf;
01110                             break;
01111                         default:
01112                             InformError(_R(IDS_CORRUPTEDINDEXFILE), _R(IDS_OK));
01113                             mainIndex.DeinitLexer();
01114                             goto FAIL;
01115                     }
01116                     if (nFieldOffset == 2) // finished reading a line, so try adding the corresponding library
01117                     {
01118                         // append a slash to the root URL if necessary
01119                         if (camStrstr((TCHAR*) strRootURL, _T("file://")))
01120                         {
01121                             if (strRootURL[strRootURL.Length() - 1] != _T('\\'))
01122                                 strRootURL += _T('\\');
01123                         }
01124                         else if (strRootURL[strRootURL.Length() - 1] != _T('/'))
01125                             strRootURL += _T('/');
01126                         Library::URLBase = strRootURL; // set the base URL (this is a static variable at present)
01127                         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpAddWebLibrary));
01128                         if (pOpDesc != NULL)
01129                         {
01130                             AddWebFoldersParam* Param = NULL;
01131                             try
01132                             {
01133                                 Param = new AddWebFoldersParam;
01134                             }
01135                             catch (CMemoryException* pExc)
01136                             {
01137                                 pExc->Delete();
01138                                 Error::SetError(_R(IDS_OUT_OF_MEMORY));
01139                                 InformError();
01140                                 mainIndex.DeinitLexer();
01141                                 goto FAIL;
01142                             }
01143                             // Set up the web library's param
01144                             Param->localFile.SetPathName((TCHAR *) MakeLocalPath(strRelativePath)); // local path of catalog file
01145                             // We change the file extention from .txt to .tmp to avoid overwriting the old one - if any - so that we can compare
01146                             // their sizes and figure out if the web catalog has been modified since the last download
01147                             ERROR3IF(Param->localFile.GetType() != _T("txt") && Param->localFile.GetType() != _T("TXT"),
01148                                 "Catalog files are expected to have the .txt extention");
01149                             Param->localFile.SetType(String_32(_T("tmp")));
01150                             Param->strURL = MakeURL(strRelativePath, strRootURL); // URL of catalog file on our web server
01151                             Param->pLibGal = pParam->pLibGal; // pass on the pointer to the gallery
01152                             Param->strFolderName = strFolderName;
01153                             Param->type = pParam->type; // pass on the gallery type
01154                             // Invoke the operation
01155                             // This will initiate a download of the catalog file - if it succeeds, the folder will be added to the gallery
01156                             pOpDesc->Invoke((OpParam*) Param);
01157                         }                   
01158                         nRecords++; // we've gone through another record
01159                         nFieldOffset = 0; // reset field pointer
01160                     }
01161                     else
01162                     {
01163                         nFieldOffset++;
01164                     }
01165                 }
01166                 else if (tokType == TOKEN_EOL)
01167                 {
01168                     // if the field pointer is not 0, the previous line must have had either less or more than 3 fields - the
01169                     // file might have been corrupted or contains an error, so we skip the rest
01170                     if (nFieldOffset)
01171                     {
01172                         InformError(_R(IDS_CORRUPTEDINDEXFILE), _R(IDS_OK));
01173                         mainIndex.DeinitLexer();
01174                         goto FAIL;
01175                     }
01176                 }
01177             }
01178             // We are now finished with the lexer
01179             mainIndex.DeinitLexer();
01180             mainIndex.close();
01181             // remove the file as we don't need it anymore. Using remove() is OK in this case as the file is not in the cache
01182             _tremove((TCHAR*) String_256(pParam->localFile.GetPath()));
01183             if  (!nRecords) // eof reached without coming across any records - a bit fishy
01184             {
01185                 InformError(_R(IDS_CORRUPTEDINDEXFILE), _R(IDS_OK));
01186                 goto FAIL;
01187             }
01188             // if we got this far we can assume we succeeded
01189             SucceedAndDiscard();
01190             End();
01191             return FALSE;
01192         }
01193 
01194         case AsynchDownload::STATE_FAILED:
01195         {
01196             String_256 strErrorMsg;
01197             strErrorMsg.MakeMsg(_R(IDS_CATALOGDOWNLOADFAILED), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GALLERY_DESCRIPTIONS)),
01198                     (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GETX_CAPTIONS)));
01199             Error::SetError(0, strErrorMsg, 0);
01200             InformError();
01201             goto FAIL;
01202         }
01203 
01204         case AsynchDownload::STATE_ABORTED:
01205         {
01206             // no errror message as this state is the result of a user cancel
01207             goto FAIL;
01208         }
01209 
01210         default:
01211             ERROR3("Error or unrecognized state");
01212             goto FAIL;
01213     }
01214 
01215 FAIL:
01216     // Make sure the file is closed so we can delete it
01217     if (mainIndex.isOpen())
01218         mainIndex.close();
01219     _tremove((TCHAR*) String_256(pParam->localFile.GetPath()));
01220     Success[pParam->type] = FALSE; 
01221     FailAndDiscard();
01222     End();
01223     return FALSE;
01224 }
01225             
01226 
01228 // OpAddWebLibrary
01230 
01231 INT32 OpAddWebLibrary::InstanceCount[8];
01232 INT32 OpAddWebLibrary::FoldersAdded[8];
01233 INT32 OpAddWebLibrary::ErrorCount[8];
01234 INT32 OpAddWebLibrary::CachedFilesUsed[8];
01235 BOOL OpAddWebLibrary::m_bIsSuspended = FALSE;
01236 std::list<DOWNLOAD_HANDLE> OpAddWebLibrary::m_lstPendingDownloads;
01237 
01238 
01239 OpAddWebLibrary::OpAddWebLibrary()
01240 {
01241     // The instance count is incremented in DoWithParam and not here, as at this point the type of the op is not known
01242     pParam = NULL;
01243     GetApplication()->RegisterIdleProcessor(IDLEPRIORITY_LOW, this);
01244     m_hDownload = 0;
01245     OpFlags.HasOwnTimeIndicator = TRUE;
01246 }       
01247 
01248 /********************************************************************************************
01249 
01250 >   OpAddWebLibrary::~OpAddWebLibrary() 
01251 
01252     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01253     Created:    20/12/96
01254     Inputs:     -
01255     Outputs:    -
01256     Returns:    -
01257     Purpose:    OpAddWebLibrary destructor
01258     Errors:     -
01259     SeeAlso:    -
01260 
01261 ********************************************************************************************/
01262 
01263 OpAddWebLibrary::~OpAddWebLibrary()
01264 {
01265     GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_LOW, this);
01266     if (pParam)
01267     {
01268         InstanceCount[pParam->type]--;
01269         delete pParam;
01270     }
01271 }
01272 
01273 /******************************************************************************************
01274 
01275 >   BOOL OpAddWebLibrary::Init()
01276 
01277     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01278     Created:    20/12/96
01279     Returns:    FALSE if it fails (due to lack of memory)
01280     Purpose:    Creates an OpDescriptor for an OpAddWebLibrary operation
01281     SeeAlso:
01282 
01283 ******************************************************************************************/
01284 
01285 BOOL OpAddWebLibrary::Init()
01286 {  
01287 
01288     return RegisterOpDescriptor(
01289         0,                              // Tool ID
01290         _R(IDS_OPADDWEBLIBRARY),                // String resource ID
01291         CC_RUNTIME_CLASS(OpAddWebLibrary),  // Runtime class
01292         OPTOKEN_OPADDWEBLIBRARY,            // Token string
01293         OpAddWebLibrary::GetState,          // GetState function
01294         0,                              // Help ID
01295         0,                              // Bubble ID
01296         0,                              // Resource ID
01297         0                               // Control ID
01298     );
01299 }   
01300 
01301 /******************************************************************************************
01302 
01303 >   OpState OpAddWebLibrary::GetState(String_256* pString, OpDescriptor* pOpDesc)
01304 
01305     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01306     Created:    20/12/96
01307     Purpose:    Returns the OpState of the OpAddWebLibrary operation.
01308     SeeAlso:
01309 
01310 ******************************************************************************************/
01311 
01312 OpState OpAddWebLibrary::GetState(String_256* pString, OpDescriptor* pOpDesc)
01313 {
01314     OpState OpSt;
01315     return(OpSt);
01316 }
01317 
01318 /********************************************************************************************
01319 
01320 >   void OpAddWebLibrary::Do(OpDescriptor*)
01321 
01322     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01323     Created:    20/3/95
01324     Inputs:     OpAddWebLibrary (unused)
01325     Outputs:    -
01326     Returns:    -
01327     Purpose:    
01328     Errors:     Always fails - should not be called
01329     SeeAlso:    -
01330 
01331 ********************************************************************************************/
01332             
01333 void OpAddWebLibrary::Do(OpDescriptor *NotUsed)
01334 {
01335     ERROR3("OpAddWebLibrary does not provide a Do() function - Use DoWithParam");
01336     End();
01337 }
01338 
01339 /******************************************************************************************
01340 >   void OpAddWebLibrary::DoWithParam(OpDescriptor* pOp, OpParam* pAddWebFoldersParam)
01341 
01342     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
01343     Created:    7/01/97
01344     Inputs:     pOp - OpDescriptor as for all Do() functions
01345                     pAddWebFoldersParam - pointer to  AddWebFoldersParam structure
01346     Outputs:    - none
01347     Returns:    -
01348     Purpose:    attempts to download asynchronously the library's catalog (xaraclip.txt) file - in case
01349                     of success a corresponding folder will be added to the clipart gallery
01350     
01351 
01352 ******************************************************************************************/
01353 
01354 void OpAddWebLibrary::DoWithParam(OpDescriptor* pOp, OpParam* pAddWebFoldersParam)
01355 {
01356     AddWebFoldersParam* pInfo = (AddWebFoldersParam*) pAddWebFoldersParam;
01357     if (pInfo == NULL || m_bIsSuspended) 
01358     {
01359         ERROR3IF(!pInfo, "OpAddWebLibrary called with NULL info pointer");
01360         goto FAIL;
01361     }
01362     else
01363     {
01364         if (!pInfo->localFile.IsValid() || pInfo->strURL.IsEmpty() || pInfo->strFolderName.IsEmpty() || !pInfo->pLibGal)
01365         {
01366             ERROR3("OpAddWebLibrary: invalid parameters");
01367             goto FAIL;
01368         }
01369         // Register the file for download
01370         String_256 strDescription(GetStringField((UINT32) pInfo->type, _R(IDS_GALLERY_DESCRIPTIONS)));
01371         strDescription += String_32(_R(IDS_CATALOGFILE));
01372         DOWNLOADINFO downloadInfo;
01373         downloadInfo.strURL = pInfo->strURL;
01374         downloadInfo.strLocalFile = (String_256) pInfo->localFile.GetPath();
01375         downloadInfo.nFileType = TYPE_CATALOG;
01376         downloadInfo.nPriority = AsynchDownload::PRIORITY_NORMAL;
01377         downloadInfo.strDescription = strDescription;
01378         downloadInfo.bHasProgressDlg = TRUE;
01379         downloadInfo.hwndNotifyWindow = 0;
01380         downloadInfo.lNotifyToken = 0;
01381         m_hDownload = InternetManager::RegisterDownload(&downloadInfo);
01382         if (!m_hDownload || m_hDownload == (DOWNLOAD_HANDLE) INVALID_HANDLE_VALUE)
01383         {
01384             String_256 strErrorMsg;
01385             strErrorMsg.MakeMsg(_R(IDS_CATALOGDOWNLOADFAILED), (TCHAR*) (String_256) GetStringField((UINT32) pInfo->type, _R(IDS_GALLERY_DESCRIPTIONS)),
01386                     (TCHAR*) (String_256) GetStringField((UINT32) pInfo->type, _R(IDS_GETX_CAPTIONS)));
01387             Error::SetError(0, strErrorMsg, 0);
01388             InformError();
01389         }
01390         else
01391             m_lstPendingDownloads.push_back(m_hDownload);
01392         pParam = pInfo;
01393         InstanceCount[pParam->type]++; // update instance count
01394         if (InstanceCount[pParam->type] == 1) // first instance, reset counters
01395         {
01396             ErrorCount[pParam->type] = 0; 
01397             FoldersAdded[pParam->type] = 0;
01398             CachedFilesUsed[pParam->type] = 0;
01399         }
01400     }
01401     return;
01402 FAIL:
01403         OpAddWebFolders::Success[pParam->type] = FALSE; 
01404         FailAndExecute(); 
01405         End();
01406 }
01407 
01408 
01409 /******************************************************************************************
01410 >   virtual BOOL OpAddWebLibrary::OnDeathMsg()
01411 
01412     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
01413     Created:    7/01/97
01414     Inputs:     -
01415     Outputs:    - 
01416                         
01417     Returns:    - always TRUE
01418     Purpose:    - aborts the download (so that we won't leak resources) 
01419                         and ends the op on Webster exit
01420 
01421 ******************************************************************************************/
01422 BOOL OpAddWebLibrary::OnDeathMsg()
01423 {
01424     InternetManager::UnregisterDownload(m_hDownload);
01425     End();
01426     return TRUE;
01427 }
01428 
01429 
01430 
01431 /******************************************************************************************
01432 >   virtual BOOL OpAddWebLibrary::OnIdleEvent()
01433 
01434     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
01435     Created:    7/01/97
01436     Inputs:     -
01437     Outputs:    - 
01438                         
01439     Returns:    - TRUE if we want to continue polling, FALSE otherwise
01440     Purpose:    - idle time polling loop; continues until either the download completes
01441                         or the operation is terminated on receiving a death message.
01442                         Different actions are taken according to the state of the download
01443                         on completion (succeeded/aborted/failed)
01444 
01445 ******************************************************************************************/
01446 
01447 
01448 BOOL OpAddWebLibrary::OnIdleEvent()
01449 {
01450     ERROR2IF(!pParam, FALSE, "Unexpected NULL pointer");
01451     if (m_bIsSuspended)
01452         return FALSE;
01453     UINT32 nModifiedFlag = FOLDER_UNMODIFIED; // flag indicating folder's status (FOLDER_UNMODIFIED/FOLDER_UPDATED/FOLDER_NEW)
01454     BOOL bHaveCatalogFile = FALSE; // flag indicating if we should add this folder to the gallery
01455     PathName localFile(pParam->localFile); // path to local (current) catalog file (may not exist if this is a new folder)
01456     localFile.SetType(String_32(_T("txt"))); // should be a .txt file
01457     PathName oldFile(pParam->localFile); // path to old catalog file (may not exist if this is a new folder)
01458     oldFile.SetType(String_32(_T("old")));
01459 
01460     LibraryGallery* pGallery = pParam->pLibGal;
01461     switch (InternetManager::GetDownloadState(m_hDownload))
01462     {
01463         case AsynchDownload::STATE_PENDING:
01464             // download pending, so we continue polling
01465             return TRUE;
01466         
01467         case AsynchDownload::STATE_SUCCEEDED:
01468         {
01469             // Check if the folder exists
01470             BOOL bFolderExists = (pGallery->FindLibrary((String_256) localFile.GetPath())) ? TRUE : FALSE;
01471             // File has transferred successfully, check if we have an older copy
01472             if (_taccess((String_256) localFile.GetPath(), 0) == -1) // not  found
01473             {
01474                 if (DownloadCache::RenameFile((String_256) pParam->localFile.GetPath(), (String_256) localFile.GetPath()))
01475                 {
01476                     InformError(_R(IDS_LOCALFILEERROR), _R(IDS_OK));
01477                     goto FAIL; // couldn't rename it for some reason
01478                 }
01479                 else
01480                 {
01481                     bHaveCatalogFile = TRUE;
01482                     nModifiedFlag = FOLDER_NEW;
01483                 }
01484             }
01485             else // we already have an older version of this file, so we compare the sizes to see if the web version is different
01486             {
01487                 CCDiskFile currentVersion, newVersion;
01488                 if (!currentVersion.open(localFile, ios::in) || !newVersion.open(pParam->localFile, ios::in))
01489                 {
01490                     // Cannot compare sizes due to some I/O error, so in case one of the files is good we'll just use that
01491                     BOOL bCurrentVersionBad = currentVersion.bad(); 
01492                     BOOL bNewVersionBad = newVersion.bad(); 
01493                     currentVersion.close();
01494                     newVersion.close();
01495                     if (!bNewVersionBad)
01496                     {
01497                         // move the new version over the old one
01498                         if (DownloadCache::RemoveFile((String_256) localFile.GetPath())) // failed - can't move
01499                         {
01500                                 InformError(_R(IDS_LOCALFILEERROR), _R(IDS_OK));
01501                                 DownloadCache::RemoveFile((String_256) pParam->localFile.GetPath());
01502                                 goto FAIL;
01503                         }
01504                         else // rename the new version 
01505                         {
01506                             if (DownloadCache::RenameFile((String_256) pParam->localFile.GetPath(), (String_256) localFile.GetPath()))
01507                             {
01508                                 InformError(_R(IDS_LOCALFILEERROR), _R(IDS_OK));
01509                                 goto FAIL; // couldn't rename it for some reason
01510                             }
01511                             else
01512                             {
01513                                 bHaveCatalogFile = TRUE;
01514                                 if (!bFolderExists)
01515                                     nModifiedFlag = FOLDER_NEW;
01516                             }
01517                         }
01518                     }
01519                     else if (!bCurrentVersionBad)
01520                     {
01521                         // the downloaded catalog file may be corrupted, so delete it and use the current one
01522                         DownloadCache::RemoveFile((String_256) pParam->localFile.GetPath());
01523                         bHaveCatalogFile = TRUE;
01524                         if (!bFolderExists)
01525                             nModifiedFlag = FOLDER_NEW;
01526                     }
01527                     else // none of the files can be opened - just clean up and inform the error
01528                     {
01529                         DownloadCache::RemoveFile((String_256) pParam->localFile.GetPath());
01530                         InformError(_R(IDS_LOCALFILEERROR), _R(IDS_OK));
01531                         goto FAIL; 
01532                     }
01533                 }
01534                 else
01535                 {
01536                     if (!bFolderExists)
01537                         nModifiedFlag = FOLDER_NEW;
01538                     else if (newVersion.Size() != currentVersion.Size())
01539                         nModifiedFlag = FOLDER_UPDATED;
01540                     currentVersion.close();
01541                     newVersion.close();
01542                     DownloadCache::RemoveFile((String_256) oldFile.GetPath());
01543                     if (DownloadCache::RenameFile((String_256) localFile.GetPath(), (String_256) oldFile.GetPath())) // failed - can't move
01544                     {
01545                             InformError(_R(IDS_LOCALFILEERROR), _R(IDS_OK));
01546                             DownloadCache::RemoveFile((String_256) pParam->localFile.GetPath());
01547                             goto FAIL;
01548                     }
01549                     else // rename the new version
01550                     {
01551                         if (DownloadCache::RenameFile((String_256) pParam->localFile.GetPath(), (String_256) localFile.GetPath()))
01552                         {
01553                             InformError(_R(IDS_LOCALFILEERROR), _R(IDS_OK));
01554                             goto FAIL; // couldn't rename it for some reason
01555                         }
01556                         else
01557                         {
01558                             bHaveCatalogFile = TRUE;
01559                         }
01560                     }
01561                 }
01562             }
01563         }
01564         break;
01565 
01566         case AsynchDownload::STATE_FAILED:
01567         {
01568             ErrorCount[pParam->type]++;
01569             OpAddWebFolders::Success[pParam->type] = FALSE; 
01570             // If we have on older catalog file we'll use that, otherwise we'll FAIL
01571             if (_taccess((String_256) localFile.GetPath(), 0) == -1) // not  found
01572             {
01573                 goto FAIL;
01574             }
01575             else 
01576             {
01577                 CachedFilesUsed[pParam->type]++;
01578                 bHaveCatalogFile = TRUE;
01579             }
01580         }
01581         break;
01582 
01583         case AsynchDownload::STATE_ABORTED:
01584         {
01585             // no errror message as this state is the result of a user cancel
01586             Suspend(); // ensure we are not reentered while we remove pending downloads
01587             std::list<DOWNLOAD_HANDLE>::iterator listIterator = m_lstPendingDownloads.begin();
01588             INT32 nListSize = m_lstPendingDownloads.size();
01589             for (INT32 i = 0; i < nListSize; i++)
01590                 InternetManager::UnregisterDownload(*listIterator++);
01591             Resume();
01592             goto FAIL;
01593         }
01594 
01595         default:
01596             ERROR3("Error or unrecognized state");
01597             goto FAIL;
01598     }
01599     // Add/update the folder if everything's fine
01600     if (bHaveCatalogFile && (nModifiedFlag == FOLDER_UPDATED || nModifiedFlag == FOLDER_NEW)) 
01601     {
01602         LibraryFile* LibFile = NULL;
01603         try
01604         {
01605             LibFile  = new LibraryFile;
01606         }
01607         catch (CMemoryException* pExc)
01608         {
01609             pExc->Delete();
01610             Error::SetError(_R(IDS_OUT_OF_MEMORY));
01611             InformError();
01612             goto FAIL;
01613         }
01614         String_256 strFileName(localFile.GetFileName());
01615         PathName FilesPath(localFile.GetLocation());
01616         pGallery->RemoveSimilarLibraryGroups(&FilesPath, &strFileName, TRUE, FALSE, NULL);
01617         if (!LibFile->AddSpecificIndex(pGallery, &localFile, pParam->type, &pParam->strFolderName, nModifiedFlag, TRUE))
01618         {
01619             delete LibFile;
01620             goto FAIL;
01621         }
01622         else
01623         {
01624             pGallery->OpenLibFiles.AddTail(LibFile);
01625             LibFile->DoScrollRedraw();
01626             FoldersAdded[pParam->type]++;
01627         }
01628         // If we got this far we can assume we succeeded
01629         SucceedAndDiscard();
01630         goto END;
01631     }
01632     else
01633     {
01634         goto END;
01635     }
01636 
01637 FAIL:
01638     OpAddWebFolders::Success[pParam->type] = FALSE; 
01639     FailAndDiscard();
01640 
01641 END:
01642     // inform errors, if any
01643     if (InstanceCount[pParam->type] == 1 && ErrorCount[pParam->type])
01644     {
01645         String_256 strErrorMsg;
01646         if (FoldersAdded[pParam->type]) // partial failure (we have added some of the folders)
01647         {
01648             if (CachedFilesUsed[pParam->type])
01649                 strErrorMsg.MakeMsg(_R(IDS_CATALOGPARTIALUSECACHE), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GALLERY_DESCRIPTIONS)),
01650                     (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GETX_CAPTIONS)));
01651             else
01652                 strErrorMsg.MakeMsg(_R(IDS_CATALOGDOWNLOADPARTIALFAIL), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GALLERY_DESCRIPTIONS)),
01653                     (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GETX_CAPTIONS)));
01654         }
01655         else
01656         {
01657             if (CachedFilesUsed[pParam->type])
01658                 strErrorMsg.MakeMsg(_R(IDS_CATALOGUSECACHE), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GALLERY_DESCRIPTIONS)),
01659                     (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GETX_CAPTIONS)));
01660             else // failed completely...
01661                 strErrorMsg.MakeMsg(_R(IDS_CATALOGDOWNLOADFAILED), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GALLERY_DESCRIPTIONS)),
01662                     (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GETX_CAPTIONS)));
01663         }
01664         Error::SetError(0, strErrorMsg, 0);
01665         InformError();
01666     }
01667     m_lstPendingDownloads.remove(m_hDownload);
01668     End();
01669     return FALSE;
01670 }
01671             
01673 // Thumbnail downloading
01675 
01676 INT32 OpThumbDownload::ErrorCount[8];
01677 INT32 OpThumbDownload::ThumbsDownloaded[8];
01678 INT32 OpThumbDownload::InstanceCount[8];
01679 BOOL OpThumbDownload::m_bIsSuspended = FALSE;
01680 std::list<SGLibDisplayItem*> OpThumbDownload::m_lstFailedItems;
01681 
01682 
01683 ThumbDownloadParam::ThumbDownloadParam()
01684 {
01685     pItem = NULL;
01686     pOp = NULL;
01687     bSuccess = FALSE;
01688     type = SGLib_Blank;
01689 }
01690 
01691 ThumbDownloadParam::~ThumbDownloadParam()
01692 {
01693 }
01694 
01695 
01696 OpThumbDownload::OpThumbDownload()
01697 {
01698     pParam = NULL;
01699     m_nPercentageCompleted = 0;
01700     m_hDownload = 0;
01701     pGallery = NULL;
01702     GetApplication()->RegisterIdleProcessor(IDLEPRIORITY_LOW, this);
01703     OpFlags.HasOwnTimeIndicator = TRUE;
01704 }       
01705 
01706 /********************************************************************************************
01707 
01708 >   OpThumbDownload::~OpThumbDownload() 
01709 
01710     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01711     Created:    20/12/96
01712     Inputs:     -
01713     Outputs:    -
01714     Returns:    -
01715     Purpose:    OpThumbDownload destructor
01716     Errors:     -
01717     SeeAlso:    -
01718 
01719 ********************************************************************************************/
01720 
01721 OpThumbDownload::~OpThumbDownload()
01722 {
01723     GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_LOW, this);
01724     if (pParam)
01725     {
01726         InstanceCount[pParam->type]--;
01727         delete pParam;
01728     }
01729 }
01730 
01731 /******************************************************************************************
01732 
01733 >   BOOL OpThumbDownload::Init()
01734 
01735     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01736     Created:    20/3/95
01737     Returns:    FALSE if it fails (due to lack of memory)
01738     Purpose:    Creates an OpDescriptor for an OpThumbDownload operation
01739     SeeAlso:
01740 
01741 ******************************************************************************************/
01742 
01743 BOOL OpThumbDownload::Init()
01744 {  
01745     return RegisterOpDescriptor(
01746         0,                              // Tool ID
01747         _R(IDS_OPTHUMBDOWNLOAD),                // String resource ID
01748         CC_RUNTIME_CLASS(OpThumbDownload),  // Runtime class
01749         OPTOKEN_OPTHUMBDOWNLOAD,            // Token string
01750         OpThumbDownload::GetState,          // GetState function
01751         0,                              // Help ID
01752         0,                              // Bubble ID
01753         0,                              // Resource ID
01754         0                               // Control ID
01755     );
01756 }   
01757 
01758 /******************************************************************************************
01759 
01760 >   OpState OpThumbDownload::GetState(String_256* pString, OpDescriptor* pOpDesc)
01761 
01762     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01763     Created:    20/3/95
01764     Purpose:    Returns the OpState of the OpThumbDownload operation.
01765     SeeAlso:
01766 
01767 ******************************************************************************************/
01768 
01769 OpState OpThumbDownload::GetState(String_256* pString, OpDescriptor* pOpDesc)
01770 {
01771     OpState OpSt;
01772     return(OpSt);
01773 }
01774 
01775 
01776 
01777 
01778 /********************************************************************************************
01779 
01780 >   void OpThumbDownload::Do(OpDescriptor*)
01781 
01782     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01783     Created:    20/01/97
01784     Inputs:      (unused)
01785     Outputs:    -
01786     Returns:    -
01787     Purpose:    
01788     Errors:     Always fails - should not be called
01789     SeeAlso:    -
01790 
01791 ******************************************************************************************/
01792         
01793 void OpThumbDownload::Do(OpDescriptor *NotUsed)
01794 {
01795     ERROR3("OpThumbDownload does not provide a Do() function - Use DoWithParam");
01796     End();
01797 }
01798 
01799 /******************************************************************************************
01800 >   void OpThumbDownload::DoWithParam(OpDescriptor* pOp, OpParam* pThumbDownloadParam)
01801 
01802     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
01803     Created:    7/01/97
01804     Inputs:     pOp - OpDescriptor as for all Do() functions
01805                 pThumbDownloadParam - pointer to  ThumbDownloadParam structure . This structure
01806                     must be created on the heap as it should not be destroyed when it goes
01807                     out of scope.
01808     Outputs:    -  none
01809                         Note that this function returns immediately after starting the download, so its success is not relevant
01810                         to the outcome of the download operation.
01811     Returns:    -
01812     Purpose:    - starts a thumbnail download
01813 
01814 ******************************************************************************************/
01815 
01816 void  OpThumbDownload::DoWithParam(OpDescriptor* pOp, OpParam* pThumbDownloadParam)
01817 {
01818     ThumbDownloadParam* pInfo = (ThumbDownloadParam*) pThumbDownloadParam;
01819 
01820     if (pInfo == NULL || pInfo->pItem == NULL)
01821     {
01822         ERROR3("OpThumbDownload called with NULL info pointer");
01823         End();
01824     }
01825     else
01826     {
01827         String_256 thumbPath;
01828         if (!pInfo->pItem->GetThumbFileName(&thumbPath))
01829         {
01830             ERROR3("Can't get thumbnail file name");
01831             goto FAIL;
01832         }
01833         String_256 thumbNetPath = thumbPath;
01834         Library* pLibrary = pInfo->pItem->GetParentLibrary();
01835         if (!pLibrary)
01836         {
01837             ERROR3("Illegal NULL pointer");
01838             goto FAIL;
01839         }
01840         if (!pLibrary->IsWebLibrary())
01841             goto FAIL;
01842         pLibrary->LocalPath2URL(&thumbNetPath);
01843         // Register the file for download
01844         DOWNLOADINFO downloadInfo;
01845         downloadInfo.strURL = thumbNetPath;
01846         downloadInfo.strLocalFile = thumbPath;
01847         downloadInfo.nFileType = TYPE_THUMBNAIL;
01848         downloadInfo.nPriority = AsynchDownload::PRIORITY_HIGH;
01849         downloadInfo.bHasProgressDlg = FALSE;
01850         downloadInfo.hwndNotifyWindow = 0;
01851         downloadInfo.lNotifyToken = 0;
01852         m_hDownload = InternetManager::RegisterDownload(&downloadInfo);
01853         if (!m_hDownload || m_hDownload == (DOWNLOAD_HANDLE) INVALID_HANDLE_VALUE)
01854         {
01855             InformWarning(_R(IDS_THUMBDOWNLOADFAILED), _R(IDS_OK));
01856             if (pGallery = (LibraryGallery*) pInfo->pItem->GetParentGallery())
01857                 pGallery->bThumbDownloading = FALSE; // turn off thumb downloading so we don't flood the user with error messages 
01858             goto FAIL;
01859         }
01860         pParam = pInfo;
01861         if (pGallery = (LibraryGallery*) pInfo->pItem->GetParentGallery())
01862             pGallery->m_lstPendingThumbs.push_back(this);
01863         pInfo->pOp = this;
01864         pInfo->bSuccess = TRUE;
01865         InstanceCount[pParam->type]++;
01866         // thumb downloads occur in "bursts", so when a new burst begins we must reset the error and download counters
01867         // so that we don't get confused by previous errors
01868         if (InstanceCount[pParam->type] == 1)
01869         {
01870             ErrorCount[pParam->type] = 0;
01871             ThumbsDownloaded[pParam->type] = 0;
01872             pGallery->SelectionHasChanged();
01873         }
01874         return;
01875     }
01876 FAIL:
01877         FailAndExecute(); 
01878         End();
01879 }
01880 
01881 /********************************************************************************************
01882 
01883 >   void  OpThumbDownload::End()
01884 
01885     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01886     Created:    21/01/97
01887     Inputs:     -
01888     Outputs:    -
01889     Returns:    -
01890     Purpose:    Ends the download operation, displaying the thumbnail if successful 
01891                 
01892     Errors:     -
01893     SeeAlso:    Operation::End()
01894 
01895 ********************************************************************************************/
01896 
01897 void  OpThumbDownload::End()
01898 {
01899     // Abort the download if still pending - this can only happen if the item is being destroyed
01900     if (m_hDownload && InternetManager::GetDownloadState(m_hDownload) ==  AsynchDownload::STATE_PENDING)
01901         InternetManager::UnregisterDownload(m_hDownload);
01902     LibraryGallery* pGallery = (LibraryGallery*) pParam->pItem->GetParentGallery();
01903     if (pGallery)
01904     {
01905         pGallery->m_lstPendingThumbs.remove(this);
01906         if (InstanceCount[pParam->type] == 1)
01907             pGallery->SelectionHasChanged();
01908     }
01909     if (pParam && pParam->pItem) // tell the item that the thumb download is finished
01910         pParam->pItem->OnThumbDownloadComplete();
01911     Operation::End();
01912 }   
01913 
01914 
01915 
01916 /********************************************************************************************
01917 
01918 >   void  OpThumbDownload::Abort()
01919 
01920     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
01921     Created:    21/01/97
01922     Inputs:     -
01923     Outputs:    -
01924     Returns:    -
01925     Purpose:    Aborts the download operation
01926                 
01927     Errors:     -
01928     SeeAlso:    Operation::End()
01929 
01930 ********************************************************************************************/
01931 
01932 void  OpThumbDownload::Abort()
01933 {
01934     if (m_hDownload && InternetManager::GetDownloadState(m_hDownload) ==  AsynchDownload::STATE_PENDING)
01935         InternetManager::UnregisterDownload(m_hDownload);
01936     LibraryGallery* pGallery = (LibraryGallery*) pParam->pItem->GetParentGallery();
01937     if (pGallery)
01938     {
01939         pGallery->m_lstPendingThumbs.remove(this);
01940         if (InstanceCount[pParam->type] == 1)
01941             pGallery->SelectionHasChanged();
01942     }
01943     Operation::End();
01944 }   
01945 
01946 
01947 
01948 /******************************************************************************************
01949 >   virtual BOOL OpThumbDownload::OnIdleEvent()
01950 
01951     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
01952     Created:    7/01/97
01953     Inputs:     -
01954     Outputs:    - 
01955                         
01956     Returns:    - TRUE if we want to continue polling, FALSE otherwise
01957     Purpose:    - idle time polling loop; continues until either the download completes
01958                         or the operation is terminated by a call to End().
01959                         Different actions are taken according to the state of the download
01960                         on completion (succeeded/aborted/failed)
01961 
01962 ******************************************************************************************/
01963 
01964 BOOL OpThumbDownload::OnIdleEvent()
01965 {
01966     ERROR2IF(!pParam, FALSE, "Unexpected NULL pointer");
01967     if (m_bIsSuspended) // if the Op is suspended we don't do anything
01968         return FALSE;
01969     switch (InternetManager::GetDownloadState(m_hDownload))
01970     {
01971         case AsynchDownload::STATE_PENDING:
01972         {
01973             // check the percentage downloaded so far
01974             INT32 nPercentageCompleted = InternetManager::GetPercentageDownloaded(m_hDownload);
01975             ERROR3IF(nPercentageCompleted == -1, "Invalid download handle");
01976             if (nPercentageCompleted != m_nPercentageCompleted) // we made some progress
01977             {
01978                 m_nPercentageCompleted = nPercentageCompleted;
01979                  if (pParam && pParam->pItem) // tell the item to update itself
01980                      pParam->pItem->OnThumbDownloadProgress(nPercentageCompleted);
01981             }
01982             // the download is still pending, so we continue polling
01983             return TRUE;
01984         }
01985         case AsynchDownload::STATE_SUCCEEDED:
01986         {
01987             // We got lucky
01988             ThumbsDownloaded[pParam->type]++;
01989             SucceedAndDiscard();
01990             goto END;
01991         }
01992         case AsynchDownload::STATE_FAILED:
01993         {
01994             ErrorCount[pParam->type]++;
01995             m_lstFailedItems.push_back(pParam->pItem);
01996             goto FAIL;
01997         }
01998         case AsynchDownload::STATE_ABORTED:
01999         {
02000             // user cancel
02001             goto FAIL;
02002         }
02003         default:
02004             ERROR3("Error or unrecognized state");
02005             goto FAIL;
02006     }
02007 
02008 FAIL:
02009     FailAndDiscard();
02010 END:
02011     // Thumb downloads occur in "bursts", so we report errors only once per burst
02012     if (InstanceCount[pParam->type] == 1 && ErrorCount[pParam->type])
02013     {
02014         String_256 strErrorMsg;
02015         if (ThumbsDownloaded[pParam->type]) // partial failure
02016             strErrorMsg.MakeMsg(_R(IDS_THUMBDOWNLOADPARTIALFAIL), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GETX_CAPTIONS)));
02017         else // complete failure...
02018             strErrorMsg.MakeMsg(_R(IDS_THUMBDOWNLOADFAILED), (TCHAR*) (String_256) GetStringField((UINT32) pParam->type, _R(IDS_GETX_CAPTIONS)));
02019 
02020         // As something went wrong (most likely a connection problem) suspend thumb downloading. This means the 
02021         // user can scroll this gallery without more such error popups. Fixes,with LibraryGallery change, #10471
02022         pGallery->bThumbDownloading = FALSE;
02023         
02024         Error::SetError(0, strErrorMsg, 0);
02025         InformError();
02026     }
02027     End();
02028     return FALSE;
02029 }
02030             
02031 
02032 /******************************************************************************************
02033 >   static INT32 OpThumbDownload::GetLastError(SGLibDisplayItem* pItem)
02034 
02035     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
02036     Created:    7/01/97
02037     Inputs:     - pointer to a SGLibDisplayItem
02038     Outputs:    - 
02039                         
02040     Returns:    - an error code (DOWNLOAD_ERROR) if the item got an error while downloading 
02041                     its thumb, 0 otherwise
02042     Purpose:    - used to decide whether or not we should reattempt a download - if the item got
02043                     an error no further attempts are made before the error is cleared by the user
02044 
02045 ******************************************************************************************/
02046 
02047 INT32 OpThumbDownload::GetLastError(SGLibDisplayItem* pItem)
02048  {
02049     if (m_lstFailedItems.empty())
02050         return 0;
02051     std::list<SGLibDisplayItem*>::iterator listIterator = m_lstFailedItems.begin();
02052     INT32 nListSize = m_lstFailedItems.size();
02053     for (INT32 i = 0; i < nListSize; i++)
02054         if (pItem == *listIterator++)
02055             return DOWNLOAD_ERROR;
02056     return 0;
02057 }
02058 
02059 
02060 /******************************************************************************************
02061 >   static void OpThumbDownload::ClearErrors()
02062 
02063     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
02064     Created:    7/01/97
02065     Inputs:     - 
02066     Outputs:    - 
02067                         
02068     Returns:    - 
02069     Purpose:    - resets the error counter and flushes the list of items with download problems,
02070                         which will allow us to reattempt downloads for these items
02071 
02072 ******************************************************************************************/
02073 
02074 void OpThumbDownload::ClearErrors()
02075 {
02076     memset(&ErrorCount, 0x00, sizeof(ErrorCount));
02077     if (!m_lstFailedItems.empty())
02078     {
02079         std::list<SGLibDisplayItem*>::iterator itrBegin = m_lstFailedItems.begin();
02080         std::list<SGLibDisplayItem*>::iterator itrEnd = m_lstFailedItems.end();
02081         m_lstFailedItems.erase(itrBegin, itrEnd); // zapp the entire list
02082         ERROR3IF(!m_lstFailedItems.empty(), "Warning: failed to empty error list");
02083     }
02084 }
02085 
02086 
02087 // OpAsynchFontInstall 
02089 
02090 
02091 WebFontInstallParam::WebFontInstallParam()
02092 {
02093     bIsTemp = FALSE;
02094     pGallery = NULL;
02095 }
02096 
02097 WebFontInstallParam::~WebFontInstallParam()
02098 {
02099 }
02100 
02101 
02102 /********************************************************************************************
02103   > BOOL OpAsynchFontInstall::Init()
02104 
02105     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
02106     Created:    4/04/97
02107     Returns:    FALSE if it fails (due to lack of memory)
02108     Purpose:    Creates an OpDescriptor for an WebFontInstall operation
02109     SeeAlso:
02110 
02111 ******************************************************************************************/
02112 
02113 
02114 BOOL OpAsynchFontInstall::Init()
02115 {  
02116     return RegisterOpDescriptor(
02117         0,                              // Tool ID
02118         _R(IDS_OPASYNCHFONTINSTALL),                // String resource ID
02119         CC_RUNTIME_CLASS(OpAsynchFontInstall),  // Runtime class
02120         OPTOKEN_OPASYNCHFONTINSTALL,            // Token string
02121         DownloadOp::GetState,           // GetState function
02122         0,                              // Help ID
02123         0,                              // Bubble ID
02124         0,                              // Resource ID
02125         0                               // Control ID
02126     );
02127 }   
02128 
02129 
02130 /******************************************************************************************
02131 >   virtual void OpAsynchFontInstall::OnDownloadSuccess()
02132 
02133     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
02134     Created:    7/01/97
02135     Inputs:     -
02136     Outputs:    - 
02137                         
02138     Returns:    - 
02139     Purpose:    - Performs the actual install using the font file just downloaded.
02140 
02141 ******************************************************************************************/
02142 
02143 void OpAsynchFontInstall::OnDownloadSuccess()
02144 {
02145     // Verify that the pointer is valid & the right type
02146     WebFontInstallParam* pInstallParam =  (WebFontInstallParam*) pParam;
02147     if (!pInstallParam->pGallery || !pInstallParam->pGallery->IsKindOf(CC_RUNTIME_CLASS(FontsSGallery)))
02148     {
02149         ERROR3("Invalid gallery pointer");
02150         return;
02151     }
02152 
02153     // if we have just downloaded a "pfb" file we need to download the
02154     // corresponding .pfm file
02155     String_256 FileExt((String_256)pInstallParam->file.GetType());
02156     FileExt.toLower();
02157     if (FileExt == String_256("pfb"))
02158     {
02159         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpAsynchFontInstall));
02160         if (pOpDesc != NULL)
02161         {
02162             BOOL ok = TRUE;
02163             WebFontInstallParam* Param = new WebFontInstallParam;
02164             ERROR3IF(!Param, "Memory allocation error");
02165             if (!Param)
02166                 return;
02167 
02168             // Set up the parameters which we need to download and install the font
02169             Param->type = TYPE_FONT;
02170             Param->priority = AsynchDownload::PRIORITY_HIGH;
02171             Param->pGallery = pInstallParam->pGallery;
02172             PathName FileName(pInstallParam->file);
02173             FileName.SetType("pfm");
02174             Param->file = FileName;
02175             Param->strDescription = pInstallParam->strDescription;
02176             Param->strAltDescription = pInstallParam->strAltDescription;
02177 
02178             // get the url address of the font
02179             String_256 URL;
02180             UINT32 Count = pInstallParam->strURL.Length() - FileName.GetFileName().Length();
02181             pInstallParam->strURL.Left(&Param->strURL, Count);
02182 
02183             // add the file name
02184             String_256 FName = FileName.GetFileName();
02185             FName.toLower();
02186             Param->strURL += FName;
02187             Param->bIsTemp = FALSE;
02188             Param->Output = &ok;
02189 
02190             // Invoke the operation
02191             pOpDesc->Invoke((OpParam*) Param);
02192             return;
02193         }
02194         else
02195         {
02196             ERROR3("Can't find Op descriptor");
02197         }
02198             return;
02199     }
02200     else if (FileExt == String_256("pfm"))
02201         pInstallParam->file.SetType(String_256("pfb"));
02202     
02203     FontsSGallery* pFontsGallery = (FontsSGallery*) pInstallParam->pGallery; // the cast should be safe at this point
02204     String_64 SlowJob;
02205     SlowJob.MakeMsg(_R(IDS_FONTS_INSTALLING), (TCHAR*) pInstallParam->strAltDescription);
02206     BeginSlowJob(-1, FALSE, &SlowJob);
02207     FontsSGallery::DontUpdate = TRUE;
02208     BOOL ok = pFontsGallery->InstallFont(&pInstallParam->file, &pInstallParam->strDescription, pInstallParam->bIsTemp);
02209     FontsSGallery::DontUpdate = FALSE;
02210     EndSlowJob();
02211     if (!ok)
02212     {
02213         // Problems installing a specified font
02214         String_256 ErrMsg;
02215         ErrMsg.MakeMsg(_R(IDS_PROBLEMS_INSTALLING), (TCHAR *) pInstallParam->strAltDescription);
02216         Error::SetError(0, ErrMsg, 0);
02217         InformError();
02218         Error::ClearError();
02219     }
02220     else
02221     {
02222         // Warn everyone that the fonts have changed - and update our gallery
02223         SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
02224     }
02225     // remove the temporary font file
02226     DownloadCache::RemoveFile((String_256) pInstallParam->file.GetPath());
02227     pFontsGallery->SelectionHasChanged();
02228 }
02229 
02230 
02231 
02232 
02233 // OpAsynchBitmapImport 
02235 
02236 
02237 AsynchBitmapImportParam::AsynchBitmapImportParam()
02238 {
02239     pTargetDoc      = 0;
02240     TagObjectToFill = 0;
02241     TagObjectValid  = false;
02242     pObject         = 0;
02243     pObjectValid    = false;
02244 }
02245 
02246 
02247 /********************************************************************************************
02248   > BOOL OpAsynchBitmapImport::Init()
02249 
02250     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
02251     Created:    4/04/97
02252     Returns:    FALSE if it fails (due to lack of memory)
02253     Purpose:    Creates an OpDescriptor for an AsynchBitmapImport operation
02254     SeeAlso:
02255 
02256 ******************************************************************************************/
02257 
02258 
02259 BOOL OpAsynchBitmapImport::Init()
02260 {  
02261     return RegisterOpDescriptor(
02262         0,                              // Tool ID
02263         _R(IDS_OPASYNCHBITMAPIMPORT),               // String resource ID
02264         CC_RUNTIME_CLASS(OpAsynchBitmapImport), // Runtime class
02265         OPTOKEN_ASYNCHBITMAPIMPORT,         // Token string
02266         DownloadOp::GetState,           // GetState function
02267         0,                              // Help ID
02268         0,                              // Bubble ID
02269         0,                              // Resource ID
02270         0                               // Control ID
02271     );
02272 }   
02273 
02274 
02275 /******************************************************************************************
02276 >   virtual void OpAsynchBitmapImport::OnDownloadSuccess()
02277 
02278     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com> 
02279     Created:    7/01/97
02280     Inputs:     -
02281     Outputs:    - 
02282                         
02283     Returns:    - 
02284     Purpose:    - Performs - if required - the actual import using the bitmap file just downloaded.
02285 
02286 ******************************************************************************************/
02287 
02288 void OpAsynchBitmapImport::OnDownloadSuccess()
02289 {
02290     AsynchBitmapImportParam* pImportParam =  (AsynchBitmapImportParam*) pParam;
02291 
02292     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpBitmapImport));
02293 
02294     if (pOpDesc != 0)
02295     {
02296         BitmapImportParam Param;
02297 
02298         Param.File              = &pImportParam->file;
02299         Param.Result            = TRUE;
02300         Param.FillType          = pImportParam->FillType;
02301         Param.pTargetDoc        = pImportParam->pTargetDoc;
02302         Param.TagObjectToFill   = pImportParam->TagObjectToFill;
02303         Param.TagObjectValid    = pImportParam->TagObjectValid;
02304         Param.pObject           = pImportParam->pObject;
02305         Param.pObjectValid      = pImportParam->pObjectValid;
02306         Param.pSpread           = pImportParam->pSpread;
02307         Param.DropPos           = pImportParam->DropPos;
02308 
02309         // Do it...
02310         pOpDesc->Invoke((OpParam *) &Param);
02311 
02312         if (!Param.Result)
02313             ERROR3("Problem importing file from internet");
02314     }
02315 }
02316 
02317 
02318 /******************************************************************************************
02319 
02320 >   BOOL OpAsynchBitmapImport::OnDocChangingMsg(Document* pChangingDoc, DocChangingMsg::DocState State)
02321 
02322     Author:     Adrian_Stoicar (Xara Group Ltd) <camelotdev@xara.com>
02323     Created:    12/01/97
02324     Returns:    - 
02325     Purpose:    Notifies us if the document we intend to import into is about to be destroyed,
02326                     in which case we should abort the operation
02327     SeeAlso:    MessageHandler::OnDocChangingMsg()
02328 
02329 ******************************************************************************************/
02330 
02331 BOOL OpAsynchBitmapImport::OnDocChangingMsg(Document* pChangingDoc, DocChangingMsg::DocState State)
02332 {
02333     AsynchBitmapImportParam* pImportParam = (AsynchBitmapImportParam*) pParam;
02334     if (pChangingDoc == pImportParam->pTargetDoc && State == DocChangingMsg::ABOUTTODIE)
02335     {
02336         // We end the operation, but don't abort the clipart download - it's up to the user to do that
02337         FailAndExecute(); 
02338         End();
02339     }
02340     return TRUE;
02341 }
02342 
02343 
02344 
02345 
02346 
02347 

Generated on Sat Nov 10 03:45:33 2007 for Camelot by  doxygen 1.4.4