00001 // $Id: convert.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 // These functions provide conversion between Millipoints and Strings. 00099 00100 /* Author: Rik 00101 Created: 11/5/93 00102 Purpose: These functions will provide a means of converting from Doc Coords (millipoints) 00103 to Strings and visa versa. For example, convert 72000 millipoints to the string 00104 1in or 72pt as well as converting from the string '1in72pt' to 144000 00105 millipoints. The units to convert to can be chosen, as can the number of 00106 decimal points. When converting from string back to millipoints, all the valid 00107 units are added together. If an error is detected (ie '4cm72zx' ), then 00108 everything up to the error will be used (4cm). */ 00109 00110 00111 00112 // Better find out about the string class and all the other types and stuff 00113 00114 #include "camtypes.h" // Good ol' Camtypes 00115 //#include "ccmaths.h" // 64 bit muldiv - in camtypes.h [AUTOMATICALLY REMOVED] 00116 //#include "convert.h" // function prototypes - in camtypes.h [AUTOMATICALLY REMOVED] 00117 //#include "markn.h" // For unit constants 00118 //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00119 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00120 //#include "units.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00121 //#include "app.h" // Camelot object - in camtypes.h [AUTOMATICALLY REMOVED] 00122 //#include "peter.h" // _R(IDS_MEMORYFORMAT_BYTE) ... 00123 #include "localenv.h" // for locale string settings 00124 //#include "richard3.h" // more naughty inline strings... 00125 00126 00127 // Put my version number into the About box 00128 DECLARE_SOURCE( "$Revision: 1282 $" ); 00129 00130 // Declare smart memory handling in Debug builds 00131 #define new CAM_DEBUG_NEW 00132 00133 CC_IMPLEMENT_DYNAMIC(DimScale, CCObject) 00134 00135 // Set up the defaults for the Convert class 00136 00137 // The default DimScale object is an inactive one that is used as a fall-back in the 00138 // frightening event of one not being found by DimScale::GetPtrDimScale(Node*) 00139 DimScale* pDefaultDimScale = NULL; 00140 00141 char Convert::DecimalPoint = '.'; // Character to separate whole part of number from fractional part 00142 char Convert::ThousandSep = ','; // Char to separate thousands, e.g. 10,000 00143 char Convert::MinusSign = '-'; // What to show if go less than zero 00144 UINT32 Convert::NumDecimalPlaces = 2; // Number of decimal places to display to by default 00145 00146 /****************************************************************************************** 00147 00148 > static BOOL Convert::Init() 00149 00150 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00151 Created: 25/1/95 00152 Inputs: - 00153 Outputs: - 00154 Returns: - 00155 Purpose: AppPrefsDlg Init method. Called when the kernel initialises. 00156 It reads from the Windows ini file the settings for things like the 00157 current decimal point character, thousands separator and number of 00158 decimal places and stores these for later use. 00159 SeeAlso: GetCurrentNumberFormat(); 00160 00161 ******************************************************************************************/ 00162 00163 BOOL Convert::Init() 00164 { 00165 00166 // // Declare any preferences that we require. 00167 // if ( Camelot.DeclareSection(TEXT("Preferences"), 3) ) 00168 // { 00169 // // section declared ok so now define the preference option 00170 // Camelot.DeclarePref(TEXT("Preferences"), TEXT("DecimalPointChar"), &DecimalPoint, 0, 255); 00171 // Camelot.DeclarePref(TEXT("Preferences"), TEXT("ThousandSepChar"), &ThousandSep, 0, 255); 00172 // } 00173 00174 // Get the current details from the OS about the number format specified by the user 00175 // If fails then return this to the caller. 00176 return GetCurrentNumberFormat(); 00177 } 00178 00179 /******************************************************************************************** 00180 00181 > static BOOL Convert::GetCurrentNumberFormat() 00182 00183 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00184 Created: 12/9/95 00185 Inputs: - 00186 Outputs: - 00187 Returns: - 00188 Purpose: Read from the operating system what the user has defined to be their decimal 00189 point character and thousands separator character and store these in the 00190 class variables. 00191 It is now also called from the mainframe message handler, when it 00192 receives a WM_WININICHANGE message. 00193 Errors: - 00194 SeeAlso: CMainFrame::OnWinIniChange() 00195 00196 ********************************************************************************************/ 00197 00198 BOOL Convert::GetCurrentNumberFormat() 00199 { 00200 String_8 ThousandsSepStr( _T(",") ); 00201 String_8 DecimalPointStr( _T(".") ); 00202 NumDecimalPlaces = 2; 00203 00204 // Read from the operating system what the user has defined to be their decimal point 00205 // character and thousands separator character. 00206 LocalEnvironment::GetThousandsSeparator(&ThousandsSepStr); 00207 LocalEnvironment::GetDecimalPointChar(&DecimalPointStr); 00208 LocalEnvironment::GetNumberOfDecimalPlaces(&NumDecimalPlaces); 00209 00210 // Set up the static char variables to reflect these 00211 ThousandSep = ((TCHAR *) ThousandsSepStr)[0]; 00212 DecimalPoint = ((TCHAR *) DecimalPointStr)[0]; 00213 00214 // Check for "testing" of internationalisation. 00215 ERROR3IF(ThousandSep == DecimalPoint, 00216 "Convert::GetCurrentNumberFormat: decimal point and " 00217 "thousands separator are the same"); 00218 00219 //char to TCHAR for DBCS 00220 TRACEUSER( "Neville", wxT("InitConvert() ThousandsSepStr=%s\n"), (TCHAR *)ThousandsSepStr ); 00221 TRACEUSER( "Neville", wxT("InitConvert() DecimalPointStr=%s\n"), (TCHAR *)DecimalPointStr ); 00222 TRACEUSER( "Neville", wxT("InitConvert() NumDecimalPlaces=%d\n"), NumDecimalPlaces ); 00223 00224 return TRUE; 00225 } 00226 00227 00228 /******************************************************************************************** 00229 00230 > static char Convert::GetDecimalPointChar() 00231 00232 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00233 Created: 12/9/95 00234 Inputs: - 00235 Outputs: - 00236 Returns: The current decimal point character being used. 00237 Purpose: To find out what the current decimal point character is. 00238 SeeAlso: SetDecimalPointChar(); GetCurrentNumberFormat(); 00239 00240 ********************************************************************************************/ 00241 00242 char Convert::GetDecimalPointChar() 00243 { 00244 return DecimalPoint; 00245 } 00246 00247 /******************************************************************************************** 00248 00249 > static char Convert::GetThousandsSepChar() 00250 00251 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00252 Created: 12/9/95 00253 Inputs: - 00254 Outputs: - 00255 Returns: The current thousands separator character being used. 00256 Purpose: To find out what the current thousands separator character is. 00257 SeeAlso: SetThousandsSepChar(); GetCurrentNumberFormat(); 00258 00259 ********************************************************************************************/ 00260 00261 char Convert::GetThousandsSepChar() 00262 { 00263 return ThousandSep; 00264 } 00265 00266 00267 /******************************************************************************************** 00268 00269 > static UINT32 Convert::GetNumberDecimalPlaces() 00270 00271 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00272 Created: 12/9/95 00273 Inputs: - 00274 Outputs: - 00275 Returns: The current number of decimal places being used. 00276 Purpose: To find out what the current number of decimal places is. 00277 SeeAlso: SetNumberDecimalPlaces(); 00278 00279 ********************************************************************************************/ 00280 00281 UINT32 Convert::GetNumberDecimalPlaces() 00282 { 00283 return NumDecimalPlaces; 00284 } 00285 00286 /******************************************************************************************** 00287 00288 > static BOOL Convert::SetDecimalPointChar(char NewDecimalPoint) 00289 00290 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00291 Created: 12/9/95 00292 Inputs: - 00293 Outputs: - 00294 Returns: True if set correctly, False otherwise. 00295 Purpose: Allows the setting up of the character to separate whole part of number from 00296 the fractional part in displayed numbers e.g. 56.79 00297 This is read from the OS at present. This function just provided just in case 00298 we wish to overide this in the future. 00299 SeeAlso: GetDecimalPointChar(); GetCurrentNumberFormat(); 00300 00301 ********************************************************************************************/ 00302 00303 BOOL Convert::SetDecimalPointChar(char NewDecimalPoint) 00304 { 00305 // Don't allow a blank to be set. 00306 //if (NewDecimalPoint = '') return FALSE; 00307 00308 DecimalPoint = NewDecimalPoint; 00309 00310 return TRUE; 00311 } 00312 00313 /******************************************************************************************** 00314 00315 > static BOOL Convert::SetThousandsSepChar(char NewThousandsSep) 00316 00317 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00318 Created: 12/9/95 00319 Inputs: - 00320 Outputs: - 00321 Returns: True if set correctly, False otherwise. 00322 Purpose: Allows the setting up of the character to be used to separate thousands in 00323 displayed numbers e.g. 10,000. 00324 This is read from the OS at present. This function just provided just in case 00325 we wish to overide this in the future. 00326 00327 SeeAlso: GetThousandsSepChar(); GetCurrentNumberFormat(); 00328 00329 ********************************************************************************************/ 00330 00331 BOOL Convert::SetThousandsSepChar(char NewThousandsSep) 00332 { 00333 // Don't allow a blank to be set. 00334 //if (NewThousandsSep = '') return FALSE; 00335 00336 ThousandSep = NewThousandsSep; 00337 00338 return TRUE; 00339 } 00340 00341 /******************************************************************************************** 00342 00343 > static BOOL Convert::SetNumberDecimalPlaces(UINT32 NewDPs) 00344 00345 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00346 Created: 12/9/95 00347 Inputs: NewDPs new number of decimal places to use 00348 Outputs: - 00349 Returns: True if set correctly, False otherwise. 00350 Purpose: Allows the setting up of the number of decimal places to display to by default 00351 This is read from the OS at present. This function just provided just in case 00352 we wish to overide this in the future. 00353 SeeAlso: GetNumberDecimalPlaces(); GetCurrentNumberFormat(); 00354 00355 ********************************************************************************************/ 00356 00357 BOOL Convert::SetNumberDecimalPlaces(UINT32 NewDPs) 00358 { 00359 // Set some limit to the number allowed 00360 if (NewDPs > 9) return FALSE; 00361 00362 NumDecimalPlaces = NewDPs; 00363 00364 return TRUE; 00365 } 00366 00367 00368 /****************************************************************************************** 00369 00370 > static BOOL Convert::ReplaceDecimalPoint(StringBase* pString) 00371 00372 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00373 Created: 27/1/95 00374 Inputs: pString - Pointer to the string to be parsed. 00375 Outputs: pString - Pointer to the string that should now have the proper decimal point 00376 Returns: TRUE if the conversion worked, false otherwise 00377 Purpose: Searches the specified string for a decimal point and replaces this with the 00378 specified DecimalPoint character. It assumes that a check has been made 00379 already to see if we are using a non-decimal point character and so this 00380 routine is only called when the replacement is actually required. 00381 This MUST ALWAYS be after the StripTrailingZeros code. Otherwise, the 00382 StripTrailingZeros code would have to search for two items, a decimal point 00383 and the international form of the decimal point. 00384 00385 SeeAlso: MillipointsToString; DimScale::ConvertToUnits; DoubleToString; 00386 Convert::StripTrailingZeros; 00387 00388 ********************************************************************************************/ 00389 00390 BOOL Convert::ReplaceDecimalPoint(StringBase* pString) 00391 { 00392 // Could probably be optimised to be quicker 00393 00394 // Make up a string of the new decimal point character 00395 String_8 InsertStr; 00396 ((TCHAR *) InsertStr)[0] = DecimalPoint; 00397 ((TCHAR *) InsertStr)[1] = 0; 00398 00399 // Work out the position of the current decimal point character, - 1 if none 00400 INT32 Position; 00401 String_8 InsertMark(_R(IDS_CONVERT_DP_CHAR)); 00402 00403 Position = pString->Sub(InsertMark); 00404 00405 // If decimal point was found then put the new decimal point character in place 00406 if (Position > 0) 00407 { 00408 pString->Remove(Position, 1); 00409 pString->Insert(InsertStr, Position); 00410 } 00411 00412 return TRUE; 00413 } 00414 00415 /******************************************************************************************** 00416 00417 > static BOOL Convert::StripTrailingZeros(StringBase* pString) 00418 00419 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00420 Created: 12/7/95 00421 Inputs: pString - string to have trailing zeros removed 00422 Outputs: pString - string with trailing zeros removed 00423 Returns: FALSE if fails 00424 Purpose: Strip trailing zeros (& decimal point) from a string containing a decimal number 00425 This MUST ALWAYS be called before the replace decimal point character code. 00426 Otherwise, we would have to search for two items, a decimal point and the 00427 international form of the decimal point. 00428 SeeAlso: MillipointsToString; DimScale::ConvertToUnits; DoubleToString; 00429 Convert::ReplaceDecimalPoint; 00430 00431 ********************************************************************************************/ 00432 00433 BOOL Convert::StripTrailingZeros(StringBase* pString) 00434 { 00435 // Get the decimal point character that we are going to search for into one of our 00436 // strings. This MUST be the decimal point character as this is ALWAYS called before 00437 // the replace decimal point character. Otherwise, we would have to search for two 00438 // items. 00439 String_8 DPChar(_R(IDS_CONVERT_DP_CHAR)); 00440 const String_8 ZeroChar(_R(IDS_CONVERT_ZERO_CHAR)); 00441 00442 // if there is a decimal point in the string ... 00443 if (pString->Sub(DPChar)!=-1) 00444 { 00445 // skip backwards over trailing zeros 00446 String_8 TmpStr; 00447 INT32 NewStrLen = pString->Length(); 00448 do 00449 { 00450 NewStrLen-=1; 00451 pString->Mid(&TmpStr,NewStrLen,1); 00452 } while (TmpStr==ZeroChar); 00453 00454 // if this previous char is NOT a decimal point DO NOT strip it 00455 if (TmpStr!=DPChar) 00456 NewStrLen+=1; 00457 00458 // remove the trailing zeros from the original string 00459 pString->Left(pString,NewStrLen); 00460 } 00461 00462 return TRUE; 00463 } 00464 00465 00466 /******************************************************************************************** 00467 00468 > static BOOL Convert::IsCharUnitType(TCHAR Char) 00469 00470 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00471 Created: 27/6/94 00472 Inputs: Char - the character to check 00473 Outputs: - 00474 Returns: TRUE - This could be part of a unit type specifier 00475 FALSE - Sorry, but it's either a white space or a number 00476 Purpose: Checks to see if this char could be part of a string that specifies a unit 00477 We have to allow most chars so that arbitrary units can be defined like such 00478 as pounds, dollars or percentages 00479 Illegal unit specifier chars are :- 00480 ASCII value <= ' ' 00481 Numericals - '1', '2', etc 00482 Minus sign - '-' 00483 Decimal point - '.' 00484 Thousand separator - ',' as in "10,000" 00485 Errors: - 00486 00487 ********************************************************************************************/ 00488 00489 BOOL Convert::IsCharUnitType(TCHAR Char) 00490 { 00491 return ( (unsigned(Char) > unsigned(TEXT(' '))) && 00492 (!StringBase::IsNumeric(Char)) && 00493 (Char != MinusSign) && 00494 (Char != DecimalPoint) && 00495 (Char != ThousandSep) 00496 ); 00497 } 00498 00499 /******************************************************************************************** 00500 00501 > static BOOL Convert::IsCharStartOfNumber(TCHAR Char) 00502 00503 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00504 Created: 27/6/94 00505 Inputs: Char - the character to check 00506 Outputs: - 00507 Returns: TRUE - This could be the first char of a number 00508 FALSE - Sorry, but it's definitely not a number 00509 Purpose: Checks to see if this char could be the first char in a string that specifies 00510 a number 00511 Legal number-starting chars are :- 00512 Numericals - '1', '2', etc 00513 Minus sign - '-' 00514 Decimal point - '.' 00515 Errors: - 00516 00517 ********************************************************************************************/ 00518 00519 BOOL Convert::IsCharStartOfNumber(TCHAR Char) 00520 { 00521 return ( (StringBase::IsNumeric(Char)) || 00522 (Char == MinusSign) || 00523 (Char == DecimalPoint) 00524 ); 00525 } 00526 00527 /******************************************************************************************** 00528 00529 > static BOOL Convert::ReadUnitType(StringBase* pStr,INT32* pPos,UnitType* pUnitType) 00530 00531 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00532 Created: 27/6/94 00533 Inputs: pStr - Ptr to the string to get unit type 00534 pPos - *pPos = the pos to start scannning the string from (0 is first char) 00535 pUnitType - Ptr to a UnitType 00536 Outputs: *pPos is the pos the scanning stopped 00537 *pUnitType is the units represented by the string 00538 Returns: TRUE - units have been recognised and value stored in *pUnitType is valid 00539 OR 00540 no units have been specified and *pUnitType == NOTYPE 00541 FALSE - What are these units eh? 00542 Purpose: General purpose routine for extracting the unit type from a string 00543 E.g. "42cm45mm" with *pPos = 2 returns TRUE with *pUnitType == CENTIMETRES & *pPos == 4 00544 "42cm45mm" with *pPos = 6 returns TRUE with *pUnitType == MILLIMETRES & *pPos == 8 00545 Errors: - 00546 00547 ********************************************************************************************/ 00548 00549 BOOL Convert::ReadUnitType(const StringBase &Str,INT32* pPos,UnitType* pUnitType) 00550 { 00551 INT32 len = Str.Length(); 00552 const TCHAR *pChar = (const TCHAR *)Str; 00553 TCHAR UnitCharArray[256]; 00554 INT32 i; 00555 BOOL ok = TRUE; 00556 //Added for DBCS; Strip leading crap 00557 while (*pPos < len && iswspace(pChar[*pPos])) //while (*pPos < len && pChar[*pPos] <= ' ') 00558 (*pPos)++ ; 00559 00560 i = 0; 00561 if (IsCharUnitType(pChar[*pPos])) 00562 { 00563 // Copy unit-specifying chars into UnitCharArray 00564 // NO LONGER copes with wierd unit specifiers that contain numbers too. e.g. "nu2", "b54c" 00565 // as of 18/5/95 (MarkN) 00566 while ( *pPos < len && (IsCharUnitType(pChar[*pPos])) && i<256) // || StringBase::IsNumeric(pChar[*pPos])) && 00567 UnitCharArray[i++] = pChar[(*pPos)++]; 00568 } 00569 00570 UnitCharArray[i] = 0; // Visit the string Terminator (I'm a null char; that's what I do) 00571 00572 String_256 UnitString = UnitCharArray; 00573 00574 //char changed to TCHAR for DBCS 00575 // TCHAR* p = UnitString; // for debugging purposes 00576 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 00577 00578 if (!UnitString.IsEmpty()) 00579 { 00580 // if the string isn't empty, then we must recognise the unit 00581 // otherwise we'll have to fail 00582 *pUnitType = pDocUnitList->FindUnitType(UnitString); 00583 ok = (*pUnitType != NOTYPE); 00584 } 00585 else 00586 *pUnitType = NOTYPE; // Empty string means NOTYPE means use a default type from somewhere 00587 00588 00589 return (ok); 00590 } 00591 00592 00593 /******************************************************************************************** 00594 00595 > static BOOL Convert::ReadNumber(StringBase* pStr,INT32* pPos,double* pResult) 00596 00597 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00598 Created: 27/6/94 00599 Inputs: pStr - Ptr to the string to get value from 00600 pPos - *pPos = the pos to start scannning the string from (0 is first char) 00601 pResult - Ptr to a double 00602 Outputs: *pPos is the pos the scanning stopped 00603 *pResult = The number represented at the specified portion of the string 00604 Returns: TRUE - a valid number was read 00605 FALSE - something's a bit dodgey about that number mate 00606 Purpose: General purpose routine for extracting the number from a string 00607 E.g. "42cm45.7mm" with *pPos == 0 returns TRUE with *pResult and 42.0 & *pPos == 2 00608 "42cm-45.7mm" with *pPos == 4 returns TRUE with *pResult and -45.7 & *pPos == 9 00609 Errors: - 00610 00611 ********************************************************************************************/ 00612 00613 BOOL Convert::ReadNumber( const StringBase &Str,INT32* pPos,double* pResult) 00614 { 00615 INT32 len = Str.Length(); 00616 const TCHAR *pChar = Str; 00617 BOOL IsNegative = FALSE; 00618 double Number = 0.0; 00619 00620 //Added for DBCS Strip leading crap 00621 while (*pPos < len && iswspace(pChar[*pPos])) //while (*pPos < len && pChar[*pPos] <= ' ') 00622 (*pPos)++; 00623 00624 // Check for a minus sign; Added for DBCS 00625 if( pChar[*pPos] == MinusSign ) //if ( pChar[*pPos] == MinusSign ) 00626 { 00627 IsNegative = TRUE; 00628 (*pPos)++; 00629 if (*pPos >= len) return FALSE; 00630 } 00631 00632 // Get the actual number Added for DBCS 00633 while( *pPos < len && 00634 ( StringBase::IsNumeric(pChar[*pPos]) || 00635 pChar[*pPos] == ThousandSep ) )//|| pChar[*pPos] == ThousandSep) ) 00636 { 00637 //Added for DBCS 00638 if (pChar[*pPos] != ThousandSep ) //if (pChar[*pPos] != ThousandSep) 00639 { 00640 Number = (Number * 10.0) + ( pChar[*pPos] - TEXT('0') ); 00641 } 00642 (*pPos)++; 00643 } 00644 00645 // Check for a decimal place; Added for DBCS 00646 if ( pChar[*pPos] == DecimalPoint) //if ( pChar[*pPos] == DecimalPoint ) 00647 { 00648 (*pPos)++; 00649 if (*pPos < len) // If the string ends in a DP, then we return the number now 00650 { 00651 // Otherwise, we continue reading the fractional part of the string... 00652 INT32 DecimalFactor = 10; 00653 while ( *pPos < len && StringBase::IsNumeric(pChar[*pPos]) ) 00654 { 00655 Number += (double)( pChar[*pPos] - TEXT('0') ) / DecimalFactor; 00656 DecimalFactor *= 10; 00657 (*pPos)++; 00658 } 00659 } 00660 } 00661 00662 // If the number started with a minus sign, then make sure it is negative 00663 if (IsNegative) 00664 Number = -Number; 00665 00666 *pResult = Number; 00667 return TRUE; 00668 } 00669 00670 /******************************************************************************************** 00671 00672 > static double Convert::ConvertToNewUnits(double Value,UnitType Units,UnitType NewUnits) 00673 00674 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00675 Created: 27/6/94 00676 Inputs: Value - value to convert 00677 OldUnits- units Value is defined in 00678 NewUnits- the units you want Value to be converted toTYPE 00679 Outputs: - 00680 Returns: The new value 00681 Purpose: Used convert one value into an equivalent value in another unit base 00682 E.g. ConvertToNewUnits(3,CENTIMETRES,MILLIMETRES) would return 30.0 00683 because 3cm == 30mm 00684 00685 ********************************************************************************************/ 00686 00687 double Convert::ConvertToNewUnits(double Value,UnitType OldUnits,UnitType NewUnits) 00688 { 00689 ENSURE(NewUnits != NOTYPE,"Can't convert to NOTYPE units"); 00690 00691 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 00692 Unit* pNewUnit = pDocUnitList->FindUnit(NewUnits); 00693 double NumMillipoints = 1.0; 00694 00695 if (OldUnits != NOTYPE) 00696 { 00697 Unit* pOldUnit = pDocUnitList->FindUnit(OldUnits); 00698 NumMillipoints = Value * pOldUnit->GetMillipoints(); 00699 } 00700 else 00701 NumMillipoints = Value; 00702 00703 return (NumMillipoints / pNewUnit->GetMillipoints()); 00704 } 00705 00706 /******************************************************************************************** 00707 00708 > Static BOOL Convert::StringToComponents(StringBase* InputString, 00709 double* pValue, UnitType* pUnits) 00710 00711 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00712 Created: 14/6/94 (changed considerably on 27/6/94 by Markn) 00713 Inputs: InputString - The string to get values from 00714 pValue - The value of the numerical part of the string 00715 pUnits - The unit value of the unit part of the string 00716 if no units are specified, *pUnits = NOTYPE 00717 Outputs: - 00718 Returns: TRUE - Valid string 00719 FALSE - Something wrong with the string 00720 Purpose: General purpose routine for extracting the value and unit components of a string. 00721 E.g.1 the string "42.6in" would extract the value 42.6 and the unit type INCHES 00722 E.g.2 The string "42.6" would give *pValue=42.6,*pUnits=NOTYPE, and TRUE is returned. 00723 E.g.3 "4in5in" gives *pValue=9,*pUnits=INCHES, and returns TRUE 00724 E.g.4 "1in2cm" gives *pValue = 1.79,*pUnits=INCHES, and returns TRUE 00725 In this case it takes the first unit specified as the dominant unit (INCHES in this 00726 case), so the result is 1in plus 2cm converted to INCHES which is about 0.79in 00727 Errors: This function can fail if the string was not a valid one. ie the 00728 string '12zx'. zx is not a unit that Camelot understands 00729 and so fails. 00730 00731 ********************************************************************************************/ 00732 00733 BOOL Convert::StringToComponents( const StringBase &str,double* pValue,UnitType* pUnits) 00734 { 00735 TCHAR* MyString; 00736 TCHAR Char; 00737 INT32 Pos = 0; 00738 INT32 len = str.Length(); 00739 String_256 InputString( str ); 00740 // BOOL IsNegative = FALSE; 00741 double Result = 0.0; 00742 UnitType MainUnits = NOTYPE; 00743 00744 *pValue = 1.0; 00745 *pUnits = INCHES; 00746 00747 // Make sure that the string is in lower case as per SI units 00748 InputString.toLower(); 00749 MyString = (TCHAR *)InputString; 00750 00751 // I might consider adding this to the base class StringBase, BUT at the moment 00752 // its not really necessary .... 00753 // 00754 // JCF: fixed this to be internationally portable ie. what is alphanumeric in 00755 // your language? 00756 // 00757 while (Pos < len) 00758 { 00759 if (!StringBase::IsAlphaNumeric(MyString[Pos]) && 00760 MyString[Pos] != TEXT('-') && 00761 MyString[Pos] != TEXT('.') && 00762 MyString[Pos] != TEXT(',')) 00763 { 00764 return FALSE; 00765 } 00766 00767 Pos++; 00768 } 00769 00770 Pos = 0; 00771 00772 while (Pos < len) 00773 { 00774 double Number = 0.0; 00775 UnitType Units; 00776 00777 // Strip leading crap Added for DBCS 00778 while (Pos < len && iswspace( MyString[Pos] )) //while (Pos < len && MyString[Pos] <= ' ') 00779 Pos++; 00780 00781 Char = MyString[Pos]; 00782 00783 if (IsCharStartOfNumber(Char)) 00784 { 00785 if (!ReadNumber(InputString,&Pos,&Number)) 00786 return FALSE; 00787 if (!ReadUnitType(InputString,&Pos,&Units)) 00788 return FALSE; 00789 } 00790 else 00791 { 00792 if (!ReadUnitType(InputString,&Pos,&Units)) 00793 return FALSE; 00794 if (!ReadNumber(InputString,&Pos,&Number)) 00795 return FALSE; 00796 } 00797 00798 if (MainUnits == NOTYPE) MainUnits = Units; 00799 00800 if (MainUnits != Units && MainUnits != NOTYPE) 00801 Number = ConvertToNewUnits(Number,Units,MainUnits); 00802 00803 Result += Number; 00804 } 00805 00806 *pUnits = MainUnits; 00807 *pValue = Result; 00808 00809 return TRUE; 00810 } 00811 00812 /******************************************************************************************** 00813 00814 > static double Convert::StringToDouble( StringBase* pInputString, UnitType Default, 00815 BOOL* ValidString ) 00816 00817 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00818 Created: 8/3/94 - modified 14/6/94 00819 Inputs: pInputString - The string to convert to its millipoint value 00820 Default - the Unit type to be used if no other units have been 00821 specified in the string 00822 Outputs: ValidString - The Address of a bool. This will be set to TRUE if 00823 the function converted the string without error, FALSE otherwise. 00824 Returns: double - the number of Millipoints represented by the string 00825 Purpose: Convert the string into a floating point representation of the number of 00826 millipoints. eg '1in' would be converted to 72000.0 millipoints. 00827 Does NOT cope with '0.25in0.75in' - this would return 18000.0 millipoints 00828 instead of 72000.0 millipoints. 00829 If you want a MILLIPOINT value, use StringToMillipoint to ensure correct 00830 rounding. 00831 Errors: This function can fail if the string was not a valid one. ie the 00832 string '12zx'. zx is not a unit that StringToDouble understands 00833 and so fails. 00834 SeeAlso: StringToMillipoint 00835 00836 ********************************************************************************************/ 00837 00838 double Convert::StringToDouble( const StringBase &InputString, UnitType Default, BOOL* ValidString ) 00839 { 00840 double Number = 1.0; 00841 UnitType Units; 00842 00843 *ValidString = StringToComponents( InputString,&Number,&Units); 00844 00845 if (Units == NOTYPE) 00846 Units = Default; 00847 00848 if (*ValidString) 00849 { 00850 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 00851 Unit* pUnit = pDocUnitList->FindUnit(Units); 00852 return (Number * pUnit->GetMillipoints()); // Get the number to millipoints and multiply 00853 } 00854 else 00855 return 72000.0; 00856 } 00857 00858 00859 /******************************************************************************************** 00860 00861 > static MILLIPOINT Convert::StringToMillipoints( StringBase* pInputString, UnitType Default, 00862 BOOL* ValidString ) 00863 00864 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00865 Created: 8/3/94 - modified 14/6/94 00866 Inputs: pInputString - The string to convert to its millipoint value 00867 Default - the Unit type to be used if no other units have been 00868 specified in the string 00869 Outputs: ValidString - The Address of a bool. This will be set to TRUE if 00870 the function converted the string without error, FALSE otherwise. 00871 Returns: MILLIPOINT - An integer version of the number of Millipoints represented by 00872 the string 00873 Purpose: Convert the string into a MILLIPOINT representation of the number of 00874 millipoints. eg '1in' would be converted to 72000 millipoints. 00875 Does NOT cope with '0.25in0.75in' - this would return 18000 millipoints 00876 instead of 72000 millipoints. 00877 Errors: This function can fail if the string was not a valid one. ie the 00878 string '12zx'. zx is not a unit that StringToDouble understands 00879 and so fails. 00880 00881 ********************************************************************************************/ 00882 00883 MILLIPOINT Convert::StringToMillipoints( const StringBase &InputString, UnitType Default, BOOL* ValidString ) 00884 { 00885 double result = StringToDouble( InputString,Default,ValidString); 00886 00887 return (MILLIPOINT)(result+0.5); 00888 } 00889 00890 00891 /******************************************************************************************** 00892 00893 > static void Convert::NumberToString( MILLIPOINT Number, StringBase* MyString ) 00894 00895 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00896 Created: 1/9/93 00897 Inputs: Number - The number to be turned into a string 00898 Outputs: MyString - the string is appended to this string 00899 Purpose: Appends the string representation of the given number to the end 00900 of MyString 00901 00902 ********************************************************************************************/ 00903 00904 void Convert::NumberToString( MILLIPOINT Number, StringBase* MyString ) 00905 { 00906 INT32 Factor = 1; 00907 TCHAR ch[2]; 00908 ch[1] = TEXT('\0'); 00909 00910 // Get a factor that 00911 while (Factor*10 <= Number) 00912 Factor *= 10; 00913 00914 while (Factor > 1) 00915 { 00916 // calculate the most significant digit and remove it from the number 00917 INT32 Digit = INT32(Number / Factor); 00918 ch[0] = TEXT('0') + Digit; 00919 *MyString += String_8(ch); 00920 00921 // Add the digit into the string 00922 Number = Number - (Digit*Factor); 00923 Factor /= 10; 00924 } 00925 00926 // add in the last character 00927 ch[0] = TEXT('0') + (INT32)Number; 00928 *MyString += String_8(ch); 00929 00930 } 00931 00932 00933 00934 00935 /******************************************************************************************** 00936 00937 > static BOOL Convert::MillipointsToString( double MpValue, UnitType TheUnit, 00938 StringBase* OutputString, INT32 DecimalPlaces = -1) 00939 00940 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> (rewritten by MarkN to use new units system - 6/7/94) 00941 Created: 1/9/93 00942 Inputs: MpValue - The number of millipoints to be converted 00943 TheUnit - The units that you need the result in 00944 OutputString - Stirng to put value into (See outputs) 00945 DecimalPlaces - The number of Decimal places required (0-3). This defaults to 00946 -1 which means use the default preference value. 00947 Outputs: OutputString - pointer to a string that is big enough to hold 00948 the resulting number plus its type (ie 12.45cm) 00949 Returns: TRUE if all went well and the string is valid, FALSE otherwise 00950 Purpose: Convert a number in MpValue to a string representation of that 00951 number in the given units. ie converting 72000 millipoints to inches 00952 would give the string '1in'. 00953 If DecimalPlaces = -1 then use the default preference value which the user 00954 has specified. 00955 See Also: DocUnitList 00956 00957 ********************************************************************************************/ 00958 00959 BOOL Convert::MillipointsToString( double MpValue, UnitType TheUnit, StringBase* OutputString, 00960 INT32 DecimalPlaces) 00961 { 00962 ERROR2IF(OutputString == NULL,FALSE,"MillipointsToString NULL output string supplied"); 00963 // Decimal places will be -1 if the default number is to be used. 00964 00965 double Value = 1.0; 00966 String_32 Specifier; 00967 TCHAR p[256], format[256], dpformat[256]; 00968 00969 DocUnitList* pDocUnitList = DocUnitList::GetCurrentDocUnitList(); 00970 DocUnitList FactoryDefUnits; 00971 if(pDocUnitList==NULL) 00972 { 00973 // certain classes (eg OpDescriptors) may want to call this function to set 00974 // values in controls after they have been read in by the bars/dialogs etc... 00975 // However at that point (Document::GetCurrent() == NULL) so you can't get 00976 // a DocUnitList from the current doc. Hence create our own default units 00977 FactoryDefUnits.Init(); 00978 FactoryDefUnits.MakeDefaultUnits(); 00979 pDocUnitList = &FactoryDefUnits; 00980 } 00981 00982 Unit* pUnit = pDocUnitList->FindUnit(TheUnit); 00983 00984 // Find out how many Units MpValue represents 00985 Value = MpValue / pUnit->GetMillipoints(); 00986 00987 // Get the specifier of the units we're in 00988 Specifier = pUnit->GetSpecifier(); 00989 00990 // check if we want the default number of decimal places 00991 if (DecimalPlaces == -1) DecimalPlaces = NumDecimalPlaces; 00992 00993 //_stprintf(dpformat,"%%.%df",DecimalPlaces); // Makes "%.xf" where x is num dp 00994 // Makes the output form "%.xf" where x is num dp. 00995 // %g instead of %f gives leading zero supression but then requires number significant 00996 // figures rather than number of decimal places. 00997 camSnprintf( dpformat, 256, TEXT("%%.%df"), DecimalPlaces) ; 00998 00999 // Create the string to stick in an editable field (or wherever you like) 01000 if (pUnit->IsPrefix()) 01001 { 01002 // Prefix units so show units followed by value 01003 camSnprintf( format, 256, _T("%%s%s"), (LPCTSTR) dpformat ); // ie. %s %.3f 01004 camSnprintf( p, 256, format, (LPCTSTR)Specifier, (double)Value ); // uses FP 01005 *OutputString = p; 01006 // Look for all zeros after decimal point and if so then remove 01007 //StripTrailingZeros(OutputString); 01008 } 01009 else 01010 { 01011 // Suffix units so show value followed by units 01012 camSnprintf( p, 256, dpformat, (double)Value ); // uses FP 01013 *OutputString = p; 01014 01015 // Look for all zeros after decimal point and if so then remove 01016 StripTrailingZeros(OutputString); 01017 01018 // Finally, add in the unit specifier 01019 *OutputString += Specifier; 01020 } 01021 01022 01023 // Extra bodge required so that if the user has specified display values using 01024 // a non full stop to show decimal points then we must replace the point that 01025 // is present by the specified character. 01026 if (DecimalPoint != '.') 01027 { 01028 ReplaceDecimalPoint(OutputString); 01029 } 01030 01031 return TRUE; 01032 } 01033 01034 01035 /******************************************************************************************** 01036 01037 > static BOOL Convert::LongToString( INT32 Number, StringBase* OutputString ) 01038 01039 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 01040 Created: 17/9/93 01041 Inputs: Number - The number you want turning into a string 01042 Outputs: OutputString - The string that gets created 01043 Returns: TRUE if the conversion worked, false otherwise 01044 Purpose: Converts a INT32 to a its string equivalent. 01045 SeeAlso: StringToLong 01046 01047 ********************************************************************************************/ 01048 01049 BOOL Convert::LongToString( INT32 Number, StringBase* OutputString ) 01050 { 01051 OutputString -> Empty(); 01052 01053 if (Number < 0) 01054 { 01055 TCHAR buff[2] ; 01056 buff[0] = TEXT('-'); 01057 buff[1] = TEXT('\0'); 01058 01059 *OutputString += String_8(buff); 01060 Number = -Number; 01061 01062 } 01063 01064 NumberToString( Number, OutputString ); 01065 01066 return TRUE; 01067 } 01068 01069 /******************************************************************************************** 01070 01071 > static BOOL Convert::DoubleToString( double Number, StringBase* OutputString, INT32 DecimalPlaces ) 01072 01073 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01074 Created: 16/12/94 01075 Inputs: Number - The number you want turning into a string 01076 DecimalPlaces - The number of Decimal places required (0-3). This defaults to 01077 -1 which means use the default preference value. Don't override it unless 01078 absolutely necessary. 01079 01080 Outputs: OutputString - The string that gets created 01081 Returns: TRUE if the conversion worked, false otherwise 01082 Purpose: Converts a double to a its string equivalent. 01083 SeeAlso: StringToDouble 01084 01085 This routine is a bit of a bodge 01086 01087 ********************************************************************************************/ 01088 01089 BOOL Convert::DoubleToString( double Number, StringBase* OutputString, INT32 DecimalPlaces /* =-1 */ ) 01090 { 01091 // Generate the output string in a simple char array 01092 TCHAR dpformat[32]; 01093 TCHAR TempString[32]; 01094 01095 // Use the default/preference or desired number of decimal places 01096 if (DecimalPlaces < 0) 01097 DecimalPlaces = (INT32) NumDecimalPlaces; // Use the preference value 01098 01099 camSnprintf( dpformat, 32, _T("%%.%df"), (INT32) DecimalPlaces); // make %.xf formatting string 01100 camSnprintf( TempString, 32, dpformat, (double)Number ); // uses FP 01101 01102 *OutputString = TempString; // Copy the resulting string into the String 01103 01104 // Look for all zeros after decimal point and if so then remove 01105 StripTrailingZeros(OutputString); 01106 01107 // Extra bodge required so that if the user has specified display values using 01108 // a non full stop to show decimal points then we must replace the point that 01109 // is present by the specified character. 01110 if (DecimalPoint != '.') 01111 { 01112 ReplaceDecimalPoint(OutputString); 01113 } 01114 return TRUE; 01115 } 01116 01117 01118 /******************************************************************************************** 01119 01120 > static BOOL Convert::StringToLong( StringBase* InputString, INT32* Number ) 01121 01122 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 01123 Created: 17/9/93 01124 Inputs: InputString - The string that you want turning into a number 01125 Outputs: Number - The number you want turning into a string 01126 Returns: TRUE if the conversion worked, false otherwise 01127 Purpose: Converts a string into its INT32 equivalent 01128 SeeAlso: LongToString 01129 01130 ********************************************************************************************/ 01131 01132 BOOL Convert::StringToLong( const StringBase &InputString, INT32* pNumber) 01133 { 01134 // Get a pointer version of the string 01135 const TCHAR* pMyString = (const TCHAR*)InputString; 01136 INT32 nLength = InputString.Length(); 01137 INT32 nPos = 0; 01138 01139 // Check for a minus sign - added for DBCS 01140 BOOL fIsNegative = FALSE; 01141 if (pMyString[nPos] == TEXT('-') ) // if (pMyString[Pos] == TEXT('-')) 01142 { 01143 fIsNegative = TRUE; 01144 nPos++; 01145 if (nPos >= nLength) return 0; 01146 } 01147 01148 // Get the actual number 01149 INT32 nTotal = 0; 01150 while (nPos < nLength && StringBase::IsNumeric(pMyString[nPos])) 01151 { 01152 nTotal = (nTotal * 10) + pMyString[nPos] - TEXT('0'); 01153 nPos++; 01154 } 01155 01156 // If we have not read in the whole string, then it was not valid 01157 if (nPos < nLength && !StringBase::IsSpace(pMyString[nPos])) return FALSE; 01158 01159 // If the number started with a minus sign, then make sure it is negative 01160 if (fIsNegative) nTotal = -nTotal; 01161 01162 *pNumber = nTotal; 01163 return TRUE; 01164 } 01165 01166 /******************************************************************************************** 01167 01168 > static BOOL Convert::StringToDouble( StringBase* InputString, double * Number ) 01169 01170 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01171 Created: 16/12/94 01172 Inputs: InputString - The string that you want turning into a double 01173 Outputs: Number - The number you want turning into a string 01174 Returns: TRUE if the conversion worked, false otherwise 01175 Purpose: Converts a string into its double equivalent 01176 SeeAlso: DoubleToString 01177 01178 Used to be a bodge as atof() doesn't work in unicode but converted to use 01179 the other functions which should do it properly. 01180 01181 ********************************************************************************************/ 01182 01183 BOOL Convert::StringToDouble( const StringBase &InputString, double * Number ) 01184 { 01185 //#if UNICODE 01186 //#error "I'm screwed! atof() doesn't work for UNICODE" 01187 //#else 01188 // *Number = atof((char *)*InputString); 01189 // return(TRUE); 01190 //#endif 01191 01192 // Cannot use atof as does not cope with a non-decimal point character which 01193 // the user may be specifying so use our form of atof. 01194 // atof will also allow say 26.98mm where we should really be erroring. 01195 // ReadNumber ignores everything after a dodgy decimal point which is not correct. 01196 // StringToComponents will include units as well. We do not want this part so ignore it. 01197 UnitType Units; 01198 BOOL ok = StringToComponents(InputString,Number,&Units); 01199 01200 // Check if units are NOTYPE and if not then return failure. 01201 if (Units != NOTYPE) 01202 return FALSE; 01203 01204 return ok; 01205 } 01206 01207 01208 #define MIN_MILLIPOINT_VAL (-2147483648.0) // Min signed 32 bit val - 0x80000000 01209 #define MAX_MILLIPOINT_VAL ( 2147483647.0) // Max signed 32 bit val - 0x7fffffff 01210 01211 /******************************************************************************************** 01212 01213 > static BOOL Convert::ConvertDoubleToMillipoint(double Value,MILLIPOINT* pResult) 01214 01215 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01216 Created: 6/7/94 01217 Inputs: Value = the fp value to convert 01218 Outputs: pResult = the MILLIPOINT var to place the result in 01219 Returns: TRUE if the conversion was OK 01220 FALSE if the conversion caused an overflow error 01221 Purpose: Converts a double to a MILLIPOINT, checking first whether such a conversion 01222 is possible. 01223 It returns FALSE if Value is beyond the limits of a signed 32 bit integer. 01224 SeeAlso: ConvertMillipointToDouble 01225 01226 ********************************************************************************************/ 01227 01228 BOOL Convert::ConvertDoubleToMillipoint(double Value,MILLIPOINT* pResult) 01229 { 01230 Value += 0.5; // Round up the value 01231 01232 if ((Value < MIN_MILLIPOINT_VAL) || (Value > MAX_MILLIPOINT_VAL)) 01233 return FALSE; 01234 01235 *pResult = (MILLIPOINT)Value; 01236 return TRUE; 01237 } 01238 01239 /******************************************************************************************** 01240 01241 > static void Convert::ConvertMillipointToDouble(MILLIPOINT Value,double* pResult) 01242 01243 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01244 Created: 6/7/94 01245 Inputs: Value = the MILLIPOINT value to convert 01246 Outputs: pResult = the double var to place the result in 01247 Returns: - 01248 Purpose: Converts a MILLIPOINT to a double. 01249 At the moment, this function just does a simple cast. 01250 I've only put it in because I did the sister function ConvertDoubleToMillipoint 01251 SeeAlso: ConvertDoubleToMillipoint 01252 01253 ********************************************************************************************/ 01254 01255 void Convert::ConvertMillipointToDouble(MILLIPOINT Value,double* pResult) 01256 { 01257 *pResult = (double)Value; 01258 } 01259 01260 01261 /****************************************************************************************** 01262 01263 > static UINT32 Convert::StringToBytes(String_256 *pStr, BOOL *Valid) 01264 01265 Author: Richard_Millican (Xara Group Ltd) <camelotdev@xara.com> 01266 Created: 20/1/95 01267 Inputs: pStr - pointer to all manner of memory am