{****************************************************
 * Author  : Dumitru Uzun (DUzun)
 * Web     : http://duzun.teologie.net
 * Created : 02.05.2009
 * 
 *    Acest modul contine subprograme pentru 
 *  manipularea informatiei textuale din diferite
 *  componente vizuale (si nu numai) - citire/scriere.  
 ****************************************************}

unit Interfata;

interface
uses StdCtrls, SysUtils, Menus, Classes;
(*-----------------------------------------------------------------*)
const  endl   = #13#10; {End Line}
(*-----------------------------------------------------------------*)
var 
   FormatSettings: TFormatSettings;
   FloatPrecision: Integer;
   FloatDigits:    Integer;
(*-----------------------------------------------------------------*)
{ Formeaza instructiunea de atribuire: " VarName := Val ; " }
function ValToVar(const VarName: string; Val: string): string;

{Citeste o expresie Pascal din Edit}
function ReadExpr(Sender: TObject): string;

{Citirea/Scrierea textului din/in componenta vizuala Sender}
function PutText (Sender: TObject; s: String): Boolean;
function ReadText(Sender: TObject): String;
{Citeste textul din Sender, asigurand formatul numeric corect}
function ReadNr  (Sender: TObject): String;
function ReadInt (Sender: TObject): String;

{Formateaza un string care contine un numar real}
function FormatFloatStr(Nr: String; Precision:Integer=0; Digits:Integer=0; Exp:Boolean=false): String;
function FloatStrToInt(Nr: String; Factor: real=1): integer;
function StrToReal(Nr: String): Extended;
function RealToStr(Nr: Extended; Precision:Integer=0; Digits:Integer=0; Exp:Boolean=false): String;

{Inpartirea unui text intr-o lista}
procedure Split(const Delimiter: char; Input: string; const Strings: TStrings; DelNil: boolean=false);
{Unirea elementelor unei liste intr-un text}
function Join(const Delimiter: char; Input: TStrings): string;

{In Dest inlocuieste SubStr cu Str}

function Max(x, y: Integer): Integer;
function Min(x, y: Integer): Integer;
(*-----------------------------------------------------------------*)
implementation
//uses Compilator;
(*-----------------------------------------------------------------*)
function Max(x, y: Integer): Integer; begin if x > y then Result := x else Result := y; end;
function Min(x, y: Integer): Integer; begin if x < y then Result := x else Result := y; end;
(*-----------------------------------------------------------------*)
function ValToVar(const VarName: string; Val: string): string;
begin
  if Val = '' then Val := '''''';
  if VarName = '' then Result := ''
                  else Result := VarName + ' := ' + Val + ';' + endl ;
end;
(*-----------------------------------------------------------------*)
function PutText(Sender: TObject; s: String): Boolean;
begin
  if not Assigned(Sender) then exit;
  Result:=true;
  if Sender is TCustomEdit then TCustomEdit(Sender).Text := s else
  if(Sender is TMenuItem)  then TMenuItem(Sender).Caption := s else
  if(Sender is TLabel)     then TLabel(Sender).Caption := s else
  if(Sender is TButton)    then TButton(Sender).Caption := s
                           else Result:=false;
  s := Sender.ClassName;
end;
(*-----------------------------------------------------------------*)
function ReadText(Sender: TObject): String;
begin
  Result := '';
  if not Assigned(Sender) then exit;
  if Sender is TCustomEdit then Result := TCustomEdit(Sender).Text else
  if(Sender is TLabel)     then Result := TLabel(Sender).Caption  else
  if(Sender is TButton)    then Result := TButton(Sender).Caption else
  if(Sender is TMenuItem)  then Result := StringReplace(TMenuItem(Sender).Caption, '&', '', [rfReplaceAll]) else
                           Result := '';
end;
(*-----------------------------------------------------------------*)
function ReadNr  (Sender: TObject): String;
var i, j, l: integer;
    s: string;
begin
   s := Trim(ReadText(Sender));
   i := 1;
   if s = '' then s := '0' else
   if s[i] in ['-','+'] then begin Result := s[i]; inc(i) end else 
   Result := '';
   l := Length(s);
   
   {Substituim ',' prin '.'}
   j := Pos(',', s);
   if j > 0 then s[j] := '.';
   j := i;

   {Partea intreaga}
   while (i <= l) and (s[i] in ['0'..'9']) do inc(i);
   if i>j then Result := Result + Copy(s, j, i-j) else Result := '0';
   j := i;

   {Mantisa}
   if(i<=l)and(s[i]='.') then begin
      inc(i);
      while (i <= l) and (s[i] in ['0'..'9']) do inc(i);
      if i-1>j then Result := Result + Copy(s, j, i-j);      
      j := i;
   end;
   
   {Exponentul}
   if(i<l)and(UpCase(s[i])='E')and(s[i+1] in ['-','+']) then begin
     inc(i, 2);
     while (i <= l) and (s[i] in ['0'..'9']) do inc(i);
     if i-2>j then Result := Result + Copy(s, j, i-j);      
   end;

   PutText(Sender, Result);
