Bugfix : Zooming works correct, no more errors on screen.
[xara-cairo.git] / wxOil / stemplate.cpp
blobd1cf7e57e8b2c7826f7c5994e369ed8bdb9601eb
1 // $Id: stemplate.cpp 1282 2006-06-09 09:46:49Z alex $
2 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
3 ================================XARAHEADERSTART===========================
5 Xara LX, a vector drawing and manipulation program.
6 Copyright (C) 1993-2006 Xara Group Ltd.
7 Copyright on certain contributions may be held in joint with their
8 respective authors. See AUTHORS file for details.
10 LICENSE TO USE AND MODIFY SOFTWARE
11 ----------------------------------
13 This file is part of Xara LX.
15 Xara LX is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License version 2 as published
17 by the Free Software Foundation.
19 Xara LX and its component source files are distributed in the hope
20 that it will be useful, but WITHOUT ANY WARRANTY; without even the
21 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License along
25 with Xara LX (see the file GPL in the root directory of the
26 distribution); if not, write to the Free Software Foundation, Inc., 51
27 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 ADDITIONAL RIGHTS
31 -----------------
33 Conditional upon your continuing compliance with the GNU General Public
34 License described above, Xara Group Ltd grants to you certain additional
35 rights.
37 The additional rights are to use, modify, and distribute the software
38 together with the wxWidgets library, the wxXtra library, and the "CDraw"
39 library and any other such library that any version of Xara LX relased
40 by Xara Group Ltd requires in order to compile and execute, including
41 the static linking of that library to XaraLX. In the case of the
42 "CDraw" library, you may satisfy obligation under the GNU General Public
43 License to provide source code by providing a binary copy of the library
44 concerned and a copy of the license accompanying it.
46 Nothing in this section restricts any of the rights you have under
47 the GNU General Public License.
50 SCOPE OF LICENSE
51 ----------------
53 This license applies to this program (XaraLX) and its constituent source
54 files only, and does not necessarily apply to other Xara products which may
55 in part share the same code base, and are subject to their own licensing
56 terms.
58 This license does not apply to files in the wxXtra directory, which
59 are built into a separate library, and are subject to the wxWindows
60 license contained within that directory in the file "WXXTRA-LICENSE".
62 This license does not apply to the binary libraries (if any) within
63 the "libs" directory, which are subject to a separate license contained
64 within that directory in the file "LIBS-LICENSE".
67 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
68 ----------------------------------------------
70 Subject to the terms of the GNU Public License (see above), you are
71 free to do whatever you like with your modifications. However, you may
72 (at your option) wish contribute them to Xara's source tree. You can
73 find details of how to do this at:
74 http://www.xaraxtreme.org/developers/
76 Prior to contributing your modifications, you will need to complete our
77 contributor agreement. This can be found at:
78 http://www.xaraxtreme.org/developers/contribute/
80 Please note that Xara will not accept modifications which modify any of
81 the text between the start and end of this header (marked
82 XARAHEADERSTART and XARAHEADEREND).
85 MARKS
86 -----
88 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
89 designs are registered or unregistered trademarks, design-marks, and/or
90 service marks of Xara Group Ltd. All rights in these marks are reserved.
93 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
94 http://www.xara.com/
96 =================================XARAHEADEREND============================
100 #include "camtypes.h"
101 #include "webaddr.h"
103 //#include "ccobject.h" - in camtypes.h [AUTOMATICALLY REMOVED]
104 //#include "pathname.h" - in camtypes.h [AUTOMATICALLY REMOVED]
106 //#include "resimmap.h"
109 DECLARE_SOURCE("$Revision: 1282 $");
111 CC_IMPLEMENT_DYNAMIC(WebAddress, CCObject)
113 /**********************************************************************************************
115 > WebAddress::WebAddress()
117 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
118 Created: 17/9/96
119 Inputs: None
120 Outputs: None
121 Returns: None
122 Purpose: Default WebAddress class constructor
123 Errors: None
125 **********************************************************************************************/
127 WebAddress::WebAddress()
129 Absolute = FALSE;
132 /**********************************************************************************************
134 > WebAddress::WebAddress(const WebAddress& newPath)
136 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
137 Created: 17/9/96
138 Inputs: InAddress
139 Outputs: None
140 Returns: None
141 Purpose: Copy Constructor for the WebAddress class
142 Errors: None
144 **********************************************************************************************/
146 WebAddress::WebAddress(const WebAddress& InAddress)
148 Absolute = InAddress.Absolute;
150 Scheme=InAddress.Scheme;
151 NetLoc=InAddress.NetLoc;
152 Path=InAddress.Path;
153 Parameters=InAddress.Parameters;
154 Query=InAddress.Query;
155 Fragment=InAddress.Fragment;
158 /**********************************************************************************************
160 > WebAddress& WebAddress::operator=(const WebAddress& InAddress)
162 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
163 Created: 17/9/96
164 Inputs: InAddress
165 Outputs: None
166 Returns: None
167 Purpose: Assignment operator
168 Errors: None
170 **********************************************************************************************/
172 WebAddress& WebAddress::operator=(const WebAddress& InAddress)
174 Absolute = InAddress.Absolute;
176 Scheme=InAddress.Scheme;
177 NetLoc=InAddress.NetLoc;
178 Path=InAddress.Path;
179 Parameters=InAddress.Parameters;
180 Query=InAddress.Query;
181 Fragment=InAddress.Fragment;
183 return *this;
186 /**********************************************************************************************
188 > WebAddress::WebAddress(const String_256&, WebCorrectFlags wcfToUse=WebCorrectFlags())
190 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
191 Created: 17/9/96
192 Inputs: StringToParse String representing the path.
193 wcfToUse Flags indicating how the string should be
194 corrected before it is parsed. Some options
195 are: www.xara.com should be corrected to
196 http://www.xara.com/, d:\dir1\filename.gif
197 should be corrected to file://d|/dir1/filename.gif.
199 Outputs: None
200 Returns: None
201 Purpose: Corrects the string, then parses the corrected string.
202 SeeAlso: WebCorrectFlags
204 **********************************************************************************************/
206 WebAddress::WebAddress(const String_256& StringToParse, WebCorrectFlags wcfToUse)
208 //First make a copy of the string we've been given
209 String_256 strCopy=StringToParse;
211 //And correct the copy
212 Correct(&strCopy, wcfToUse);
214 //Then parse the corrected string
215 Parse(strCopy);
217 //And finally set the class's flags
218 SetFlags();
221 /**********************************************************************************************
223 > INT32 WebAddress::operator==(WebAddress& Other)
225 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
226 Created: 10/6/97
227 Inputs: -
229 Outputs: -
230 Returns: -
231 Purpose: Equality operator
232 SeeAlso: WebCorrectFlags
234 **********************************************************************************************/
236 INT32 WebAddress::operator==(WebAddress& Other)
238 return (Scheme==Other.Scheme &&
239 NetLoc==Other.NetLoc &&
240 Path==Other.Path &&
241 Parameters==Other.Parameters &&
242 Query==Other.Query &&
243 Fragment==Other.Fragment);
248 /**********************************************************************************************
250 > WebAddress::Parse()
252 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
253 Created: 1/9/96
254 Inputs: String representing the full URL
255 Outputs: None
256 Returns: None
257 Purpose: Takes the string and splits it into its component parts.
259 Notes: The parsing rules follow the guidelines given in
260 http://ds.internic.net/rfc/rfc1808.txt. So there!
261 (That means, don't change them unless you know what you're doing).
263 These rules can be pretty unforgiving...if you get the query, fragment
264 and parameters in the wrong order, the parsing rules don't accommodate
265 this. But I'm sticking with the rules because of funny things like...
266 a query could, theoretically, have a # in the middle of it.
268 Note that this parsing function should split InString into
269 several different strings and put those strings into
270 member variables, but it should not change the actual text
271 of InString.
273 In other words, if you concatenate the following member
274 variables:
276 Scheme+NetLoc+Path+Parameters+Query+Fragment
278 You should *always* end up with the string InString you passed into
279 the function.
281 *Please* don't change the parsing rules unless you really know what
282 you're doing and have read the guideline document referred to above.
283 The parsing that is performed below may look easy, but it is
284 performed by qualified professionals and is extremely dangerous.
285 Do not imitate the parsing that you see below at home.
287 **********************************************************************************************/
289 BOOL WebAddress::Parse(const String_256& InString)
291 //First set all the member strings to zero.
292 Absolute=FALSE;
294 Scheme.Empty();
295 NetLoc.Empty();
296 Path.Empty();
297 Parameters.Empty();
298 Query.Empty();
299 Fragment.Empty();
300 Scheme.Empty();
302 //If InString="", that's all we need to do...
303 if (InString.IsEmpty())
304 return TRUE;
306 //And set up a couple of strings we can play around with
307 String_256 StringToParse=InString;
309 //If the parse string is empty, we need do nothing, because all our fields are
310 //already blank. Return TRUE.
312 if (StringToParse.IsEmpty()) return TRUE;
314 //Now set up some strings. These are all hard coded cos it reduces code size
315 //This shouldn't matter for purposes of internationalisation, because URLs
316 //are an international system.
317 String_256 sNetloc="//";
319 INT32 iLowerCaseA=INT32 ('a');
320 INT32 iLowerCaseZ=INT32 ('z');
321 INT32 iUpperCaseA=INT32 ('A');
322 INT32 iUpperCaseZ=INT32 ('Z');
324 char cBackslash='\\';
325 char cSlash='/';
326 char cHash='#';
327 char cColon=':';
328 char cQuestionmark='?';
329 char cSemicolon=';';
331 //First we want to find the Fragment section of the URL.
332 //This should start with a #
333 INT32 iFound=StringToParse.FindNextChar(cHash);
335 //If we've found a #, copy the whole identifier into the "fragment" member variable
336 if(iFound>=0)
337 StringToParse.Split(&StringToParse, &Fragment, iFound, FALSE);
339 //Now search the parse string for a scheme (the bit at the start,
340 //e.g. http:). To do this we search for a colon.
341 iFound=StringToParse.FindNextChar(cColon);
343 //Have we found a colon?
344 if(iFound>=0)
346 BOOL IsAScheme=TRUE;
348 //Yes. We now need to check that everything before that colon is a letter.
349 for (INT32 iStringPtr=(iFound-1); iStringPtr>=0; iStringPtr--)
351 if (!StringBase::IsAlpha(StringToParse[iStringPtr]))
353 IsAScheme=FALSE;
358 //Was everything before the colon a letter?
359 if (IsAScheme)
360 //Yes, so split the string after that colon
361 StringToParse.Split(&Scheme, &StringToParse, iFound, TRUE);
364 //Now look for a network location
365 iFound=StringToParse.Sub(sNetloc);
367 //Have we found a //?
368 if(iFound>=0)
370 //Yes. So find the next / (or the end of the string)
372 //To do this, set up a string pointer that starts from two
373 //characters after iFound
374 INT32 iStringPtr=iFound+2;
376 //And move that string pointer forwards until
377 //either it points at a slash or it reaches the end of the
378 //string
379 while (iStringPtr<StringToParse.Length() && StringToParse[iStringPtr]!=cSlash)
381 iStringPtr++;
384 StringToParse.Split(&NetLoc, &StringToParse, iStringPtr, FALSE);
387 //Now look for query information.
388 iFound=StringToParse.FindNextChar(cQuestionmark);
390 //Have we found a question mark?
391 if(iFound>=0)
392 StringToParse.Split(&StringToParse, &Query, iFound,FALSE);
395 //Now look for parameter information.
396 iFound=StringToParse.FindNextChar(cSemicolon);
398 //Have we found a semicolon?
399 if(iFound>=0)
400 StringToParse.Split(&StringToParse, &Parameters, iFound, FALSE);
402 //And whatever is left is the path.
403 Path=StringToParse;
406 return TRUE;
409 /**********************************************************************************************
411 > void WebAddress::SetFlags()
413 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
414 Created: 17/9/96
415 Purpose: Sets the Web Address flags - at the moment the only flag is Absolute - by
416 looking at the Web Address string member variables.
418 **********************************************************************************************/
420 BOOL WebAddress::SetFlags()
422 Absolute=!Scheme.IsEmpty();
424 return TRUE;
427 /**********************************************************************************************
429 > void WebAddress::Combine(WebAddress Base)
431 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
432 Created: 17/9/96
433 Inputs: A Base URL
434 Purpose: Combines this Web Address with a base Web Address.
436 This is used when this Web Address is relative and the base
437 web address is the address of the current document. This function
438 allows this Web Address to inherit the appropriate components of the
439 base address so this Address becomes relative.
441 This is quite hard to explain, so here's an example: if this Web
442 address is "myfile.xar" and the base Web Address is
443 "http://www.xara.com/currentfile.xar" then this function makes
444 this Web Address into "http://www.xara.com/myfile.xar".
446 This function follows the guidelines given in some international
447 standard somewhere. (The one I was talking about above)
449 Because it follows these guidelines (almost) exactly, this function
450 contains one hell of a lot of loops within loops. Sorry! I've tried
451 to comment them helpfully.
453 Notes: The parsing rules follow the guidelines given in
454 http://ds,internic.net/rfc/rfc1808.txt.
456 *Please* don't change the parsing rules unless you really know what
457 you're doing and have read the guideline document referred to above.
458 The code below is written according to that document. Do not imitate
459 at home what you have seen on Gladiators, etc, etc.
461 **********************************************************************************************/
463 void WebAddress::Combine(WebAddress Base)
465 //Strings are hard coded to reduce code size
466 String_256 sSlashDotSlash="/./";
467 String_256 sSlashDotDotSlash="/../";
469 TCHAR cSlash='/';
471 //Now start the parsing.
473 //If the base Web Address is empty, this Web Address does not change
474 if (Base.IsEmpty())
475 goto ReturnNow;
477 //If this Web Address is empty, then it inherits everything from the
478 //base Web Address
479 if (IsEmpty())
481 Absolute = Base.Absolute;
483 Scheme=Base.Scheme;
484 NetLoc=Base.NetLoc;
485 Path=Base.Path;
486 Parameters=Base.Parameters;
487 Query=Base.Query;
488 Fragment=Base.Fragment;
489 goto ReturnNow;
492 //If this Web Address is absolute, it does not change
493 if (IsAbsolute())
494 goto ReturnNow;
496 //If none of the above apply, this Web Address inherits the scheme of
497 //the Base address
498 Scheme=Base.Scheme;
500 //If this Web Address has a net location, we need do nothing more to it.
501 if (!NetLoc.IsEmpty())
502 goto ReturnNow;
504 //Otherwise, this Web Address inherits the Net Location of the base address.
505 NetLoc=Base.NetLoc;
507 //If the path of this Web Address starts with a slash, it is non-relative
508 //and we need only add it on to the Net Location
509 if ((*(Path))==cSlash) goto ReturnNow;
512 //This is where all the loops within loops start. Hang on to your curly brackets.
514 //Does this Web Address have a path?
515 if (!Path.IsEmpty())
517 //Yes. Then the full path is given by:
518 //The Base URL path up to the rightmost slash + the URL of this Web Address
520 //This string will hold the base URL path up to the rightmost slash
521 String_256 sTempPath="";
523 //First find the rightmost slash in Base.Path
524 INT32 iFound=Base.Path.ReverseFind(cSlash);
526 //Did we find a slash?
527 if (iFound>=0)
529 //Yes. So copy everything up to that slash into sTempPath
532 Base.Path.Split(&sTempPath, NULL, iFound, TRUE);
534 sTempPath+=Path;
536 Path=sTempPath;
537 }//End IF there's a slash in Base.Path
540 //We now need to check the path for ../ and ./
541 //First let's search for /./
542 iFound=Path.Sub(sSlashDotSlash);
544 //If we've found a /./
545 while (iFound>=0)
547 //Then remove the ./ part of it.
548 Path.Remove(iFound+1, 2);
550 //And look for the next /./ to remove
551 iFound=Path.Sub(sSlashDotSlash);
554 //Now we want to remove all occurrences of /[path segment/../
555 //So first let's do a search for /../
557 iFound=Path.Sub(sSlashDotDotSlash);
559 //If we've found a /./
560 while (iFound>=0)
562 //Then go back until we find the start of the path segment before it
563 INT32 iStartOfSection=iFound-1;
565 while (iStartOfSection>=0 && Path[iStartOfSection]!=cSlash)
566 iStartOfSection--;
568 if (iStartOfSection>=0)
570 //Get iStartOfSection to represent the character after the slash,
571 //rather than the slash
572 iStartOfSection++;
574 //So if we've found something, then set a pointer to the end of that
575 //section
576 INT32 iEndOfSection=iFound+3;
578 Path.Remove(iStartOfSection, (iEndOfSection-iStartOfSection+1));
580 else
581 //If we found an unparsable /../, then break now before we
582 //get into trouble...
583 break;
585 //And find the next /../
586 iFound=Path.Sub(sSlashDotDotSlash);
589 else
591 //No, this Web Address doesn't have a path.
592 //So it inherits the path of the base URL.
593 Path=Base.Path;
595 //If this Web Address has some parameters, we need do nothin more to it
596 if (!Parameters.IsEmpty())
597 goto ReturnNow;
599 //Otherwise this Web Address inherits the parameters of the base URL
600 Parameters=Base.Parameters;
602 //If this Web Address has a query, we need do nothin more to it
603 if (!Query.IsEmpty())
604 goto ReturnNow;
606 //Otherwise this Web Address inherits the parameters of the base URL
607 Query=Base.Query;
609 //And that's it. (Fragments are never inherited).
610 //So we can return.
611 goto ReturnNow;
613 }//End if (!Path.IsEmpty()) else...
615 ReturnNow:
616 //Set the "Absolute" flag to whatever it's meant to be, and return
617 SetFlags();
618 return;
621 /**********************************************************************************************
623 > String_256 WebAddress::GetWebAddress()
625 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
626 Created: 17/9/96
627 Inputs: -
628 Returns: The full URL string
629 Purpose: Returns the URL string
631 **********************************************************************************************/
633 String_256 WebAddress::GetWebAddress()
635 String_256 strToReturn=Scheme;
637 strToReturn+=NetLoc;
638 strToReturn+=Path;
639 strToReturn+=Parameters;
640 strToReturn+=Query;
641 strToReturn+=Fragment;
643 return strToReturn;
649 /**********************************************************************************************
651 > BOOL WebAddress::IsHTTP()
653 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
654 Created: 17/9/96
655 Inputs: -
656 Returns: TRUE if this Web Address starts with HTTP
657 Purpose: Finds whether this Web Address starts with "HTTP:"
659 **********************************************************************************************/
661 BOOL WebAddress::IsHTTP() const
663 return (Scheme.SubWithoutCase(String_256(_R(IDS_URL_HTTPCOLON)))==0);
666 /**********************************************************************************************
668 > BOOL WebAddress::IsValidHTTP()
670 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
671 Created: 27/6/97
672 Inputs: -
673 Returns: TRUE if this Web Address starts with HTTP and has a net location
674 Purpose: Finds whether this Web Address is a valid HTTP address.
676 We say it's a valid HTTP address if:
677 a. It starts with HTTP
678 b. It has a net location
680 Note that a valid http address may be valid but refer to a non-existent
681 network location - for example:
683 http://nonsensenonsense
685 is a valid HTTP URL that refers to a server called "nonsensenonsense", which
686 does not exist.
690 **********************************************************************************************/
692 BOOL WebAddress::IsValidHTTP() const
694 return (IsHTTP() && !NetLocIsEmpty());
698 /**********************************************************************************************
700 > static BOOL WebAddress::IsHTTP(const String_256& strTest)
702 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
703 Created: 17/9/96
704 Inputs: -
705 Returns: TRUE if strTest starts with HTTP
706 Purpose: Finds whether strTest starts with "HTTP:"
708 **********************************************************************************************/
710 BOOL WebAddress::IsHTTP(const String_256& strTest)
712 WebAddress urlTest(strTest);
713 return (urlTest.IsHTTP());
717 /********************************************************************************************
719 BOOL WebAddress::IsLocalFile()
721 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
722 Created: 10/6/97
723 Inputs: -
724 Outputs: -
726 Returns: TRUE if we consider pstrCorrect to be a local filename
727 FALSE otherwise
729 Purpose: Works out if we consider this Web Address to be a local filename.
731 It's a local filename if its scheme is "file:"
733 Errors: -
735 SeeAlso: WebAddress::GetPathName()
737 ********************************************************************************************/
739 BOOL WebAddress::IsLocalFile() const
741 return (Scheme=="file:");
745 /********************************************************************************************
747 PathName WebAddress::GetPathName()
749 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
750 Created: 10/6/97
751 Inputs: -
752 Outputs: -
754 Returns: The PathName that is equivalent to this URL.
756 Purpose: This is used to convert a local file URL (that is, a URL
757 whose scheme is "file:") to a pathname.
759 Before calling this function, call "IsLocalFile()" to
760 make sure the scheme is "file:".
762 For example, this function converts:
764 file://d|/dir1/file.htm to d:\dir1\file.htm
766 file:////Netloc/dir1/file.htm to \\Netloc\dir1\file.htm
768 It also converts the following URLs correctly. Note that
769 these URLs are illegal - but they appear in the IE3
770 URL bar!
772 file://d:\dir1\file.htm to d:\dir1\file.htm
773 file://\\netloc\dir1\file.htm to \\netloc\dir1\file.htm
775 It does this as follows:
777 1. First, the "file:" part is removed
779 2. Then, if the net location starts with "//", that "//"
780 is removed.
782 3. All forward slashes are converted to backslashes
784 4. All "|" characters are converted to colons
786 Of course there's no guarantee that what's left is
787 a valid path name.
789 Errors: -
791 SeeAlso: WebAddress::IsLocalFile()
793 ********************************************************************************************/
795 PathName WebAddress::GetPathName() const
797 //We needn't actually do anything to remove the Scheme - we just don't
798 //use it
800 //First concatenate the net location and the path
801 String_256 strToReturn=NetLoc;
802 strToReturn+=Path;
804 //So, does that string start with "//"?
805 if (strToReturn.Sub(String_256("//"))==0)
807 //Yes. So remove it
808 strToReturn.Split(NULL, &strToReturn, 1, TRUE);
811 //Convert all forward slashes to backslashes
812 strToReturn.SwapChar('/', '\\');
814 //Convert all | characters to colons
815 strToReturn.SwapChar('|', ':');
817 //Put our string into a PathName object
818 PathName pthToReturn(strToReturn);
820 //And return it
821 return pthToReturn;
826 /********************************************************************************************
828 WebAddress correction functions
830 These functions correct the URL. For example, www.xara.com might be corrected
831 to http://www.xara.com/
833 ********************************************************************************************/
835 /********************************************************************************************
837 void WebAddress::Correct(String_256* pstrCorrect, WebCorrectFlags wcfToUse)
839 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
840 Created: 28/5/97
841 Inputs: pstrCorrect - the string to correct
842 wcfToUse - a set of flags which detail how to correct
843 the string
844 Outputs: pstrCorrect - the corrected string
846 Returns: -
848 Purpose: Corrects the URL string that the user has entered, according to the
849 correction flags.
851 Errors: -
853 SeeAlso: WebAddress::ApplyWebAddressToSelection; WebCorrectFlags
855 ********************************************************************************************/
857 void WebAddress::Correct(String_256* pstrCorrect, WebCorrectFlags wcfToUse)
859 //If we should be correcting backslashes to forward slashes, do so now
860 if (wcfToUse.CorrectBackslashes())
861 CorrectBackslashes(pstrCorrect);
863 //If we should be correcting local filenames
864 if (wcfToUse.CorrectLocalFilenames() && ShouldCorrectLocalFilenames(pstrCorrect))
866 //Then correct it to a URL pointing to a local filename
867 CorrectLocalFilenames(pstrCorrect);
870 //Now, if we should be correcting Netscape local URLs to IE3 ones
871 if (wcfToUse.CorrectNetscapeFilenames() && ShouldCorrectNetscapeFilenames(pstrCorrect))
873 //Then correct it
874 CorrectNetscapeFilenames(pstrCorrect);
876 //Otherwise if we should be correcting ftp addresses
877 else if (wcfToUse.CorrectFTP() && ShouldCorrectFTP(pstrCorrect))
879 //Then add "ftp:" to the front
880 CorrectFTP(pstrCorrect);
882 //Otherwise if we should be adding http:// to the front
883 else if (wcfToUse.CorrectHTTP() && ShouldCorrectHTTP(pstrCorrect))
885 //Then add "http://" to the front
886 CorrectHTTP(pstrCorrect);
889 //Otherwise if the string contains an @
890 else if (ShouldCorrectMailto(pstrCorrect))
892 //Then add "mailto:" to the front
893 CorrectMailto(pstrCorrect);
896 //If we should be ensuring that http addresses have a net location
897 if (wcfToUse.CorrectNoNetLoc() && ShouldCorrectNoNetLoc(pstrCorrect))
899 //Then add a slash to the end
900 CorrectNoNetLoc(pstrCorrect);
904 //And finally, if we should be adding a slash to the end
905 if (wcfToUse.CorrectNoSlash() && ShouldCorrectNoSlash(pstrCorrect))
907 //Then add a slash to the end
908 CorrectNoSlash(pstrCorrect);
913 /********************************************************************************************
915 void WebAddress::CorrectBackslashes(String_256* pstrCorrect)
917 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
918 Created: 28/5/97
919 Inputs: pstrCorrect - the string to correct
920 Outputs: pstrCorrect - the corrected string
922 Returns: -
924 Purpose: Corrects any backslashes in the entered string to slashes
926 Errors: -
928 SeeAlso: WebAddress::Correct()
930 ********************************************************************************************/
932 void WebAddress::CorrectBackslashes(String_256* pstrCorrect)
934 //Check our parameter
935 if (pstrCorrect==NULL)
937 ERROR2RAW("WebAddress::CorrectBackslashes - NULL parameter");
938 return;
941 //And correct all backslashes to forward slashes
942 pstrCorrect->SwapChar('\\', '/');
946 /********************************************************************************************
948 BOOL WebAddress::ShouldCorrectLocalFilenames(String_256* pstrCorrect)
950 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
951 Created: 28/5/97
952 Inputs: pstrCorrect - the string to test
953 Outputs: -
955 Returns: TRUE if we consider pstrCorrect to be a local filename
956 FALSE otherwise
958 Purpose: Works out if we consider this string to be a local filename.
960 We consider this to be a local filename if
961 a. It begins with a letter followed by a colon
962 b. It begins with \\, in which case it is a UNC pathname
964 Errors: -
966 SeeAlso: WebAddress::Correct()
968 ********************************************************************************************/
970 BOOL WebAddress::ShouldCorrectLocalFilenames(String_256* pstrCorrect)
972 //Check our parameter
973 ERROR2IF(pstrCorrect==NULL, FALSE, "WebAddress::CorrectBackslash - NULL parameter");
975 //If the length of the string is less than two characters, return FALSE
976 if (pstrCorrect->Length()<2)
977 return FALSE;
979 //Now, if the first character is a letter and the second character is a
980 //colon, return TRUE
981 if (StringBase::IsAlpha((*pstrCorrect)[0]) && (*pstrCorrect)[1]==':')
983 return TRUE;
986 //Otherwise, if the first two characters are forward slashes, return TRUE
987 if ((*pstrCorrect)[0]=='/' && (*pstrCorrect)[1]=='/')
989 return TRUE;
992 //Otherwise return FALSE
993 return FALSE;
997 /********************************************************************************************
999 void WebAddress::CorrectLocalFilenames(String_256* pstrCorrect)
1001 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1002 Created: 28/5/97
1003 Inputs: pstrCorrect - the string to correct
1004 Outputs: pstrCorrect - the corrected string
1006 Returns: -
1008 Purpose: Assumes pstrCorrect is a local filename, then converts
1009 it to a URL referring to a local filename.
1011 It does this by calling the function PathName::GetWebAddress()
1013 Errors: -
1015 SeeAlso: WebAddress::Correct(), PathName::GetWebAddress()
1017 ********************************************************************************************/
1019 void WebAddress::CorrectLocalFilenames(String_256* pstrCorrect)
1021 //Check our parameter
1022 if(pstrCorrect==NULL)
1024 ERROR2RAW("WebAddress::CorrectBackslash - NULL parameter");
1025 return;
1029 //Now, create a pathname out of our string
1030 PathName pthTemp=*pstrCorrect;
1032 //And call the GetWebAddress function
1033 *pstrCorrect=pthTemp.GetWebAddress();
1037 /********************************************************************************************
1039 BOOL WebAddress::ShouldCorrectNetscapeFilenames(String_256* pstrCorrect)
1041 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1042 Created: 25/6/97
1043 Inputs: pstrCorrect - the string to test
1044 Outputs: -
1046 Returns: TRUE if we consider pstrCorrect to be a Netscape local filename.
1047 FALSE otherwise
1049 Purpose: Works out if we consider this string to be a Netscape local filename.
1051 We consider this to be a Netscape local filename if it begins
1052 with "file:///", but does not begin with "file:////".
1054 The problem here is that Netscape refers to local filenames as follows:
1056 file:///d|/dir1/myname.htm
1058 But IE3 refers to local filenames as:
1060 file://d|/dir1/myname.htm
1062 Note the difference in the number of slashes. We correct it to the IE3 version.
1065 Errors: -
1067 SeeAlso: WebAddress::Correct()
1069 ********************************************************************************************/
1071 BOOL WebAddress::ShouldCorrectNetscapeFilenames(String_256* pstrCorrect)
1073 //Check our parameter
1074 ERROR2IF(pstrCorrect==NULL, FALSE, "WebAddress::CorrectNetscapeFilenames - NULL parameter");
1076 //Set up some strings to search for
1077 String_256 strThreeSlashes("file:///");
1078 String_256 strFourSlashes("file:////");
1080 //Now, if the string begins with "file:///"...
1081 if (pstrCorrect->SubWithoutCase(strThreeSlashes)==0)
1083 //But the string doesn't begin with "file:////"
1084 if (pstrCorrect->SubWithoutCase(strFourSlashes)!=0)
1085 //Then we shoul correct it
1086 return TRUE;
1089 //Otherwise return FALSE
1090 return FALSE;
1094 /********************************************************************************************
1096 void WebAddress::CorrectNetscapeFilenames(String_256* pstrCorrect)
1098 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1099 Created: 28/5/97
1100 Inputs: pstrCorrect - the string to correct
1101 Outputs: pstrCorrect - the corrected string
1103 Returns: -
1105 Purpose: Converts a Netscape local filename (file:///xxxxxxx) to an IE3 local filename
1106 (file://xxxxxxx) by simply removing the third slash.
1108 Errors: -
1110 SeeAlso: WebAddress::Correct(), PathName::GetWebAddress()
1112 ********************************************************************************************/
1114 void WebAddress::CorrectNetscapeFilenames(String_256* pstrCorrect)
1116 //Check our parameter
1117 if(pstrCorrect==NULL)
1119 ERROR2RAW("WebAddress::CorrectBackslash - NULL parameter");
1120 return;
1123 //Simply delete the fifth character, removing one of the slashes
1124 pstrCorrect->Remove(6, 1);
1128 /********************************************************************************************
1130 BOOL WebAddress::ShouldCorrectFTP(String_256* pstrCorrect)
1132 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1133 Created: 28/5/97
1134 Inputs: pstrCorrect - the string to test
1135 Outputs: -
1137 Returns: TRUE if we consider pstrCorrect to be an ftp address
1138 FALSE otherwise
1140 Purpose: Works out if we consider this string to be a ftp address with
1141 the "ftp:" missing.
1143 We do so if the string starts "ftp.".
1145 Errors: -
1147 SeeAlso: WebAddress::Correct()
1149 ********************************************************************************************/
1151 BOOL WebAddress::ShouldCorrectFTP(String_256* pstrCorrect)
1153 //Check our parameter
1154 ERROR2IF(pstrCorrect==NULL, FALSE, "WebAddress::CorrectBackslash - NULL parameter");
1156 //Are the first four characters "ftp." ?
1157 if (pstrCorrect->SubWithoutCase(String_256("ftp."))==0)
1158 return TRUE;
1160 //Otherwise return FALSE
1161 return FALSE;
1165 /********************************************************************************************
1167 void WebAddress::CorrectFTP(String_256* pstrCorrect)
1169 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1170 Created: 28/5/97
1171 Inputs: pstrCorrect - the string to correct
1172 Outputs: pstrCorrect - the corrected string
1174 Returns: -
1176 Purpose: Puts "ftp:" on the start of pstrCorrect.
1178 Errors: -
1180 SeeAlso: WebAddress::Correct()
1182 ********************************************************************************************/
1184 void WebAddress::CorrectFTP(String_256* pstrCorrect)
1186 //Check our parameter
1187 if(pstrCorrect==NULL)
1189 ERROR2RAW("WebAddress::CorrectBackslash - NULL parameter");
1190 return;
1193 //If our string is over two hundred and fifty characters long, return
1194 if (pstrCorrect->Length()>250)
1195 return;
1197 //Otherwise, create a new string containing "ftp://"
1198 String_256 strToReturn="ftp://";
1200 //Add our other string onto the end of it
1201 strToReturn+=*pstrCorrect;
1203 //And copy our new string into our old string
1204 *pstrCorrect=strToReturn;
1207 /********************************************************************************************
1209 BOOL WebAddress::ShouldCorrectHTTP(String_256* pstrCorrect)
1211 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1212 Created: 28/5/97
1213 Inputs: pstrCorrect - the string to test
1214 Outputs: -
1216 Returns: TRUE if we consider pstrCorrect to be an http address
1217 FALSE otherwise
1219 Purpose: Works out if we consider this string to be a http address with
1220 the "http:" missing.
1222 We do so if the string starts with a string of the following
1223 characters:
1225 ;?:&=%$-_.+!*'(),abcdefghijklmnopqrstuvwxyz
1226 ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
1228 ...which contains at least two full stops. (This string
1229 of characters is taken from http://ds.internic.net/rfc/rfc1808.txt,
1230 page 4, but altered slightly).
1232 The first character should not be a full stop and there
1233 should not be two full stops together.
1235 For example:
1237 abc-def12.gh4i3.jkl.mno
1239 Errors: -
1241 SeeAlso: WebAddress::Correct()
1243 ********************************************************************************************/
1245 BOOL WebAddress::ShouldCorrectHTTP(String_256* pstrCorrect)
1247 //Check our parameter
1248 ERROR2IF(pstrCorrect==NULL, FALSE, "WebAddress::CorrectBackslash - NULL parameter");
1250 //Get the length of the string
1251 INT32 iLength=pstrCorrect->Length();
1253 //If the string is empty, return FALSE
1254 if (iLength<=0)
1255 return FALSE;
1257 //Now, here is the set of characters to test for
1258 TCHAR* strAllowed=";?&=%abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$-_.+!*'(),";
1260 //If the first character is a full stop, return FALSE
1261 if ((*pstrCorrect)[0]=='.')
1262 return FALSE;
1264 //And this variable will keep a count of the number of full stops
1265 INT32 iFullStops=0;
1267 //This variable will tell us if the last character we looked at
1268 //was a full stop
1269 BOOL fLastCharWasFullStop=FALSE;
1271 //Now, starting at the first character in the string, scan through
1272 //each character in turn until we get to something that is not
1273 //in our set of allowed characters
1274 for (INT32 i=0; i<iLength && (camStrchr(strAllowed, (*pstrCorrect)[i]))!=NULL; i++)
1276 //If the letter we are looking at is a full stop,
1277 if ((*pstrCorrect)[i]=='.')
1279 //Then, was the last character we looked at a full stop?
1280 if (fLastCharWasFullStop)
1282 //Yes. So we've found two full stops together. Return FALSE
1283 return FALSE;
1285 else
1287 //No. So add one to our count of full stops and remember
1288 //that this character was a full stop
1289 iFullStops++;
1290 fLastCharWasFullStop=TRUE;
1293 else
1295 //No, this character is not a full stop
1296 fLastCharWasFullStop=FALSE;
1300 //And return true if we found more than one full stop
1301 return (iFullStops>=2);
1305 /********************************************************************************************
1307 void WebAddress::CorrectHTTP(String_256* pstrCorrect)
1309 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1310 Created: 28/5/97
1311 Inputs: pstrCorrect - the string to correct
1312 Outputs: pstrCorrect - the corrected string
1314 Returns: -
1316 Purpose: Puts "http:" on the start of pstrCorrect.
1318 Errors: -
1320 SeeAlso: WebAddress::Correct()
1322 ********************************************************************************************/
1324 void WebAddress::CorrectHTTP(String_256* pstrCorrect)
1326 //Check our parameter
1327 if(pstrCorrect==NULL)
1329 ERROR2RAW("WebAddress::CorrectBackslash - NULL parameter");
1330 return;
1333 //If our string is over two hundred and fifty characters long, return
1334 if (pstrCorrect->Length()>250)
1335 return;
1337 //Otherwise, create a new string containing "http:"
1338 String_256 strToReturn="http://";
1340 //Add our other string onto the end of it
1341 strToReturn+=*pstrCorrect;
1343 //And copy our new string into our old string
1344 *pstrCorrect=strToReturn;
1347 /********************************************************************************************
1349 BOOL WebAddress::ShouldCorrectNoSlash(String_256* pstrCorrect)
1351 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1352 Created: 28/5/97
1353 Inputs: pstrCorrect - the string to test
1354 Outputs: -
1356 Returns: TRUE if we consider that pstrCorrect is a URL to which the
1357 user has forgotten to add a trailing slash
1358 FALSE otherwise
1360 Purpose: Works out if we consider this string to be a URL with a trailing
1361 slash missing.
1363 We do this by creating a Web Address object to parse the string.
1364 (Note that if this function is called, then the URL will already
1365 have had an "http://" added to the front if necessary).
1367 Then we consider that the URL should have a slash added if
1368 a. The string consists of a net location but no path
1369 (e.g. "http://www.xara.com", which should become
1370 "http://www.xara.com/")
1372 b. The path portion of the URL does not end in a slash, and
1373 the final segment of the path does not have a full stop
1374 character in it.
1376 That is, "http://www.bbc.co.uk/radio1" should have a slash
1377 added on the end, but "http://www.bbc.co.uk/index.htm" should
1378 not.
1381 Errors: -
1383 SeeAlso: WebAddress::Correct()
1385 ********************************************************************************************/
1387 BOOL WebAddress::ShouldCorrectNoSlash(String_256* pstrCorrect)
1389 //Check our parameter
1390 ERROR2IF(pstrCorrect==NULL, FALSE, "WebAddress::CorrectNoSlash - NULL parameter");
1392 //First create a Web Address from our string
1393 WebAddress urlTest(*pstrCorrect);
1395 //Now, does the Web Address start with HTTP:, and does it have a net location
1396 //specified?
1397 if (urlTest.IsHTTP() && !urlTest.NetLocIsEmpty())
1399 //Yes.
1401 //So, does the Web Address have an empty path?
1402 if (urlTest.PathIsEmpty())
1404 //Yes. So we should add a slash to it.
1405 return TRUE;
1407 else
1409 //No, there is something in the path.
1411 //So, does the path end in something other than a slash?
1412 INT32 iLength=urlTest.Path.Length();
1414 if (urlTest.Path[iLength-1]!='/')
1416 //Yes. So we should add a slash only if
1417 //the last segment of the path does not contain a full stop.
1419 //First try and find a slash in the path string, starting
1420 //from the end
1421 INT32 iSlashFound=urlTest.Path.ReverseFind('/');
1423 //Now try and find a full stop in the path string, starting
1424 //from the end
1425 INT32 iFullStopFound=urlTest.Path.ReverseFind('.');
1427 //Now...
1429 //If we didn't find a full stop, we should add a slash
1430 if (iFullStopFound==-1)
1431 return TRUE;
1433 //Otherwise, we should only add a slash if the slash
1434 //was found after the full stop
1435 if (iSlashFound>iFullStopFound)
1436 return TRUE;
1438 //Otherwise, we don't add a slash
1443 //So, none of our conditions were met.
1444 //So we don't add a slash
1445 return FALSE;
1448 /********************************************************************************************
1450 void WebAddress::CorrectNoSlash(String_256* pstrCorrect)
1452 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1453 Created: 28/5/97
1454 Inputs: pstrCorrect - the string to correct
1455 Outputs: pstrCorrect - the corrected string
1457 Returns: -
1459 Purpose: Adds a slash to the end of the string
1462 Errors: -
1464 SeeAlso: WebAddress::Correct(); WebAddress::ShouldCorrectNoSlash()
1466 ********************************************************************************************/
1468 void WebAddress::CorrectNoSlash(String_256* pstrCorrect)
1470 //Check our parameter
1471 if(pstrCorrect==NULL)
1473 ERROR2RAW("WebAddress::CorrectNoSlash - NULL parameter");
1474 return;
1477 //And if the string is long enough
1478 if (pstrCorrect->Length()<255)
1480 //Add a slash to the end
1481 *pstrCorrect+='/';
1489 /********************************************************************************************
1491 BOOL WebAddress::ShouldCorrectMailto(String_256* pstrCorrect)
1493 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1494 Created: 28/5/97
1495 Inputs: pstrCorrect - the string to test
1496 Outputs: -
1498 Returns: TRUE if we consider pstrCorrect to be a mail address
1499 FALSE otherwise
1501 Purpose: Works out if we consider this string to be a mail address with
1502 the "mailto:" missing.
1504 We do so if it contains an @ character and does not
1505 contain a colon
1507 Errors: -
1509 SeeAlso: WebAddress::Correct()
1511 ********************************************************************************************/
1513 BOOL WebAddress::ShouldCorrectMailto(String_256* pstrCorrect)
1515 //Check our parameter
1516 ERROR2IF(pstrCorrect==NULL, FALSE, "WebAddress::CorrectBackslash - NULL parameter");
1518 //Find the first @ symbol
1519 INT32 iLocationOfAtSymbol=pstrCorrect->FindNextChar('@');
1521 //If we found one
1522 if (iLocationOfAtSymbol>0)
1524 //Then check for a colon
1525 INT32 iLocationOfColon=pstrCorrect->FindNextChar(':');
1527 //If we didn't find one, return TRUE
1528 if (iLocationOfColon<0)
1529 return TRUE;
1532 return FALSE;
1536 /********************************************************************************************
1538 void WebAddress::CorrectMailto(String_256* pstrCorrect)
1540 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1541 Created: 28/5/97
1542 Inputs: pstrCorrect - the string to correct
1543 Outputs: pstrCorrect - the corrected string
1545 Returns: -
1547 Purpose: Puts "mailto:" on the start of pstrCorrect.
1549 Errors: -
1551 SeeAlso: WebAddress::Correct()
1553 ********************************************************************************************/
1555 void WebAddress::CorrectMailto(String_256* pstrCorrect)
1557 //Check our parameter
1558 if(pstrCorrect==NULL)
1560 ERROR2RAW("WebAddress::CorrectBackslash - NULL parameter");
1561 return;
1564 //If our string is over two hundred and fifty characters long, return
1565 if (pstrCorrect->Length()>250)
1566 return;
1568 //Otherwise, create a new string containing "mailto:"
1569 String_256 strToReturn="mailto:";
1571 //Add our other string onto the end of it
1572 strToReturn+=*pstrCorrect;
1574 //And copy our new string into our old string
1575 *pstrCorrect=strToReturn;
1578 /********************************************************************************************
1580 BOOL WebAddress::ShouldCorrectNoNetLoc(String_256* pstrCorrect)
1582 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1583 Created: 27/6/97
1584 Inputs: pstrCorrect - the string to test
1585 Outputs: -
1587 Returns: TRUE if pstrCorrect starts with "http" but does not
1588 have "//" afterwards to signify a net location
1589 FALSE otherwise
1591 Purpose: Works out if we consider this string to be an HTTP address
1592 with the "//" to signify a network location missing. For example:
1594 http:www.xara.com
1596 Errors: -
1598 SeeAlso: WebAddress::Correct()
1600 ********************************************************************************************/
1602 BOOL WebAddress::ShouldCorrectNoNetLoc(String_256* pstrCorrect)
1604 //Check our parameter
1605 ERROR2IF(pstrCorrect==NULL, FALSE, "WebAddress::CorrectBackslash - NULL parameter");
1607 //Return TRUE if the string starts with "http:" but doesn't start with "http://"
1608 String_256 strHTTP("http:");
1609 String_256 strHTTPSlashSlash("http://");
1611 return (pstrCorrect->SubWithoutCase(strHTTP)==0 && pstrCorrect->SubWithoutCase(strHTTPSlashSlash)!=0);
1615 /********************************************************************************************
1617 void WebAddress::CorrectNoNetLoc(String_256* pstrCorrect)
1619 Author: Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
1620 Created: 28/5/97
1621 Inputs: pstrCorrect - the string to correct
1622 Outputs: pstrCorrect - the corrected string
1624 Returns: -
1626 Purpose: Ensures that pstrCorrect starts with "http://"
1628 Errors: -
1630 SeeAlso: WebAddress::Correct()
1632 ********************************************************************************************/
1634 void WebAddress::CorrectNoNetLoc(String_256* pstrCorrect)
1636 //Check our parameter
1637 if(pstrCorrect==NULL)
1639 ERROR2RAW("WebAddress::CorrectBackslash - NULL parameter");
1640 return;
1643 //We already know that our string does not start with "http://"
1644 //But does it start with "http:/"?
1645 if (pstrCorrect->SubWithoutCase(String_256("http:/"))==0)
1647 //Yes it does. So insert an extra slash
1648 pstrCorrect->Insert(&String_256("/"), 5);
1650 else
1652 //No it doesn't. So insert an extra two slashes after the HTTP
1653 pstrCorrect->Insert(&String_256("//"), 5);