UNIT Unit3;
INTERFACE
USES
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StrUtils, Menus, ExtCtrls, StdCtrls,Unit2,Unit8, Math, Buttons;

TYPE
  TCharForm = Class(TForm)
    timer_actualize: TTimer;
    memo: TMemo;
    timer_freeze: TTimer;
    Timer1: TTimer;
    PROCEDURE timer_freezeTimer(Sender: TObject);
    PROCEDURE timer_actualizeTimer(Sender: TObject);
    PROCEDURE FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    PROCEDURE EditClick(Sender: TObject);
    PROCEDURE OpenCloseClick(Sender: TObject);
  PRIVATE
  PUBLIC
  END;

FUNCTION GetItemNumber(name:String):Byte;

VAR
  CharForm: TCharForm;
  _charformsinitialized:Boolean;
  CharData: Array[0..ais_controlled] OF TStructures;
  CharGroups: Array[0..ais_controlled] OF Array[1..number_char_groups] OF TGroup;

IMPLEMENTATION
USES Unit1, Unit7;
{$R *.dfm}

FUNCTION GetItemNumber(name:String):Byte;
  VAR i:Byte;
  BEGIN
    result:=0;
  END;

PROCEDURE TCharForm.EditClick(Sender: TObject);
  VAR bytes,charnumber,itemnumber:Byte;
    tempint:Integer;
    tempfloat:Single;
    address:LongWord;
  BEGIN
    charnumber:=StrToInt(MidStr(TComponent(Sender).GetParentComponent.GetParentComponent.Name, 5, 10));
    IF NOT _connected THEN exit;
    IF _ais_active[charnumber] THEN BEGIN
      itemnumber:=StrToInt(MidStr(TComponent(Sender).Name, 5, 10));
      IF CharData[charnumber].Items[itemnumber].updating THEN exit;
      WITH CharData[charnumber] DO BEGIN
        IF Items[itemnumber].struct=0 THEN address:=Items[itemnumber].offset
        ELSE address:=Structs[Items[itemnumber].struct]+Items[itemnumber].offset;
        WITH Items[itemnumber] DO BEGIN
          CASE data_type OF
            1..4:BEGIN
                  bytes:=data_type;
                  IF TryStrToInt(TEdit(Sender).Text,tempint) THEN BEGIN
                    IF range>0 THEN BEGIN
                      IF tempint>range THEN tempint:=Floor(range);
                      IF tempint<0 THEN tempint:=0;
                      TEdit(Sender).Text:=IntToStr(tempint);
                      WriteMem(address,bytes,Encode_Int(tempint));
                    END ELSE BEGIN
                      IF tempint>=Floor(Power(256,bytes)) THEN tempint:=Floor(Power(256,bytes))-1;
                      IF tempint<0 THEN tempint:=0;
                      TEdit(Sender).Text:=IntToStr(tempint);
                      WriteMem(address,bytes,Encode_Int(tempint));
                    END;
                  END;
                END;
            5:  BEGIN
                  bytes:=4;
                  IF TryStrToFloat(TEdit(Sender).Text,tempfloat) THEN BEGIN
                    IF Pos('[0-360]',CharData[charnumber].Items[itemnumber].name)>0 THEN BEGIN
                      tempfloat:=tempfloat*pi/180;
                    END;
                    IF range>0 THEN BEGIN
                      IF tempfloat>range THEN BEGIN
                        tempfloat:=range;
                        IF Pos('[0-360]',CharData[charnumber].Items[itemnumber].name)>0 THEN BEGIN
                          TEdit(Sender).Text:=FloatToStr(tempfloat*180/pi);
                        END ELSE BEGIN
                          TEdit(Sender).Text:=FloatToStr(tempfloat);
                        END;
                      END;
                      IF tempfloat<0 THEN BEGIN
                        tempfloat:=0;
                        IF Pos('[0-360]',CharData[charnumber].Items[itemnumber].name)>0 THEN BEGIN
                          TEdit(Sender).Text:=FloatToStr(tempfloat*180/pi);
                        END ELSE BEGIN
                          TEdit(Sender).Text:=FloatToStr(tempfloat);
                        END;
                      END;
                      WriteMem(address,bytes,Encode_Float(tempfloat));
                    END ELSE BEGIN
                      WriteMem(address,bytes,Encode_Float(tempfloat));
                    END;
                  END;
                END;
            6:  BEGIN
                  bytes:=Floor(range);
                  WriteMem(address,bytes,Encode_Str(TEdit(Sender).Text,bytes));
                END;
          END;
        END;
      END;
    END;
  END;

