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

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