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

Last change on this file since 113 was 113, checked in by alloc, 15 years ago
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, 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.Data[hex.SelStart + j] > 0) and ((hex.SelStart + j) < hex.DataSize) do
471        begin
472          if hex.Data[hex.selstart + j] >= 32 then
473            str := str + Char(hex.Data[hex.SelStart + j])
474          else
475            str := str + '.';
476          Inc(j);
477        end;
478      end
479      else
480      begin
481        for j := 0 to hex.SelCount - 1 do
482          if hex.Data[hex.selstart + j] >= 32 then
483            str := str + Char(hex.Data[hex.SelStart + j])
484          else if hex.Data[hex.selstart + j] > 0 then
485            str := str + '.'
486          else
487            Break;
488      end;
489      value_viewer.Cells[1, i] := str;
490    end;
491  end;
492end;
493
494
495
496
497function TForm_BinEdit.Save: Boolean;
498var
499  mem:  TMemoryStream;
500  i:    Integer;
501begin
502  case MessageBox(Self.Handle, PChar('Save changes to file ' +
503      ConManager.Connection[ConID].GetFileInfo(fileid).Name + '?'), PChar('Data changed...'),
504      MB_YESNOCANCEL + MB_ICONQUESTION) of
505    idYes:
506    begin
507      mem := TMemoryStream.Create;
508      hex.SaveToStream(mem);
509      mem.Seek(0, soFromBeginning);
510      ConManager.Connection[ConID].UpdateDatFile(fileid, mem);
511      mem.Free;
512      hex.Modified := False;
513      for i := 0 to hex.Datasize - 1 do
514        hex.ByteChanged[i] := False;
515      Result := True;
516    end;
517    idNo:
518      Result := True;
519    idCancel:
520    begin
521      Result := False;
522    end;
523  end;
524end;
525
526
527
528
529procedure TForm_BinEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
530begin
531  if hex.Modified then
532  begin
533    if not Save then
534      CanClose := False;
535  end;
536end;
537
538
539
540
541procedure TForm_BinEdit.ClearStructViewer;
542begin
543  VST.Clear;
544end;
545
546
547
548
549
550
551procedure TForm_BinEdit.hexChange(Sender: TObject);
552begin
553  ClearValues;
554  if hex.DataSize > 0 then
555  begin
556    WriteStructureInfos;
557    WriteValues;
558  end;
559end;
560
561
562
563
564procedure TForm_BinEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
565//var
566//  temps: String;
567begin
568  if (Shift = [ssCtrl]) and (Key = Ord('C')) then
569  begin
570    if hex.SelCount > 0 then
571    begin
572      if hex.InCharField then
573        Clipboard.AsText := hex.SelectionAsText
574      else
575        Clipboard.AsText := hex.SelectionAsHex;
576    end;
577  end;
578  if (Shift = [ssCtrl]) and (Key = Ord('V')) then
579  begin
580{      temps:=Clipboard.AsText;
581      IF hex.SelStart+Length(temps)>hex.DataSize THEN
582        SetLength(temps, hex.DataSize-hex.SelStart);
583      hex.Sel
584      hex.SelCount:=Length(temps);
585      hex.ReplaceSelection(temps,Length(temps));
586}    end;
587end;
588
589
590
591
592procedure TForm_BinEdit.hexSelectionChanged(Sender: TObject);
593var
594  selstart: Integer;
595  node:     PVirtualNode;
596  pdata:    PNodeData;
597begin
598  if hex.DataSize > 0 then
599  begin
600    WriteValues;
601    selstart := hex.SelStart;
602    if VST.RootNodeCount > 0 then
603    begin
604      Node := VST.GetFirst;
605      while Assigned(Node) do
606      begin
607        pdata := VST.GetNodeData(Node);
608        if pdata.DataType > 0 then
609        begin
610          if ((selstart - pdata.Offset) < GetDataTypeLength(pdata.DataType)) and
611            ((selstart - pdata.Offset) >= 0) then
612          begin
613            VST.FocusedNode    := Node;
614            VST.Selected[Node] := True;
615            Break;
616          end;
617        end;
618        Node := VST.GetNext(Node);
619      end;
620    end;
621  end;
622end;
623
624
625
626
627procedure TForm_BinEdit.value_viewer_contextPopup(Sender: TObject);
628var
629  i: Byte;
630begin
631  for i := 0 to value_viewer_context.Items.Count - 1 do
632    value_viewer_context.Items.Items[i].Visible := False;
633  with value_viewer do
634  begin
635    if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then
636    begin
637      if Pos(' byte', Cells[0, Row]) = 2 then
638      begin
639        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
640        value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True;
641        value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True;
642      end;
643      if Pos('Float', Cells[0, Row]) = 1 then
644        value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True;
645      if Pos('Bitset', Cells[0, Row]) = 1 then
646        value_viewer_context.Items.Find(
647          'Copy to clipboard (as &bitset)').Visible := True;
648      if Pos('String', Cells[0, Row]) = 1 then
649        value_viewer_context.Items.Find(
650          'Copy to clipboard (as &string)').Visible := True;
651      if Pos('Selected length', Cells[0, Row]) = 1 then
652        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
653    end;
654  end;
655end;
656
657
658
659
660procedure TForm_BinEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
661  Shift: TShiftState; X, Y: Integer);
662var
663  ACol, ARow: Integer;
664begin
665  if Button = mbRight then
666  begin
667    value_viewer.MouseToCell(x, y, ACol, ARow);
668    if ARow > 0 then
669    begin
670      value_viewer.Col := ACol;
671      value_viewer.Row := ARow;
672    end;
673  end;
674end;
675
676
677
678
679procedure TForm_BinEdit.value_viewer_context_copyClick(Sender: TObject);
680var
681  Name:  String;
682  Value: Integer;
683begin
684  Name := TMenuItem(Sender).Name;
685  if Pos('asstring', Name) > 0 then
686  begin
687    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
688  end
689  else if Pos('asfloat', Name) > 0 then
690  begin
691    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
692  end
693  else if Pos('asbitset', Name) > 0 then
694  begin
695    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
696  end
697  else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then
698  begin
699    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
700    begin
701      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
702        ((hex.SelStart + 1) > hex.DataSize) then
703        Value := hex.Data[hex.SelStart];
704    end;
705    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
706    begin
707      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
708        ((hex.SelStart + 2) > hex.DataSize) then
709        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
710    end;
711    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
712    begin
713      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
714        ((hex.SelStart + 4) > hex.DataSize) then
715        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
716          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
717    end;
718    if Pos('asdec', Name) > 0 then
719    begin
720      Clipboard.AsText := IntToStr(Value);
721    end
722    else
723    begin
724      if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
725        Clipboard.AsText := '0x' + IntToHex(Value, 2);
726      if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
727        Clipboard.AsText := '0x' + IntToHex(Value, 4);
728      if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
729        Clipboard.AsText := '0x' + IntToHex(Value, 8);
730    end;
731  end
732  else
733  begin
734    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
735  end;
736end;
737
738
739
740
741procedure TForm_BinEdit.VSTDblClick(Sender: TObject);
742var
743  node: PVirtualNode;
744  nodedata: PNodeData;
745  form: TForm_ToolTemplate;
746begin
747  if VST.FocusedColumn = 3 then
748  begin
749    node     := VST.FocusedNode;
750    nodedata := VST.GetNodeData(node);
751
752    if not (nodedata.datatype in [11, 12]) and
753      ((nodedata.DataType < 100) or (nodedata.DataType > 300)) then
754    begin
755      Form_ValueEdit.MakeVarInput(nodedata.Caption, nodedata.offset,
756        nodedata.datatype, nodedata.Value, Self);
757    end
758    else
759    begin
760      if (nodedata.DataType = 11) and (nodedata.Value <> 'unused') then
761      begin
762        if ConManager.Connection[ConID].GetRawInfo(fileid, nodedata.offset).RawSize > 0 then
763          Form_Main.open_child('rawedit', ConID, fileid);
764      end;
765      if (nodedata.DataType = 12) and (nodedata.Value <> 'no link') then
766      begin
767        if (StrToInt(nodedata.Value) < ConManager.Connection[ConID].GetFileCount) and
768          (StrToInt(nodedata.Value) > 0) and
769          (StrToInt(nodedata.Value) <> fileid) then
770        begin
771          if ConManager.Connection[ConID].GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then
772            Form_Main.open_child('binedit', ConID, StrToInt(nodedata.Value))
773          else
774            ShowMessage('Linked filed is a zero-byte-file');
775        end;
776      end;
777      if (nodedata.DataType >= 100) and (nodedata.DataType <= 300) then
778      begin
779        form := Form_Main.open_child('binedit', ConID, -1);
780        if Assigned(form) then
781          form.SetFileFilters(nodedata.Value, '', False);
782      end;
783    end;
784
785  end;
786end;
787
788
789
790
791procedure TForm_BinEdit.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
792  Column: TColumnIndex);
793var
794  Data: PNodeData;
795begin
796  Data := VST.GetNodeData(node);
797  if Data.DataType > 0 then
798  begin
799    hex.SelStart := Data.Offset;
800    hex.SelEnd   := Data.Offset + GetDataTypeLength(Data.DataType) - 1;
801  end
802  else
803  begin
804    hex.SelStart := Data.Offset;
805    hex.SelEnd   := Data.Offset + StrToInt(Data.Value) - 1;
806  end;
807end;
808
809
810
811
812procedure TForm_BinEdit.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
813  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
814var
815  Data: PNodeData;
816begin
817  Data     := Sender.GetNodeData(Node);
818  CellText := '';
819  if TextType = ttNormal then
820  begin
821    case Column of
822      0:
823        CellText := Data.Caption;
824      1:
825        if Data.DataType > 0 then
826          CellText := '0x' + IntToHex(Data.Offset, 8)
827        else if Data.Offset > 0 then
828          CellText := '0x' + IntToHex(Data.Offset, 8);
829      2:
830        if Data.DataType > 0 then
831          CellText := GetDataType(Data.DataType);
832      3:
833        if Data.DataType > 0 then
834          CellText := Data.Value //GetValue(data.DataType, data.Offset)
835        else if Length(Data.Value) > 0 then
836          CellText := IntToStr(StrToInt(Data.Value)) + ' Bytes';
837      4:
838        CellText := Data.Description;
839    end;
840  end;
841end;
842
843
844
845
846procedure TForm_BinEdit.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
847  OldPosition: Integer);
848begin
849  if Sender.Columns.Items[column].Position < 1 then
850    Sender.Columns.Items[column].Position := OldPosition;
851end;
852
853
854
855
856procedure TForm_BinEdit.VTHPopupColumnChange(const Sender: TBaseVirtualTree;
857  const Column: TColumnIndex; Visible: Boolean);
858begin
859  if column = 0 then
860    TVirtualStringTree(Sender).Header.Columns.Items[column].Options :=
861      TVirtualStringTree(Sender).Header.Columns.Items[column].Options + [coVisible];
862end;
863
864
865
866
867procedure TForm_BinEdit.SetNewValue(datatype: Word; offset: Integer; Value: String);
868var
869  Data: TByteData;
870  value_int: LongWord;
871  value_float: Single;
872  i: Word;
873begin
874  case datatype of
875    1..4:
876    begin
877      value_int := StrToInt(Value);
878      SetLength(Data, datatype);
879      for i := 0 to datatype - 1 do
880      begin
881        Data[i]   := value_int mod 256;
882        value_int := value_int div 256;
883      end;
884    end;
885    5..8:
886    begin
887      value_int := StrToInt('$' + Value);
888      SetLength(Data, datatype - 4);
889      for i := 0 to datatype - 5 do
890      begin
891        Data[i]   := value_int mod 256;
892        value_int := value_int div 256;
893      end;
894    end;
895    9:
896    begin
897      value_float := StrToFloat(Value);
898      Data := Encode_Float(value_float);
899    end;
900    10:
901    begin
902      value_int := BinToInt(Value);
903      SetLength(Data, 1);
904      Data[0] := value_int;
905    end;
906    10000..65535:
907    begin
908      SetLength(Data, datatype - 10000);
909      for i := 1 to datatype - 10000 do
910      begin
911        if i <= Length(Value) then
912          Data[i - 1] := Ord(Value[i])
913        else
914          Data[i - 1] := 0;
915      end;
916    end;
917  end;
918  for i := 0 to High(Data) do
919  begin
920    if hex.Data[offset + i] <> Data[i] then
921      hex.ByteChanged[offset + i] := True;
922    hex.Data[offset + i] := Data[i];
923  end;
924  hex.Modified := True;
925  hexChange(Self);
926  hex.Repaint;
927end;
928
929
930
931
932procedure TForm_BinEdit.value_viewerDblClick(Sender: TObject);
933var
934  offset:     Integer;
935  datatype:   Word;
936  objectname: String;
937  Value:      String;
938begin
939  if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then
940  begin
941    offset := hex.SelStart;
942    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
943      datatype := 1;
944    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
945      datatype := 2;
946    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
947      datatype := 4;
948    if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then
949      datatype := 10;
950    if value_viewer.Cells[0, value_viewer.Row] = 'Float' then
951      datatype := 9;
952    if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then
953      Exit;
954    if value_viewer.Cells[0, value_viewer.Row] = 'String' then
955    begin
956      if hex.SelCount > 0 then
957        datatype := 10000 + hex.SelCount
958      else
959        datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]);
960    end;
961    objectname := '';
962    Value      := GetValue(datatype, offset);
963    Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self);
964  end;
965end;
966
967
968
969
970procedure TForm_BinEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
971begin
972  if (Shift = [ssCtrl]) and (Key = 83) then
973    if hex.Modified then
974      if not Save then
975        Exit;
976end;
977
978
979begin
980  AddToolListEntry('binedit', 'Binary .dat-Editor', '');
981end.
Note: See TracBrowser for help on using the repository browser.