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

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