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