{
    $Id$
    This file is part of the Free Pascal run time library.
    Copyright (c) 2001 by the Free Pascal development team

    This include file contains the implementation for variants
    support in FPC as far as it is part of the system unit

    See the file COPYING.FPC, included in this distribution,
    for details about the copyright.

    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.

 **********************************************************************}

var
   variantmanager : tvariantmanager;   

procedure invalidvariantop;
  begin
     HandleErrorFrame(221,get_frame);
  end;

procedure vardisperror;

  begin
     HandleErrorFrame(222,get_frame);
  end;


{ ---------------------------------------------------------------------
    Compiler helper routines.
  ---------------------------------------------------------------------}
 

procedure varclear(var v : tvardata);
begin
   if not(v.vtype in [varempty,varerror,varnull]) then
     invalidvariantop;
end;

procedure variant_init(var v : variant);[Public,Alias:'FPC_VARIANT_INIT'];

  begin
     variantmanager.varinit(v);
  end;

procedure variant_clear(var v : variant);[Public,Alias:'FPC_VARIANT_CLEAR'];

  begin
     variantmanager.varclear(v);
  end;

{ ---------------------------------------------------------------------
    Overloaded operators.
  ---------------------------------------------------------------------}
  

{ Integer }

operator :=(const source : byte) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromInt(Dest,Source,1);
end;


operator :=(const source : shortint) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromInt(Dest,Source,-1);
end;


operator :=(const source : word) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromInt(Dest,Source,2);
end;


operator :=(const source : smallint) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromInt(Dest,Source,-2);
end;


operator :=(const source : dword) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromInt(Dest,Source,4);
end;


operator :=(const source : longint) dest : variant;

begin
//  Variant_Init(Dest);
  Variantmanager.varfromInt(Dest,Source,-4);
end;


operator :=(const source : qword) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromWord64(Dest,Source);
end;


operator :=(const source : int64) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromInt64(Dest,Source);
end;

{ Boolean }

operator :=(const source : boolean) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromBool(Dest,Source);
end;


operator :=(const source : wordbool) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromBool(Dest,Boolean(Source));
end;


operator :=(const source : longbool) dest : variant;

begin
  Variant_Init(Dest);
  Variantmanager.varfromBool(Dest,Boolean(Source));
end;


{ Chars }

operator :=(const source : char) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromPStr(Dest,Source);
end;


operator :=(const source : widechar) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromWStr(Dest,Source);
end;

{ Strings }

operator :=(const source : shortstring) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromPStr(Dest,Source);
end;


operator :=(const source : ansistring) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromLStr(Dest,Source);
end;


operator :=(const source : widestring) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromWStr(Dest,Source);
end;

{ Floats }

operator :=(const source : single) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromReal(Dest,Source);
end;


operator :=(const source : double) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromReal(Dest,Source);
end;


operator :=(const source : extended) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromReal(Dest,Source);
end;

Operator :=(const source : comp) dest : variant;

begin
  Variant_Init(Dest);
  VariantManager.VarFromReal(Dest,Source);
end;

{ Misc. }
{ Fixme!!!
operator :=(const source : currency) dest : variant;
  begin
  end;

operator :=(const source : tdatetime) dest : variant;
  begin
  end;
}
{**********************************************************************
                       from Variant assignments
 **********************************************************************}

{ Integer }

operator :=(const source : variant) dest : byte;

begin     
  dest:=variantmanager.vartoint(source);
end;


operator :=(const source : variant) dest : shortint;

begin
  dest:=variantmanager.vartoint(source);
end;


operator :=(const source : variant) dest : word;

begin
  dest:=variantmanager.vartoint(source);
end;


operator :=(const source : variant) dest : smallint;

begin
  dest:=variantmanager.vartoint(source);
end;


operator :=(const source : variant) dest : dword;

begin
  dest:=variantmanager.vartoint(source);
end;


operator :=(const source : variant) dest : longint;

begin
  dest:=variantmanager.vartoint(source);
end;


operator :=(const source : variant) dest : qword;

begin
  dest:=variantmanager.vartoword64(source);
end;


operator :=(const source : variant) dest : int64;

begin
  dest:=variantmanager.vartoint64(source);
end;


{ Boolean }

operator :=(const source : variant) dest : boolean;

begin
  dest:=variantmanager.vartobool(source);
end;


operator :=(const source : variant) dest : wordbool;

begin
  dest:=variantmanager.vartobool(source);
end;


operator :=(const source : variant) dest : longbool;

begin
   dest:=variantmanager.vartobool(source);
end;


{ Chars }

operator :=(const source : variant) dest : char;

Var
  S : String;

begin
  VariantManager.VarToPStr(S,Source);
  If Length(S)>0 then
    Dest:=S[1];
end;


operator :=(const source : variant) dest : widechar;

Var
  WS : WideString;

begin
  VariantManager.VarToWStr(WS,Source);
  If Length(WS)>0 then
    Dest:=WS[1];
end;


{ Strings }

operator :=(const source : variant) dest : shortstring;

begin
  VariantManager.VarToPStr(Dest,Source);
end;

operator :=(const source : variant) dest : ansistring;

begin
  VariantManager.vartolstr(dest,source);
end;

operator :=(const source : variant) dest : widestring;

begin
  variantmanager.vartowstr(dest,source);
end;

{ Floats }

operator :=(const source : variant) dest : single;

begin
  dest:=variantmanager.vartoreal(source);
end;


operator :=(const source : variant) dest : double;

begin
  dest:=variantmanager.vartoreal(source);
end;


operator :=(const source : variant) dest : extended;

begin
  dest:=variantmanager.vartoreal(source);
end;


operator :=(const source : variant) dest : comp;

begin
  dest:=comp(variantmanager.vartoreal(source));
end;

{ Misc. }
{ FIXME !!!!!!!

operator :=(const source : variant) dest : currency;

begin
  dest:=variantmanager.vartocurr(source);
end;


operator :=(const source : variant) dest : tdatetime;

begin

end;
}

{ ---------------------------------------------------------------------
    Variant manager functions
  ---------------------------------------------------------------------}
  


procedure GetVariantManager(var VarMgr: TVariantManager);

begin
  VarMgr:=VariantManager;
end;

procedure SetVariantManager(const VarMgr: TVariantManager);

begin
  VariantManager:=VarMgr;
end;

function IsVariantManagerSet: Boolean;

var
   i : longint;     
begin
   I:=0;
   Result:=True; 
   While Result and (I<(sizeof(tvariantmanager) div sizeof(pointer))-1) do
     begin
     Result:=Pointer(ppointer(@variantmanager+i*sizeof(pointer))^)<>Pointer(@invalidvariantop);
     Inc(I);
     end;
end;


procedure initvariantmanager;
  var
     i : longint;
  begin
     VarDispProc:=@vardisperror;
     DispCallByIDProc:=@vardisperror;
     for i:=0 to (sizeof(tvariantmanager) div sizeof(pointer))-1 do
       ppointer(@variantmanager+i*sizeof(pointer))^:=@invalidvariantop;
     pointer(variantmanager.varclear):=@varclear
  end;


{
  $Log$
  Revision 1.4  2001-11-14 23:00:16  michael
  + First working variant support

  Revision 1.3  2001/11/08 20:59:10  michael
  + System unit implementation of variants

  Revision 1.2  2001/11/08 16:17:30  florian
    + beginning of variant dispatching

  Revision 1.1  2001/08/19 21:02:01  florian
    * fixed and added a lot of stuff to get the Jedi DX8 headers
      compiled
}
