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

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