mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 09:32:00 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			2825 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			2825 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| {
 | |
|     *********************************************************************
 | |
|     Copyright (C) 1997, 1998 Gertjan Schouten
 | |
| 
 | |
|     This program is free software; you can redistribute it and/or modify
 | |
|     it under the terms of the GNU General Public License as published by
 | |
|     the Free Software Foundation; either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU General Public License
 | |
|     along with this program; if not, write to the Free Software
 | |
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
|     *********************************************************************
 | |
| 
 | |
|     System Utilities For Free Pascal
 | |
| }
 | |
| 
 | |
| {   NewStr creates a new PString and assigns S to it
 | |
|     if length(s) = 0 NewStr returns Nil   }
 | |
| 
 | |
| function NewStr(const S: string): PString;
 | |
| begin
 | |
|   if (S='') then
 | |
|    Result:=nil
 | |
|   else
 | |
|    begin
 | |
|      new(result);
 | |
|      if (Result<>nil) then
 | |
|        Result^:=s;
 | |
|    end;
 | |
| end;
 | |
| 
 | |
| {   DisposeStr frees the memory occupied by S   }
 | |
| 
 | |
| procedure DisposeStr(S: PString);
 | |
| begin
 | |
|   if S <> Nil then
 | |
|    begin
 | |
|      dispose(s);
 | |
|      S:=nil;
 | |
|    end;
 | |
| end;
 | |
| 
 | |
| {   AssignStr assigns S to P^   }
 | |
| 
 | |
| procedure AssignStr(var P: PString; const S: string);
 | |
| begin
 | |
|   P^ := s;
 | |
| end ;
 | |
| 
 | |
| {   AppendStr appends S to Dest   }
 | |
| 
 | |
| procedure AppendStr(var Dest: String; const S: string);
 | |
| begin
 | |
| Dest := Dest + S;
 | |
| end ;
 | |
| 
 | |
| {   UpperCase returns a copy of S where all lowercase characters ( from a to z )
 | |
|     have been converted to uppercase   }
 | |
| 
 | |
| 
 | |
| Function UpperCase(Const S : String) : String;
 | |
| 
 | |
| Var
 | |
|   i : Integer;
 | |
|   P : PChar;
 | |
| 
 | |
| begin
 | |
|   Result := S;
 | |
|   if not assigned(pointer(result)) then exit;
 | |
|   UniqueString(Result);
 | |
|   P:=Pchar(pointer(Result));
 | |
|   for i := 1 to Length(Result) do
 | |
|     begin
 | |
|     if (P^ in ['a'..'z']) then P^ := char(byte(p^) - 32);
 | |
|       Inc(P);
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| {   LowerCase returns a copy of S where all uppercase characters ( from A to Z )
 | |
|     have been converted to lowercase  }
 | |
| 
 | |
| Function Lowercase(Const S : String) : String;
 | |
| 
 | |
| Var
 | |
|   i : Integer;
 | |
|   P : PChar;
 | |
| 
 | |
| begin
 | |
|   Result := S;
 | |
|   if not assigned(pointer(result)) then exit;
 | |
|   UniqueString(Result);
 | |
|   P:=Pchar(pointer(Result));
 | |
|   for i := 1 to Length(Result) do
 | |
|     begin
 | |
|     if (P^ in ['A'..'Z']) then P^ := char(byte(p^) + 32);
 | |
|       Inc(P);
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| function LowerCase(const V: variant): string; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=LowerCase(ansistring(V));
 | |
|   end;
 | |
| 
 | |
| 
 | |
| {   CompareStr compares S1 and S2, the result is the based on
 | |
|     substraction of the ascii values of the characters in S1 and S2
 | |
|     case     result
 | |
|     S1 < S2  < 0
 | |
|     S1 > S2  > 0
 | |
|     S1 = S2  = 0     }
 | |
| 
 | |
| function CompareStr(const S1, S2: string): Integer;
 | |
| var count, count1, count2: integer;
 | |
| begin
 | |
|   result := 0;
 | |
|   Count1 := Length(S1);
 | |
|   Count2 := Length(S2);
 | |
|   if Count1>Count2 then
 | |
|     Count:=Count2
 | |
|   else
 | |
|     Count:=Count1;
 | |
|   result := CompareMemRange(Pointer(S1),Pointer(S2), Count);
 | |
|   if result=0 then
 | |
|     result:=Count1-Count2;
 | |
| end;
 | |
| 
 | |
| {   CompareMemRange returns the result of comparison of Length bytes at P1 and P2
 | |
|     case       result
 | |
|     P1 < P2    < 0
 | |
|     P1 > P2    > 0
 | |
|     P1 = P2    = 0    }
 | |
| 
 | |
| function CompareMemRange(P1, P2: Pointer; Length: cardinal): integer;
 | |
| 
 | |
| var
 | |
|   i: cardinal;
 | |
| 
 | |
| begin
 | |
|   i := 0;
 | |
|   result := 0;
 | |
|   while (result=0) and (I<length) do
 | |
|     begin
 | |
|     result:=byte(P1^)-byte(P2^);
 | |
|     P1:=pchar(P1)+1;            // VP compat.
 | |
|     P2:=pchar(P2)+1;
 | |
|     i := i + 1;
 | |
|    end ;
 | |
| end ;
 | |
| 
 | |
| function CompareMem(P1, P2: Pointer; Length: cardinal): Boolean;
 | |
| var
 | |
|   i: cardinal;
 | |
| begin
 | |
|   Result:=True;
 | |
|   I:=0;
 | |
|   If (P1)<>(P2) then
 | |
|     While Result and (i<Length) do
 | |
|       begin
 | |
|       Result:=PByte(P1)^=PByte(P2)^;
 | |
|       Inc(I);
 | |
|       Inc(pchar(P1));
 | |
|       Inc(pchar(P2));
 | |
|       end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| {   CompareText compares S1 and S2, the result is the based on
 | |
|     substraction of the ascii values of characters in S1 and S2
 | |
|     comparison is case-insensitive
 | |
|     case     result
 | |
|     S1 < S2  < 0
 | |
|     S1 > S2  > 0
 | |
|     S1 = S2  = 0     }
 | |
| 
 | |
| function CompareText(const S1, S2: string): integer;
 | |
| 
 | |
| var
 | |
|   i, count, count1, count2: integer; Chr1, Chr2: byte;
 | |
| begin
 | |
|   result := 0;
 | |
|   Count1 := Length(S1);
 | |
|   Count2 := Length(S2);
 | |
|   if (Count1>Count2) then
 | |
|     Count := Count2
 | |
|   else
 | |
|     Count := Count1;
 | |
|   i := 0;
 | |
|   while (result=0) and (i<count) do
 | |
|     begin
 | |
|     inc (i);
 | |
|      Chr1 := byte(s1[i]);
 | |
|      Chr2 := byte(s2[i]);
 | |
|      if Chr1 in [97..122] then
 | |
|        dec(Chr1,32);
 | |
|      if Chr2 in [97..122] then
 | |
|        dec(Chr2,32);
 | |
|      result := Chr1 - Chr2;
 | |
|      end ;
 | |
|   if (result = 0) then
 | |
|     result:=(count1-count2);
 | |
| end;
 | |
| 
 | |
| function SameText(const s1,s2:String):Boolean;
 | |
| 
 | |
| begin
 | |
|  Result:=CompareText(S1,S2)=0;
 | |
| end;
 | |
| 
 | |
| {==============================================================================}
 | |
| {   Ansi string functions                                                      }
 | |
| {   these functions rely on the character set loaded by the OS                 }
 | |
| {==============================================================================}
 | |
| 
 | |
| function GenericAnsiUpperCase(const s: string): string;
 | |
|   var
 | |
|     len, i: integer;
 | |
| begin
 | |
|   len := length(s);
 | |
|   SetLength(result, len);
 | |
|   for i := 1 to len do
 | |
|      result[i] := UpperCaseTable[ord(s[i])];
 | |
| end;
 | |
| 
 | |
| 
 | |
| function GenericAnsiLowerCase(const s: string): string;
 | |
|   var
 | |
|     len, i: integer;
 | |
| begin
 | |
|   len := length(s);
 | |
|   SetLength(result, len);
 | |
|   for i := 1 to len do
 | |
|      result[i] := LowerCaseTable[ord(s[i])];
 | |
| end;
 | |
| 
 | |
| 
 | |
| function GenericAnsiCompareStr(const S1, S2: string): PtrInt;
 | |
|   Var
 | |
|     I,L1,L2 : SizeInt;
 | |
| begin
 | |
|   Result:=0;
 | |
|   L1:=Length(S1);
 | |
|   L2:=Length(S2);
 | |
|   I:=1;
 | |
|   While (Result=0) and ((I<=L1) and (I<=L2)) do
 | |
|     begin
 | |
|     Result:=Ord(S1[I])-Ord(S2[I]); //!! Must be replaced by ansi characters !!
 | |
|     Inc(I);
 | |
|     end;
 | |
|   If Result=0 Then
 | |
|     Result:=L1-L2;
 | |
| end;
 | |
| 
 | |
| function GenericAnsiCompareText(const S1, S2: string): PtrInt;
 | |
|   Var
 | |
|     I,L1,L2 : SizeInt;
 | |
| begin
 | |
|   Result:=0;
 | |
|   L1:=Length(S1);
 | |
|   L2:=Length(S2);
 | |
|   I:=1;
 | |
|   While (Result=0) and ((I<=L1) and (I<=L2)) do
 | |
|     begin
 | |
|     Result:=Ord(LowerCaseTable[Ord(S1[I])])-Ord(LowerCaseTable[Ord(S2[I])]); //!! Must be replaced by ansi characters !!
 | |
|     Inc(I);
 | |
|     end;
 | |
|   If Result=0 Then
 | |
|     Result:=L1-L2;
 | |
| end;
 | |
| 
 | |
| function AnsiSameText(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
| 
 | |
| begin
 | |
|  AnsiSameText:=AnsiCompareText(S1,S2)=0;
 | |
| end;
 | |
| 
 | |
| function AnsiSameStr(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
| 
 | |
| begin
 | |
|   AnsiSameStr:=AnsiCompareStr(S1,S2)=0;
 | |
| end;
 | |
| 
 | |
| function GenericAnsiStrComp(S1, S2: PChar): PtrInt;
 | |
| 
 | |
| begin
 | |
|   Result:=0;
 | |
|   If S1=Nil then
 | |
|     begin
 | |
|       If S2=Nil Then Exit;
 | |
|       result:=-1;
 | |
|       exit;
 | |
|     end;
 | |
|   If S2=Nil then
 | |
|     begin
 | |
|       Result:=1;
 | |
|       exit;
 | |
|     end;
 | |
|   Repeat
 | |
|     Result:=Ord(S1^)-Ord(S2^); //!! Must be replaced by ansi characters !!
 | |
|     Inc(S1);
 | |
|     Inc(S2);
 | |
|   Until (Result<>0) or (S1^=#0) or (S2^=#0);
 | |
|   if (Result=0) and (S1^<>S2^) then // loop ended because exactly one has #0
 | |
|     if S1^=#0 then // shorter string is smaller
 | |
|       result:=-1
 | |
|     else
 | |
|       result:=1;
 | |
| end;
 | |
| 
 | |
| 
 | |
| function GenericAnsiStrIComp(S1, S2: PChar): PtrInt;
 | |
| 
 | |
| begin
 | |
|   Result:=0;
 | |
|   If S1=Nil then
 | |
|     begin
 | |
|     If S2=Nil Then Exit;
 | |
|     result:=-1;
 | |
|     exit;
 | |
|     end;
 | |
|   If S2=Nil then
 | |
|     begin
 | |
|     Result:=1;
 | |
|     exit;
 | |
|     end;
 | |
|   Repeat
 | |
|     Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
 | |
|     Inc(S1);
 | |
|     Inc(S2);
 | |
|   Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0))
 | |
| end;
 | |
| 
 | |
| 
 | |
| function GenericAnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
 | |
| 
 | |
| Var I : cardinal;
 | |
| 
 | |
| begin
 | |
|   Result:=0;
 | |
|   If MaxLen=0 then exit;
 | |
|   If S1=Nil then
 | |
|     begin
 | |
|     If S2=Nil Then Exit;
 | |
|     result:=-1;
 | |
|     exit;
 | |
|     end;
 | |
|   If S2=Nil then
 | |
|     begin
 | |
|     Result:=1;
 | |
|     exit;
 | |
|     end;
 | |
|   I:=0;
 | |
|   Repeat
 | |
|     Result:=Ord(S1[0])-Ord(S2[0]); //!! Must be replaced by ansi characters !!
 | |
|     Inc(S1);
 | |
|     Inc(S2);
 | |
|     Inc(I);
 | |
|   Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0)) or (I=MaxLen)
 | |