PROCEDURE TCharForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  VAR charnumber:Byte;
  BEGIN
    Self.Visible:=False;
    charnumber:=StrToInt(MidStr(Self.Name, 5, 10));
    CharMenus[charnumber].Checked:=False;
    CanClose:=False;
  END;

FUNCTION Check_Addresses_Changed(charnumber:Byte):Boolean;
  VAR struct3_id:byte;
  BEGIN
    result:=False;
    _temp:=ReadMem(PointerStruct1PointerArray1,4);
    _ais_active[charnumber]:=True;
    IF NOT (_temp[250]=123) THEN BEGIN
      _tempvalue:=Decode_Int(_temp);
      _temp:=ReadMem(_tempvalue+4*charnumber,4);
      IF NOT (_temp[250]=123) THEN BEGIN
        _tempvalue:=Decode_Int(_temp);
        IF NOT (_tempvalue=CharData[charnumber].Structs[1]) THEN BEGIN
          CharForms[charnumber].memo.lines.Strings[0]:='Struct1-Addy ('+IntToStr(_temp[250])+'): 0x'+IntToHex(_tempvalue,8);
          CharData[charnumber].Structs[1]:=_tempvalue;
          result:=True;
        END;
      END ELSE BEGIN
        _ais_active[charnumber]:=False;
      END;

      struct3_id:=charnumber;//Decode_Int(ReadMem(CharData[charnumber].Structs[1]+$000,1));

      _tempvalue:=Decode_Int(ReadMem(PointerStruct3,4));
      _tempvalue:=_tempvalue+(struct3_id*$2838);
      CharForms[charnumber].memo.Lines.Strings[2]:='Struct3-Addy: 0x'+IntToHex(_tempvalue,8);
      CharData[charnumber].Structs[3]:=_tempvalue;
      
      _temp:=ReadMem(CharData[charnumber].Structs[3]+4,4);
      IF NOT (_temp[250]=123) THEN BEGIN
        _tempvalue:=Decode_Int(_temp);
        IF NOT (_tempvalue=CharData[charnumber].Structs[2]) THEN BEGIN
          CharForms[charnumber].memo.lines.Strings[1]:='Struct2-Addy ('+IntToStr(_temp[250])+'): 0x'+IntToHex(_tempvalue,8);
          CharData[charnumber].Structs[2]:=_tempvalue;
          result:=True;
        END;
      END;
    END ELSE BEGIN
      _ais_active[charnumber]:=False;
    END;
    IF Decode_Str(ReadMem(CharData[charnumber].Structs[1]+$14,100))='' THEN _ais_active[charnumber]:=False;
    IF charnumber>0 THEN Check_CharInOverview(charnumber);
  END;

