unit BinEdit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, VirtualTrees, Grids, Wrapgrid, MPHexEditor, StdCtrls, Menus, VTHeaderPopup, ExtCtrls, Buttons, StrUtils, Clipbrd, Data, TypeDefs, ConnectionManager, Template, _BaseTemplate, _TemplateFile, _TemplateFileList; type TForm_BinEdit = class(TForm_ToolTemplate) hex: TMPHexEditor; Splitter2: TSplitter; value_viewer: TWrapGrid; VST: TVirtualStringTree; Splitter3: TSplitter; value_viewer_context: TPopupMenu; value_viewer_context_copy: TMenuItem; value_viewer_context_copyasdec: TMenuItem; value_viewer_context_copyasfloat: TMenuItem; value_viewer_context_copyasbitset: TMenuItem; value_viewer_context_copyasstring: TMenuItem; value_viewer_context_copyashex: TMenuItem; VTHPopup: TVTHeaderPopupMenu; panel_imexport: TPanel; btn_export: TButton; btn_import: TButton; procedure FormCreate(Sender: TObject); procedure NewFile(fileinfo: TFileInfo); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure hexSelectionChanged(Sender: TObject); procedure hexChange(Sender: TObject); procedure LoadDat(_fileid: Integer); function Save: Boolean; function GetValue(datatype: Word; offset: Integer): String; procedure SetNewValue(datatype: Word; offset: Integer; Value: String); procedure WriteStructureInfos; procedure ClearStructViewer; procedure VSTDblClick(Sender: TObject); procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); procedure VTHPopupColumnChange(const Sender: TBaseVirtualTree; const Column: TColumnIndex; Visible: Boolean); procedure VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex; OldPosition: Integer); procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); procedure ClearValues; procedure WriteValues; procedure value_viewerDblClick(Sender: TObject); procedure value_viewer_context_copyClick(Sender: TObject); procedure value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure value_viewer_contextPopup(Sender: TObject); private fileid: Integer; ConID: Integer; rawlist: TRawDataList; public end; var Form_BinEdit: TForm_BinEdit; implementation uses ValueEdit, Main, Functions, DatStructureLoader, RawEdit; {$R *.dfm} type PNodeData = ^TNodeData; TNodeData = record Caption: String; Offset: LongInt; DataType: Word; Value: String; Description: String; end; procedure TForm_BinEdit.FormCreate(Sender: TObject); begin inherited; Self.OnNewFileSelected := NewFile; Self.Caption := ''; fileid := 0; VST.NodeDataSize := SizeOf(TNodeData); value_viewer.ColCount := 2; value_viewer.RowCount := 8; value_viewer.FixedRows := 1; value_viewer.FixedCols := 1; value_viewer.Cells[0, 0] := 'Type'; value_viewer.Cells[1, 0] := 'Value'; value_viewer.Cells[0, 1] := '1 byte, unsigned'; value_viewer.Cells[0, 2] := '2 bytes, unsigned'; value_viewer.Cells[0, 3] := '4 bytes, unsigned'; value_viewer.Cells[0, 4] := 'Bitset'; value_viewer.Cells[0, 5] := 'Float'; value_viewer.Cells[0, 6] := 'String'; value_viewer.Cells[0, 7] := 'Selected length'; value_viewer.ColWidths[0] := 120; value_viewer.ColWidths[1] := 1000; // hex.Height := content.Height - 215; // value_viewer.Font.Charset := AppSettings.CharSet; VST.Font.Charset := AppSettings.CharSet; hex.Translation := tkAsIs; hex.Font.Charset := AppSettings.CharSet; // end; procedure TForm_BinEdit.NewFile(fileinfo: TFileInfo); begin LoadDat(fileinfo.ID); end; function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode; ARecord: TNodeData): PVirtualNode; var Data: PNodeData; begin Result := AVST.AddChild(ANode); Data := AVST.GetNodeData(Result); AVST.ValidateNode(Result, False); Data^ := ARecord; end; procedure TForm_BinEdit.LoadDat(_fileid: Integer); var mem: TMemoryStream; begin if ConID <> -1 then begin if hex.Modified then begin if not Save then begin Self.SelectFileID(ConnectionID, FileID); Exit; end; end; end; if _fileid >= 0 then begin fileid := _fileid; ConID := ConnectionID; if ConManager.Connection[ConID].ExtractFileIDOfName(filelist.Items.Strings[filelist.ItemIndex]) <> fileid then Self.SelectFileID(ConnectionID, fileid); Self.ClearStructViewer; mem := nil; ConManager.Connection[ConID].LoadDatFile(fileid, TStream(mem)); rawlist := ConManager.Connection[ConID].GetRawList(fileid); hex.LoadFromStream(mem); mem.Free; ClearValues; WriteStructureInfos; end else begin fileid := _fileid; ConID := -1; Self.ClearStructViewer; ClearValues; hex.DataSize := 0; SetLength(rawlist, 0); end; end; function TForm_BinEdit.GetValue(datatype: Word; offset: Integer): String; var Data: TByteData; i: Integer; floatformat: TFormatSettings; begin floatformat.DecimalSeparator := '.'; case datatype of 1: Result := IntToStr(hex.Data[offset]); 2: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256); 3: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256); 4: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256); 5: Result := '0x' + IntToHex(hex.Data[offset], 2); 6: Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4); 7: Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256, 6); 8: Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8); 9: begin SetLength(Data, 4); Data[0] := hex.Data[offset]; Data[1] := hex.Data[offset + 1]; Data[2] := hex.Data[offset + 2]; Data[3] := hex.Data[offset + 3]; Result := FloatToStr(Decode_Float(Data), floatformat); end; 10: Result := IntToBin(hex.Data[offset]); 11: begin if Length(rawlist) > 0 then begin for i := 0 to High(rawlist) do if rawlist[i].SrcOffset = offset then begin if rawlist[i].RawAddr > 0 then Result := '0x' + IntToHex(rawlist[i].RawAddr, 8) else Result := 'unused'; Break; end; if i > High(rawlist) then Result := 'unused'; end; end; 12: if hex.Data[offset] = 1 then Result := FormatNumber(hex.Data[offset + 1] + hex.Data[offset + 2] * 256 + hex.Data[offset + 3] * 256 * 256, 5, '0') else Result := 'no link'; 13: Result := IntToStr(hex.Data[offset]); 14: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256); 15: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256); 16: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256); 17: Result := IntToStr((hex.Data[offset + 3]) div 2); 100..300: begin Result := ''; for i := 1 to datatype - 100 do begin if hex.Data[offset + i - 1] >= 32 then Result := Result + Chr(hex.Data[offset + i - 1]) else Break; end; end; 1000..9999: begin Result := ''; for i := 1 to datatype - 1000 do begin if hex.Data[offset + i - 1] >= 32 then Result := Result + Chr(hex.Data[offset + i - 1]) else Result := Result + '.'; end; end; 10000..65535: begin Result := ''; for i := 1 to datatype - 10000 do begin if hex.Data[offset + i - 1] >= 32 then Result := Result + Chr(hex.Data[offset + i - 1]) else Result := Result + '.'; end; end; end; end; procedure TForm_BinEdit.WriteStructureInfos; var i, j: Integer; pdata: PNodeData; Data: TNodeData; node: PVirtualNode; structs: TStructDef; begin VST.BeginUpdate; if VST.RootNodeCount = 0 then begin structs := LoadStructureDefinition(ConID, fileid); if structs.Data then begin if Length(structs.Global) > 0 then begin for i := 0 to High(structs.Global) do begin Data.Caption := structs.Global[i].Name; Data.Offset := structs.Global[i].offset; Data.DataType := structs.Global[i].datatype; Data.Value := GetValue(structs.Global[i].datatype, structs.Global[i].offset); Data.Description := structs.Global[i].description; AddVSTEntry(VST, nil, Data); end; end; if Length(structs.Subs) > 0 then begin for i := 0 to High(structs.Subs) do begin with structs.Subs[i] do begin if Length(Entries) > 0 then begin if Pos('#', SubName) > 0 then begin Data.Offset := StrToInt('$'+MidStr(SubName, Pos('#', SubName) + 1, 8)); Data.Value := '$' + MidStr(SubName, PosEx('#', SubName, Pos('#', SubName) + 1) + 1, 8); Data.Caption := MidStr(SubName, 1, Pos('#', SubName) - 1); Data.Description := SubDesc; end else begin Data.Caption := SubName; Data.Description := SubDesc; Data.Offset := 0; Data.Value := ''; end; Data.DataType := 0; node := AddVSTEntry(VST, nil, Data); Data.Description := ''; for j := 0 to High(Entries) do begin Data.Caption := Entries[j].Name; Data.Offset := Entries[j].offset; Data.DataType := Entries[j].datatype; Data.Value := GetValue(Entries[j].datatype, Entries[j].offset); Data.Description := Entries[j].description; AddVSTEntry(VST, node, Data); end; end; end; end; end; end; if VST.RootNodeCount > 0 then VST.FocusedNode := VST.GetFirst; end else begin Node := VST.GetFirst; while Assigned(Node) do begin pdata := VST.GetNodeData(Node); if pdata.DataType > 0 then pdata.Value := GetValue(pdata.Datatype, pdata.Offset); Node := VST.GetNext(Node); end; end; VST.EndUpdate; end; procedure TForm_BinEdit.ClearValues; var i: Byte; begin for i := 1 to value_viewer.RowCount - 1 do begin value_viewer.Cells[1, i] := ''; end; end; procedure TForm_BinEdit.WriteValues; var i, j: Integer; Data: TByteData; str: String; Value: Integer; floatformat: TFormatSettings; begin floatformat.DecimalSeparator := '.'; for i := 1 to value_viewer.RowCount - 1 do begin if value_viewer.Cells[0, i] = '1 byte, unsigned' then begin if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not ((hex.SelStart + 1) > hex.DataSize) then begin Value := hex.Data[hex.SelStart]; value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = '2 bytes, unsigned' then begin if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not ((hex.SelStart + 2) > hex.DataSize) then begin Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256; value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = '4 bytes, unsigned' then begin if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not ((hex.SelStart + 4) > hex.DataSize) then begin Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 + hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256; value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = 'Bitset' then begin if (hex.SelCount <= 8) then begin if hex.SelCount = 0 then begin SetLength(Data, 1); Data[0] := hex.Data[hex.SelStart]; end else begin SetLength(Data, hex.SelCount); for j := 0 to hex.SelCount - 1 do Data[j] := hex.Data[hex.SelStart + j]; end; value_viewer.Cells[1, i] := DataToBin(Data); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = 'Float' then begin if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not ((hex.SelStart + 4) > hex.DataSize) then begin SetLength(Data, 4); for j := 0 to 3 do Data[j] := hex.Data[hex.SelStart + j]; value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data), floatformat); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = 'Selected length' then begin value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes'; end; if value_viewer.Cells[0, i] = 'String' then begin j := 0; str := ''; if hex.SelCount = 0 then begin while (hex.SelStart + j) < hex.DataSize do begin if hex.Data[hex.SelStart + j] = 0 then Break; if hex.Data[hex.selstart + j] >= 32 then str := str + Char(hex.Data[hex.SelStart + j]) else str := str + '.'; Inc(j); end; end else begin for j := 0 to hex.SelCount - 1 do if hex.Data[hex.selstart + j] >= 32 then str := str + Char(hex.Data[hex.SelStart + j]) else if hex.Data[hex.selstart + j] > 0 then str := str + '.' else Break; end; value_viewer.Cells[1, i] := str; end; end; end; function TForm_BinEdit.Save: Boolean; var mem: TMemoryStream; i: Integer; begin case MessageBox(Self.Handle, PChar('Save changes to file ' + ConManager.Connection[ConID].GetFileInfo(fileid).Name + '?'), PChar('Data changed...'), MB_YESNOCANCEL + MB_ICONQUESTION) of idYes: begin mem := TMemoryStream.Create; hex.SaveToStream(mem); mem.Seek(0, soFromBeginning); ConManager.Connection[ConID].UpdateDatFile(fileid, mem); mem.Free; hex.Modified := False; for i := 0 to hex.Datasize - 1 do hex.ByteChanged[i] := False; Result := True; end; idNo: Result := True; idCancel: begin Result := False; end; end; end; procedure TForm_BinEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin if hex.Modified then begin if not Save then CanClose := False; end; end; procedure TForm_BinEdit.ClearStructViewer; begin VST.Clear; end; procedure TForm_BinEdit.hexChange(Sender: TObject); begin ClearValues; if hex.DataSize > 0 then begin WriteStructureInfos; WriteValues; end; end; procedure TForm_BinEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); //var // temps: String; begin if (Shift = [ssCtrl]) and (Key = Ord('C')) then begin if hex.SelCount > 0 then begin if hex.InCharField then Clipboard.AsText := hex.SelectionAsText else Clipboard.AsText := hex.SelectionAsHex; end; end; if (Shift = [ssCtrl]) and (Key = Ord('V')) then begin { temps:=Clipboard.AsText; IF hex.SelStart+Length(temps)>hex.DataSize THEN SetLength(temps, hex.DataSize-hex.SelStart); hex.Sel hex.SelCount:=Length(temps); hex.ReplaceSelection(temps,Length(temps)); } end; end; procedure TForm_BinEdit.hexSelectionChanged(Sender: TObject); var selstart: Integer; node: PVirtualNode; pdata: PNodeData; begin if hex.DataSize > 0 then begin WriteValues; selstart := hex.SelStart; if VST.RootNodeCount > 0 then begin Node := VST.GetFirst; while Assigned(Node) do begin pdata := VST.GetNodeData(Node); if pdata.DataType > 0 then begin if ((selstart - pdata.Offset) < GetDataTypeLength(pdata.DataType)) and ((selstart - pdata.Offset) >= 0) then begin VST.FocusedNode := Node; VST.Selected[Node] := True; Break; end; end; Node := VST.GetNext(Node); end; end; end; end; procedure TForm_BinEdit.value_viewer_contextPopup(Sender: TObject); var i: Byte; begin for i := 0 to value_viewer_context.Items.Count - 1 do value_viewer_context.Items.Items[i].Visible := False; with value_viewer do begin if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then begin if Pos(' byte', Cells[0, Row]) = 2 then begin value_viewer_context.Items.Find('Copy to &clipboard').Visible := True; value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True; value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True; end; if Pos('Float', Cells[0, Row]) = 1 then value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True; if Pos('Bitset', Cells[0, Row]) = 1 then value_viewer_context.Items.Find( 'Copy to clipboard (as &bitset)').Visible := True; if Pos('String', Cells[0, Row]) = 1 then value_viewer_context.Items.Find( 'Copy to clipboard (as &string)').Visible := True; if Pos('Selected length', Cells[0, Row]) = 1 then value_viewer_context.Items.Find('Copy to &clipboard').Visible := True; end; end; end; procedure TForm_BinEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var ACol, ARow: Integer; begin if Button = mbRight then begin value_viewer.MouseToCell(x, y, ACol, ARow); if ARow > 0 then begin value_viewer.Col := ACol; value_viewer.Row := ARow; end; end; end; procedure TForm_BinEdit.value_viewer_context_copyClick(Sender: TObject); var Name: String; Value: Integer; begin Name := TMenuItem(Sender).Name; if Pos('asstring', Name) > 0 then begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end else if Pos('asfloat', Name) > 0 then begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end else if Pos('asbitset', Name) > 0 then begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then begin if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then begin if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not ((hex.SelStart + 1) > hex.DataSize) then Value := hex.Data[hex.SelStart]; end; if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then begin if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not ((hex.SelStart + 2) > hex.DataSize) then Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256; end; if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then begin if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not ((hex.SelStart + 4) > hex.DataSize) then Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 + hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256; end; if Pos('asdec', Name) > 0 then begin Clipboard.AsText := IntToStr(Value); end else begin if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then Clipboard.AsText := '0x' + IntToHex(Value, 2); if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then Clipboard.AsText := '0x' + IntToHex(Value, 4); if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then Clipboard.AsText := '0x' + IntToHex(Value, 8); end; end else begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end; end; procedure TForm_BinEdit.VSTDblClick(Sender: TObject); var node: PVirtualNode; nodedata: PNodeData; rawinfo: TRawDataInfo; form: TForm_TemplateFileList; begin if VST.FocusedColumn = 3 then begin node := VST.FocusedNode; nodedata := VST.GetNodeData(node); if not (nodedata.datatype in [11, 12]) and ((nodedata.DataType < 100) or (nodedata.DataType > 300)) then begin Form_ValueEdit.MakeVarInput(nodedata.Caption, nodedata.offset, nodedata.datatype, nodedata.Value, Self); end else begin if (nodedata.DataType = 11) and (nodedata.Value <> 'unused') then begin rawinfo := ConManager.Connection[ConID].GetRawInfo(fileid, nodedata.offset); if rawinfo.RawSize > 0 then begin form := nil; form := TForm_TemplateFileList(Form_Main.open_child('rawedit', ConID, fileid)); if Assigned(form) then TForm_RawEdit(form).LoadRaw(rawinfo); end; end; if (nodedata.DataType = 12) and (nodedata.Value <> 'no link') then begin if (StrToInt(nodedata.Value) < ConManager.Connection[ConID].GetFileCount) and (StrToInt(nodedata.Value) > 0) and (StrToInt(nodedata.Value) <> fileid) then begin if ConManager.Connection[ConID].GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then Form_Main.open_child('binedit', ConID, StrToInt(nodedata.Value)) else ShowMessage('Linked filed is a zero-byte-file'); end; end; if (nodedata.DataType >= 100) and (nodedata.DataType <= 300) then begin form := TForm_TemplateFileList(Form_Main.open_child('binedit', ConID)); if Assigned(form) then form.SetFileFilters(nodedata.Value, '', False); end; end; end; end; procedure TForm_BinEdit.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); var Data: PNodeData; begin Data := VST.GetNodeData(node); if Data.DataType > 0 then begin hex.SelStart := Data.Offset; hex.SelEnd := Data.Offset + GetDataTypeLength(Data.DataType) - 1; end else begin hex.SelStart := Data.Offset; hex.SelEnd := Data.Offset + StrToInt(Data.Value) - 1; end; end; procedure TForm_BinEdit.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var Data: PNodeData; begin Data := Sender.GetNodeData(Node); CellText := ''; if TextType = ttNormal then begin case Column of 0: CellText := Data.Caption; 1: if Data.DataType > 0 then CellText := '0x' + IntToHex(Data.Offset, 8) else if Data.Offset > 0 then CellText := '0x' + IntToHex(Data.Offset, 8); 2: if Data.DataType > 0 then CellText := GetDataType(Data.DataType); 3: if Data.DataType > 0 then CellText := Data.Value //GetValue(data.DataType, data.Offset) else if Length(Data.Value) > 0 then CellText := IntToStr(StrToInt(Data.Value)) + ' Bytes'; 4: CellText := Data.Description; end; end; end; procedure TForm_BinEdit.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex; OldPosition: Integer); begin if Sender.Columns.Items[column].Position < 1 then Sender.Columns.Items[column].Position := OldPosition; end; procedure TForm_BinEdit.VTHPopupColumnChange(const Sender: TBaseVirtualTree; const Column: TColumnIndex; Visible: Boolean); begin if column = 0 then TVirtualStringTree(Sender).Header.Columns.Items[column].Options := TVirtualStringTree(Sender).Header.Columns.Items[column].Options + [coVisible]; end; procedure TForm_BinEdit.SetNewValue(datatype: Word; offset: Integer; Value: String); var Data: TByteData; value_int: LongWord; value_float: Single; i: Word; begin case datatype of 1..4: begin value_int := StrToInt(Value); SetLength(Data, datatype); for i := 0 to datatype - 1 do begin Data[i] := value_int mod 256; value_int := value_int div 256; end; end; 5..8: begin value_int := StrToInt('$' + Value); SetLength(Data, datatype - 4); for i := 0 to datatype - 5 do begin Data[i] := value_int mod 256; value_int := value_int div 256; end; end; 9: begin value_float := StrToFloat(Value); Data := Encode_Float(value_float); end; 10: begin value_int := BinToInt(Value); SetLength(Data, 1); Data[0] := value_int; end; 10000..65535: begin SetLength(Data, datatype - 10000); for i := 1 to datatype - 10000 do begin if i <= Length(Value) then Data[i - 1] := Ord(Value[i]) else Data[i - 1] := 0; end; end; end; for i := 0 to High(Data) do begin if hex.Data[offset + i] <> Data[i] then hex.ByteChanged[offset + i] := True; hex.Data[offset + i] := Data[i]; end; hex.Modified := True; hexChange(Self); hex.Repaint; end; procedure TForm_BinEdit.value_viewerDblClick(Sender: TObject); var offset: Integer; datatype: Word; objectname: String; Value: String; begin if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then begin offset := hex.SelStart; if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then datatype := 1; if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then datatype := 2; if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then datatype := 4; if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then datatype := 10; if value_viewer.Cells[0, value_viewer.Row] = 'Float' then datatype := 9; if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then Exit; if value_viewer.Cells[0, value_viewer.Row] = 'String' then begin if hex.SelCount > 0 then datatype := 10000 + hex.SelCount else datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]); end; objectname := ''; Value := GetValue(datatype, offset); Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self); end; end; procedure TForm_BinEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (Shift = [ssCtrl]) and (Key = 83) then if hex.Modified then if not Save then Exit; end; begin AddToolListEntry('binedit', 'Binary .dat-Editor', ''); end.