source: oup/current/Tools/BinEdit.pas @ 92

Last change on this file since 92 was 92, checked in by alloc, 16 years ago

Rev86 was first after multi-cons

File size: 27.4 KB
Line 
1unit BinEdit;
2interface
3uses
4  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
5  Dialogs, Template, StdCtrls, ExtCtrls, VirtualTrees, Grids, Wrapgrid,
6  MPHexEditor, VTHeaderPopup, Menus, StrUtils, Clipbrd,
7  Data, OniDataClass, Functions, DataStructures, Exporters, Buttons;
8
9type
10  TForm_BinEdit = class(TForm_ToolTemplate)
11    hex: TMPHexEditor;
12    Splitter2: TSplitter;
13    value_viewer: TWrapGrid;
14    VST: TVirtualStringTree;
15    Splitter3: TSplitter;
16    value_viewer_context: TPopupMenu;
17    value_viewer_context_copy: TMenuItem;
18    value_viewer_context_copyasdec: TMenuItem;
19    value_viewer_context_copyasfloat: TMenuItem;
20    value_viewer_context_copyasbitset: TMenuItem;
21    value_viewer_context_copyasstring: TMenuItem;
22    value_viewer_context_copyashex: TMenuItem;
23    VTHPopup: TVTHeaderPopupMenu;
24    procedure FormCreate(Sender: TObject);
25    procedure NewFile(fileinfo: TFileInfo);
26
27    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
28    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
29
30    procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
31    procedure hexSelectionChanged(Sender: TObject);
32    procedure hexChange(Sender: TObject);
33
34    procedure LoadDat(_fileid: Integer);
35    function Save: Boolean;
36    function GetValue(datatype: Word; offset: LongWord): String;
37    procedure SetNewValue(datatype: Word; offset: LongWord; Value: String);
38
39    procedure WriteStructureInfos;
40    procedure ClearStructViewer;
41    procedure VSTDblClick(Sender: TObject);
42    procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
43      Column: TColumnIndex);
44    procedure VTHPopupColumnChange(const Sender: TBaseVirtualTree;
45      const Column: TColumnIndex; Visible: Boolean);
46    procedure VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
47      OldPosition: Integer);
48    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
49      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
50
51    procedure ClearValues;
52    procedure WriteValues;
53    procedure value_viewerDblClick(Sender: TObject);
54    procedure value_viewer_context_copyClick(Sender: TObject);
55    procedure value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
56      Shift: TShiftState; X, Y: Integer);
57    procedure value_viewer_contextPopup(Sender: TObject);
58  private
59    con: TOniData;
60    fileid: Integer;
61  public
62  end;
63
64var
65  Form_BinEdit: TForm_BinEdit;
66
67implementation
68
69uses Helper_ValueEdit, Main, RawEdit;
70{$R *.dfm}
71
72type
73  PNodeData = ^TNodeData;
74
75  TNodeData = record
76    Caption:  String;
77    Offset:   LongInt;
78    DataType: Word;
79    Value:    String;
80    Description: String;
81  end;
82
83
84
85procedure TForm_BinEdit.FormCreate(Sender: TObject);
86begin
87  inherited;
88  Self.OnNewFileSelected := NewFile;
89
90  Self.Caption := '';
91  fileid     := 0;
92  VST.NodeDataSize := SizeOf(TNodeData);
93  value_viewer.ColCount := 2;
94  value_viewer.RowCount := 8;
95  value_viewer.FixedRows := 1;
96  value_viewer.FixedCols := 1;
97  value_viewer.Cells[0, 0] := 'Type';
98  value_viewer.Cells[1, 0] := 'Value';
99  value_viewer.Cells[0, 1] := '1 byte, unsigned';
100  value_viewer.Cells[0, 2] := '2 bytes, unsigned';
101  value_viewer.Cells[0, 3] := '4 bytes, unsigned';
102  value_viewer.Cells[0, 4] := 'Bitset';
103  value_viewer.Cells[0, 5] := 'Float';
104  value_viewer.Cells[0, 6] := 'String';
105  value_viewer.Cells[0, 7] := 'Selected length';
106  value_viewer.ColWidths[0] := 120;
107  value_viewer.ColWidths[1] := 1000;
108//  hex.Height := content.Height - 215;
109  //
110  value_viewer.Font.Charset := AppSettings.CharSet;
111  VST.Font.Charset := AppSettings.CharSet;
112  hex.Translation := tkAsIs;
113  hex.Font.Charset := AppSettings.CharSet;
114  //
115end;
116
117procedure TForm_BinEdit.NewFile(fileinfo: TFileInfo);
118begin
119  LoadDat(fileinfo.ID);
120end;
121
122
123
124
125function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
126  ARecord: TNodeData): PVirtualNode;
127var
128  Data: PNodeData;
129begin
130  Result := AVST.AddChild(ANode);
131  Data   := AVST.GetNodeData(Result);
132  AVST.ValidateNode(Result, False);
133  Data^ := ARecord;
134end;
135
136
137
138
139procedure TForm_BinEdit.LoadDat(_fileid: Integer);
140var
141  mem:  TMemoryStream;
142  Data: Tdata;
143begin
144  if con <> nil then
145  begin
146    if hex.Modified then
147    begin
148      if not Save then
149      begin
150        Self.SelectFileID(Connection, fileid);
151        Exit;
152      end;
153    end;
154  end;
155  if _fileid >= 0 then
156  begin
157    fileid := _fileid;
158    con := Connection;
159    if con.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]) <> fileid then
160      Self.SelectFileID(Connection, fileid);
161    Self.ClearStructViewer;
162    Data := con.LoadDatFile(fileid);
163    if Length(Data) > 0 then
164    begin
165      mem := TMemoryStream.Create;
166      mem.Write(Data[0], Length(Data));
167      mem.Seek(0, soFromBeginning);
168      hex.LoadFromStream(mem);
169      mem.Free;
170      WriteStructureInfos;
171    end
172    else
173    begin
174      ClearValues;
175      hex.DataSize := 0;
176    end;
177  end
178  else
179  begin
180    fileid := _fileid;
181    con := nil;
182    Self.ClearStructViewer;
183    ClearValues;
184    hex.DataSize := 0;
185  end;
186end;
187
188
189
190
191function IntToBin(Value: Byte): String;
192var
193  i: Byte;
194begin
195  Result := '';
196  for i := 7 downto 0 do
197  begin
198    Result := Result + IntToStr((Value shr i) and $01);
199  end;
200end;
201
202
203
204
205function TForm_BinEdit.GetValue(datatype: Word; offset: LongWord): String;
206var
207  Data: Tdata;
208  i:    Word;
209  floatformat: TFormatSettings;
210begin
211  floatformat.DecimalSeparator := '.';
212  case datatype of
213    1:
214      Result := IntToStr(hex.Data[offset]);
215    2:
216      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
217    3:
218      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
219    4:
220      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
221        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
222    5:
223      Result := '0x' + IntToHex(hex.Data[offset], 2);
224    6:
225      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4);
226    7:
227      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
228        hex.Data[offset + 2] * 256 * 256, 6);
229    8:
230      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
231        hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8);
232    9:
233    begin
234      SetLength(Data, 4);
235      Data[0] := hex.Data[offset];
236      Data[1] := hex.Data[offset + 1];
237      Data[2] := hex.Data[offset + 2];
238      Data[3] := hex.Data[offset + 3];
239      Result  := FloatToStr(Decode_Float(Data), floatformat);
240    end;
241    10:
242      Result := IntToBin(hex.Data[offset]);
243    11:
244      Result := '0x' + IntToHex(con.GetRawInfo(fileid, offset).raw_addr, 8);
245    12:
246      Result := FormatNumber(hex.Data[offset + 1] + hex.Data[offset + 2] * 256 +
247        hex.Data[offset + 3] * 256 * 256, 5, '0');
248    13:
249      Result := IntToStr(hex.Data[offset]);
250    14:
251      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
252    15:
253      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
254    16:
255      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
256        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
257    17:
258      Result := IntToStr((hex.Data[offset + 3]) div 2);
259    100..300:
260    begin
261      Result := '';
262      for i := 1 to datatype - 100 do
263      begin
264        if hex.Data[offset + i - 1] >= 32 then
265          Result := Result + Chr(hex.Data[offset + i - 1])
266        else
267          Break;
268      end;
269    end;
270    1000..9999:
271    begin
272      Result := '';
273      for i := 1 to datatype - 1000 do
274      begin
275        if hex.Data[offset + i - 1] >= 32 then
276          Result := Result + Chr(hex.Data[offset + i - 1])
277        else
278          Result := Result + '.';
279      end;
280    end;
281    10000..65535:
282    begin
283      Result := '';
284      for i := 1 to datatype - 10000 do
285      begin
286        if hex.Data[offset + i - 1] >= 32 then
287          Result := Result + Chr(hex.Data[offset + i - 1])
288        else
289          Result := Result + '.';
290      end;
291    end;
292  end;
293end;
294
295
296
297
298procedure TForm_BinEdit.WriteStructureInfos;
299var
300  i, j:    LongWord;
301  pdata:   PNodeData;
302  Data:    TNodeData;
303  node:    PVirtualNode;
304  structs: TStructDef;
305begin
306  VST.BeginUpdate;
307  if VST.RootNodeCount = 0 then
308  begin
309    structs := LoadStructureDefinition(con, fileid);
310    if structs.Data then
311    begin
312      if Length(structs.Global) > 0 then
313      begin
314        for i := 0 to High(structs.Global) do
315        begin
316          Data.Caption  := structs.Global[i].Name;
317          Data.Offset   := structs.Global[i].offset;
318          Data.DataType := structs.Global[i].datatype;
319          Data.Value    := GetValue(structs.Global[i].datatype, structs.Global[i].offset);
320          Data.Description := structs.Global[i].description;
321          AddVSTEntry(VST, nil, Data);
322        end;
323      end;
324      if Length(structs.Subs) > 0 then
325      begin
326        for i := 0 to High(structs.Subs) do
327        begin
328          with structs.Subs[i] do
329          begin
330            if Length(Entries) > 0 then
331            begin
332              if Pos('#', SubName) > 0 then
333              begin
334                Data.Offset  := HexToLong(MidStr(SubName, Pos('#', SubName) + 1, 8));
335                Data.Value   :=
336                  MidStr(SubName, PosEx('#', SubName, Pos('#', SubName) + 1) + 1, 8);
337                Data.Caption := MidStr(SubName, 1, Pos('#', SubName) - 1);
338                Data.Description := SubDesc;
339              end
340              else
341              begin
342                Data.Caption := SubName;
343                Data.Description := SubDesc;
344                Data.Offset := 0;
345                Data.Value := '';
346              end;
347              Data.DataType := 0;
348              node := AddVSTEntry(VST, nil, Data);
349              Data.Description := '';
350              for j := 0 to High(Entries) do
351              begin
352                Data.Caption  := Entries[j].Name;
353                Data.Offset   := Entries[j].offset;
354                Data.DataType := Entries[j].datatype;
355                Data.Value    := GetValue(Entries[j].datatype, Entries[j].offset);
356                Data.Description := Entries[j].description;
357                AddVSTEntry(VST, node, Data);
358              end;
359            end;
360          end;
361        end;
362      end;
363    end;
364    if VST.RootNodeCount > 0 then
365      VST.FocusedNode := VST.GetFirst;
366  end
367  else
368  begin
369    Node := VST.GetFirst;
370    while Assigned(Node) do
371    begin
372      pdata := VST.GetNodeData(Node);
373      if pdata.DataType > 0 then
374        pdata.Value := GetValue(pdata.Datatype, pdata.Offset);
375      Node := VST.GetNext(Node);
376    end;
377  end;
378  VST.EndUpdate;
379end;
380
381
382
383
384procedure TForm_BinEdit.ClearValues;
385var
386  i: Byte;
387begin
388  for i := 1 to value_viewer.RowCount - 1 do
389  begin
390    value_viewer.Cells[1, i] := '';
391  end;
392end;
393
394
395
396
397procedure TForm_BinEdit.WriteValues;
398var
399  i, j:  Byte;
400  Data:  Tdata;
401  str:   String;
402  Value: LongWord;
403  floatformat: TFormatSettings;
404begin
405  floatformat.DecimalSeparator := '.';
406  for i := 1 to value_viewer.RowCount - 1 do
407  begin
408    if value_viewer.Cells[0, i] = '1 byte, unsigned' then
409    begin
410      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
411        ((hex.SelStart + 1) > hex.DataSize) then
412      begin
413        Value := hex.Data[hex.SelStart];
414        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2);
415      end
416      else
417        value_viewer.Cells[1, i] := '';
418    end;
419    if value_viewer.Cells[0, i] = '2 bytes, unsigned' then
420    begin
421      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
422        ((hex.SelStart + 2) > hex.DataSize) then
423      begin
424        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
425        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4);
426      end
427      else
428        value_viewer.Cells[1, i] := '';
429    end;
430    if value_viewer.Cells[0, i] = '4 bytes, unsigned' then
431    begin
432      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
433        ((hex.SelStart + 4) > hex.DataSize) then
434      begin
435        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
436          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
437        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8);
438      end
439      else
440        value_viewer.Cells[1, i] := '';
441    end;
442    if value_viewer.Cells[0, i] = 'Bitset' then
443    begin
444      if (hex.SelCount <= 8) then
445      begin
446        if hex.SelCount = 0 then
447        begin
448          SetLength(Data, 1);
449          Data[0] := hex.Data[hex.SelStart];
450        end
451        else
452        begin
453          SetLength(Data, hex.SelCount);
454          for j := 0 to hex.SelCount - 1 do
455            Data[j] := hex.Data[hex.SelStart + j];
456        end;
457        value_viewer.Cells[1, i] := DataToBin(Data);
458      end
459      else
460        value_viewer.Cells[1, i] := '';
461    end;
462    if value_viewer.Cells[0, i] = 'Float' then
463    begin
464      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
465        ((hex.SelStart + 4) > hex.DataSize) then
466      begin
467        SetLength(Data, 4);
468        for j := 0 to 3 do
469          Data[j] := hex.Data[hex.SelStart + j];
470        value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data), floatformat);
471      end
472      else
473        value_viewer.Cells[1, i] := '';
474    end;
475    if value_viewer.Cells[0, i] = 'Selected length' then
476    begin
477      value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes';
478    end;
479    if value_viewer.Cells[0, i] = 'String' then
480    begin
481      j   := 0;
482      str := '';
483      if hex.SelCount = 0 then
484      begin
485        while (hex.Data[hex.SelStart + j] > 0) and ((hex.SelStart + j) < hex.DataSize) do
486        begin
487          if hex.Data[hex.selstart + j] >= 32 then
488            str := str + Char(hex.Data[hex.SelStart + j])
489          else
490            str := str + '.';
491          Inc(j);
492        end;
493      end
494      else
495      begin
496        for j := 0 to hex.SelCount - 1 do
497          if hex.Data[hex.selstart + j] >= 32 then
498            str := str + Char(hex.Data[hex.SelStart + j])
499          else if hex.Data[hex.selstart + j] > 0 then
500            str := str + '.'
501          else
502            Break;
503      end;
504      value_viewer.Cells[1, i] := str;
505    end;
506  end;
507end;
508
509
510
511
512function TForm_BinEdit.Save: Boolean;
513var
514  mem:  TMemoryStream;
515  Data: Tdata;
516  i:    LongWord;
517begin
518  case MessageBox(Self.Handle, PChar('Save changes to file ' +
519      con.GetFileInfo(fileid).FileName + '?'), PChar('Data changed...'),
520      MB_YESNOCANCEL) of
521    idYes:
522    begin
523      mem := TMemoryStream.Create;
524      hex.SaveToStream(mem);
525      mem.Seek(0, soFromBeginning);
526      SetLength(Data, mem.Size);
527      mem.Read(Data[0], mem.Size);
528      mem.Free;
529      con.UpdateDatFile(fileid, Data);
530      hex.Modified := False;
531      for i := 0 to hex.Datasize - 1 do
532        hex.ByteChanged[i] := False;
533      Result := True;
534    end;
535    idNo:
536      Result := True;
537    idCancel:
538    begin
539      Result := False;
540    end;
541  end;
542end;
543
544
545
546
547procedure TForm_BinEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
548begin
549  if hex.Modified then
550  begin
551    if not Save then
552      CanClose := False;
553  end;
554end;
555
556
557
558
559procedure TForm_BinEdit.ClearStructViewer;
560begin
561  VST.Clear;
562end;
563
564
565
566
567
568
569procedure TForm_BinEdit.hexChange(Sender: TObject);
570begin
571  ClearValues;
572  if hex.DataSize > 0 then
573  begin
574    WriteStructureInfos;
575    WriteValues;
576  end;
577end;
578
579
580
581
582procedure TForm_BinEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
583//var
584//  temps: String;
585begin
586  if (Shift = [ssCtrl]) and (Key = Ord('C')) then
587  begin
588    if hex.SelCount > 0 then
589    begin
590      if hex.InCharField then
591        Clipboard.AsText := hex.SelectionAsText
592      else
593        Clipboard.AsText := hex.SelectionAsHex;
594    end;
595  end;
596  if (Shift = [ssCtrl]) and (Key = Ord('V')) then
597  begin
598{      temps:=Clipboard.AsText;
599      IF hex.SelStart+Length(temps)>hex.DataSize THEN
600        SetLength(temps, hex.DataSize-hex.SelStart);
601      hex.Sel
602      hex.SelCount:=Length(temps);
603      hex.ReplaceSelection(temps,Length(temps));
604}    end;
605end;
606
607
608
609
610procedure TForm_BinEdit.hexSelectionChanged(Sender: TObject);
611var
612  selstart: Integer;
613  node:     PVirtualNode;
614  pdata:    PNodeData;
615begin
616  if hex.DataSize > 0 then
617  begin
618    WriteValues;
619    selstart := hex.SelStart;
620    if VST.RootNodeCount > 0 then
621    begin
622      Node := VST.GetFirst;
623      while Assigned(Node) do
624      begin
625        pdata := VST.GetNodeData(Node);
626        if pdata.DataType > 0 then
627        begin
628          if ((selstart - pdata.Offset) < GetTypeDataLength(pdata.DataType)) and
629            ((selstart - pdata.Offset) >= 0) then
630          begin
631            VST.FocusedNode    := Node;
632            VST.Selected[Node] := True;
633            Break;
634          end;
635        end;
636        Node := VST.GetNext(Node);
637      end;
638    end;
639  end;
640end;
641
642
643
644
645procedure TForm_BinEdit.value_viewer_contextPopup(Sender: TObject);
646var
647  i: Byte;
648begin
649  for i := 0 to value_viewer_context.Items.Count - 1 do
650    value_viewer_context.Items.Items[i].Visible := False;
651  with value_viewer do
652  begin
653    if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then
654    begin
655      if Pos(' byte', Cells[0, Row]) = 2 then
656      begin
657        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
658        value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True;
659        value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True;
660      end;
661      if Pos('Float', Cells[0, Row]) = 1 then
662        value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True;
663      if Pos('Bitset', Cells[0, Row]) = 1 then
664        value_viewer_context.Items.Find(
665          'Copy to clipboard (as &bitset)').Visible := True;
666      if Pos('String', Cells[0, Row]) = 1 then
667        value_viewer_context.Items.Find(
668          'Copy to clipboard (as &string)').Visible := True;
669      if Pos('Selected length', Cells[0, Row]) = 1 then
670        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
671    end;
672  end;
673end;
674
675
676
677
678procedure TForm_BinEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
679  Shift: TShiftState; X, Y: Integer);
680var
681  ACol, ARow: Integer;
682begin
683  if Button = mbRight then
684  begin
685    value_viewer.MouseToCell(x, y, ACol, ARow);
686    if ARow > 0 then
687    begin
688      value_viewer.Col := ACol;
689      value_viewer.Row := ARow;
690    end;
691  end;
692end;
693
694
695
696
697procedure TForm_BinEdit.value_viewer_context_copyClick(Sender: TObject);
698var
699  Name:  String;
700  Value: LongWord;
701begin
702  Name := TMenuItem(Sender).Name;
703  if Pos('asstring', Name) > 0 then
704  begin
705    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
706  end
707  else if Pos('asfloat', Name) > 0 then
708  begin
709    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
710  end
711  else if Pos('asbitset', Name) > 0 then
712  begin
713    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
714  end
715  else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then
716  begin
717    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
718    begin
719      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
720        ((hex.SelStart + 1) > hex.DataSize) then
721        Value := hex.Data[hex.SelStart];
722    end;
723    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
724    begin
725      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
726        ((hex.SelStart + 2) > hex.DataSize) then
727        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
728    end;
729    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
730    begin
731      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
732        ((hex.SelStart + 4) > hex.DataSize) then
733        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
734          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
735    end;
736    if Pos('asdec', Name) > 0 then
737    begin
738      Clipboard.AsText := IntToStr(Value);
739    end
740    else
741    begin
742      if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
743        Clipboard.AsText := '0x' + IntToHex(Value, 2);
744      if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
745        Clipboard.AsText := '0x' + IntToHex(Value, 4);
746      if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
747        Clipboard.AsText := '0x' + IntToHex(Value, 8);
748    end;
749  end
750  else
751  begin
752    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
753  end;
754end;
755
756
757
758
759procedure TForm_BinEdit.VSTDblClick(Sender: TObject);
760var
761  node: PVirtualNode;
762  nodedata: PNodeData;
763  form: TForm_ToolTemplate;
764begin
765  if VST.FocusedColumn = 3 then
766  begin
767    node     := VST.FocusedNode;
768    nodedata := VST.GetNodeData(node);
769
770    if not (nodedata.datatype in [11, 12]) and
771      ((nodedata.DataType < 100) or (nodedata.DataType > 300)) then
772    begin
773      Form_ValueEdit.MakeVarInput(nodedata.Caption, nodedata.offset,
774        nodedata.datatype, nodedata.Value, Self);
775    end
776    else
777    begin
778      if nodedata.DataType = 11 then
779      begin
780        if con.GetRawInfo(fileid, nodedata.offset).raw_size > 0 then
781          Form_Main.open_child('rawedit', Connection, fileid);
782      end;
783      if nodedata.DataType = 12 then
784      begin
785        if (StrToInt(nodedata.Value) < con.GetFilesCount) and
786          (StrToInt(nodedata.Value) > 0) and
787          (StrToInt(nodedata.Value) <> fileid) then
788        begin
789          if con.GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then
790            Form_Main.open_child('binedit', Connection, StrToInt(nodedata.Value))
791          else
792            ShowMessage('Linked filed is a zero-byte-file');
793        end;
794      end;
795      if (nodedata.DataType >= 100) and (nodedata.DataType <= 300) then
796      begin
797        form := Form_Main.open_child('binedit', Connection, -1);
798        if Assigned(form) then
799          form.SetFileFilters(nodedata.Value, '', False);
800      end;
801    end;
802
803  end;
804end;
805
806
807
808
809procedure TForm_BinEdit.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
810  Column: TColumnIndex);
811var
812  Data: PNodeData;
813begin
814  Data := VST.GetNodeData(node);
815  if Data.DataType > 0 then
816  begin
817    hex.SelStart := Data.Offset;
818    hex.SelEnd   := Data.Offset + GetTypeDataLength(Data.DataType) - 1;
819  end
820  else
821  begin
822    hex.SelStart := Data.Offset;
823    hex.SelEnd   := Data.Offset + HexToLong(Data.Value) - 1;
824  end;
825end;
826
827
828
829
830procedure TForm_BinEdit.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
831  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
832var
833  Data: PNodeData;
834begin
835  Data     := Sender.GetNodeData(Node);
836  CellText := '';
837  if TextType = ttNormal then
838  begin
839    case Column of
840      0:
841        CellText := Data.Caption;
842      1:
843        if Data.DataType > 0 then
844          CellText := '0x' + IntToHex(Data.Offset, 8)
845        else if Data.Offset > 0 then
846          CellText := '0x' + IntToHex(Data.Offset, 8);
847      2:
848        if Data.DataType > 0 then
849          CellText := GetDataType(Data.DataType);
850      3:
851        if Data.DataType > 0 then
852          CellText := Data.Value //GetValue(data.DataType, data.Offset)
853        else if Length(Data.Value) > 0 then
854          CellText := IntToStr(HexToLong(Data.Value)) + ' Bytes';
855      4:
856        CellText := Data.Description;
857    end;
858  end;
859end;
860
861
862
863
864procedure TForm_BinEdit.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
865  OldPosition: Integer);
866begin
867  if Sender.Columns.Items[column].Position < 1 then
868    Sender.Columns.Items[column].Position := OldPosition;
869end;
870
871
872
873
874procedure TForm_BinEdit.VTHPopupColumnChange(const Sender: TBaseVirtualTree;
875  const Column: TColumnIndex; Visible: Boolean);
876begin
877  if column = 0 then
878    TVirtualStringTree(Sender).Header.Columns.Items[column].Options :=
879      TVirtualStringTree(Sender).Header.Columns.Items[column].Options + [coVisible];
880end;
881
882
883
884
885procedure TForm_BinEdit.SetNewValue(datatype: Word; offset: LongWord; Value: String);
886var
887  Data: Tdata;
888  value_int: LongWord;
889  value_float: Single;
890  i: Word;
891begin
892  case datatype of
893    1..4:
894    begin
895      value_int := StrToInt(Value);
896      SetLength(Data, datatype);
897      for i := 0 to datatype - 1 do
898      begin
899        Data[i]   := value_int mod 256;
900        value_int := value_int div 256;
901      end;
902    end;
903    5..8:
904    begin
905      value_int := StrToInt('$' + Value);
906      SetLength(Data, datatype - 4);
907      for i := 0 to datatype - 5 do
908      begin
909        Data[i]   := value_int mod 256;
910        value_int := value_int div 256;
911      end;
912    end;
913    9:
914    begin
915      value_float := StrToFloat(Value);
916      Data := Encode_Float(value_float);
917    end;
918    10:
919    begin
920      value_int := BinToInt(Value);
921      SetLength(Data, 1);
922      Data[0] := value_int;
923    end;
924    10000..65535:
925    begin
926      SetLength(Data, datatype - 10000);
927      for i := 1 to datatype - 10000 do
928      begin
929        if i <= Length(Value) then
930          Data[i - 1] := Ord(Value[i])
931        else
932          Data[i - 1] := 0;
933      end;
934    end;
935  end;
936  for i := 0 to High(Data) do
937  begin
938    if hex.Data[offset + i] <> Data[i] then
939      hex.ByteChanged[offset + i] := True;
940    hex.Data[offset + i] := Data[i];
941  end;
942  hex.Modified := True;
943  hexChange(Self);
944  hex.Repaint;
945end;
946
947
948
949
950procedure TForm_BinEdit.value_viewerDblClick(Sender: TObject);
951var
952  offset:     LongWord;
953  datatype:   Word;
954  objectname: String;
955  Value:      String;
956begin
957  if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then
958  begin
959    offset := hex.SelStart;
960    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
961      datatype := 1;
962    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
963      datatype := 2;
964    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
965      datatype := 4;
966    if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then
967      datatype := 10;
968    if value_viewer.Cells[0, value_viewer.Row] = 'Float' then
969      datatype := 9;
970    if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then
971      Exit;
972    if value_viewer.Cells[0, value_viewer.Row] = 'String' then
973    begin
974      if hex.SelCount > 0 then
975        datatype := 10000 + hex.SelCount
976      else
977        datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]);
978    end;
979    objectname := '';
980    Value      := GetValue(datatype, offset);
981    Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self);
982  end;
983end;
984
985
986
987
988procedure TForm_BinEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
989begin
990  if (Shift = [ssCtrl]) and (Key = 83) then
991    if hex.Modified then
992      if not Save then
993        Exit;
994end;
995
996
997begin
998  AddToolListEntry('binedit', 'Binary .dat-Editor', '');
999end.
Note: See TracBrowser for help on using the repository browser.