PROCEDURE TCharForm.OpenCloseClick(Sender: TObject);
  VAR number,i,charnumber:Byte;
    _top:Word;
  BEGIN
    number:=StrToInt(MidStr(TSpeedButton(Sender).Name, 10, 10));
    charnumber:=StrToInt(MidStr(Self.Name,5,10));
    IF CharGroups[charnumber][number].OpenClose.Down THEN BEGIN
      CharGroups[charnumber][number].Item.Height:=20;
      FOR i:=1 TO number_items DO BEGIN
        WITH CharData[charnumber].Items[i] DO BEGIN
          IF group=number THEN BEGIN
            Item_Freeze.Visible:=False;
            Item_Edit.Visible:=False;
            break;
          END;
        END;
      END;
      _top:=1;
      FOR i:=1 TO number_char_groups DO BEGIN
        WITH CharGroups[charnumber][i] DO BEGIN
          Item.Top:=_top;
          _top:=_top+Item.Height;
        END;
      END;
      CharForms[charnumber].memo.Top:=_top+4;
      CharForms[charnumber].Height:=_top+CharForms[charnumber].memo.Height+30;
    END ELSE BEGIN
      CharGroups[charnumber][number].Item.Height:=CharGroups[charnumber][number].Count*19+20;
      FOR i:=1 TO number_items DO BEGIN
        WITH CharData[charnumber].Items[i] DO BEGIN
          IF group=number THEN BEGIN
            Item_Freeze.Visible:=True;
            Item_Edit.Visible:=True;
            break;
          END;
        END;
      END;
      _top:=1;
      FOR i:=1 TO number_char_groups DO BEGIN
        WITH CharGroups[charnumber][i] DO BEGIN
          Item.Top:=_top;
          _top:=_top+Item.Height;
        END;
      END;
      CharForms[charnumber].memo.Top:=_top+4;
      CharForms[charnumber].Height:=_top+CharForms[charnumber].memo.Height+30;
    END;
  END;

FUNCTION Get_Data_Struct(charnumber:Byte):Boolean;
  VAR i:Byte;
    bytes:Byte;
    address:LongWord;
    floatval:Single;
    charoverviewcol:Byte;
  BEGIN
    IF charnumber=0 THEN charoverviewcol:=1
    ELSE charoverviewcol:=GetCharOverviewCol(charnumber);
    WITH CharData[charnumber] DO BEGIN
      FOR i:=1 TO number_items DO BEGIN
        CASE Items[i].data_type OF
          1: bytes:=1;
          2: bytes:=2;
          3: bytes:=3;
          4: bytes:=4;
          5: bytes:=4;
          6: bytes:=100;
        END;
        IF Items[i].Struct=0 THEN address:=Items[i].offset
        ELSE address:=Structs[Items[i].struct]+Items[i].offset;
        _temp:=ReadMem(address,bytes);
        CASE Items[i].data_type OF
          1..4: BEGIN
                IF (NOT Items[i].Item_Edit.Focused) AND (NOT Items[i].Item_Freeze.Checked) THEN BEGIN
                  Items[i].updating:=True;
                  Items[i].Item_Edit.Text:=IntToStr(Decode_Int(_temp));
                  Items[i].updating:=False;
                END;
                Form7.grid.Cells[charoverviewcol,i]:=IntToStr(Decode_Int(_temp));
              END;
          5:  IF Pos('[0-360]',Items[i].hint)=0 THEN BEGIN
                IF (NOT Items[i].Item_Edit.Focused) AND (NOT Items[i].Item_Freeze.Checked) THEN BEGIN
                  Items[i].updating:=True;
                  Items[i].Item_Edit.Text:=FloatToStr(Decode_Float(_temp));
                  Items[i].updating:=False;
                END;
                Form7.grid.Cells[charoverviewcol,i]:=FloatToStr(Decode_Float(_temp));
              END ELSE BEGIN
                floatval:=Decode_Float(_temp);
                IF (NOT Items[i].Item_Edit.Focused) AND (NOT Items[i].Item_Freeze.Checked) THEN BEGIN
                  Items[i].updating:=True;
                  Items[i].Item_Edit.Text:=FloatToStr((floatval/pi)*180);
                  Items[i].updating:=False;
                END;
                Form7.grid.Cells[charoverviewcol,i]:=FloatToStr((floatval/pi)*180);
              END;
          6:  BEGIN
                IF (NOT Items[i].Item_Edit.Focused) AND (NOT Items[i].Item_Freeze.Checked) THEN BEGIN
                  Items[i].updating:=True;
                  Items[i].Item_Edit.Text:=Decode_Str(_temp);
                  Items[i].updating:=False;
                END;
                Form7.grid.Cells[charoverviewcol,i]:=Decode_Str(_temp);
              END;
        END;
      END;
    END;
  END;