| end;
 | |
| 
 | |
| 
 | |
| function GenericAnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
 | |
| 
 | |
| Var I : cardinal;
 | |
| 
 | |
| begin
 | |
|   Result:=0;
 | |
|   If MaxLen=0 then exit;
 | |
|   If S1=Nil then
 | |
|     begin
 | |
|     If S2=Nil Then Exit;
 | |
|     result:=-1;
 | |
|     exit;
 | |
|     end;
 | |
|   If S2=Nil then
 | |
|     begin
 | |
|     Result:=1;
 | |
|     exit;
 | |
|     end;
 | |
|   I:=0;
 | |
|   Repeat
 | |
|     Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
 | |
|     Inc(S1);
 | |
|     Inc(S2);
 | |
|     Inc(I);
 | |
|   Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0)) or (I=MaxLen)
 | |
| end;
 | |
| 
 | |
| 
 | |
| function GenericAnsiStrLower(Str: PChar): PChar;
 | |
| begin
 | |
| result := Str;
 | |
| if Str <> Nil then begin
 | |
|    while Str^ <> #0 do begin
 | |
|       Str^ := LowerCaseTable[byte(Str^)];
 | |
|       Str := Str + 1;
 | |
|       end;
 | |
|    end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| function GenericAnsiStrUpper(Str: PChar): PChar;
 | |
| begin
 | |
| result := Str;
 | |
| if Str <> Nil then begin
 | |
|    while Str^ <> #0 do begin
 | |
|       Str^ := UpperCaseTable[byte(Str^)];
 | |
|       Str := Str + 1;
 | |
|       end ;
 | |
|    end ;
 | |
| end ;
 | |
| 
 | |
| function AnsiLastChar(const S: string): PChar;
 | |
| 
 | |
| begin
 | |
|   //!! No multibyte yet, so we return the last one.
 | |
|   result:=StrEnd(Pchar(pointer(S)));  // strend checks for nil
 | |
|   Dec(Result);
 | |
| end ;
 | |
| 
 | |
| function AnsiStrLastChar(Str: PChar): PChar;
 | |
| begin
 | |
|   //!! No multibyte yet, so we return the last one.
 | |
|   result:=StrEnd(Str);
 | |
|   Dec(Result);
 | |
| end ;
 | |
| 
 | |
| 
 | |
