htmlfltr.cpp

Go to the documentation of this file.
00001 // $Id: htmlfltr.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 
00099 
00100 #include "camtypes.h" 
00101 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00102 //#include "filtrres.h"
00103 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 #include "htmlfltr.h"
00105 #include "htmllist.h"
00106 #include "backgrnd.h"
00107 //#include "htmldwnd.h"
00108 #include "fileutil.h"
00109 //#include "fixmem.h"       // CCMalloc, CCFree - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "spread.h"       // See FindFirstImportPosition below - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "cutop.h"      // To get the duplication distance
00112 #include "webaddr.h"    // class WebAddress
00113 //#include "docview.h"  //For DocView::FindTopLeftImportPosition - in camtypes.h [AUTOMATICALLY REMOVED]
00114 
00115 //#include "resimmap.h" //For some resources
00116 
00117 
00118 DECLARE_SOURCE("$Revision: 1282 $");
00119 
00120 CC_IMPLEMENT_DYNAMIC(HTMLFilter, BaseTextFilter)
00121 
00122 
00123 #define new CAM_DEBUG_NEW
00124 
00125 //#define MAXTAGLENGTH  255
00126 #define MAXTAGLENGTH    10240   // 10Ko 
00127 
00128 // HTML tags
00129 #define HTMLTAG_UNKNOWN     -1      // unknown tag
00130 #define HTMLTAG_UNUSED      0       // known tags but unused during parsing
00131 
00132 #define HTMLTAG_IMGSRC      1
00133 #define HTMLTAG_BODY        2
00134 #define HTMLTAG_BODYEND     3
00135 #define HTMLTAG_LINK        4
00136 #define HTMLTAG_LINKEND     5
00137 #define HTMLTAG_INPUT       6
00138 #define HTMLTAG_SELECT      7
00139 #define HTMLTAG_HTML        8
00140 #define HTMLTAG_HTMLEND     9
00141 #define HTMLTAG_TITLE       10
00142 #define HTMLTAG_TITLEEND    11
00143 #define HTMLTAG_HEAD        12
00144 #define HTMLTAG_HEADEND     13
00145 #define HTMLTAG_CENTER      14
00146 #define HTMLTAG_CENTEREND   15
00147 #define HTMLTAG_EMBED       16
00148 
00149 
00150 // how many tags ?
00151 #define HTMLNUM_TAGS        16
00152 
00153 BOOL HTMLFilter::ImportingHTML = FALSE;
00154 
00155 // list of all tags
00156 static struct {
00157     TCHAR *tag;     
00158     HTMLTAG_TYPE Id;        
00159 } HTML_Table[] = {  {_T("img"), HTMLTAG_IMGSRC},
00160                     {_T("body"),    HTMLTAG_BODY},
00161                     {_T("input"),   HTMLTAG_INPUT},
00162                     {_T("center"),  HTMLTAG_CENTER},
00163                     {_T("/center"),HTMLTAG_CENTEREND},
00164                     {_T("embed"),   HTMLTAG_EMBED},
00165 
00166                     // The following tags are not used during the parsing,
00167                     // but are used during HowCompatible()
00168                     {_T("a href"),  HTMLTAG_UNUSED},
00169                     {_T("select"),  HTMLTAG_UNUSED},
00170                     {_T("/body"),   HTMLTAG_UNUSED},
00171                     {_T("/a"),      HTMLTAG_UNUSED},
00172                     {_T("html"),    HTMLTAG_UNUSED},
00173                     {_T("/html"),   HTMLTAG_UNUSED},
00174                     {_T("title"),   HTMLTAG_UNUSED},
00175                     {_T("/title"),  HTMLTAG_UNUSED},
00176                     {_T("head"),    HTMLTAG_UNUSED},
00177                     {_T("/head"),   HTMLTAG_UNUSED},
00178                                     
00182 };
00183 
00184 
00185 // Lookup for a token in the list of known HTML tags
00186 static INT32 FindTagId(const TCHAR* Token)
00187 {
00188     //Changed by Graham 29/5/97 so the comparison is case insensitive
00189     for (INT32 i=0;i<HTMLNUM_TAGS;i++)
00190         if (camStricmp(HTML_Table[i].tag,Token) == 0) return (HTML_Table[i].Id);
00191 
00192     return (HTMLTAG_UNKNOWN);
00193 }
00194 
00195 // reverse a string
00196 static BOOL ReverseString(String_256& In, char* OutString)
00197 {
00198     if (In.IsEmpty() && OutString == NULL)
00199         return FALSE;
00200 
00201     char* InString = (TCHAR*)In;
00202 
00203     //INT32 length = strlen(InString)-1;
00204     INT32 length = In.Length()-1;
00205 
00206     char* OutStringTmp = OutString;
00207     
00208     while ( length != -1 )
00209     {
00210         *OutStringTmp = *(InString+length);
00211         OutStringTmp++;
00212         length--;
00213     }
00214 
00215     *OutStringTmp = '\0';
00216 
00217     return TRUE;
00218 }
00219 
00220 
00221 
00222 /********************************************************************************************
00223 >   HTMLFilter::HTMLFilter()
00224 
00225     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00226     Created:    26/03/97
00227     Purpose:    Constructor.  Initialises member variables and load ressources
00228 ********************************************************************************************/
00229 HTMLFilter::HTMLFilter()
00230 {
00231     // Set up filter descriptions.
00232     FilterName.Load(_R(IDS_FILTERNAME_HTML));
00233     FilterInfo.Load(_R(IDS_FILTERINFO_HTML));
00234     FilterID = FILTERID_HTML;
00235 
00236 #ifndef STANDALONE
00237     Flags.CanImport = TRUE;
00238     Flags.CanExport = FALSE;
00239 #else
00240     Flags.CanImport = FALSE;
00241     Flags.CanExport = FALSE;
00242 #endif
00243 
00244     m_WarningsString.Empty();
00245 }
00246 
00247 /********************************************************************************************
00248 >   HTMLFilter::~HTMLFilter()
00249 
00250     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00251     Created:    26/03/97
00252     Purpose:    Destructor.  Frees memory and cleans up.
00253 ********************************************************************************************/
00254 HTMLFilter::~HTMLFilter()
00255 {
00256     //DeInit1();
00257 }
00258 
00259 
00260 /********************************************************************************************
00261 
00262 >   INT32 HTMLFilter::Init()
00263 
00264     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00265     Created:    26/03/97
00266     Returns:    TRUE if init ok
00267     Purpose:    Initialisation of the filter
00268 
00269 ********************************************************************************************/
00270 
00271 INT32 HTMLFilter::Init()
00272 {
00273     // allocate memory for member variables
00274     //if (!Init1())
00275     //  return FALSE;
00276 
00277     // Get the OILFilter object
00278     pOILFilter = new HTMLOILFilter(this);
00279     if (pOILFilter == NULL)
00280         return FALSE;
00281 
00282     // init the Bitmap download operation
00283      if(!OpBitmapDownload::Init())
00284          return FALSE;
00285 
00286     // All ok
00287     return TRUE;
00288 }
00289 
00290 /********************************************************************************************
00291 
00292 >   BOOL HTMLFilter::PreHowCompatible()
00293 
00294     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00295     Created:    26/03/97
00296     Returns:    True if it it worked ok.
00297     Purpose:    Allows a filter or set of filters to take some action or set up variables
00298                 before being called by HowCompatible. A group of filters which share common
00299                 code may require some variable set up before being asked to check the type.  
00300                 Base class does nothing and so works for all filters which do not require it.
00301     SeeAlso:    HowCompatible
00302 
00303 ********************************************************************************************/
00304 
00305 BOOL HTMLFilter::PreHowCompatible()
00306 {
00307     return TRUE;
00308 }
00309 
00310 /********************************************************************************************
00311 
00312 >   INT32 HTMLFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize,UINT32 FileSize)
00313 
00314     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00315     Created:    27/03/97
00316     Returns:    a value <= 10 depending on how we like the file. 10 mean it's HTML, 0 is definetely
00317                 not HTML.
00318     Purpose:    check whether the file is HTML or not
00319                 I've considered that the file is HTML as soon as there is one HTML tags.
00320     SeeAlso:    
00321 
00322 ********************************************************************************************/
00323 
00324 INT32 HTMLFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize,UINT32 FileSize)
00325 {
00326 PORTNOTE("byteorder", "TODO: Check byte ordering")
00327     if (FileSize == 0 || pOILFilter == NULL)
00328         return 0;
00329 
00330     INT32 IsCompatible = 0;
00331     INT32 MaxCompatible = 0;
00332 
00333     // If this file doesn't have the right extension, then claim with a value lower than 10.
00334     // If we don't check the extension, this function will return 10 if it finds any HTML tag ID
00335     // within the buffer, even if the string is not contained within "<>"
00336     //
00337     // The header could be the text part on an EPS file (e.g. v1.1 native file format), so without
00338     // the extension match, this filter may try and import it, instead of leaving it to the EPS filter.
00339     //
00340     // Really, this function should be vamped up so that it spots real HTML tags, rather than just the tag ID
00341     // string. (Markn & Neville 7/8/97)
00342     // Reduced the 6 to 4 as most EPS filters return 5 if the %!Adobe is at the start of the file
00343     // Neville 27/10/97
00344     if (pOILFilter->DoesExtensionOfPathNameMatch(&Filename))
00345         MaxCompatible = 10;
00346     else
00347         MaxCompatible = 4;
00348 
00349     // Convert to lower case
00350     // CAN NOT do this on the main buffer as this would screw up all filters in the
00351     // chain below us. So take a copy of the buffer and then lower case that
00352     char * CopyFilterBuf = (char *) CCMalloc(HeaderSize);
00353     if (CopyFilterBuf == NULL)
00354         return 0;
00355     
00356     // Take a copy of the buffer
00357     memcpy(CopyFilterBuf, HeaderStart, HeaderSize);
00358     // and now finally, lower case it
00359     CopyFilterBuf = _strlwr(CopyFilterBuf);
00360 
00361     // all known HTML tags
00362     for (INT32 i=0;i<HTMLNUM_TAGS;i++)
00363     {
00364 /*      TCHAR* Tag = new TCHAR[camStrlen(HTML_Table[i].tag)+3];
00365         *Tag = '\0';
00366         camStrcat(Tag, "<");
00367         camStrcat(Tag, HTML_Table[i].tag);
00368 */
00369 
00370         // is there an occurence of the string 'HTML_Table[i].tag' in the string 'HeaderStart'
00371         if ( SearchStr(CopyFilterBuf, HTML_Table[i].tag) != NULL )
00372         {
00373             IsCompatible = MaxCompatible;
00374 //          delete [] Tag;
00375             break;
00376 
00377         }
00378 //      delete [] Tag;
00379     }
00380 
00381     CCFree(CopyFilterBuf);
00382 
00383     return IsCompatible;
00384 }
00385 
00386 /********************************************************************************************
00387 
00388 >   BOOL HTMLFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document *DestDoc,
00389                                     BOOL AutoChosen = FALSE, ImportPosition *Pos = NULL, String_256* URL)
00390 
00391     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00392     Created:    26/03/97
00393     Inputs:     Op - pointer to the operation that this input process is associated with.
00394                 pFile - The file that we should load
00395                 DestDoc - 
00396                 URL - URL of the original imported file
00397     Returns:    TRUE if the input operation worked ok, FALSE if not.
00398     Purpose:    
00399     Errors:     Fails (returns FALSE) if the document structure is incorrect, or if there
00400                 is a problem with the bitmap.
00401 
00402 ********************************************************************************************/
00403 
00404 BOOL HTMLFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos,
00405                           KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL)
00406 {
00407     ERROR2IF(Op == NULL, FALSE,         "HTMLFilter::DoImportNULL operation supplied");
00408     ERROR2IF(DestDoc == NULL, FALSE,        "HTMLFilter::DoImportNULL document supplied");
00409 
00410     // Blank our warnings string
00411     m_WarningsString.Empty();
00412     
00413     HTMLFileList* HTMLList = new HTMLFileList;
00414 
00415     // Parse the file and add bitmap names in the list
00416     BOOL ok = ParseHTMLFile(pFile, HTMLList);
00417 
00418     //Now let's get the path to the file we are importing
00419     PathName pthImport=pFile->GetPathName();
00420 
00421     if (URL == NULL)
00422     {
00423         String_256 URLTemp = "";
00424         // import each bitmap
00425         ok = ScanListAndImport(HTMLList, &URLTemp, DestDoc, Op, pthImport);
00426     }
00427     else
00428         ok = ScanListAndImport(HTMLList, URL, DestDoc, Op, pthImport);
00429     
00430     // empty the list 
00431     if ( HTMLList->GetCount())
00432         HTMLList->DeleteAll();
00433     delete HTMLList;
00434 
00435     // Now check the warning about problem data string
00436     // If it has anything in then warn the user about the problem
00437     if (ok && !m_WarningsString.IsEmpty())
00438     {
00439         Error::SetError(0, m_WarningsString, 0);
00440         InformWarning();        
00441     }
00442 
00443     // All ok
00444     return ok;
00445 }
00446 
00447 /********************************************************************************************
00448 
00449 >   BOOL HTMLFilter::ScanListAndImport(HTMLFileList* HTMLList, String_256 &Address, Document *DestDoc, PathName pthImportFile)
00450 
00451     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00452     Created:    30/04/97
00453     Inputs:     HTMLList - the list of bitmap
00454                 Address - the original URL 
00455                 DestDoc -
00456                 pthImportFile - the path name of the HTML file that's being imported
00457     Returns:    TRUE 
00458     Purpose:    scan the list and call DoImportBitmap()
00459     
00460 ********************************************************************************************/
00461 
00462 BOOL HTMLFilter::ScanListAndImport(HTMLFileList* HTMLList, String_256* URL, Document *DestDoc, SelOperation *Op, PathName pthImportFile)
00463 {
00464     ERROR2IF(DestDoc == NULL, FALSE,        "HTMLFilter::ScanListAndImport NULL document supplied");
00465     ERROR2IF(HTMLList == NULL, FALSE,       "HTMLFilter::ScanListAndImport NULL list supplied");
00466     ERROR2IF(URL == NULL, FALSE,        "HTMLFilter::ScanListAndImport NULL URL supplied");
00467 
00468     // make sure there is at least one file in the list
00469     INT32 FileNumber = HTMLList->GetCount();
00470 
00471     //If there were no files in the list, tell the user
00472     ERROR1IF(FileNumber==0, TRUE, _R(IDE_HTMLIMPORT_NOIMAGESINFILE));
00473 
00474     // current file
00475     INT32 FileNum = 0;
00476     //Get the first position at which to import a bitmap
00477     DocCoord PosTranslate=GetImportPosition(DestDoc, FileNum);
00478     
00479 
00480     // first, get a pointer to the first element
00481     HTMLFileListItem* ListBitmaps = (HTMLFileListItem*)HTMLList->GetHead();
00482     String_256 NewName;
00483 
00484     // scan the list
00485     while(ListBitmaps != NULL)
00486     {
00487         // get the Tag ID associated with the bitmap
00488         HTMLTAG_TYPE TagId = ListBitmaps->GetTagId();
00489 
00490         //Get the name of the bitmap
00491         NewName= ListBitmaps->GetFileName();
00492 
00493         // if only it's a web address then I call the bitmap download operation
00494         if (WebAddress::IsHTTP(*URL) || WebAddress::IsHTTP(ListBitmaps->GetFileName()))
00495         {
00496         
00497             // create the webaddress according base and relative URL
00498             WebAddress WebFileName(ListBitmaps->GetFileName());
00499             WebFileName.Combine(*URL);                          // combine the existing URL with the filename
00500 
00501             // reconstitute the web address
00502             String_256 WebPath = WebFileName.GetWebAddress();
00503 
00504             // call the bitmap download op
00505             //Graham 30/5/97: When the asynchronous download op completes,
00506             //it will delete this object
00507             BitmapDownloadParam* Param=new BitmapDownloadParam;
00508     
00509             OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_OPBITMAPDOWNLOAD);
00510 
00511             if (pOpDesc != NULL)
00512             {   
00513                 // get the temporary dir
00514                 TCHAR TempDir[MAX_PATH];
00515                 FileUtil::GetTemporaryPath(MAX_PATH,TempDir);
00516                 // get temp file name
00517                 TCHAR TempFileName[256];
00518                 TCHAR Prefix[] = "BMP"; // the first three letters of the new file name
00519                 FileUtil::GetTemporaryFileName(TempDir,Prefix,0,TempFileName);
00520 
00521                 // extract the original filename
00522                 INT32 lg = WebPath.Length()+1;
00523                 char* TmpPath = new char[lg];
00524                 char* TmpPath2=TmpPath;
00525                 ReverseString(WebPath, TmpPath);
00526                 char* RevFileName = new char [lg];
00527                 char* FileNameTmp = RevFileName;
00528                 while (*TmpPath2!='\\' && *TmpPath2!='/' && *TmpPath2!=NULL)
00529                     *(FileNameTmp++) = *(TmpPath2++);
00530                 *FileNameTmp = '\0';
00531 
00532                 // we download only if there is a file to download
00533                 if (*RevFileName != '\0')
00534                 {
00535                     String_256 StrRevFileName(RevFileName);
00536                     char* FileName = new char[lg];
00537                     ReverseString(StrRevFileName, FileName);
00538                     //delete [] OutPath;
00539                     String_256 StrFileName(TempDir);
00540                     StrFileName += String_256(FileName);
00541 
00542                     // fill in the struct (minimum necessary information)
00543                     Param->type = TYPE_BITMAP;
00544                     Param->priority = AsynchDownload::PRIORITY_NORMAL;
00545                     Param->file = String_256(TempFileName);                 // temporary file name
00546                     //Param->file = StrFileName;                                    // temporary file name
00547                     Param->strURL = WebPath;
00548                     //Param->strDescription = "Bitmap file Download";
00549                     BOOL ok = TRUE;
00550                     Param->Output = &ok;
00551 
00552                     // other information relative to the filter
00553                     //Param->m_Op = Op;                             // I need the Op
00554                     Param->m_FileName = FileName;                   // original filename
00555                     Param->m_DestDoc = DestDoc;                     // I also need the document
00556                     Param->m_TagId = (INT32)TagId;                  // Id of tag associated with the bitmap
00557                     Param->m_FileNum = FileNum;                     // current file
00558                     Param->m_FileNumber = FileNumber;               // number of files
00559                     Param->m_PosTranslate = PosTranslate;           // coordinates of the bitmap in the document
00560                     Param->m_IsCenter = FALSE;          
00561 
00562                     // Invoke the operation
00563                     pOpDesc->Invoke((OpParam*) Param);
00564 
00565                     //Graham 2/6/97: Delete FileName
00566                     delete [] FileName;
00567                 }
00568 
00569                 //Graham 2/6/97: And delete everything we need to delete
00570                 delete [] TmpPath;
00571                 delete [] RevFileName;
00572 
00573             }
00574             else    
00575                 return FALSE;
00576         }
00577         else        // we can directly call the DoImportBitmap as the file is not a URL
00578         {
00579             //Rewritten by Graham 2/6/97
00580 
00581             //First get the name of the file we're going to import
00582             String_256 szFileName = ListBitmaps->GetFileName();
00583 
00584             //Then make a copy of the path of the file we are importing
00585             PathName Path=pthImportFile;
00586 
00587             //And set the file name of that path to the file name we are going
00588             //to import.
00589             Path.SetFileNameAndType(szFileName);
00590 
00591             //And import the bitmap
00592             if (!DoImportBitmap(TagId, Op, DestDoc, Path, FileNum, FileNumber, PosTranslate, FALSE, &NewName))
00593             {
00594                 // Make up an error string adding a default 'Problem loading images. This includes' and
00595                 // then add the pathname.
00596                 if (m_WarningsString.IsEmpty())
00597                 {
00598                     m_WarningsString = String_256(_R(IDE_HTMLIMPORT_BADIMAGESINFILE));
00599                 }
00600 
00601                 String_256 Sep(_R(IDS_TAG_ERROR_LIST_SEP)); 
00602                 String_256 Temp = Path.GetPath();
00603                 // Only add it if there is enough room to fit it all in
00604                 if (Sep.Length() + Temp.Length() + m_WarningsString.Length() < m_WarningsString.MaxLength())
00605                 {
00606                     m_WarningsString += Sep;
00607                     m_WarningsString += Temp;
00608                 }
00609                 else
00610                 {
00611                     // Try using the filename plus extension only
00612                     Temp = Path.GetFileName();
00613                     if (Sep.Length() + Temp.Length() + m_WarningsString.Length() < m_WarningsString.MaxLength())
00614                     {
00615                         m_WarningsString += Sep;
00616                         m_WarningsString += Temp;
00617                     }
00618                 }
00619             }
00620         }
00621         
00622         FileNum++;
00623 
00624         // Update the import position translation
00625         PosTranslate=GetImportPosition(DestDoc, FileNum);
00626         
00627         // Get the next element in the list
00628         ListBitmaps = (HTMLFileListItem*)HTMLList->GetNext(ListBitmaps);
00629     }
00630 
00631     return TRUE;
00632 }
00633 
00634 
00635 /********************************************************************************************
00636 
00637 >   static BOOL HTMLFilter::DoImportBitmap(HTMLTAG_TYPE TagId, SelOperation *Op, Document *DestDoc, 
00638                                 PathName Path, INT32 FileNum, 
00639                                 INT32 FileNumber, DocCoord& PosTranslate, BOOL IsCentre=FALSE)
00640 
00641     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00642     Created:    30/04/97
00643     Inputs:     TagId - tag associated with the bitmap
00644                 Op - pointer to the operation that this input process is associated with.       
00645                 DestDoc - 
00646                 ppImportedBitmap - KernelBitmap for bitmap background
00647                 Path - Path of the file
00648                 FileNum - current file
00649                 FileNumer - number of files
00650     Returns:    TRUE 
00651     Purpose:    how to import (bitmap background or formatting bitmap)
00652     
00653 ********************************************************************************************/
00654 
00655 
00656 BOOL HTMLFilter::DoImportBitmap(HTMLTAG_TYPE TagId, SelOperation *Op, Document *DestDoc, 
00657                                 PathName Path, INT32 FileNum,   INT32 FileNumber, 
00658                                 DocCoord& PosTranslate, BOOL IsCentre, String_256* NewName)
00659 {
00660     BOOL ok = FALSE;
00661     KernelBitmap* pKernelBitmap = NULL;
00662 
00663     if (TagId == HTMLTAG_BODY)
00664     {
00665         // if it's body background then
00666         if (!ImportBitmap(Op, Path, &pKernelBitmap, NULL, FileNum+1, FileNumber, NewName))
00667             return FALSE;
00668         
00669         Spread *pSpread = NULL;
00670 PORTNOTE("spread", "Multi-spread warning!")
00671         pSpread = GetFirstSpread(DestDoc);
00672 
00673         // can't be NULL
00674         if (!pSpread && !pKernelBitmap)
00675             return FALSE;
00676 
00677         // call the background op
00678         OpBackground::MakePageBackground(Op, pSpread, pKernelBitmap);
00679         return TRUE;
00680     }
00681     else
00682     {
00683                 //Taken out by Graham 12/6/97
00684         /*if (IsCentre)
00685         {
00686             // formatting, arbitrary position :-(
00687             PosTranslate.x =  288000;
00688             //PosTranslate.y = -(72000*0.2)*i;
00689             
00690         } */
00691         
00692         //Modified by Graham 30/5/97 so it *doesn't* leak every bitmap it tries
00693         //to import! 8-)
00694         if (!ImportBitmap(Op, Path, &pKernelBitmap, &PosTranslate, FileNum+1, FileNumber, NewName))
00695             return FALSE;
00696 
00697     }
00698 
00699     //And finally, set the name of the bitmap to our new name
00700     if (pKernelBitmap && NewName)
00701         pKernelBitmap->SetName(*NewName);
00702 
00703     return TRUE;
00704 }
00705 
00706 
00707 /********************************************************************************************
00708 
00709 >   static BOOL HTMLFilter::ParseHTMLFile(CCLexFile* pFile, HTMLFileList* HTMLList)
00710 
00711     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com> (rewritten by Graham)
00712     Created:    30/04/97
00713     Inputs:     Op - pointer to the operation that this input process is associated with.
00714                 pFile - The file that we should load
00715                 DestDoc - 
00716     Returns:    TRUE if the input operation worked ok, FALSE if not.
00717     Purpose:    Parse the html file then create the list of bitmaps and finally call ImportBitmap
00718     Errors:     Fails (returns FALSE) if the document structure is incorrect, or if there
00719                 is a problem with the bitmap.
00720 
00721 ********************************************************************************************/
00722 
00723 
00724 BOOL HTMLFilter::ParseHTMLFile(CCLexFile* pFile, HTMLFileList* HTMLList)
00725 {
00726     //First check our parameters
00727     ERROR2IF(pFile == NULL, FALSE,  "HTMLFilter::ParseHTMLFile NULL diskfile supplied");
00728     ERROR2IF(HTMLList == NULL, FALSE, "HTMLFile::PArseHTMLFile NULL HTMLList supplied");
00729 
00730     // Set up some variables
00731     BOOL IsCenter = FALSE;  // this is used for formatting
00732     TCHAR* pTagName = new TCHAR[MAXTAGLENGTH];
00733     TCHAR* pTagAttrib = new TCHAR[MAXTAGLENGTH];
00734     TCHAR* pTokenBuf = new TCHAR[MAXTAGLENGTH];
00735 
00736     //First initialise the lexer
00737     pFile->InitLexer(FALSE, TRUE);
00738 
00739     HTMLTAG_TYPE Token = HTMLTAG_UNKNOWN;
00740 
00741     BOOL ok = TRUE;
00742 
00743     //And now do the parsing until we reach the end of the file
00744     while (!pFile->IsEndOfHTMLFile())
00745     {
00746         //First get an HTML token. This token will either be
00747         //a tag "<xxxx>" or text "xxxx".
00748         //The two parameters mean that we want to ignore any EOL characters
00749         //but we do not want the case to be corrected to upper case
00750         pFile->GetHTMLToken(TRUE, FALSE);
00751 
00752         //Now, if the HTML token is a tag
00753         if (pFile->IsHTMLTag())
00754         {
00755             //Then get the name of the tag
00756             String_256 szTagName=pFile->GetHTMLTagName();
00757 
00758             //Now try and find our token in the HTML table
00759             Token = FindTagId(szTagName);
00760 
00761             switch (Token)
00762             {
00763                 case HTMLTAG_IMGSRC:
00764                 {   
00765                     //It's an IMG tag.
00766                     //Get the value of the SRC parameter. The "FALSE" indicates we shouldn't
00767                     //correct the case of the value
00768                     String_256 szValue=pFile->GetHTMLParameterValue(String_256("SRC"), FALSE);
00769                     
00770                     //And, if we found an SRC parameter value
00771                     if (!szValue.IsEmpty())
00772                     {
00773                         //Create a new HTMLFileListItem
00774                         HTMLFileListItem* NewItem = new HTMLFileListItem((TCHAR*) szValue, Token, FALSE);
00775 
00776                         //And try to add it to the list
00777                         //If it doesn't get added, delete it
00778                         if (!HTMLList->Add(NewItem))
00779                             delete NewItem;
00780                     }
00781                     
00782                 }
00783                 break;
00784 
00785             case HTMLTAG_EMBED:
00786                 {   
00787                     //It's an EMBED tag.
00788                     //Get the value of the SRC parameter. The "FALSE" indicates we shouldn't
00789                     //correct the case of the value
00790                     String_256 szValue=pFile->GetHTMLParameterValue(String_256("SRC"), FALSE);
00791                     
00792                     //And, if we found an SRC parameter value
00793                     if (!szValue.IsEmpty())
00794                     {
00795                         //Create a new HTMLFileListItem
00796                         HTMLFileListItem* NewItem = new HTMLFileListItem((TCHAR*) szValue, Token, FALSE);
00797 
00798                         //And try to add it to the list
00799                         //If it doesn't get added, delete it
00800                         if (!HTMLList->Add(NewItem))
00801                             delete NewItem;
00802                     }
00803                     
00804                 }
00805                 break;
00806 
00807             case HTMLTAG_BODY:
00808                 {
00809                     // It's a BODY tag
00810 
00811                     //Get the value of the BACKGROUND parameter, if any
00812                     String_256 szValue=pFile->GetHTMLParameterValue(String_256("BACKGROUND"), FALSE);
00813 
00814                     //And if we found a value
00815                     if (!szValue.IsEmpty())
00816                     {
00817                         //Create a new HTMLFileListItem
00818                         HTMLFileListItem* NewItem = new HTMLFileListItem((TCHAR*) szValue, Token, FALSE);
00819                         
00820                         //And try to add it to the list
00821                         //If it doesn't get added, delete it
00822                         if (!HTMLList->Add(NewItem))
00823                             delete NewItem;
00824                     }
00825                 }
00826                 break;
00827 
00828             case HTMLTAG_INPUT: // e.g. : <input type=image src="image.gif">
00829                 {
00830                     //It's an input tag
00831 
00832                     //Get the value of the TYPE parameter, if any
00833                     String_256 szTypeValue=pFile->GetHTMLParameterValue(String_256("TYPE"), FALSE);
00834 
00835                     //And if we found a TYPE parameter and its value was
00836                     //IMAGE
00837                     if (camStricmp(szTypeValue, "image")==0)
00838                     {
00839                         // Then look for an "SRC" parameter
00840                         String_256 szSRCValue=pFile->GetHTMLParameterValue(String_256("SRC"), FALSE);
00841 
00842                         //And if we found an SRC parameter value
00843                         if (!szSRCValue.IsEmpty())
00844                         {
00845                             //Then create a new HTMLFileListItem
00846                             HTMLFileListItem* NewItem = new HTMLFileListItem((TCHAR*) szSRCValue, Token, FALSE);
00847 
00848                         //And try to add it to the list
00849                         //If it doesn't get added, delete it
00850                         if (!HTMLList->Add(NewItem))
00851                             delete NewItem;
00852                         }
00853                     }
00854                 }
00855                 break;
00856 
00857             case HTMLTAG_UNUSED:
00858             case HTMLTAG_UNKNOWN:
00859             default:
00860                 break;
00861             }
00862         }
00863 
00864         Token = HTMLTAG_UNKNOWN;
00865     }
00866 
00867     // We are now finished with the lexer
00868     pFile->DeinitLexer();
00869 
00870     delete [] pTagName;
00871     delete [] pTagAttrib;
00872     delete [] pTokenBuf;
00873 
00874     // All ok
00875     return TRUE;
00876 }
00877 
00878 
00879 
00880 /********************************************************************************************
00881 
00882 >   static BOOL HTMLFilter::ImportBitmap(SelOperation *Op, PathName &Path, KernelBitmap** ppImportedBitmap, 
00883                                 DocCoord* pPosTranslate, INT32 FileNum, INT32 FileNumber, String_256* NewName)
00884 
00885     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00886     Created:    14/04/97
00887     Inputs:     Op - 
00888                 Path = the path of the file to import
00889                 ppImportedBitmap - The kernelBitmap I need to set the bitmap background up
00890                 pPosTranslate - used for formatting
00891                 FileNum - number of the file presently imported
00892                 NewName - name of the bitmap
00893     Returns:    TRUE if import ok 
00894     Purpose:    
00895     Errors:     Fails (returns FALSE) if can't import the bitmap
00896                 
00897 ********************************************************************************************/
00898 
00899 BOOL HTMLFilter::ImportBitmap(SelOperation *Op, PathName &Path, KernelBitmap** ppImportedBitmap, 
00900                               DocCoord* pPosTranslate, INT32 FileNum, INT32 FileNumber, String_256* NewName)
00901 {
00902     BOOL ok = FALSE;
00903 
00904     if (!SGLibOil::FileExists(&Path))
00905         return FALSE;
00906 
00907     // which filter to use ?
00908     Filter *pFilter = Filter::GetFirst();
00909     while (pFilter != NULL)
00910     {
00911         // what kind of bitmap is it ?
00912         UINT32 Size = 1024;
00913         INT32 FileSize;
00914         ADDR FilterBuf = pFilter->LoadInitialSegment(Path, &Size, &FileSize);
00915 
00916         // If there has been a problem in the load initial segment then fail now.
00917         if (FilterBuf == NULL)
00918         {
00919             ok = FALSE;
00920             break;
00921         }
00922 
00923         // Inform any filters that we are about to do a HowCompatible call.
00924         // This would allow a set of filters which have common functionality hidden in a
00925         // filter that cannot import and cannot export handle this call and hence set
00926         // itself up. This would allow it to maybe cache a result which should only be
00927         // checked by the first filter in the group. 
00928         pFilter->PreHowCompatible();
00929             
00930         // Change this to be less than 8 as the filters like the Accusoft forms return
00931         // 8 and 9 to make sure that they are last in the chain.
00932         if (pFilter->HowCompatible(Path, FilterBuf, Size, FileSize) > 8)
00933         {
00934             ok = TRUE;
00935             CCFree(FilterBuf);
00936             // This is the filter!
00937             break;
00938         }
00939 
00940         //Free the initial segment
00941         CCFree(FilterBuf);
00942 
00943         // Try the next filter
00944         pFilter = Filter::GetNext(pFilter);
00945     }
00946 
00947     // filter found ?
00948     if (pFilter == NULL || !ok)
00949         return FALSE;       // no filter found
00950 
00951     // now import bitmap
00952 
00953     // First off, we have to try and open the file
00954     CCDiskFile DiskFile(1024, FALSE, TRUE);
00955 
00956     // Get pointer to current doc 'cos we'll need it several times...
00957     Document* pCurDoc = Document::GetCurrent();
00958 
00959     // open the file
00960     if (!DiskFile.open(Path, ios::in | ios::binary))
00961         return FALSE;
00962 
00963     //Graham 15/7/97: Now, we want to import into the top left hand corner of the view
00964     DocView* pDocView=DocView::GetCurrent();
00965 
00966     ERROR2IF(pDocView==NULL, FALSE, "HTMLFilter::DoImport - no current view");
00967 
00968     ImportPosition posImport=pDocView->GetCentreImportPosition();
00969 
00970     //And add on the amount by which to translate the bitmap
00971     if (pPosTranslate)
00972     {
00973         posImport.Position.x+=pPosTranslate->x;
00974         posImport.Position.y+=pPosTranslate->y;
00975     }
00976 
00977     // then import the file
00978     if (!pFilter->DoImport(Op, &DiskFile, pCurDoc, FALSE, NULL, ppImportedBitmap, pPosTranslate, NULL))
00979     {
00980         // Close the file again
00981         if (DiskFile.isOpen())
00982             DiskFile.close();
00983 
00984         Error::ClearError();    // remove the error so it won't get reported
00985 
00986         return FALSE;
00987     }
00988 
00989     // Close the file again
00990     if (DiskFile.isOpen())
00991         DiskFile.close();
00992 
00993     return TRUE;
00994 }
00995 
00996 
00997 /********************************************************************************************
00998 
00999 >   BOOL HTMLFilter::GetTag(TCHAR* pTokenBuf, TCHAR* pTagName, const TCHAR* TokenBuffer)
01000 
01001     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
01002     Created:    03/04/97
01003     Inputs:     TokenBuffer: e.g. : 'img src="image.gif"'
01004     Returns:    TRUE if it had found another known HTML tag
01005     Purpose:    extract the TAGNAME from the tokenbuf 
01006                 (e.g.: will extract 'img' from 'img src=image.gif')
01007     Errors:     
01008 
01009 ********************************************************************************************/
01010 
01011 BOOL HTMLFilter::GetTag(TCHAR* pTokenBuf, TCHAR* pTagName, const TCHAR* TokenBuffer)
01012 {
01013     if (TokenBuffer == NULL)
01014         return FALSE;
01015 
01016     // convert to lower case
01017     camStrcpy(pTokenBuf, TokenBuffer);
01018     pTokenBuf = _strlwr(pTokenBuf);
01019 
01020     // all known HTML tags
01021     for (INT32 i=0;i<HTMLNUM_TAGS;i++)
01022     {
01023         const TCHAR* TokenBufTmp = pTokenBuf;
01024         *pTagName = '\0';
01025         TCHAR* TagNameTmp = pTagName;
01026         TCHAR* HTML_Tag = HTML_Table[i].tag;
01027 
01028         while(*TokenBufTmp == *HTML_Tag && *TokenBufTmp!=NULL && *HTML_Tag!=NULL)
01029         {
01030             *(TagNameTmp++) = *(TokenBufTmp++);
01031             HTML_Tag++;
01032         }
01033         if (*HTML_Tag == NULL)
01034         {
01035             *TagNameTmp = '\0';
01036             break;
01037         }
01038     }
01039 
01040     return TRUE;
01041 }
01042 
01043 
01044 /********************************************************************************************
01045 
01046 >   BOOL HTMLFilter::GetAttribute(const TCHAR* AttrName, TCHAR* pTokenBuf, TCHAR* pTagAttrib)
01047 
01048     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
01049     Created:    03/04/97
01050     Inputs:     AttrName - store the name of the tag attribute (e.g. : img, or src....)
01051     Returns:    TRUE if it had extracted the attribute
01052     Purpose:    Extract the attribute from the tag
01053     Errors:     
01054 
01055 ********************************************************************************************/
01056 
01057 BOOL HTMLFilter::GetAttribute(const TCHAR* AttrName, const TCHAR* pTokenBuf, TCHAR* pTagAttrib)
01058 {
01059     // they shouldn't be NULL
01060     if (AttrName == NULL && pTokenBuf == NULL && pTagAttrib == NULL)
01061         return FALSE;
01062 
01063     // e.g. : 'img src=image.gif'
01064     // we move the pointer until 'src'
01065     const TCHAR* TokenBufTmp = pTokenBuf;
01066     TCHAR* TagAttribute = pTagAttrib;
01067     while (TRUE)
01068     {
01069         const TCHAR* AttrNameTmp = AttrName;
01070         // find the first occurence of the first letter of AttrName
01071         TokenBufTmp = strchr(TokenBufTmp, (INT32)(*AttrName));
01072         if (TokenBufTmp == NULL)
01073             return FALSE;
01074 
01075         // extract "AttrName" from TokenBuf
01076         while ( *TokenBufTmp == *AttrNameTmp && *AttrNameTmp!=NULL && *TokenBufTmp!=NULL)
01077         {
01078             TokenBufTmp++;
01079             AttrNameTmp++;
01080         }
01081         if (*TokenBufTmp == NULL)
01082             return FALSE;
01083         if (*AttrNameTmp == NULL)
01084             break;
01085     }
01086 
01087     // move the pointer to reach the first letter
01088     while ( (*TokenBufTmp=='=' || *TokenBufTmp==' ' ||
01089             *TokenBufTmp=='\t' || *TokenBufTmp=='\"') && 
01090             *TokenBufTmp!=NULL)
01091     {
01092         TokenBufTmp++;
01093     }
01094     if (*TokenBufTmp == NULL)
01095         return FALSE;
01096 
01097     // extract the attribute
01098     while ( *TokenBufTmp!='\"' && *TokenBufTmp!=' ' && *TokenBufTmp!='\t' && *TokenBufTmp!=NULL)
01099     {
01100         *(TagAttribute++) = *(TokenBufTmp++);
01101     }
01102 
01103     *TagAttribute = '\0';
01104 
01105     return TRUE;
01106 }
01107 
01108 
01109 
01110 /********************************************************************************************
01111 
01112 >   TCHAR* HTMLFilter::SearchStr(const char* A, const char* B)
01113 
01114     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
01115     Created:    09/04/97
01116     Inputs:     A - string to search
01117                 B- string to search for
01118                 
01119     Returns:    a pointer to the first occurence of B
01120     Purpose:    Search for string B in string A
01121     Errors:     
01122 
01123 ********************************************************************************************/
01124 
01125 TCHAR* HTMLFilter::SearchStr(const char* A, const char* B)
01126 {
01127     if (A==NULL || B==NULL)
01128         return NULL;
01129 
01130     return ((TCHAR*)strstr(A, B));
01131 }
01132 
01133 /********************************************************************************************
01134 
01135 >   DocCoord HTMLFilter::GetImportPosition(Document* pdocTarget, INT32 iPosNumber)
01136 
01137     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01138     Created:    05/6/97
01139     Inputs:     pdocTarget      - The document to import into
01140                 iPosNumber      - The number of the position
01141                 
01142     Returns:    The offset by which to offset bitmap number iPosNumber.
01143     Purpose:    Finds the offset by which to offset the iPosNumber-th bitmap
01144                 imported.
01145 
01146                 The first bitmap imported is offset by 0,0.
01147                 
01148                 Then the next bitmap is offset by the standard offset
01149                 which the duplication operation uses.
01150 
01151                 And so on: the offset of the Nth bitmap equals
01152                 the offset of the (N-1)th bitmap plus the duplication offset.
01153 
01154                 This carries on until the offset is such so that the offset
01155                 of the Mth bitmap would place it off the spread.
01156 
01157                 Instead, then, the offset of the Mth bitmap is the horizontal 
01158                 component of the duplication offset. And then we go
01159                 back to the general iterative rule.
01160 
01161                 Not very well explained I'm afraid but I've got to get this done.
01162 
01163     Errors:     Null parameters
01164 
01165 ********************************************************************************************/
01166 
01167 DocCoord HTMLFilter::GetImportPosition(Document* pdocTarget, INT32 iPosNumber)
01168 {
01169     //First check our parameter
01170     ERROR2IF(pdocTarget==NULL, DocCoord(-1,-1), "HTMLFilter::GetFirstImportPosition - NULL parameter");
01171 
01172     //This variable will remember how many times we have returned the import position
01173     //back to the top left hand corner
01174     INT32 iReturned=0;
01175 
01176     //Now get the first spread in the document
01177 PORTNOTE("spread", "Multi-spread warning!")
01178     Spread* psprFirst=pdocTarget->FindFirstSpread();
01179 
01180     //Do some checking
01181     ERROR2IF(psprFirst==NULL, DocCoord(-1, -1), "HTMLFilter::GetFirstImportPosition - no spread in document");
01182 
01183     //And get its bounding rectangle
01184     DocRect rectBounding;
01185     psprFirst->GetPagesRect(&rectBounding);
01186 
01187     //Now translate that rectangle so that its top left hand corner is at
01188     //0,0
01189     DocCoord dcTopLeft(rectBounding.lo.x, rectBounding.hi.y);
01190 
01191     rectBounding.Translate(-dcTopLeft.x, -dcTopLeft.y);
01192     
01193     //Now, the first bitmap will be imported at 0,0
01194     DocCoord dcThisPosition(0, 0);
01195 
01196     //And this is the standard duplication offset
01197 //  DocCoord dcOffset(OpDuplicate::DuplicatePlacementX, OpDuplicate::DuplicatePlacementY);
01198     DocCoord dcOffset = pdocTarget->GetDuplicationOffset();
01199 
01200 
01201 
01202     //Do the following a number of times equal to the number
01203     //of the bitmaps we are importing
01204     for (INT32 i=0; i<iPosNumber; i++)
01205     {
01206         //Increase dcThisPosition by dcOffset
01207         dcThisPosition.x=dcThisPosition.x+dcOffset.x;
01208         dcThisPosition.y=dcThisPosition.y+dcOffset.y;
01209         
01210         //Now, if that import position is outside the spread
01211         if (!rectBounding.ContainsRectCoord(dcThisPosition))
01212         {
01213             //Then set the import position back to the top left hand corner of the
01214             //spread
01215             dcThisPosition=DocCoord(rectBounding.lo.x, rectBounding.hi.y);
01216 
01217             //And increase our count of the number of times we have set the 
01218             //import position back to the top left hand corner
01219             iReturned++;
01220 
01221             //And offset the import position by the horizontal component
01222             //of the duplication distance, a number of times equal to 
01223             //the number of times we have reset the import position
01224             dcThisPosition.x+=dcOffset.x*iReturned;
01225 
01226             //Now, if *that* import position is outside the spread
01227             if (!rectBounding.ContainsRectCoord(dcThisPosition))
01228             {
01229                 //Then go back to the very first import position
01230                 //and set iReturned to zero
01231                 dcThisPosition=DocCoord(rectBounding.lo.x, rectBounding.hi.y);
01232 
01233                 iReturned=0;
01234             }
01235         }
01236 
01237     }
01238 
01239     //And return our calculated import position
01240     return dcThisPosition;
01241 }
01242 
01243 
01244 
01245 

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