PROCEDURE TCharForm.timer_actualizeTimer(Sender: TObject);
  VAR charnumber,i:Byte;
  BEGIN
    IF _connected THEN BEGIN
      charnumber:=StrToInt(MidStr(Self.Name, 5, 10));

      Check_Addresses_Changed(charnumber);
      IF _ais_active[charnumber] THEN Get_Data_Struct(charnumber);
    END;
  END;

PROCEDURE TCharForm.timer_freezeTimer(Sender: TObject);
  VAR charnumber,i,bytes:Byte;
    tempint:Integer;
    tempfloat:Single;
    address:LongWord;
    charstring:string;
    _component:TComponent;
    framename:String;
  BEGIN
    charnumber:=StrToInt(MidStr(Self.Name, 5, 10));
    IF NOT _ais_active[charnumber] THEN exit;
    IF NOT _connected THEN exit;
    WITH CharData[charnumber] DO BEGIN
      FOR i:=1 TO number_items DO BEGIN
        IF Items[i].Item_Freeze.Checked THEN BEGIN
          IF Items[i].struct=0 THEN address:=Items[i].offset
          ELSE address:=Structs[Items[i].struct]+Items[i].offset;
          WITH Items[i] DO BEGIN
            CASE data_type OF
              1..4:BEGIN
                    bytes:=data_type;
                    IF TryStrToInt(Item_Edit.Text,tempint) THEN BEGIN
                      IF range>0 THEN BEGIN
                        IF tempint>range THEN tempint:=Floor(range);
                        IF tempint<0 THEN tempint:=0;
                        Item_Edit.Text:=IntToStr(tempint);
                        WriteMem(address,bytes,Encode_Int(tempint));
                      END ELSE BEGIN
                        WriteMem(address,bytes,Encode_Int(tempint));
                      END;
                    END;
                  END;
              5:  BEGIN
                    bytes:=4;
                    IF TryStrToFloat(Item_Edit.Text,tempfloat) THEN BEGIN
                      IF Pos('[0-360]',CharData[charnumber].Items[i].name)>0 THEN BEGIN
                        tempfloat:=tempfloat*pi/180;
                      END;
                      IF range>0 THEN BEGIN
                        IF tempfloat>range THEN BEGIN
                          tempfloat:=range;
                          IF Pos('[0-360]',CharData[charnumber].Items[i].name)>0 THEN BEGIN
                            Item_Edit.Text:=FloatToStr(tempfloat*180/pi);
                          END ELSE BEGIN
                            Item_Edit.Text:=FloatToStr(tempfloat);
                          END;
                        END;
                        IF tempfloat<0 THEN BEGIN
                          tempfloat:=0;
                          IF Pos('[0-360]',CharData[charnumber].Items[i].name)>0 THEN BEGIN
                            Item_Edit.Text:=FloatToStr(tempfloat*180/pi);
                          END ELSE BEGIN
                            Item_Edit.Text:=FloatToStr(tempfloat);
                          END;
                        END;
                        WriteMem(address,bytes,Encode_Float(tempfloat));
                      END ELSE BEGIN
                        WriteMem(address,bytes,Encode_Float(tempfloat));
                      END;
                    END;
                  END;
              6:  BEGIN
                    bytes:=Floor(range);
                    WriteMem(address,bytes,Encode_Str(Item_Edit.Text,bytes));
                  END;
            END;
          END;
        END;
      END;
    END;
  END;

END.