end;
(*-----------------------------------------------------------------*)
function ReadInt (Sender: TObject): String;
var i, j, l: integer;
    s: string;
begin
   s := Trim(ReadText(Sender));
   i := 1;
   if s = '' then s := '0' else
   if s[i] in ['-','+'] then begin Result := s[i]; inc(i) end else 
   Result := '';

   {Substituim ',' prin '.'}
   j := Pos(',', s);
   if j > 0 then s[j] := '.';
   j := i;

   {Partea intreaga}
   while (i <= l) and (s[i] in ['0'..'9']) do inc(i);
   if i>j then Result := Result + Copy(s, j, i-j) else Result := '0';
   j := i;

   PutText(Sender, Result);
end;
(*-----------------------------------------------------------------*)
function ReadExpr(Sender: TObject): string;
var i: integer;
    state: integer;
begin
   Result := Trim(ReadText(Sender));
   state  := 0;
   i      := 1;
   while i < length(Result) do begin
      case state of
      0: case UpCase(Result[i]) of  {operator}
         '0'..'9', '.': state := 2;
         'A'..'Z', '_': state := 1;
         end;
      1: case UpCase(Result[i]) of  {identificator} 
         '0'..'9', 'A'..'Z', '_': ;
         else state := 0;
         end;
      2: case UpCase(Result[i]) of  {numar}
         'A'..'Z', '_': 
            begin 
               Insert('*', Result, i); 
               inc(i); 
               state := 1; 
            end;
         '0'..'9', '.': ;
         else state := 0;
         end;
      end;   
      inc(i);
   end;
   PutText(Sender, Result);
end;
(*-----------------------------------------------------------------*)
procedure Split(const Delimiter: Char; Input: string; const Strings: TStrings; DelNil: boolean=false);
var d: Char;
    i, c: integer;
begin
   Assert(Assigned(Strings)) ;
   d := Strings.Delimiter;
   Strings.Clear;
   Strings.Delimiter := Delimiter;
   Strings.DelimitedText := Input;
   Strings.Delimiter := d;
   if DelNil then begin
      i := Strings.Count;
      while i > 0 do begin
         dec(i);
         if Trim(Strings.Strings[i]) = '' then
            Strings.Delete(i);
      end;
   end;
end;
(*-----------------------------------------------------------------*)
function Join(const Delimiter: Char; Input: TStrings): string;
var d: Char;
begin
   Assert(Assigned(Input)) ;
   d := Input.Delimiter;
   Input.Delimiter := Delimiter;
   Result := Input.DelimitedText;
   Input.Delimiter := d;
end;
(*-----------------------------------------------------------------*)
function FormatFloatStr(Nr: String; Precision:Integer=0; Digits:Integer=0; Exp:Boolean=false): String;
begin Result := RealToStr(StrToFloat(Trim(Nr), FormatSettings), Precision, Digits, Exp);end;
(*-----------------------------------------------------------------*)
function FloatStrToInt(Nr: String; Factor: real=1): integer;
begin Result := trunc(StrToFloat(Nr, FormatSettings)*Factor); end;
(*-----------------------------------------------------------------*)
function StrToReal(Nr: String): Extended; begin Result := StrToFloat(Nr, FormatSettings);end;
(*-----------------------------------------------------------------*)
function RealToStr(Nr: Extended;Precision:Integer=0; Digits:Integer=0; Exp:Boolean=false): String;
var Format: TFloatFormat;
    Buffer: PAnsiChar;
begin
  if Exp then Format := ffExponent else Format := ffFixed;
  if Digits    = 0 then Digits    := FloatDigits;
  if Precision = 0 then Precision := FloatPrecision;
  Buffer := AllocMem(256);
  Digits := FloatToText(Buffer, Nr, fvExtended,  Format, Precision, Digits, FormatSettings);
  Buffer[Digits] := #0;
  Result := String(Buffer);
  FreeMem(Buffer);
end;
(*-----------------------------------------------------------------*)
begin
  {Setarile implicite pentru formatarea numerelor reale}
  GetLocaleFormatSettings(0, FormatSettings);
  FormatSettings.DecimalSeparator := '.';  {Indiferent de setarile din sistem, separatorul zecimal va fi '.'}
  FloatPrecision := 30;
  FloatDigits    := 10;

end.
