unit uSize;

interface

uses
{$IFDEF LINUX}
  Types,
{$ENDIF}
{$IFDEF MSWINDOWS}
  Windows,
{$ENDIF}
  Rubies;

var
  cSize: Tvalue;

function ap_cSize: Tvalue;
function Size_alloc(klass: Tvalue; real: TSize): Tvalue;
function ap_iSize(real: TSize; owner: Tvalue): Tvalue;
procedure Init_Size;

implementation

uses SysUtils, uDefUtils, uIntern, uAlloc, uPhi, uConv;

procedure ap_dispose(p: Pointer); cdecl;
begin
  try
    Dispose(p);
  except
    on E: Exception do;
  end;
end;

function ap_cSize: Tvalue;
begin
  result := cSize;
end;

function Size_alloc(klass: Tvalue; real: TSize): Tvalue;
var
  p: PSize;
begin
  new(p);
  result := rb_data_object_alloc(klass, p, nil, @ap_dispose);
  p^.cx := real.cx;
  p^.cy := real.cy;
end;

function ap_iSize(real: TSize; owner: Tvalue): Tvalue;
begin
  result := Size_alloc(cSize, real);
  ap_owner(result, owner);
end;

function Size_new(argc: integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  args: array of Tvalue;
  p: PSize;
begin
  SetLength(args, argc);
  args := argv;
  new(p);
  result := rb_data_object_alloc(This, p, nil, @ap_dispose);
  case argc of
  0:
    begin
      p^.cx := 0;
      p^.cy := 0;
    end;
  2:
    begin
      p^.cx := dl_Integer(args[0]);
      p^.cy := dl_Integer(args[1]);
    end;
  else
    ap_raise(ap_eArgError, sWrong_num_of_args);
  end;

  ap_obj_call_init(result, argc, argv);
end;

function Size_to_s(This: Tvalue): Tvalue; cdecl;
var
  real: TSize;
begin
  real := PSize(ap_data_get_struct(This))^;
  with real do result := ap_String(Format(
    '#<%s: cx=%d cy=%d>', [dl_class_name_of(This), cx, cy]));
end;

function Size_to_a(This: Tvalue): Tvalue; cdecl;
begin
  with PSize(ap_data_get_struct(This))^ do begin
    result := rb_ary_new;
    rb_ary_push(result, INT2FIX(cx));
    rb_ary_push(result, INT2FIX(cy));
  end
end;

function Size_set_cx(This, v: Tvalue): Tvalue; cdecl;
begin
  PSize(ap_data_get_struct(This))^.cx := dl_Integer(v);
  result := v;
end;

function Size_get_cx(This: Tvalue): Tvalue; cdecl;
begin
  result := INT2FIX(PSize(ap_data_get_struct(This))^.cx);
end;

function Size_set_cy(This, v: Tvalue): Tvalue; cdecl;
begin
  PSize(ap_data_get_struct(This))^.cy := dl_Integer(v);
  result := v;
end;

function Size_get_cy(This: Tvalue): Tvalue; cdecl;
begin
  result := INT2FIX(PSize(ap_data_get_struct(This))^.cy);
end;

procedure Init_Size;
begin
  cSize := rb_define_class_under(mPhi, 'Size', ap_cObject);
  DefineSingletonMethod(cSize, 'new', Size_new);
  DefineAttrSet(cSize, 'cx', Size_set_cx);
  DefineAttrGet(cSize, 'cx', Size_get_cx);
  DefineAttrSet(cSize, 'cy', Size_set_cy);
  DefineAttrGet(cSize, 'cy', Size_get_cy);
  DefineAttrGet(cSize, 'to_s', Size_to_s);
  DefineAttrGet(cSize, 'to_a', Size_to_a);
  rb_define_alias(cSize, 'to_ary', 'to_a');
  rb_define_alias(cSize, 'width=', 'cx=');
  rb_define_alias(cSize, 'width', 'cx');
  rb_define_alias(cSize, 'height=', 'cy=');
  rb_define_alias(cSize, 'height', 'cy');
end;

end.
