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

Last change on this file since 87 was 87, checked in by alloc, 16 years ago
File size: 27.2 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: Integer;
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;
193  floatformat: TFormatSettings;
194begin
195  floatformat.DecimalSeparator := '.';
196  case datatype of
197    1:
198      Result := IntToStr(hex.Data[offset]);
199    2:
200      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
201    3:
202      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
203    4:
204      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
205        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
206    5:
207      Result := '0x' + IntToHex(hex.Data[offset], 2);
208    6:
209      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4);
210    7:
211      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
212        hex.Data[offset + 2] * 256 * 256, 6);
213    8:
214      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
215        hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8);
216    9:
217    begin
218      SetLength(Data, 4);
219      Data[0] := hex.Data[offset];
220      Data[1] := hex.Data[offset + 1];
221      Data[2] := hex.Data[offset + 2];
222      Data[3] := hex.Data[offset + 3];
223      Result  := FloatToStr(Decode_Float(Data), floatformat);
224    end;
225    10:
226      Result := IntToBin(hex.Data[offset]);
227    11:
228      Result := '0x' + IntToHex(OniDataConnection.GetRawInfo(fileid, offset).raw_addr, 8);
229    12:
230      Result := FormatNumber(hex.Data[offset + 1] + hex.Data[offset + 2] * 256 +
231        hex.Data[offset + 3] * 256 * 256, 5, '0');
232    13:
233      Result := IntToStr(hex.Data[offset]);
234    14:
235      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
236    15:
237      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
238    16:
239      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
240        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
241    17:
242      Result := IntToStr((hex.Data[offset + 3]) div 2);
243    100..300:
244    begin
245      Result := '';
246      for i := 1 to datatype - 100 do
247      begin
248        if hex.Data[offset + i - 1] >= 32 then
249          Result := Result + Chr(hex.Data[offset + i - 1])
250        else
251          Break;
252      end;
253    end;
254    1000..9999:
255    begin
256      Result := '';
257      for i := 1 to datatype - 1000 do
258      begin
259        if hex.Data[offset + i - 1] >= 32 then
260          Result := Result + Chr(hex.Data[offset + i - 1])
261        else
262          Result := Result + '.';
263      end;
264    end;
265    10000..65535:
266    begin
267      Result := '';
268      for i := 1 to datatype - 10000 do
269      begin
270        if hex.Data[offset + i - 1] >= 32 then
271          Result := Result + Chr(hex.Data[offset + i - 1])
272        else
273          Result := Result + '.';
274      end;
275    end;
276  end;
277end;
278
279
280
281
282procedure TForm_BinEdit.WriteStructureInfos;
283var
284  i, j:    LongWord;
285  pdata:   PNodeData;
286  Data:    TNodeData;
287  node:    PVirtualNode;
288  structs: TStructDef;
289begin
290  VST.BeginUpdate;
291  if VST.RootNodeCount = 0 then
292  begin
293    structs := LoadStructureDefinition(Connection, fileid);
294    if structs.Data then
295    begin
296      if Length(structs.Global) > 0 then
297      begin
298        for i := 0 to High(structs.Global) do
299        begin
300          Data.Caption  := structs.Global[i].Name;
301          Data.Offset   := structs.Global[i].offset;
302          Data.DataType := structs.Global[i].datatype;
303          Data.Value    := GetValue(structs.Global[i].datatype, structs.Global[i].offset);
304          Data.Description := structs.Global[i].description;
305          AddVSTEntry(VST, nil, Data);
306        end;
307      end;
308      if Length(structs.Subs) > 0 then
309      begin
310        for i := 0 to High(structs.Subs) do
311        begin
312          with structs.Subs[i] do
313          begin
314            if Length(Entries) > 0 then
315            begin
316              if Pos('#', SubName) > 0 then
317              begin
318                Data.Offset  := HexToLong(MidStr(SubName, Pos('#', SubName) + 1, 8));
319                Data.Value   :=
320                  MidStr(SubName, PosEx('#', SubName, Pos('#', SubName) + 1) + 1, 8);
321                Data.Caption := MidStr(SubName, 1, Pos('#', SubName) - 1);
322                Data.Description := SubDesc;
323              end
324              else
325              begin
326                Data.Caption := SubName;
327                Data.Description := SubDesc;
328                Data.Offset := 0;
329                Data.Value := '';
330              end;
331              Data.DataType := 0;
332              node := AddVSTEntry(VST, nil, Data);
333              Data.Description := '';
334              for j := 0 to High(Entries) do
335              begin
336                Data.Caption  := Entries[j].Name;
337                Data.Offset   := Entries[j].offset;
338                Data.DataType := Entries[j].datatype;
339                Data.Value    := GetValue(Entries[j].datatype, Entries[j].offset);
340                Data.Description := Entries[j].description;
341                AddVSTEntry(VST, node, Data);
342              end;
343            end;
344          end;
345        end;
346      end;
347    end;
348    if VST.RootNodeCount > 0 then
349      VST.FocusedNode := VST.GetFirst;
350  end
351  else
352  begin
353    Node := VST.GetFirst;
354    while Assigned(Node) do
355    begin
356      pdata := VST.GetNodeData(Node);
357      if pdata.DataType > 0 then
358        pdata.Value := GetValue(pdata.Datatype, pdata.Offset);
359      Node := VST.GetNext(Node);
360    end;
361  end;
362  VST.EndUpdate;
363end;
364
365
366
367
368procedure TForm_BinEdit.ClearValues;
369var
370  i: Byte;
371begin
372  for i := 1 to value_viewer.RowCount - 1 do
373  begin
374    value_viewer.Cells[1, i] := '';
375  end;
376end;
377
378
379
380
381procedure TForm_BinEdit.WriteValues;
382var
383  i, j:  Byte;
384  Data:  Tdata;
385  str:   String;
386  Value: LongWord;
387  floatformat: TFormatSettings;
388begin
389  floatformat.DecimalSeparator := '.';
390  for i := 1 to value_viewer.RowCount - 1 do
391  begin
392    if value_viewer.Cells[0, i] = '1 byte, unsigned' then
393    begin
394      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
395        ((hex.SelStart + 1) > hex.DataSize) then
396      begin
397        Value := hex.Data[hex.SelStart];
398        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2);
399      end
400      else
401        value_viewer.Cells[1, i] := '';
402    end;
403    if value_viewer.Cells[0, i] = '2 bytes, unsigned' then
404    begin
405      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
406        ((hex.SelStart + 2) > hex.DataSize) then
407      begin
408        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
409        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4);
410      end
411      else
412        value_viewer.Cells[1, i] := '';
413    end;
414    if value_viewer.Cells[0, i] = '4 bytes, unsigned' then
415    begin
416      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
417        ((hex.SelStart + 4) > hex.DataSize) then
418      begin
419        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
420          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
421        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8);
422      end
423      else
424        value_viewer.Cells[1, i] := '';
425    end;
426    if value_viewer.Cells[0, i] = 'Bitset' then
427    begin
428      if (hex.SelCount <= 8) then
429      begin
430        if hex.SelCount = 0 then
431        begin
432          SetLength(Data, 1);
433          Data[0] := hex.Data[hex.SelStart];
434        end
435        else
436        begin
437          SetLength(Data, hex.SelCount);
438          for j := 0 to hex.SelCount - 1 do
439            Data[j] := hex.Data[hex.SelStart + j];
440        end;
441        value_viewer.Cells[1, i] := DataToBin(Data);
442      end
443      else
444        value_viewer.Cells[1, i] := '';
445    end;
446    if value_viewer.Cells[0, i] = 'Float' then
447    begin
448      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
449        ((hex.SelStart + 4) > hex.DataSize) then
450      begin
451        SetLength(Data, 4);
452        for j := 0 to 3 do
453          Data[j] := hex.Data[hex.SelStart + j];
454        value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data), floatformat);
455      end
456      else
457        value_viewer.Cells[1, i] := '';
458    end;
459    if value_viewer.Cells[0, i] = 'Selected length' then
460    begin
461      value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes';
462    end;
463    if value_viewer.Cells[0, i] = 'String' then
464    begin
465      j   := 0;
466      str := '';
467      if hex.SelCount = 0 then
468      begin
469        while (hex.Data[hex.SelStart + j] > 0) and ((hex.SelStart + j) < hex.DataSize) do
470        begin
471          if hex.Data[hex.selstart + j] >= 32 then
472            str := str + Char(hex.Data[hex.SelStart + j])
473          else
474            str := str + '.';
475          Inc(j);
476        end;
477      end
478      else
479      begin
480        for j := 0 to hex.SelCount - 1 do
481          if hex.Data[hex.selstart + j] >= 32 then
482            str := str + Char(hex.Data[hex.SelStart + j])
483          else if hex.Data[hex.selstart + j] > 0 then
484            str := str + '.'
485          else
486            Break;
487      end;
488      value_viewer.Cells[1, i] := str;
489    end;
490  end;
491end;
492
493
494
495
496function TForm_BinEdit.Save: Boolean;
497var
498  mem:  TMemoryStream;
499  Data: Tdata;
500  i:    LongWord;
501begin
502  case MessageBox(Self.Handle, PChar('Save changes to file ' +
503      OniDataConnection.GetFileInfo(fileid).FileName + '?'), PChar('Data changed...'),
504      MB_YESNOCANCEL) of
505    idYes:
506    begin
507      mem := TMemoryStream.Create;
508      hex.SaveToStream(mem);
509      mem.Seek(0, soFromBeginning);
510      SetLength(Data, mem.Size);
511      mem.Read(Data[0], mem.Size);
512      mem.Free;
513      OniDataConnection.UpdateDatFile(fileid, Data);
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) < GetTypeDataLength(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: LongWord;
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 then
763      begin
764        if OniDataConnection.GetRawInfo(fileid, nodedata.offset).raw_size > 0 then
765          Form_Main.open_child('rawedit', fileid);
766      end;
767      if nodedata.DataType = 12 then
768      begin
769        if (StrToInt(nodedata.Value) < OniDataConnection.GetFilesCount) and
770          (StrToInt(nodedata.Value) > 0) and
771          (StrToInt(nodedata.Value) <> fileid) then
772        begin
773          if OniDataConnection.GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then
774            Form_Main.open_child('binedit', 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', -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 + GetTypeDataLength(Data.DataType) - 1;
803  end
804  else
805  begin
806    hex.SelStart := Data.Offset;
807    hex.SelEnd   := Data.Offset + HexToLong(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(HexToLong(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: LongWord; Value: String);
870var
871  Data: Tdata;
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:     LongWord;
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.