| function AnsiUpperCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.UpperAnsiStringProc(s);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiLowerCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.LowerAnsiStringProc(s);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiCompareStr(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.CompareStrAnsiStringProc(s1,s2);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiCompareText(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.CompareTextAnsiStringProc(s1,s2);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiStrComp(S1, S2: PChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.StrCompAnsiStringProc(s1,s2);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiStrIComp(S1, S2: PChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.StrICompAnsiStringProc(s1,s2);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiStrLComp(S1, S2: PChar; MaxLen: cardinal): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.StrLCompAnsiStringProc(s1,s2,maxlen);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiStrLIComp(S1, S2: PChar; MaxLen: cardinal): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.StrLICompAnsiStringProc(s1,s2,maxlen);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiStrLower(Str: PChar): PChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.StrLowerAnsiStringProc(Str);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function AnsiStrUpper(Str: PChar): PChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
 | |
|   begin
 | |
|     result:=widestringmanager.StrUpperAnsiStringProc(Str);
 | |
|   end;
 | |
| 
 | |
| 
 | |
| {==============================================================================}
 | |
| {  End of Ansi functions                                                       }
 | |
| {==============================================================================}
 | |
| 
 | |
| {   Trim returns a copy of S with blanks characters on the left and right stripped off   }
 | |
| 
 | |
| Const WhiteSpace = [#0..' '];
 | |
| 
 | |
| function Trim(const S: string): string;
 | |
| var Ofs, Len: integer;
 | |
| begin
 | |
|   len := Length(S);
 | |
|   while (Len>0) and (S[Len] in WhiteSpace) do
 | |
|    dec(Len);
 | |
|   Ofs := 1;
 | |
|   while (Ofs<=Len) and (S[Ofs] in WhiteSpace) do
 | |
|    Inc(Ofs);
 | |
|   result := Copy(S, Ofs, 1 + Len - Ofs);
 | |
| end ;
 | |
| 
 | |
| {   TrimLeft returns a copy of S with all blank characters on the left stripped off  }
 | |
| 
 | |
| function TrimLeft(const S: string): string;
 | |
| var i,l:integer;
 | |
| begin
 | |
|   l := length(s);
 | |
|   i := 1;
 | |
|   while (i<=l) and (s[i] in whitespace) do
 | |
|    inc(i);
 | |
|   Result := copy(s, i, l);
 | |
| end ;
 | |
| 
 | |
| {   TrimRight returns a copy of S with all blank characters on the right stripped off  }
 | |
| 
 | |
| function TrimRight(const S: string): string;
 | |
| var l:integer;
 | |
| begin
 | |
|   l := length(s);
 | |
|   while (l>0) and (s[l] in whitespace) do
 | |
|    dec(l);
 | |
|   result := copy(s,1,l);
 | |
| end ;
 | |
| 
 | |
| {   QuotedStr returns S quoted left and right and every single quote in S
 | |
|     replaced by two quotes   }
 | |
| 
 | |
| function QuotedStr(const S: string): string;
 | |
| begin
 | |
| result := AnsiQuotedStr(s, '''');
 | |
| end ;
 | |
| 
 | |
| {   AnsiQuotedStr returns S quoted left and right by Quote,
 | |
|     and every single occurance of Quote replaced by two   }
 | |
| 
 | |
| function AnsiQuotedStr(const S: string; Quote: char): string;
 | |
| var i, j, count: integer;
 | |
| begin
 | |
| result := '' + Quote;
 | |
| count := length(s);
 | |
| i := 0;
 | |
| j := 0;
 | |
| while i < count do begin
 | |
|    i := i + 1;
 | |
|    if S[i] = Quote then begin
 | |
|       result := result + copy(S, 1 + j, i - j) + Quote;
 | |
|       j := i;
 | |
|       end ;
 | |
|    end ;
 | |
| if i <> j then
 | |
|    result := result + copy(S, 1 + j, i - j);
 | |
| result := result + Quote;
 | |
| end ;
 | |
| 
 | |
| {   AnsiExtractQuotedStr returns a copy of Src with quote characters
 | |
|     deleted to the left and right and double occurances
 | |
|     of Quote replaced by a single Quote   }
 | |
| 
 | |
| 
 | |
| function AnsiExtractQuotedStr(var  Src: PChar; Quote: Char): string;
 | |
| var
 | |
|   P,Q,R: PChar;
 | |
| begin
 | |
|  P := Src;
 | |
|  Q := StrEnd(P);
 | |
|  result:='';
 | |
|  if P=Q then exit;
 | |
|  if P^<>quote then exit;
 | |
|  inc(p);
 | |
| 
 | |
|  setlength(result,(Q-P)+1);
 | |
|  R:=@Result[1];
 | |
|  while P <> Q do
 | |
|    begin
 | |
|      R^:=P^;
 | |
|      inc(R);
 | |
|      if (P^ = Quote) then
 | |
|        begin
 | |
|          P := P + 1;
 | |
|          if (p^ <> Quote) then
 | |
|           begin
 | |
|             dec(R);
 | |
|             break;
 | |
|           end;
 | |
|        end;
 | |
|      P := P + 1;
 | |
|    end ;
 | |
|  src:=p;
 | |
|  SetLength(result, (R-pchar(@Result[1])));
 | |
| end ;
 | |
| 
 | |
| 
 | |
| {   AdjustLineBreaks returns S with all CR characters not followed by LF
 | |
|     replaced with CR/LF  }
 | |
| //  under Linux all CR characters or CR/LF combinations should be replaced with LF
 | |
| 
 | |
| function AdjustLineBreaks(const S: string): string;
 | |
| 
 | |
| begin
 | |
|   Result:=AdjustLineBreaks(S,DefaultTextLineBreakStyle);
 | |
| end;
 | |
| 
 | |
| function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle): string;
 | |
| var
 | |
|   Source,Dest: PChar;
 | |
|   DestLen: Integer;
 | |
|   I,J,L: Longint;
 | |
| 
 | |
| begin
 | |
|   Source:=Pointer(S);
 | |
|   L:=Length(S);
 | |
|   DestLen:=L;
 | |
|   I:=1;
 | |
|   while (I<=L) do
 | |
|     begin
 | |
|     case S[i] of
 | |
|       #10: if (Style=tlbsCRLF) then
 | |
|                Inc(DestLen);
 | |
|       #13: if (Style=tlbsCRLF) then
 | |
|              if (I<L) and (S[i+1]=#10) then
 | |
|                Inc(I)
 | |
|              else
 | |
|                Inc(DestLen)
 | |
|              else if (I<L) and (S[I+1]=#10) then
 | |
|                Dec(DestLen);
 | |
|     end;
 | |
|     Inc(I);
 | |
|     end;
 | |
|   if (DestLen=L) then
 | |
|     Result:=S
 | |
|   else
 | |
|     begin
 | |
|     SetLength(Result, DestLen);
 | |
|     FillChar(Result[1],DestLen,0);
 | |
|     Dest := Pointer(Result);
 | |
|     J:=0;
 | |
|     I:=0;
 | |
|     While I<L do
 | |
|       case Source[I] of
 | |
|         #10: begin
 | |
|              if Style=tlbsCRLF then
 | |
|                begin
 | |
|                Dest[j]:=#13;
 | |
|                Inc(J);
 | |
|               end;
 | |
|              Dest[J] := #10;
 | |
|              Inc(J);
 | |
|              Inc(I);
 | |
|              end;
 | |
|         #13: begin
 | |
|              if Style=tlbsCRLF then
 | |
|                begin
 | |
|                Dest[j] := #13;
 | |
|                Inc(J);
 | |
|                end;
 | |
|              Dest[j]:=#10;
 | |
|              Inc(J);
 | |
|              Inc(I);
 | |
|              if Source[I]=#10 then
 | |
|                Inc(I);
 | |
|              end;
 | |
|       else
 | |
|         Dest[j]:=Source[i];
 | |
|         Inc(J);
 | |
|         Inc(I);
 | |
|       end;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| {   IsValidIdent returns true if the first character of Ident is in:
 | |
|     'A' to 'Z', 'a' to 'z' or '_' and the following characters are
 | |
|     on of: 'A' to 'Z', 'a' to 'z', '0'..'9' or '_'    }
 | |
| 
 | |
| function IsValidIdent(const Ident: string): boolean;
 | |
| var i, len: integer;
 | |
| begin
 | |
| result := false;
 | |
| len := length(Ident);
 | |
| if len <> 0 then begin
 | |
|    result := Ident[1] in ['A'..'Z', 'a'..'z', '_'];
 | |
|    i := 1;
 | |
|    while (result) and (i < len) do begin
 | |
|       i := i + 1;
 | |
|       result := result and (Ident[i] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
 | |
|       end ;
 | |
|    end ;
 | |
| end ;
 | |
| 
 | |
| {   IntToStr returns a string representing the value of Value    }
 | |
| 
 | |
| function IntToStr(Value: integer): string;
 | |
| begin
 | |
|  System.Str(Value, result);
 | |
| end ;
 | |
| 
 | |
| 
 | |
| function IntToStr(Value: int64): string;
 | |
| begin
 | |
|  System.Str(Value, result);
 | |
| end ;
 | |
| 
 | |
| function IntToStr(Value: QWord): string;
 | |
| begin
 | |
|  System.Str(Value, result);
 | |
| end ;
 | |
| 
 | |
| 
 | |
| {   IntToHex returns a string representing the hexadecimal value of Value   }
 | |
| 
 | |
| const
 | |
|    HexDigits: array[0..15] of char = '0123456789ABCDEF';
 | |
| 
 | |
| function IntToHex(Value: integer; Digits: integer): string;
 | |
| var i: integer;
 | |
| begin
 | |
|  SetLength(result, digits);
 | |
|  for i := 0 to digits - 1 do
 | |
|   begin
 | |
|    result[digits - i] := HexDigits[value and 15];
 | |
|    value := value shr 4;
 | |
|   end ;
 | |
|  while value <> 0 do begin
 | |
|    result := HexDigits[value and 15] + result;
 | |
|    value := value shr 4;
 | |
|  end;
 | |
| end ;
 | |
| 
 | |
| function IntToHex(Value: int64; Digits: integer): string;
 | |
| var i: integer;
 | |
| begin
 | |
|  SetLength(result, digits);
 | |
|  for i := 0 to digits - 1 do
 | |
|   begin
 | |
|    result[digits - i] := HexDigits[value and 15];
 | |
|    value := value shr 4;
 | |
|   end ;
 | |
|  while value <> 0 do begin
 | |
|    result := HexDigits[value and 15] + result;
 | |
|    value := value shr 4;
 | |
|  end;
 | |
| end ;
 | |
| 
 | |
| function IntToHex(Value: QWord; Digits: integer): string;
 | |
| begin
 | |
|   result:=IntToHex(Int64(Value),Digits);
 | |
| end;
 | |
| 
 | |
| function TryStrToInt(const s: string; var i : integer) : boolean;
 | |
| var Error : word;
 | |
| begin
 | |
|   Val(s, i, Error);
 | |
|   TryStrToInt:=Error=0
 | |
| end;
 | |
| 
 | |
| {   StrToInt converts the string S to an integer value,
 | |
|     if S does not represent a valid integer value EConvertError is raised  }
 | |
| 
 | |
| function StrToInt(const S: string): integer;
 | |
| var Error: word;
 | |
| begin
 | |
|   Val(S, result, Error);
 | |
|   if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
 | |
| end ;
 | |
| 
 | |
| 
 | |
| function StrToInt64(const S: string): int64;
 | |
| var Error: word;
 | |
| begin
 | |
|   Val(S, result, Error);
 | |
|   if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
 | |
| end;
 | |
| 
 | |
| 
 | |
| function TryStrToInt64(const s: string; var i : int64) : boolean;
 | |
| var Error : word;
 | |
| begin
 | |
|   Val(s, i, Error);
 | |
|   TryStrToInt64:=Error=0
 | |
| end;
 | |
| 
 | |
| 
 | |
| function StrToQWord(const s: string): QWord;
 | |
| var Error: word;
 | |
| begin
 | |
|   Val(S, result, Error);
 | |
|   if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
 | |
| end;
 | |
| 
 | |
| 
 | |
| function TryStrToQWord(const s: string; var Q: QWord): boolean;
 | |
| var Error : word;
 | |
| begin
 | |
|   Val(s, Q, Error);
 | |
|   TryStrToQWord:=Error=0
 | |
| end;
 | |
| 
 | |
| {   StrToIntDef converts the string S to an integer value,
 | |
|     Default is returned in case S does not represent a valid integer value  }
 | |
| 
 | |
| function StrToIntDef(const S: string; Default: integer): integer;
 | |
| var Error: word;
 | |
| begin
 | |
|   Val(S, result, Error);
 | |
|   if Error <> 0 then result := Default;
 | |
| end ;
 | |
| 
 | |
| {   StrToInt64Def converts the string S to an int64 value,
 | |
|     Default is returned in case S does not represent a valid int64 value  }
 | |
| 
 | |
| function StrToInt64Def(const S: string; Default: int64): int64;
 | |
| var Error: word;
 | |
| begin
 | |
|   Val(S, result, Error);
 | |
|   if Error <> 0 then result := Default;
 | |
| end ;
 | |
| 
 | |
| {   StrToQWordDef converts the string S to an QWord value,
 | |
|     Default is returned in case S does not represent a valid QWord value  }
 | |
| 
 | |
| function StrToQWordDef(const S: string; Default: QWord): QWord;
 | |
| var Error: word;
 | |
| begin
 | |
|   Val(S, result, Error);
 | |
|   if Error <> 0 then result := Default;
 | |
| end;
 | |
| 
 | |
| {   LoadStr returns the string resource Ident.   }
 | |
| 
 | |
| function LoadStr(Ident: integer): string;
 | |
| begin
 | |
|   result:='';
 | |
| end ;
 | |
| 
 | |
| {   FmtLoadStr returns the string resource Ident and formats it accordingly   }
 | |
| 
 | |
| 
 | |
| function FmtLoadStr(Ident: integer; const Args: array of const): string;
 | |
| begin
 | |
|   result:='';
 | |
| end;
 | |
| 
 | |
| Const
 | |
|   feInvalidFormat   = 1;
 | |
|   feMissingArgument = 2;
 | |
|   feInvalidArgIndex = 3;
 | |
| 
 | |
| {$ifdef fmtdebug}
 | |
| Procedure Log (Const S: String);
 | |
| begin
 | |
|  Writeln (S);
 | |
| end;
 | |
| {$endif}
 | |
| 
 | |
| 
 | |
| Procedure DoFormatError (ErrCode : Longint);
 | |
| Var
 | |
|   S : String;
 | |
| begin
 | |
|   //!! must be changed to contain format string...
 | |
|   S:='';
 | |
|   Case ErrCode of
 | |
|    feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[s]);
 | |
|    feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[s]);
 | |
|    feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[s]);
 | |
|  end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| { we've no templates, but with includes we can simulate this :) }
 | |
| 
 | |
| {$macro on}
 | |
| {$define INFORMAT}
 | |
| {$define TFormatString:=ansistring}
 | |
| {$define TFormatChar:=char}
 | |
| 
 | |
| Function Format (Const Fmt : AnsiString; const Args : Array of const; const FormatSettings: TFormatSettings) : AnsiString;
 | |
| {$i sysformt.inc}
 | |
| 
 | |
| {$undef TFormatString}
 | |
| {$undef TFormatChar}
 | |
| {$undef INFORMAT}
 | |
| {$macro off}
 | |
| 
 | |
| Function Format (Const Fmt : AnsiString; const Args : Array of const) : AnsiString;
 | |
| 
 | |
| begin
 | |
|   Result:=Format(Fmt,Args,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function FormatBuf (Var Buffer; BufLen : Cardinal; Const Fmt; fmtLen : Cardinal; Const Args : Array of const; Const FormatSettings: TFormatSettings) : Cardinal;
 | |
| 
 | |
| Var S,F : String;
 | |
| 
 | |
| begin
 | |
|   Setlength(F,fmtlen);
 | |
|   if fmtlen > 0 then
 | |
|     Move(fmt,F[1],fmtlen);
 | |
|   S:=Format (F,Args,FormatSettings);
 | |
|   If Cardinal(Length(S))<Buflen then
 | |
|     Result:=Length(S)
 | |
|   else
 | |
|     Result:=Buflen;
 | |
|   Move(S[1],Buffer,Result);
 | |
| end;
 | |
| 
 | |
| Function FormatBuf (Var Buffer; BufLen : Cardinal;
 | |
|                      Const Fmt; fmtLen : Cardinal;
 | |
|                      Const Args : Array of const) : Cardinal;
 | |
| 
 | |
| begin
 | |
|   Result:=FormatBuf(Buffer,BufLen,Fmt,FmtLen,Args,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Procedure FmtStr(Var Res: string; const Fmt : string; Const args: Array of const; Const FormatSettings: TFormatSettings);
 | |
| 
 | |
| begin
 | |
|   Res:=Format(fmt,Args,FormatSettings);
 | |
| end;
 | |
| 
 | |
| Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
 | |
| 
 | |
| begin
 | |
|   FmtStr(Res,Fmt,Args,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
 | |
| 
 | |
| begin
 | |
|   Result:=StrFmt(Buffer,Fmt,Args,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function StrFmt(Buffer,Fmt : PChar; Const Args: Array of const; Const FormatSettings: TFormatSettings): PChar;
 | |
| 
 | |
| begin
 | |
|   Buffer[FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
 | |
|   Result:=Buffer;
 | |
| end;
 | |
| 
 | |
| Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
 | |
| 
 | |
| begin
 | |
|   Result:=StrLFmt(Buffer,MaxLen,Fmt,Args,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const; Const FormatSettings: TFormatSettings) : Pchar;
 | |
| 
 | |
| begin
 | |
|   Buffer[FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
 | |
|   Result:=Buffer;
 | |
| end;
 | |
| 
 | |
| Function StrToFloat(Const S: String): Extended;
 | |
| 
 | |
| begin
 | |
|   Result:=StrToFloat(S,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function StrToFloat(Const S : String; Const FormatSettings: TFormatSettings) : Extended;
 | |
| 
 | |
| Begin // texttofloat handles NIL properly
 | |
|   If Not TextToFloat(Pchar(pointer(S)),Result,FormatSettings) then
 | |
|     Raise EConvertError.createfmt(SInValidFLoat,[S]);
 | |
| End;
 | |
| 
 | |
| function StrToFloatDef(const S: string; const Default: Extended): Extended;
 | |
| 
 | |
| begin
 | |
|   Result:=StrToFloatDef(S,Default,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function StrToFloatDef(Const S: String; Const Default: Extended; Const FormatSettings: TFormatSettings): Extended;
 | |
| 
 | |
| begin
 | |
|    if not TextToFloat(PChar(pointer(S)),Result,fvExtended,FormatSettings) then
 | |
|      Result:=Default;
 | |
| end;
 | |
| 
 | |
| Function TextToFloat(Buffer: PChar; Var Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
 | |
| 
 | |
| Var
 | |
|   E,P : Integer;
 | |
|   S : String;
 | |
| 
 | |
| Begin
 | |
|   S:=StrPas(Buffer);
 | |
|   P:=Pos(FormatSettings.DecimalSeparator,S);
 | |
|   If (P<>0) Then
 | |
|     S[P] := '.';
 | |
|   Val(trim(S),Value,E);
 | |
|   Result:=(E=0);
 | |
| End;
 | |
| 
 | |
| Function TextToFloat(Buffer: PChar; Var Value: Extended): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=TextToFloat(Buffer,Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function TextToFloat(Buffer: PChar; Var Value; ValueType: TFloatValue): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function TextToFloat(Buffer: PChar; Var Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
 | |
| 
 | |
| Var
 | |
|   E,P : Integer;
 | |
|   S : String;
 | |
| {$ifndef FPC_HAS_STR_CURRENCY}
 | |
|   TempValue: extended;
 | |
| {$endif FPC_HAS_STR_CURRENCY}
 | |
| 
 | |
| Begin
 | |
|   S:=StrPas(Buffer);
 | |
|   P:=Pos(FormatSettings.ThousandSeparator,S);
 | |
|   While (P<>0) do
 | |
|     begin
 | |
|     Delete(S,P,1);
 | |
|     P:=Pos(FormatSettings.ThousandSeparator,S);
 | |
|     end;
 | |
|   P:=Pos(FormatSettings.DecimalSeparator,S);
 | |
|   If (P<>0) Then
 | |
|     S[P] := '.';
 | |
|   case ValueType of
 | |
|     fvCurrency:
 | |
| {$ifdef FPC_HAS_STR_CURRENCY}
 | |
|       Val(S,Currency(Value),E);
 | |
| {$else FPC_HAS_STR_CURRENCY}
 | |
|       begin
 | |
|         // needed for platforms where Currency = Int64
 | |
|         Val(S,TempValue,E);
 | |
|         Currency(Value) := TempValue;
 | |
|       end;
 | |
| {$endif FPC_HAS_STR_CURRENCY}
 | |
|     fvExtended:
 | |
|       Val(S,Extended(Value),E);
 | |
|     fvDouble:
 | |
|       Val(S,Double(Value),E);
 | |
|     fvSingle:
 | |
|       Val(S,Single(Value),E);
 | |
|     fvComp:
 | |
|       Val(S,Comp(Value),E);
 | |
|     fvReal:
 | |
|       Val(S,Real(Value),E);
 | |
|   end;
 | |
|   Result:=(E=0);
 | |
| End;
 | |
| 
 | |
| Function TryStrToFloat(Const S : String; Var Value: Single): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function TryStrToFloat(Const S : String; Var Value: Single; Const FormatSettings: TFormatSettings): Boolean;
 | |
| Begin
 | |
|   Result := TextToFloat(PChar(pointer(S)), Value, fvSingle,FormatSettings);
 | |
| End;
 | |
| 
 | |
| Function TryStrToFloat(Const S : String; Var Value: Double): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function TryStrToFloat(Const S : String; Var Value: Double; Const FormatSettings: TFormatSettings): Boolean;
 | |
| Begin
 | |
|   Result := TextToFloat(PChar(pointer(S)), Value, fvDouble,FormatSettings);
 | |
| End;
 | |
| 
 | |
| {$ifdef FPC_HAS_TYPE_EXTENDED}
 | |
| Function TryStrToFloat(Const S : String; Var Value: Extended): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function TryStrToFloat(Const S : String; Var Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
 | |
| Begin
 | |
|   Result := TextToFloat(PChar(pointer(S)), Value,FormatSettings);
 | |
| End;
 | |
| {$endif FPC_HAS_TYPE_EXTENDED}
 | |
| 
 | |
| 
 | |
| const
 | |
| {$ifdef FPC_HAS_TYPE_EXTENDED}
 | |
|   maxdigits = 17;
 | |
| {$else}
 | |
|   maxdigits = 15;
 | |
| {$endif}
 | |
| 
 | |
| Function FloatToStrFIntl(const Value; format: TFloatFormat; Precision, Digits: Integer; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): String;
 | |
| Var
 | |
|   P: Integer;
 | |
|   Negative, TooSmall, TooLarge: Boolean;
 | |
|   DS: Char;
 | |
| 
 | |
| Begin
 | |
|   DS:=FormatSettings.DecimalSeparator;
 | |
|   Case format Of
 | |
| 
 | |
|     ffGeneral:
 | |
| 
 | |
|       Begin
 | |
|         case ValueType of
 | |
|           fvCurrency:
 | |
|             begin
 | |
|               If (Precision = -1) Or (Precision > 19) Then Precision := 19;
 | |
|               TooSmall:=False;
 | |
|             end;
 | |
|           else
 | |
|             begin
 | |
|               If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
 | |
|               TooSmall := (Abs(Extended(Value)) < 0.00001) and (Extended(Value)<>0.0);
 | |
|             end;
 | |
|         end;
 | |
|         If Not TooSmall Then
 | |
|         Begin
 | |
|           case ValueType of
 | |
|             fvDouble:
 | |
|               Str(Double(Extended(Value)):0:precision, Result);
 | |
|             fvSingle:
 | |
|               Str(Single(Extended(Value)):0:precision, Result);
 | |
|             fvCurrency:
 | |
| {$ifdef FPC_HAS_STR_CURRENCY}
 | |
|               Str(Currency(Value):0:precision, Result);
 | |
| {$else}
 | |
|               Str(Extended(Currency(Value)):0:precision, Result);
 | |
| {$endif FPC_HAS_STR_CURRENCY}
 | |
|             else
 | |
|               Str(Extended(Value):0:precision, Result);
 | |
|           end;
 | |
|           P := Pos('.', Result);
 | |
|           if P<>0 then
 | |
|             Result[P] := DS;
 | |
|           TooLarge :=(P > Precision + 1) or (Pos('E', Result)<>0);
 | |
|         End;
 | |
| 
 | |
|         If TooSmall Or TooLarge Then
 | |
|           begin
 | |
|             Result := FloatToStrFIntl(Value, ffExponent, Precision, Digits, ValueType,FormatSettings);
 | |
|             // Strip unneeded zeroes.
 | |
|             P:=Pos('E',result)-1;
 | |
|             If P<>-1 then
 | |
|               begin
 | |
|                 { delete superfluous +? }
 | |
|                 if result[p+2]='+' then
 | |
|                   system.Delete(Result,P+2,1);
 | |
|                 While (P>1) and (Result[P]='0') do
 | |
|                   begin
 | |
|                     system.Delete(Result,P,1);
 | |
|                     Dec(P);
 | |
|                   end;
 | |
|                 If (P>0) and (Result[P]=DS) Then
 | |
|                   begin
 | |
|                     system.Delete(Result,P,1);
 | |
|                     Dec(P);
 | |
|                   end;
 | |
|               end;
 | |
|             end
 | |
|         else if (P<>0) then // we have a decimalseparator
 | |
|           begin
 | |
|             { it seems that in this unit "precision" must mean "number of }
 | |
|             { significant digits" rather than "number of digits after the }
 | |
|             { decimal point" (as it does in the system unit) -> adjust    }
 | |
|             { (precision+1 to count the decimal point character)          }
 | |
|             if Result[1] = '-' then
 | |
|               Inc(Precision);
 | |
|             if (Length(Result) > Precision + 1) and
 | |
|                (Precision + 1 > P) then
 | |
|               begin
 | |
|                 P := Precision + 1;
 | |
|                 SetLength(Result,P);
 | |
|               end;
 | |
|             P := Length(Result);
 | |
|             While (P>0) and (Result[P] = '0') Do
 | |
|               Dec(P);
 | |
|             If (P>0) and (Result[P]=DS) Then
 | |
|               Dec(P);
 | |
|             SetLength(Result, P);
 | |
|           end;
 | |
|       End;
 | |
| 
 | |
|     ffExponent:
 | |
| 
 | |
|       Begin
 | |
|         If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
 | |
|         case ValueType of
 | |
|           fvDouble:
 | |
|             Str(Double(Extended(Value)):Precision+7, Result);
 | |
|           fvSingle:
 | |
|             Str(Single(Extended(Value)):Precision+6, Result);
 | |
|           fvCurrency:
 | |
| {$ifdef FPC_HAS_STR_CURRENCY}
 | |
|             Str(Currency(Value):Precision+6, Result);
 | |
| {$else}
 | |
|             Str(Extended(Currency(Value)):Precision+8, Result);
 | |
| {$endif FPC_HAS_STR_CURRENCY}
 | |
|           else
 | |
|             Str(Extended(Value):Precision+8, Result);
 | |
|         end;
 | |
|         { Delete leading spaces }
 | |
|         while Result[1] = ' ' do
 | |
|           System.Delete(Result, 1, 1);
 | |
|         if Result[1] = '-' then
 | |
|           Result[3] := DS
 | |
|         else
 | |
|           Result[2] := DS;
 | |
|         P:=Pos('E',Result);
 | |
|         if P <> 0 then
 | |
|           begin
 | |
|             Inc(P, 2);
 | |
|             if Digits > 4 then
 | |
|               Digits:=4;
 | |
|             Digits:=Length(Result) - P - Digits + 1;
 | |
|             if Digits < 0 then
 | |
|               insert(copy('0000',1,-Digits),Result,P)
 | |
|             else
 | |
|               while (Digits > 0) and (Result[P] = '0') do
 | |
|                 begin
 | |
|                   System.Delete(Result, P, 1);
 | |
|                   if P > Length(Result) then
 | |
|                     begin
 | |
|                       System.Delete(Result, P - 2, 2);
 | |
|                       break;
 | |
|                     end;
 | |
|                   Dec(Digits);
 | |
|                 end;
 | |
|           end;
 | |
|       End;
 | |
| 
 | |
|     ffFixed:
 | |
| 
 | |
|       Begin
 | |
|         If Digits = -1 Then Digits := 2
 | |
|         Else If Digits > 18 Then Digits := 18;
 | |
|         case ValueType of
 | |
|           fvDouble:
 | |
|             Str(Double(Extended(Value)):0:Digits, Result);
 | |
|           fvSingle:
 | |
|             Str(Single(Extended(Value)):0:Digits, Result);
 | |
|           fvCurrency:
 | |
| {$ifdef FPC_HAS_STR_CURRENCY}
 | |
|             Str(Currency(Value):0:Digits, Result);
 | |
| {$else}
 | |
|             Str(Extended(Currency(Value)):0:Digits, Result);
 | |
| {$endif FPC_HAS_STR_CURRENCY}
 | |
|           else
 | |
|             Str(Extended(Value):0:Digits, Result);
 | |
|         end;
 | |
|         If Result[1] = ' ' Then
 | |
|           System.Delete(Result, 1, 1);
 | |
|         P := Pos('.', Result);
 | |
|         If P <> 0 Then Result[P] := DS;
 | |
|       End;
 | |
| 
 | |
|     ffNumber:
 | |
| 
 | |
|       Begin
 | |
|         If Digits = -1 Then Digits := 2
 | |
|         Else If Digits > maxdigits Then Digits := maxdigits;
 | |
|         case ValueType of
 | |
|           fvDouble:
 | |
|             Str(Double(Extended(Value)):0:Digits, Result);
 | |
|           fvSingle:
 | |
|             Str(Single(Extended(Value)):0:Digits, Result);
 | |
|           fvCurrency:
 | |
| {$ifdef FPC_HAS_STR_CURRENCY}
 | |
|             Str(Currency(Value):0:Digits, Result);
 | |
| {$else}
 | |
|             Str(Extended(Currency(Value)):0:Digits, Result);
 | |
| {$endif FPC_HAS_STR_CURRENCY}
 | |
|           else
 | |
|             Str(Extended(Value):0:Digits, Result);
 | |
|         end;
 | |
|         If Result[1] = ' ' Then System.Delete(Result, 1, 1);
 | |
|         P := Pos('.', Result);
 | |
|         If P <> 0 Then
 | |
|           Result[P] := DS
 | |
|         else
 | |
|           P := Length(Result)+1;
 | |
|         Dec(P, 3);
 | |
|         While (P > 1) Do
 | |
|         Begin
 | |
|           If Result[P - 1] <> '-' Then Insert(FormatSettings.ThousandSeparator, Result, P);
 | |
|           Dec(P, 3);
 | |
|         End;
 | |
|       End;
 | |
| 
 | |
|     ffCurrency:
 | |
| 
 | |
|       Begin
 | |
|         If Digits = -1 Then Digits := FormatSettings.CurrencyDecimals
 | |
|         Else If Digits > 18 Then Digits := 18;
 | |
|         case ValueType of
 | |
|           fvDouble:
 | |
|             Str(Double(Extended(Value)):0:Digits, Result);
 | |
|           fvSingle:
 | |
|             Str(Single(Extended(Value)):0:Digits, Result);
 | |
|           fvCurrency:
 | |
| {$ifdef FPC_HAS_STR_CURRENCY}
 | |
|             Str(Currency(Value):0:Digits, Result);
 | |
| {$else}
 | |
|             Str(Extended(Currency(Value)):0:Digits, Result);
 | |
| {$endif FPC_HAS_STR_CURRENCY}
 | |
|           else
 | |
|             Str(Extended(Value):0:Digits, Result);
 | |
|         end;
 | |
|         Negative:=Result[1] = '-';
 | |
|         if Negative then
 | |
|           System.Delete(Result, 1, 1);
 | |
|         P := Pos('.', Result);
 | |
|         If P <> 0 Then Result[P] := DS;
 | |
|         Dec(P, 3);
 | |
|         While (P > 1) Do
 | |
|         Begin
 | |
|           Insert(FormatSettings.ThousandSeparator, Result, P);
 | |
|           Dec(P, 3);
 | |
|         End;
 | |
| 
 | |
|         If Not Negative Then
 | |
|         Begin
 | |
|           Case FormatSettings.CurrencyFormat Of
 | |
|             0: Result := FormatSettings.CurrencyString + Result;
 | |
|             1: Result := Result + FormatSettings.CurrencyString;
 | |
|             2: Result := FormatSettings.CurrencyString + ' ' + Result;
 | |
|             3: Result := Result + ' ' + FormatSettings.CurrencyString;
 | |
|           End
 | |
|         End
 | |
|         Else
 | |
|         Begin
 | |
|           Case NegCurrFormat Of
 | |
|             0: Result := '(' + FormatSettings.CurrencyString + Result + ')';
 | |
|             1: Result := '-' + FormatSettings.CurrencyString + Result;
 | |
|             2: Result := FormatSettings.CurrencyString + '-' + Result;
 | |
|             3: Result := FormatSettings.CurrencyString + Result + '-';
 | |
|             4: Result := '(' + Result + FormatSettings.CurrencyString + ')';
 | |
|             5: Result := '-' + Result + FormatSettings.CurrencyString;
 | |
|             6: Result := Result + '-' + FormatSettings.CurrencyString;
 | |
|             7: Result := Result + FormatSettings.CurrencyString + '-';
 | |
|             8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
 | |
|             9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
 | |
|             10: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
 | |
|           End;
 | |
|         End;
 | |
|       End;
 | |
|   End;
 | |
| End;
 | |
| 
 | |
| 
 | |
| {$ifdef FPC_HAS_TYPE_EXTENDED}
 | |
| Function FloatToStr(Value: Extended; Const FormatSettings: TFormatSettings): String;
 | |
| Begin
 | |
|   Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvExtended,FormatSettings);
 | |
| End;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Extended): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStr(Value,DefaultFormatSettings);
 | |
| end;
 | |
| {$endif FPC_HAS_TYPE_EXTENDED}
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Currency; Const FormatSettings: TFormatSettings): String;
 | |
| Begin
 | |
|   Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvCurrency,FormatSettings);
 | |
| End;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Currency): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStr(Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Double; Const FormatSettings: TFormatSettings): String;
 | |
| var
 | |
|   e: Extended;
 | |
| Begin
 | |
|   e := Value;
 | |
|   Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvDouble,FormatSettings);
 | |
| End;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Double): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStr(Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Single; Const FormatSettings: TFormatSettings): String;
 | |
| var
 | |
|   e: Extended;
 | |
| Begin
 | |
|   e := Value;
 | |
|   Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvSingle,FormatSettings);
 | |
| End;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Single): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStr(Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Comp; Const FormatSettings: TFormatSettings): String;
 | |
| var
 | |
|   e: Extended;
 | |
| Begin
 | |
|   e := Value;
 | |
|   Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
 | |
| End;
 | |
| 
 | |
| 
 | |
| Function FloatToStr(Value: Comp): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStr(Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| {$ifndef FPC_COMP_IS_INT64}
 | |
| Function FloatToStr(Value: Int64): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStr(Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function FloatToStr(Value: Int64; Const FormatSettings: TFormatSettings): String;
 | |
| 
 | |
| var
 | |
|   e: Extended;
 | |
| 
 | |
| Begin
 | |
|   e := Comp(Value);
 | |
|   Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
 | |
| End;
 | |
| {$endif FPC_COMP_IS_INT64}
 | |
| 
 | |
| 
 | |
| Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
 | |
| Var
 | |
|   Tmp: String[40];
 | |
| Begin
 | |
|   Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
 | |
|   Result := Length(Tmp);
 | |
|   Move(Tmp[1], Buffer[0], Result);
 | |
| End;
 | |
| 
 | |
| 
 | |
| Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| {$ifdef FPC_HAS_TYPE_EXTENDED}
 | |
| Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
 | |
| begin
 | |
|   Result := FloatToStrFIntl(value,format,precision,digits,fvExtended,FormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| {$endif}
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
 | |
| begin
 | |
|   Result := FloatToStrFIntl(value,format,precision,digits,fvCurrency,FormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStrF(Value,format,Precision,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
 | |
| var
 | |
|   e: Extended;
 | |
| begin
 | |
|   e := Value;
 | |
|   result := FloatToStrFIntl(e,format,precision,digits,fvDouble,FormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
 | |
| 
 | |
| begin
 | |
|   Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
 | |
| 
 | |
| var
 | |
|   e: Extended;
 | |
| begin
 | |
|   e:=Value;
 | |
|   result := FloatToStrFIntl(e,format,precision,digits,fvSingle,FormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
 | |
| 
 | |
| begin
 | |
|   Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
 | |
| 
 | |
| var
 | |
|   e: Extended;
 | |
| begin
 | |
|   e := Value;
 | |
|   Result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| {$ifndef FPC_COMP_IS_INT64}
 | |
| Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
 | |
| 
 | |
| var
 | |
|   e: Extended;
 | |
| begin
 | |
|   e := Comp(Value);
 | |
|   result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| {$endif FPC_COMP_IS_INT64}
 | |
| 
 | |
| 
 | |
| Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer; Const FormatSettings: TFormatSettings): string;
 | |
| 
 | |
| begin
 | |
|   result:=FloatToStrF(Value,Format,19,Digits,FormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrToStrF(Value,Format,Digits,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FloatToDateTime (Const Value : Extended) : TDateTime;
 | |
| begin
 | |
|   If (Value<MinDateTime) or (Value>MaxDateTime) then
 | |
|     Raise EConvertError.CreateFmt (SInvalidDateTime,[Value]);
 | |
|   Result:=Value;
 | |
| end;
 | |
| 
 | |
| function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
 | |
|   if Result then
 | |
|     AResult := Value;
 | |
| end;
 | |
| 
 | |
| function FloatToCurr(const Value: Extended): Currency;
 | |
| 
 | |
| begin
 | |
|   if not TryFloatToCurr(Value, Result) then
 | |
|     Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function CurrToStr(Value: Currency): string;
 | |
| begin
 | |
|   Result:=FloatToStrF(Value,ffGeneral,-1,0);
 | |
| end;
 | |
| 
 | |
| function AnsiDequotedStr(const S: string; AQuote: Char): string;
 | |
| 
 | |
| var p : pchar;
 | |
| 
 | |
| begin
 | |
|   p:=pchar(pointer(s)); // work around CONST. Ansiextract is safe for nil
 | |
|   result:=AnsiExtractquotedStr(p,AQuote);
 | |
|   if result='' Then
 | |
|     result:=s;
 | |
| end;
 | |
| 
 | |
| function StrToCurr(const S: string): Currency;
 | |
| begin
 | |
|   if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
 | |
|     Raise EConvertError.createfmt(SInValidFLoat,[S]);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function TryStrToCurr(Const S : String; Var Value: Currency): Boolean;
 | |
| Begin
 | |
|   Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency);
 | |
| End;
 | |
| 
 | |
| 
 | |
| function StrToCurrDef(const S: string; Default : Currency): Currency;
 | |
| begin
 | |
|   if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
 | |
|     Result:=Default;
 | |
| end;
 | |
| 
 | |
| 
 | |
| function StrToBool(const S: string): Boolean;
 | |
| begin
 | |
|   if not(TryStrToBool(S,Result)) then
 | |
|     Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
 | |
| end;
 | |
| 
 | |
| function BoolToStr(B: Boolean;UseBoolStrs:Boolean=False): string;
 | |
| 
 | |
| procedure CheckStrs;
 | |
| begin
 | |
|     If Length(TrueBoolStrs)=0 then
 | |
|       begin
 | |
|         SetLength(TrueBoolStrs,1);
 | |
|         TrueBoolStrs[0]:='True';
 | |
|       end;
 | |
|     If Length(FalseBoolStrs)=0 then
 | |
|       begin
 | |
|         SetLength(FalseBoolStrs,1);
 | |
|         FalseBoolStrs[0]:='False';
 | |
|       end;
 | |
| end;
 | |
| 
 | |
| begin
 | |
|  if UseBoolStrs Then
 | |
|   begin
 | |
|     CheckStrs;
 | |
|     if B then
 | |
|       Result:=TrueBoolStrs[0]
 | |
|     else
 | |
|       Result:=FalseBoolStrs[0];
 | |
|   end
 | |
|  else
 | |
|   If B then
 | |
|     Result:='-1'
 | |
|   else
 | |
|     Result:='0';
 | |
| end;
 | |
| 
 | |
| function StrToBoolDef(const S: string; Default: Boolean): Boolean;
 | |
| begin
 | |
|   if not(TryStrToBool(S,Result)) then
 | |
|     Result:=Default;
 | |
| end;
 | |
| 
 | |
| function TryStrToBool(const S: string; out Value: Boolean): Boolean;
 | |
| Var
 | |
|   Temp : String;
 | |
|   D : Double;
 | |
|   Code: word;
 | |
| begin
 | |
|   Temp:=upcase(S);
 | |
|   Val(temp,D,code);
 | |
|   Result:=true;
 | |
|   If Code=0 then
 | |
|     Value:=(D<>0.0)
 | |
|   else If Temp='TRUE' then
 | |
|     Value:=true
 | |
|   else if Temp='FALSE' then
 | |
|     Value:=false
 | |
|   else
 | |
|     Result:=false;
 | |
| end;
 | |
| 
 | |
| Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
 | |
| 
 | |
| begin
 | |
|   Result:=FloatToTextFmt(Buffer,Value,Format,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar;FormatSettings : TFormatSettings): Integer;
 | |
| 
 | |
| Var
 | |
|   Digits: String[40];                         { String Of Digits                 }
 | |
|   Exponent: String[8];                        { Exponent strin                   }
 | |
|   FmtStart, FmtStop: PChar;                   { Start And End Of relevant part   }
 | |
|                                               { Of format String                 }
 | |
|   ExpFmt, ExpSize: Integer;                   { Type And Length Of               }
 | |
|                                               { exponential format chosen        }
 | |
|   Placehold: Array[1..4] Of Integer;          { Number Of placeholders In All    }
 | |
|                                               { four Sections                    }
 | |
|   thousand: Boolean;                          { thousand separators?             }
 | |
|   UnexpectedDigits: Integer;                  { Number Of unexpected Digits that }
 | |
|                                               { have To be inserted before the   }
 | |
|                                               { First placeholder.               }
 | |
|   DigitExponent: Integer;                     { Exponent Of First digit In       }
 | |
|                                               { Digits Array.                    }
 | |
| 
 | |
|   { Find end of format section starting at P. False, if empty }
 | |
| 
 | |
|   Function GetSectionEnd(Var P: PChar): Boolean;
 | |
|   Var
 | |
|     C: Char;
 | |
|     SQ, DQ: Boolean;
 | |
|   Begin
 | |
|     Result := False;
 | |
|     SQ := False;
 | |
|     DQ := False;
 | |
|     C := P[0];
 | |
|     While (C<>#0) And ((C<>';') Or SQ Or DQ) Do
 | |
|       Begin
 | |
|       Result := True;
 | |
|       Case C Of
 | |
|         #34: If Not SQ Then DQ := Not DQ;
 | |
|         #39: If Not DQ Then SQ := Not SQ;
 | |
|       End;
 | |
|       Inc(P);
 | |
|       C := P[0];
 | |
|       End;
 | |
|   End;
 | |
| 
 | |
|   { Find start and end of format section to apply. If section doesn't exist,
 | |
|     use section 1. If section 2 is used, the sign of value is ignored.       }
 | |
| 
 | |
|   Procedure GetSectionRange(section: Integer);
 | |
|   Var
 | |
|     Sec: Array[1..3] Of PChar;
 | |
|     SecOk: Array[1..3] Of Boolean;
 | |
|   Begin
 | |
|     Sec[1] := format;
 | |
|     SecOk[1] := GetSectionEnd(Sec[1]);
 | |
|     If section > 1 Then
 | |
|       Begin
 | |
|       Sec[2] := Sec[1];
 | |
|       If Sec[2][0] <> #0 Then
 | |
|         Inc(Sec[2]);
 | |
|       SecOk[2] := GetSectionEnd(Sec[2]);
 | |
|       If section > 2 Then
 | |
|         Begin
 | |
|         Sec[3] := Sec[2];
 | |
|         If Sec[3][0] <> #0 Then
 | |
|           Inc(Sec[3]);
 | |
|         SecOk[3] := GetSectionEnd(Sec[3]);
 | |
|         End;
 | |
|       End;
 | |
|     If Not SecOk[1] Then
 | |
|       FmtStart := Nil
 | |
|     Else
 | |
|       Begin
 | |
|       If Not SecOk[section] Then
 | |
|         section := 1
 | |
|       Else If section = 2 Then
 | |
|         Value := -Value;   { Remove sign }
 | |
|       If section = 1 Then FmtStart := format Else
 | |
|         Begin
 | |
|         FmtStart := Sec[section - 1];
 | |
|         Inc(FmtStart);
 | |
|         End;
 | |
|       FmtStop := Sec[section];
 | |
|       End;
 | |
|   End;
 | |
| 
 | |
|   { Find format section ranging from FmtStart to FmtStop. }
 | |
| 
 | |
|   Procedure GetFormatOptions;
 | |
|   Var
 | |
|     Fmt: PChar;
 | |
|     SQ, DQ: Boolean;
 | |
|     area: Integer;
 | |
|   Begin
 | |
|     SQ := False;
 | |
|     DQ := False;
 | |
|     Fmt := FmtStart;
 | |
|     ExpFmt := 0;
 | |
|     area := 1;
 | |
|     thousand := False;
 | |
|     Placehold[1] := 0;
 | |
|     Placehold[2] := 0;
 | |
|     Placehold[3] := 0;
 | |
|     Placehold[4] := 0;
 | |
|     While Fmt < FmtStop Do
 | |
|       Begin
 | |
|       Case Fmt[0] Of
 | |
|         #34:
 | |
|           Begin
 | |
|           If Not SQ Then
 | |
|             DQ := Not DQ;
 | |
|           Inc(Fmt);
 | |
|           End;
 | |
|         #39:
 | |
|           Begin
 | |
|           If Not DQ Then
 | |
|             SQ := Not SQ;
 | |
|           Inc(Fmt);
 | |
|           End;
 | |
|       Else
 | |
|        { if not in quotes, then interpret}
 | |
|         If Not (SQ Or DQ) Then
 | |
|           Begin
 | |
|           Case Fmt[0] Of
 | |
|             '0':
 | |
|               Begin
 | |
|               Case area Of
 | |
|                 1:
 | |
|                   area := 2;
 | |
|                 4:
 | |
|                   Begin
 | |
|                   area := 3;
 | |
|                   Inc(Placehold[3], Placehold[4]);
 | |
|                   Placehold[4] := 0;
 | |
|                   End;
 | |
|               End;
 | |
|               Inc(Placehold[area]);
 | |
|               Inc(Fmt);
 | |
|               End;
 | |
| 
 | |
|             '#':
 | |
|               Begin
 | |
|               If area=3 Then
 | |
|                 area:=4;
 | |
|               Inc(Placehold[area]);
 | |
|               Inc(Fmt);
 | |
|               End;
 | |
|             '.':
 | |
|               Begin
 | |
|               If area<3 Then
 | |
|                 area:=3;
 | |
|               Inc(Fmt);
 | |
|               End;
 | |
|             ',':
 | |
|               Begin
 | |
|               thousand := True;
 | |
|               Inc(Fmt);
 | |
|               End;
 | |
|             'e', 'E':
 | |
|               If ExpFmt = 0 Then
 | |
|                 Begin
 | |
|                 If (Fmt[0]='E') Then
 | |
|                   ExpFmt:=1
 | |
|                 Else
 | |
|                   ExpFmt := 3;
 | |
|                 Inc(Fmt);
 | |
|                 If (Fmt<FmtStop) Then
 | |
|                   Begin
 | |
|                   Case Fmt[0] Of
 | |
|                     '+':
 | |
|                       Begin
 | |
|                       End;
 | |
|                     '-':
 | |
|                       Inc(ExpFmt);
 | |
|                   Else
 | |
|                     ExpFmt := 0;
 | |
|                   End;
 | |
|                   If ExpFmt <> 0 Then
 | |
|                     Begin
 | |
|                     Inc(Fmt);
 | |
|                     ExpSize := 0;
 | |
|                     While (Fmt<FmtStop) And
 | |
|                           (ExpSize<4) And
 | |
|                           (Fmt[0] In ['0'..'9']) Do
 | |
|                       Begin
 | |
|                       Inc(ExpSize);
 | |
|                       Inc(Fmt);
 | |
|                       End;
 | |
|                     End;
 | |
|                   End;
 | |
|                 End
 | |
|               Else
 | |
|                 Inc(Fmt);
 | |
|           Else { Case }
 | |
|             Inc(Fmt);
 | |
|           End; { Case }
 | |
|           End  { Begin }
 | |
|         Else
 | |
|           Inc(Fmt);
 | |
|       End; { Case }
 | |
|       End; { While .. Begin }
 | |
|   End;
 | |
| 
 | |
|   Procedure FloatToStr;
 | |
| 
 | |
|   Var
 | |
|     I, J, Exp, Width, Decimals, DecimalPoint, len: Integer;
 | |
| 
 | |
|   Begin
 | |
|     If ExpFmt = 0 Then
 | |
|       Begin
 | |
|       { Fixpoint }
 | |
|       Decimals:=Placehold[3]+Placehold[4];
 | |
|       Width:=Placehold[1]+Placehold[2]+Decimals;
 | |
|       If (Decimals=0) Then
 | |
|         Str(Value:Width:0,Digits)
 | |
|       Else
 | |
|         Str(Value:Width+1:Decimals,Digits);
 | |
|       len:=Length(Digits);
 | |
|       { Find the decimal point }
 | |
|       If (Decimals=0) Then
 | |
|         DecimalPoint:=len+1
 | |
|       Else
 | |
|         DecimalPoint:=len-Decimals;
 | |
|       { If value is very small, and no decimal places
 | |
|         are desired, remove the leading 0.            }
 | |
|       If (Abs(Value) < 1) And (Placehold[2] = 0) Then
 | |
|         Begin
 | |
|         If (Placehold[1]=0) Then
 | |
|           Delete(Digits,DecimalPoint-1,1)
 | |
|         Else
 | |
|           Digits[DecimalPoint-1]:=' ';
 | |
|         End;
 | |
| 
 | |
|       { Convert optional zeroes to spaces. }
 | |
|       I:=len;
 | |
|       J:=DecimalPoint+Placehold[3];
 | |
|       While (I>J) And (Digits[I]='0') Do
 | |
|         Begin
 | |
|         Digits[I] := ' ';
 | |
|         Dec(I);
 | |
|         End;
 | |
|       { If integer value and no obligatory decimal
 | |
|         places, remove decimal point. }
 | |
|       If (DecimalPoint < len) And (Digits[DecimalPoint + 1] = ' ') Then
 | |
|           Digits[DecimalPoint] := ' ';
 | |
|       { Convert spaces left from obligatory decimal point to zeroes. }
 | |
|       I:=DecimalPoint-Placehold[2];
 | |
|       While (I<DecimalPoint) And (Digits[I]=' ') Do
 | |
|         Begin
 | |
|         Digits[I] := '0';
 | |
|         Inc(I);
 | |
|         End;
 | |
|       Exp := 0;
 | |
|       End
 | |
|     Else
 | |
|       Begin
 | |
|       { Scientific: exactly <Width> Digits With <Precision> Decimals
 | |
|         And adjusted Exponent. }
 | |
|       If Placehold[1]+Placehold[2]=0 Then
 | |
|         Placehold[1]:=1;
 | |
|       Decimals := Placehold[3] + Placehold[4];
 | |
|       Width:=Placehold[1]+Placehold[2]+Decimals;
 | |
|       Str(Value:Width+8,Digits);
 | |
|       { Find and cut out exponent. Always the
 | |
|         last 6 characters in the string.
 | |
|         -> 0000E+0000                         
 | |
|         *** No, not always the last 6 characters, this depends on
 | |
|             the maximally supported precision (JM)}
 | |
|       I:=Pos('E',Digits);
 | |
|       Val(Copy(Digits,I+1,255),Exp,J);
 | |
|       Exp:=Exp+1-(Placehold[1]+Placehold[2]);
 | |
|       Delete(Digits, I, 255);
 | |
|       { Str() always returns at least one digit after the decimal point.
 | |
|         If we don't want it, we have to remove it. }
 | |
|       If (Decimals=0) And (Placehold[1]+Placehold[2]<= 1) Then
 | |
|         Begin
 | |
|         If (Digits[4]>='5') Then
 | |
|           Begin
 | |
|           Inc(Digits[2]);
 | |
|           If (Digits[2]>'9') Then
 | |
|             Begin
 | |
|             Digits[2] := '1';
 | |
|             Inc(Exp);
 | |
|             End;
 | |
|           End;
 | |
|         Delete(Digits, 3, 2);
 | |
|         DecimalPoint := Length(Digits) + 1;
 | |
|         End
 | |
|       Else
 | |
|         Begin
 | |
|         { Move decimal point at the desired position }
 | |
|         Delete(Digits, 3, 1);
 | |
|         DecimalPoint:=2+Placehold[1]+Placehold[2];
 | |
|         If (Decimals<>0) Then
 | |
|           Insert('.',Digits,DecimalPoint);
 | |
|         End;
 | |
| 
 | |
|       { Convert optional zeroes to spaces. }
 | |
|       I := Length(Digits);
 | |
|       J := DecimalPoint + Placehold[3];
 | |
|       While (I > J) And (Digits[I] = '0') Do
 | |
|         Begin
 | |
|         Digits[I] := ' ';
 | |
|         Dec(I);
 | |
|         End;
 | |
| 
 | |
|       { If integer number and no obligatory decimal paces, remove decimal point }
 | |
| 
 | |
|       If (DecimalPoint<Length(Digits)) And
 | |
|          (Digits[DecimalPoint+1]=' ') Then
 | |
|           Digits[DecimalPoint]:=' ';
 | |
|       If (Digits[1]=' ') Then
 | |
|         Begin
 | |
|         Delete(Digits, 1, 1);
 | |
|         Dec(DecimalPoint);
 | |
|         End;
 | |
|       { Calculate exponent string }
 | |
|       Str(Abs(Exp), Exponent);
 | |
|       While Length(Exponent)<ExpSize Do
 | |
|         Insert('0',Exponent,1);
 | |
|       If Exp >= 0 Then
 | |
|         Begin
 | |
|         If (ExpFmt In [1,3]) Then
 | |
|           Insert('+', Exponent, 1);
 | |
|         End
 | |
|       Else
 | |
|         Insert('-',Exponent,1);
 | |
|       If (ExpFmt<3) Then
 | |
|         Insert('E',Exponent,1)
 | |
|       Else
 | |
|         Insert('e',Exponent,1);
 | |
|       End;
 | |
|     DigitExponent:=DecimalPoint-2;
 | |
|     If (Digits[1]='-') Then
 | |
|       Dec(DigitExponent);
 | |
|     UnexpectedDigits:=DecimalPoint-1-(Placehold[1]+Placehold[2]);
 | |
|   End;
 | |
| 
 | |
|   Function PutResult: LongInt;
 | |
| 
 | |
|   Var
 | |
|     SQ, DQ: Boolean;
 | |
|     Fmt, Buf: PChar;
 | |
|     Dig, N: Integer;
 | |
| 
 | |
|   Begin
 | |
|     SQ := False;
 | |
|     DQ := False;
 | |
|     Fmt := FmtStart;
 | |
|     Buf := Buffer;
 | |
|     Dig := 1;
 | |
|     While (Fmt<FmtStop) Do
 | |
|       Begin
 | |
|       //Write(Fmt[0]);
 | |
|       Case Fmt[0] Of
 | |
|         #34:
 | |
|           Begin
 | |
|           If Not SQ Then
 | |
|             DQ := Not DQ;
 | |
|           Inc(Fmt);
 | |
|           End;
 | |
|         #39:
 | |
|           Begin
 | |
|           If Not DQ Then
 | |
|             SQ := Not SQ;
 | |
|           Inc(Fmt);
 | |
|           End;
 | |
|       Else
 | |
|         If Not (SQ Or DQ) Then
 | |
|           Begin
 | |
|           Case Fmt[0] Of
 | |
|             '0', '#', '.':
 | |
|               Begin
 | |
|               If (Dig=1) And (UnexpectedDigits>0) Then
 | |
|                 Begin
 | |
|                 { Everything unexpected is written before the first digit }
 | |
|                 For N := 1 To UnexpectedDigits Do
 | |
|                   Begin
 | |
|                   Buf[0] := Digits[N];
 | |
|                   Inc(Buf);
 | |
|                   If thousand And (Digits[N]<>'-') Then
 | |
|                     Begin
 | |
|                     If (DigitExponent Mod 3 = 0) And (DigitExponent>0) Then
 | |
|                       Begin
 | |
|                       Buf[0] := FormatSettings.ThousandSeparator;
 | |
|                       Inc(Buf);
 | |
|                       End;
 | |
|                     Dec(DigitExponent);
 | |
|                     End;
 | |
|                   End;
 | |
|                 Inc(Dig, UnexpectedDigits);
 | |
|                 End;
 | |
|               If (Digits[Dig]<>' ') Then
 | |
|                 Begin
 | |
|                 If (Digits[Dig]='.') Then
 | |
|                   Buf[0] := FormatSettings.DecimalSeparator
 | |
|                 Else
 | |
|                   Buf[0] := Digits[Dig];
 | |
|                 Inc(Buf);
 | |
|                 If thousand And (DigitExponent Mod 3 = 0) And (DigitExponent > 0) Then
 | |
|                   Begin
 | |
|                   Buf[0] := FormatSettings.ThousandSeparator;
 | |
|                   Inc(Buf);
 | |
|                   End;
 | |
|                 End;
 | |
|               Inc(Dig);
 | |
|               Dec(DigitExponent);
 | |
|               Inc(Fmt);
 | |
|               End;
 | |
|             'e', 'E':
 | |
|               Begin
 | |
|               If ExpFmt <> 0 Then
 | |
|                 Begin
 | |
|                 Inc(Fmt);
 | |
|                 If Fmt < FmtStop Then
 | |
|                   Begin
 | |
|                   If Fmt[0] In ['+', '-'] Then
 | |
|                     Begin
 | |
|                     Inc(Fmt, ExpSize);
 | |
|                     For N:=1 To Length(Exponent) Do
 | |
|                       Buf[N-1] := Exponent[N];
 | |
|                     Inc(Buf,Length(Exponent));
 | |
|                     ExpFmt:=0;
 | |
|                     End;
 | |
|                   Inc(Fmt);
 | |
|                   End;
 | |
|                 End
 | |
|               Else
 | |
|                 Begin
 | |
|                 { No legal exponential format.
 | |
|                   Simply write the 'E' to the result. }
 | |
|                 Buf[0] := Fmt[0];
 | |
|                 Inc(Buf);
 | |
|                 Inc(Fmt);
 | |
|                 End;
 | |
|               End;
 | |
|           Else { Case }
 | |
|             { Usual character }
 | |
|             If (Fmt[0]<>',') Then
 | |
|               Begin
 | |
|               Buf[0] := Fmt[0];
 | |
|               Inc(Buf);
 | |
|               End;
 | |
|             Inc(Fmt);
 | |
|           End; { Case }
 | |
|           End
 | |
|         Else { IF }
 | |
|           Begin
 | |
|           { Character inside single or double quotes }
 | |
|           Buf[0] := Fmt[0];
 | |
|           Inc(Buf);
 | |
|           Inc(Fmt);
 | |
|           End;
 | |
|       End; { Case }
 | |
|     End; { While .. Begin }
 | |
|     Result:=PtrInt(Buf)-PtrInt(Buffer);
 | |
|   End;
 | |
| 
 | |
| Begin
 | |
|   If (Value>0) Then
 | |
|     GetSectionRange(1)
 | |
|   Else If (Value<0) Then
 | |
|     GetSectionRange(2)
 | |
|   Else
 | |
|     GetSectionRange(3);
 | |
|   If FmtStart = Nil Then
 | |
|     Begin
 | |
|     Result := FloatToText(Buffer, Value, ffGeneral, 15, 4, FormatSettings);
 | |
|     End
 | |
|   Else
 | |
|     Begin
 | |
|     GetFormatOptions;
 | |
|     If (ExpFmt = 0) And (Abs(Value) >= 1E18) Then
 | |
|       Result := FloatToText(Buffer, Value, ffGeneral, 15, 4, FormatSettings)
 | |
|     Else
 | |
|       Begin
 | |
|       FloatToStr;
 | |
|       Result := PutResult;
 | |
|       End;
 | |
|     End;
 | |
| End;
 | |
| 
 | |
| 
 | |
| Procedure FloatToDecimal(Out Result: TFloatRec; const Value; ValueType: TFloatValue; Precision, Decimals : integer);
 | |
| var
 | |
|   Buffer: String[254];  //Though str func returns only 25 chars, this might change in the future
 | |
|   Error, N, L, Start, C: Integer;
 | |
|   GotNonZeroBeforeDot, BeforeDot : boolean;
 | |
| begin
 | |
|   case ValueType of
 | |
|     fvExtended:
 | |
|       Str(Extended(Value):25, Buffer);
 | |
|     fvDouble,
 | |
|     fvReal:
 | |
|       Str(Double(Value):23, Buffer);
 | |
|     fvSingle:
 | |
|       Str(Single(Value):16, Buffer);
 | |
|     fvCurrency:
 | |
|       Str(Currency(Value):25, Buffer);
 | |
|     fvComp:
 | |
|       Str(Currency(Value):23, Buffer);
 | |
|   end;
 | |
| 
 | |
|   N := 1;
 | |
|   L := Byte(Buffer[0]);
 | |
|   while Buffer[N]=' ' do
 | |
|     Inc(N);
 | |
|   Result.Negative := (Buffer[N] = '-');
 | |
|   if Result.Negative then
 | |
|     Inc(N);
 | |
|   Start := N;  //Start of digits
 | |
|   Result.Exponent := 0; BeforeDot := true;
 | |
|   GotNonZeroBeforeDot := false;
 | |
|   while (L>=N) and (Buffer[N]<>'E') do
 | |
|     begin
 | |
|       if Buffer[N]='.' then
 | |
|         BeforeDot := false
 | |
|       else
 | |
|         begin
 | |
|           if BeforeDot then
 | |
|             begin  // Currently this is always 1 char
 | |
|               Inc(Result.Exponent);
 | |
|               Result.Digits[N-Start] := Buffer[N];
 | |
|               if Buffer[N] <> '0' then
 | |
|                 GotNonZeroBeforeDot := true;
 | |
|             end
 | |
|           else
 | |
|             Result.Digits[N-Start-1] := Buffer[N]
 | |
|         end;
 | |
|       Inc(N);
 | |
|     end;
 | |
|   Inc(N); // Pass through 'E'
 | |
|   if N<=L then
 | |
|     begin
 | |
|       Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
 | |
|       Inc(Result.Exponent, C);
 | |
|     end;
 | |
|   // Calculate number of digits we have from str
 | |
|   if BeforeDot then
 | |
|     N := N - Start - 1
 | |
|   else
 | |
|     N := N - Start - 2;
 | |
|   L := SizeOf(Result.Digits);
 | |
|   if N<L then
 | |
|     FillChar(Result.Digits[N], L-N, '0');  //Zero remaining space
 | |
|   if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
 | |
|     N := Decimals + Result.Exponent
 | |
|   Else
 | |
|     N := Precision;
 | |
|   if N >= L Then
 | |
|     N := L-1;
 | |
|   if N = 0 Then
 | |
|     begin
 | |
|       if Result.Digits[0] >= '5' Then
 | |
|         begin
 | |
|           Result.Digits[0] := '1';
 | |
|           Result.Digits[1] := #0;
 | |
|           Inc(Result.Exponent);
 | |
|         end
 | |
|       Else
 | |
|         Result.Digits[0] := #0;
 | |
|     end  //N=0
 | |
|   Else if N > 0 Then
 | |
|     begin
 | |
|       if Result.Digits[N] >= '5' Then
 | |
|         begin
 | |
|           Repeat
 | |
|             Result.Digits[N] := #0;
 | |
|             Dec(N);
 | |
|             Inc(Result.Digits[N]);
 | |
|           Until (N = 0) Or (Result.Digits[N] < ':');
 | |
|           If Result.Digits[0] = ':' Then
 | |
|             begin
 | |
|               Result.Digits[0] := '1';
 | |
|               Inc(Result.Exponent);
 | |
|             end;
 | |
|         end
 | |
|       Else
 | |
|         begin
 | |
|           Result.Digits[N] := '0';
 | |
|           While (N > -1) And (Result.Digits[N] = '0') Do
 | |
|             begin
 | |
|               Result.Digits[N] := #0;
 | |
|               Dec(N);
 | |
|             end;
 | |
|         end;
 | |
|       end //N>0
 | |
|   Else
 | |
|     Result.Digits[0] := #0;
 | |
|   if (Result.Digits[0] = #0) and
 | |
|      not GotNonZeroBeforeDot then
 | |
|     begin
 | |
|       Result.Exponent := 0;
 | |
|       Result.Negative := False;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| Procedure FloatToDecimal(Out Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
 | |
| 
 | |
| begin
 | |
|   FloatToDecimal(Result,Value,fvExtended,Precision,Decimals);
 | |
| end;
 | |
| 
 | |
| Function FormatFloat(Const Format : String; Value : Extended; Const FormatSettings: TFormatSettings) : String;
 | |
| 
 | |
| Var
 | |
|   buf : Array[0..1024] of char;
 | |
| 
 | |
| Begin // not changed to pchar(pointer(). Possibly not safe
 | |
|   Buf[FloatToTextFmt(@Buf[0],Value,Pchar(Format),FormatSettings)]:=#0;
 | |
|   Result:=StrPas(@Buf[0]);
 | |
| End;
 | |
| 
 | |
| Function FormatFloat(Const format: String; Value: Extended): String;
 | |
| 
 | |
| begin
 | |
|   Result:=FormatFloat(Format,Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| Function FormatCurr(const Format: string; Value: Currency; Const FormatSettings: TFormatSettings): string;
 | |
| begin
 | |
|   Result := FormatFloat(Format, Value,FormatSettings);
 | |
| end;
 | |
| 
 | |
| function FormatCurr(const Format: string; Value: Currency): string;
 | |
| 
 | |
| begin
 | |
|   Result:=FormatCurr(Format,Value,DefaultFormatSettings);
 | |
| end;
 | |
| 
 | |
| 
 | |
| {==============================================================================}
 | |
| {   extra functions                                                            }
 | |
| {==============================================================================}
 | |
| 
 | |
| {   LeftStr returns Count left-most characters from S }
 | |
| 
 | |
| function LeftStr(const S: string; Count: integer): string;
 | |
| begin
 | |
|   result := Copy(S, 1, Count);
 | |
| end ;
 | |
| 
 | |
| { RightStr returns Count right-most characters from S }
 | |
| 
 | |
| function RightStr(const S: string; Count: integer): string;
 | |
| begin
 | |
|    If Count>Length(S) then
 | |
|      Count:=Length(S);
 | |
|    result := Copy(S, 1 + Length(S) - Count, Count);
 | |
| end;
 | |
| 
 | |
| {    BCDToInt converts the BCD value Value to an integer   }
 | |
| 
 | |
| function BCDToInt(Value: integer): integer;
 | |
| var i, j: integer;
 | |
| begin
 | |
| result := 0;
 | |
| j := 1;
 | |
| for i := 0 to SizeOf(Value) shr 1 - 1 do begin
 | |
|    result := result + j * (Value and 15);
 | |
|    j := j * 10;
 | |
|    Value := Value shr 4;
 | |
|    end ;
 | |
| end ;
 | |
| 
 | |
| Function LastDelimiter(const Delimiters, S: string): Integer;
 | |
| 
 | |
| begin
 | |
|   Result:=Length(S);
 | |
|   While (Result>0) and (Pos(S[Result],Delimiters)=0) do
 | |
|     Dec(Result);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function StringReplace(const S, OldPattern, NewPattern: string;  Flags: TReplaceFlags): string;
 | |
| var
 | |
|   Srch,OldP,RemS: string; // Srch and Oldp can contain uppercase versions of S,OldPattern
 | |
|   P : Integer;
 | |
| begin
 | |
|   Srch:=S;
 | |
|   OldP:=OldPattern;
 | |
|   if rfIgnoreCase in Flags then
 | |
|     begin
 | |
|     Srch:=AnsiUpperCase(Srch);
 | |
|     OldP:=AnsiUpperCase(OldP);
 | |
|     end;
 | |
|   RemS:=S;
 | |
|   Result:='';
 | |
|   while (Length(Srch)<>0) do
 | |
|     begin
 | |
|     P:=AnsiPos(OldP, Srch);
 | |
|     if P=0 then
 | |
|       begin
 | |
|       Result:=Result+RemS;
 | |
|       Srch:='';
 | |
|       end
 | |
|     else
 | |
|       begin
 | |
|       Result:=Result+Copy(RemS,1,P-1)+NewPattern;
 | |
|       P:=P+Length(OldP);
 | |
|       RemS:=Copy(RemS,P,Length(RemS)-P+1);
 | |
|       if not (rfReplaceAll in Flags) then
 | |
|         begin
 | |
|         Result:=Result+RemS;
 | |
|         Srch:='';
 | |
|         end
 | |
|       else
 | |
|          Srch:=Copy(Srch,P,Length(Srch)-P+1);
 | |
|       end;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=False;
 | |
|   If (Index>0) and (Index<=Length(S)) then
 | |
|     Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
 | |
| end;
 | |
| 
 | |
| Function ByteToCharLen(const S: string; MaxLen: Integer): Integer;
 | |
| 
 | |
| begin
 | |
|   Result:=Length(S);
 | |
|   If Result>MaxLen then
 | |
|     Result:=MaxLen;
 | |
| end;
 | |
| 
 | |
| Function ByteToCharIndex(const S: string; Index: Integer): Integer;
 | |
| 
 | |
| begin
 | |
|   Result:=Index;
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function CharToByteLen(const S: string; MaxLen: Integer): Integer;
 | |
| 
 | |
| begin
 | |
|   Result:=Length(S);
 | |
|   If Result>MaxLen then
 | |
|     Result:=MaxLen;
 | |
| end;
 | |
| 
 | |
| Function CharToByteIndex(const S: string; Index: Integer): Integer;
 | |
| 
 | |
| begin
 | |
|   Result:=Index;
 | |
| end;
 | |
| 
 | |
| Function ByteType(const S: string; Index: Integer): TMbcsByteType;
 | |
| 
 | |
| begin
 | |
|   Result:=mbSingleByte;
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function StrByteType(Str: PChar; Index: Cardinal): TMbcsByteType;
 | |
| begin
 | |
|   Result:=mbSingleByte;
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function StrCharLength(const Str: PChar): Integer;
 | |
| begin
 | |
|   result:=widestringmanager.CharLengthPCharProc(Str);
 | |
| end;
 | |
| 
 | |
| 
 | |
| function StrNextChar(const Str: PChar): PChar;
 | |
| begin
 | |
|   result:=Str+StrCharLength(Str);
 | |
| end;
 | |
| 
 | |
| 
 | |
| Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
 | |
| 
 | |
| Var
 | |
|   I,L : Integer;
 | |
|   S,T : String;
 | |
| 
 | |
| begin
 | |
|   Result:=False;
 | |
|   S:=Switch;
 | |
|   If IgnoreCase then
 | |
|     S:=UpperCase(S);
 | |
|   I:=ParamCount;
 | |
|   While (Not Result) and (I>0) do
 | |
|     begin
 | |
|     L:=Length(Paramstr(I));
 | |
|     If (L>0) and (ParamStr(I)[1] in Chars) then
 | |
|       begin
 | |
|       T:=Copy(ParamStr(I),2,L-1);
 | |
|       If IgnoreCase then
 | |
|         T:=UpperCase(T);
 | |
|       Result:=S=T;
 | |
|       end;
 | |
|     Dec(i);
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
 | |
| end;
 | |
| 
 | |
| Function FindCmdLineSwitch(const Switch: string): Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
 | |
| end;
 | |
| 
 | |
| function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet;  MaxCol: Integer): string;
 | |
| 
 | |
| const
 | |
|   Quotes = ['''', '"'];
 | |
| 
 | |
| Var
 | |
|   L : String;
 | |
|   C,LQ,BC : Char;
 | |
|   P,BLen,Len : Integer;
 | |
|   HB,IBC : Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:='';
 | |
|   L:=Line;
 | |
|   Blen:=Length(BreakStr);
 | |
|   If (BLen>0) then
 | |
|     BC:=BreakStr[1]
 | |
|   else
 | |
|     BC:=#0;
 | |
|   Len:=Length(L);
 | |
|   While (Len>0) do
 | |
|     begin
 | |
|     P:=1;
 | |
|     LQ:=#0;
 | |
|     HB:=False;
 | |
|     IBC:=False;
 | |
|     While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
 | |
|       begin
 | |
|       C:=L[P];
 | |
|       If (C=LQ) then
 | |
|         LQ:=#0
 | |
|       else If (C in Quotes) then
 | |
|         LQ:=C;
 | |
|       If (LQ<>#0) then
 | |
|         Inc(P)
 | |
|       else
 | |
|         begin
 | |
|         HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
 | |
|         If HB then
 | |
|           Inc(P,Blen)
 | |
|         else
 | |
|           begin
 | |
|           If (P>MaxCol) then
 | |
|             IBC:=C in BreakChars;
 | |
|           Inc(P);
 | |
|           end;
 | |
|         end;
 | |
| //      Writeln('"',C,'" : IBC : ',IBC,' HB  : ',HB,' LQ  : ',LQ,' P>MaxCol : ',P>MaxCol);
 | |
|       end;
 | |
|     Result:=Result+Copy(L,1,P-1);
 | |
|     If Not HB then
 | |
|       Result:=Result+BreakStr;
 | |
|     Delete(L,1,P-1);
 | |
|     Len:=Length(L);
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| function WrapText(const Line: string; MaxCol: Integer): string;
 | |
| begin
 | |
|   Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
 | |
| end;
 | |
| 
 | |
| 
 | |
| {
 | |
|    Case Translation Tables
 | |
|    Can be used in internationalization support.
 | |
| 
 | |
|    Although these tables can be obtained through system calls
 | |
|    it is better to not use those, since most implementation are not 100%
 | |
|    WARNING:
 | |
|    before modifying a translation table make sure that the current codepage
 | |
|    of the OS corresponds to the one you make changes to
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| const
 | |
|    { upper case translation table for character set 850 }
 | |
|    CP850UCT: array[128..255] of char =
 | |
|    (#128,#154,#144,#182,#142,#182,#143,#128,#210,#211,#212,#216,#215,#222,#142,#143,
 | |
|     #144,#146,#146,#226,#153,#227,#234,#235,'Y',#153,#154,#157,#156,#157,#158,#159,
 | |
|     #181,#214,#224,#233,#165,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
 | |
|     #176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,
 | |
|     #192,#193,#194,#195,#196,#197,#199,#199,#200,#201,#202,#203,#204,#205,#206,#207,
 | |
|     #208,#209,#210,#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,#221,#222,#223,
 | |
|     #224,#225,#226,#227,#229,#229,#230,#237,#232,#233,#234,#235,#237,#237,#238,#239,
 | |
|     #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
 | |
| 
 | |
|    { lower case translation table for character set 850 }
 | |
|    CP850LCT: array[128..255] of char =
 | |
|    (#135,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#132,#134,
 | |
|     #130,#145,#145,#147,#148,#149,#150,#151,#152,#148,#129,#155,#156,#155,#158,#159,
 | |
|     #160,#161,#162,#163,#164,#164,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
 | |
|     #176,#177,#178,#179,#180,#160,#131,#133,#184,#185,#186,#187,#188,#189,#190,#191,
 | |
|     #192,#193,#194,#195,#196,#197,#198,#198,#200,#201,#202,#203,#204,#205,#206,#207,
 | |
|     #208,#209,#136,#137,#138,#213,#161,#140,#139,#217,#218,#219,#220,#221,#141,#223,
 | |
|     #162,#225,#147,#149,#228,#228,#230,#237,#232,#163,#150,#151,#236,#236,#238,#239,
 | |
|     #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
 | |
| 
 | |
|    { upper case translation table for character set ISO 8859/1  Latin 1  }
 | |
|    CPISO88591UCT: array[192..255] of char =
 | |
|    ( #192, #193, #194, #195, #196, #197, #198, #199,
 | |
|      #200, #201, #202, #203, #204, #205, #206, #207,
 | |
|      #208, #209, #210, #211, #212, #213, #214, #215,
 | |
|      #216, #217, #218, #219, #220, #221, #222, #223,
 | |
|      #192, #193, #194, #195, #196, #197, #198, #199,
 | |
|      #200, #201, #202, #203, #204, #205, #206, #207,
 | |
|      #208, #209, #210, #211, #212, #213, #214, #247,
 | |
|      #216, #217, #218, #219, #220, #221, #222, #89 );
 | |
| 
 | |
|    { lower case translation table for character set ISO 8859/1  Latin 1  }
 | |
|    CPISO88591LCT: array[192..255] of char =
 | |
|    ( #224, #225, #226, #227, #228, #229, #230, #231,
 | |
|      #232, #233, #234, #235, #236, #237, #238, #239,
 | |
|      #240, #241, #242, #243, #244, #245, #246, #215,
 | |
|      #248, #249, #250, #251, #252, #253, #254, #223,
 | |
|      #224, #225, #226, #227, #228, #229, #230, #231,
 | |
|      #232, #233, #234, #235, #236, #237, #238, #239,
 | |
|      #240, #241, #242, #243, #244, #245, #246, #247,
 | |
|      #248, #249, #250, #251, #252, #253, #254, #255 );
 | |
| 
 | |
| 
 | |
| function sscanf(const s: string; const fmt : string;const Pointers : array of Pointer) : Integer;
 | |
|   var
 | |
|     i,j,n,m : SizeInt;
 | |
|     s1      : string;
 | |
| 
 | |
|   function GetInt(unsigned : boolean=false) : Integer;
 | |
|     begin
 | |
|       s1 := '';
 | |
|       while (Length(s) > n) and (s[n] = ' ') do
 | |
|         inc(n);
 | |
|       { read sign }
 | |
|       if (Length(s)>= n) and (s[n] in ['+', '-']) then
 | |
|         begin
 | |
|           { don't accept - when reading unsigned }
 | |
|           if unsigned and (s[n]='-') then
 | |
|             begin
 | |
|               result:=length(s1);
 | |
|               exit;
 | |
|             end
 | |
|           else
 | |
|             begin
 | |
|               s1:=s1+s[n];
 | |
|               inc(n);
 | |
|             end;
 | |
|         end;
 | |
|       { read numbers }
 | |
|       while (Length(s) >= n) and
 | |
|             (s[n] in ['0'..'9']) do
 | |
|         begin
 | |
|           s1 := s1+s[n];
 | |
|           inc(n);
 | |
|         end;
 | |
|       Result := Length(s1);
 | |
|     end;
 | |
| 
 | |
| 
 | |
|   function GetFloat : Integer;
 | |
|     begin
 | |
|       s1 := '';
 | |
|       while (Length(s) > n) and (s[n] = ' ')  do
 | |
|         inc(n);
 | |
|       while (Length(s) >= n) and
 | |
|             (s[n] in ['0'..'9', '+', '-', '.', 'e', 'E']) do
 | |
|         begin
 | |
|           s1 := s1+s[n];
 | |
|           inc(n);
 | |
|         end;
 | |
|       Result := Length(s1);
 | |
|     end;
 | |
| 
 | |
| 
 | |
|   function GetString : Integer;
 | |
|     begin
 | |
|       s1 := '';
 | |
|       while (Length(s) > n) and (s[n] = ' ') do
 | |
|         inc(n);
 | |
|       while (Length(s) >= n) and (s[n] <> ' ')do
 | |
|         begin
 | |
|           s1 := s1+s[n];
 | |
|           inc(n);
 | |
|         end;
 | |
|       Result := Length(s1);
 | |
|     end;
 | |
| 
 | |
| 
 | |
|   function ScanStr(c : Char) : Boolean;
 | |
|     begin
 | |
|       while (Length(s) > n) and (s[n] <> c) do
 | |
|         inc(n);
 | |
|       inc(n);
 | |
|       If (n <= Length(s)) then
 | |
|         Result := True
 | |
|       else
 | |
|         Result := False;
 | |
|     end;
 | |
| 
 | |
| 
 | |
|   function GetFmt : Integer;
 | |
|     begin
 | |
|       Result := -1;
 | |
|       while true do
 | |
|         begin
 | |
| 
 | |
|           while (Length(fmt) > m) and (fmt[m] = ' ') do
 | |
|             inc(m);
 | |
| 
 | |
|           if (m >= Length(fmt)) then
 | |
|             break;
 | |
| 
 | |
|           if (fmt[m] = '%') then
 | |
|             begin
 | |
|               inc(m);
 | |
|               case fmt[m] of
 | |
|                 'd':
 | |
|                   Result:=vtInteger;
 | |
|                 'f':
 | |
|                   Result:=vtExtended;
 | |
|                 's':
 | |
|                   Result:=vtString;
 | |
|                 'c':
 | |
|                   Result:=vtChar;
 | |
|                 else
 | |
|                   raise EFormatError.CreateFmt(SInvalidFormat,[fmt]);
 | |
|               end;
 | |
|               inc(m);
 | |
|               break;
 | |
|             end;
 | |
| 
 | |
|           if not(ScanStr(fmt[m])) then
 | |
|             break;
 | |
|           inc(m);
 | |
|         end;
 | |
|     end;
 | |
| 
 | |
| 
 | |
|   begin
 | |
|     n := 1;
 | |
|     m := 1;
 | |
|     Result := 0;
 | |
| 
 | |
|     for i:=0 to High(Pointers) do
 | |
|       begin
 | |
|         j := GetFmt;
 | |
|         case j of
 | |
|           vtInteger :
 | |
|             begin
 | |
|               if GetInt>0 then
 | |
|                 begin
 | |
|                   pLongint(Pointers[i])^:=StrToInt(s1);
 | |
|                   inc(Result);
 | |
|                 end
 | |
|               else
 | |
|                 break;
 | |
| 
 | |
|             end;
 | |
| 
 | |
|           vtchar :
 | |
|             begin
 | |
|               if Length(s)>n then
 | |
|                 begin
 | |
|                   pchar(Pointers[i])^:=s[n];
 | |
|                   inc(n);
 | |
|                   inc(Result);
 | |
|                 end
 | |
|               else
 | |
|                 break;
 | |
| 
 | |
|             end;
 | |
| 
 | |
|           vtExtended :
 | |
|             begin
 | |
|               if GetFloat>0 then
 | |
|                 begin
 | |
|                   pextended(Pointers[i])^:=StrToFloat(s1);
 | |
|                   inc(Result);
 | |
|                 end
 | |
|               else
 | |
|                 break;
 | |
|             end;
 | |
| 
 | |
|           vtString :
 | |
|             begin
 | |
|               if GetString > 0 then
 | |
|                 begin
 | |
|                   pansistring(Pointers[i])^:=s1;
 | |
|                   inc(Result);
 | |
|                 end
 | |
|               else
 | |
|                 break;
 | |
|             end;
 | |
|           else
 | |
|             break;
 | |
|         end;
 | |
|       end;
 | |
|    end;
 | 
