source: oup/current/Tool_BinEdit.pas @ 43

Last change on this file since 43 was 43, checked in by alloc, 17 years ago

DevTree 0.33a.

File size: 32.5 KB
Line 
1unit Tool_BinEdit;
2
3interface
4
5uses
6  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7  Dialogs, Wrapgrid, StdCtrls, Grids, StrUtils, MPHexEditor, ExtCtrls, Clipbrd,
8  Data, Code_Functions, Code_DataStructures, Code_Exporters, Code_OniDataClass,
9  Menus, Math, VirtualTrees, VTHeaderPopup;
10
11type
12  TForm_BinEdit = class(TForm)
13    Splitter1: TSplitter;
14    panel_data: TPanel;
15    hex:      TMPHexEditor;
16    Splitter2: TSplitter;
17    panel_files: TPanel;
18    list:     TListBox;
19    panel_extension: TPanel;
20    lbl_filter: TLabel;
21    combo_extension: TComboBox;
22    Bevel1:   TBevel;
23    panel_imexport: TPanel;
24    btn_export: TButton;
25    btn_import: TButton;
26    opend:    TOpenDialog;
27    saved:    TSaveDialog;
28    value_viewer: TWrapGrid;
29    Splitter3: TSplitter;
30    value_viewer_context: TPopupMenu;
31    value_viewer_context_copy: TMenuItem;
32    value_viewer_context_copyashex: TMenuItem;
33    value_viewer_context_copyasdec: TMenuItem;
34    value_viewer_context_copyasfloat: TMenuItem;
35    value_viewer_context_copyasbitset: TMenuItem;
36    value_viewer_context_copyasstring: TMenuItem;
37    check_zerobyte: TCheckBox;
38    edit_filtername: TEdit;
39    check_filtername: TCheckBox;
40    VST:      TVirtualStringTree;
41    VTHPopup: TVTHeaderPopupMenu;
42    procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
43      Column: TColumnIndex);
44    procedure VSTDblClick(Sender: TObject);
45    procedure VTHPopupColumnChange(const Sender: TBaseVirtualTree;
46      const Column: TColumnIndex; Visible: Boolean);
47    procedure VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
48      OldPosition: Integer);
49    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
50      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
51    procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
52    procedure LoadDat(_fileid: LongWord);
53    procedure LoadFileNames;
54    procedure check_filternameClick(Sender: TObject);
55    procedure check_zerobyteClick(Sender: TObject);
56    procedure combo_extensionClick(Sender: TObject);
57    procedure panel_extensionResize(Sender: TObject);
58    procedure listClick(Sender: TObject);
59    procedure Recreatelist;
60
61    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
62    procedure value_viewerDblClick(Sender: TObject);
63    procedure value_viewer_context_copyClick(Sender: TObject);
64    procedure value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
65      Shift: TShiftState; X, Y: Integer);
66    procedure value_viewer_contextPopup(Sender: TObject);
67    procedure btn_importClick(Sender: TObject);
68    procedure btn_exportClick(Sender: TObject);
69    procedure panel_imexportResize(Sender: TObject);
70    function Save: Boolean;
71    procedure FormClose(Sender: TObject; var Action: TCloseAction);
72    function GetValue(datatype: Word; offset: LongWord): String;
73    procedure WriteStructureInfos; //(structinfoid:Integer);
74    procedure hexSelectionChanged(Sender: TObject);
75    procedure hexChange(Sender: TObject);
76    procedure FormResize(Sender: TObject);
77    procedure ClearStructViewer;
78    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
79    procedure FormCreate(Sender: TObject);
80    procedure ClearValues;
81    procedure WriteValues;
82    procedure SetNewValue(datatype: Word; offset: LongWord; Value: String);
83    procedure listMouseDown(Sender: TObject; Button: TMouseButton;
84      Shift: TShiftState; X, Y: Integer);
85  private
86    fileid: LongWord;
87  public
88  end;
89
90var
91  Form_BinEdit: TForm_BinEdit;
92
93implementation
94
95{$R *.dfm}
96
97uses Main, Helper_ValueEdit, Tool_Rawedit;
98
99type
100  PNodeData = ^TNodeData;
101
102  TNodeData = record
103    Caption:  String;
104    Offset:   LongInt;
105    DataType: Word;
106    Value:    String;
107    Description: String;
108  end;
109
110
111
112
113function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
114  ARecord: TNodeData): PVirtualNode;
115var
116  Data: PNodeData;
117begin
118  Result := AVST.AddChild(ANode);
119  Data   := AVST.GetNodeData(Result);
120  AVST.ValidateNode(Result, False);
121  Data^ := ARecord;
122end;
123
124
125
126
127procedure TForm_BinEdit.LoadDat(_fileid: LongWord);
128var
129  i:    LongWord;
130  mem:  TMemoryStream;
131  Data: Tdata;
132begin
133  if hex.Modified then
134  begin
135    if not Save then
136    begin
137      for i := 0 to list.Count - 1 do
138      begin
139        if OniDataConnection.ExtractFileID(list.Items.Strings[i]) = fileid then
140        begin
141          list.ItemIndex := i;
142          Exit;
143        end;
144      end;
145    end;
146  end;
147  fileid := _fileid;
148  for i := 0 to list.Count - 1 do
149    if OniDataConnection.ExtractFileID(list.Items.Strings[i]) = fileid then
150    begin
151      list.ItemIndex := i;
152      Break;
153    end;
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
175procedure TForm_BinEdit.Recreatelist;
176var
177  i:    LongWord;
178  exts: TStringArray;
179begin
180  combo_extension.Items.Clear;
181  combo_extension.Items.Add('_All files_ (' + IntToStr(
182    OniDataConnection.GetFilesCount) + ')');
183  exts := OniDataConnection.GetExtensionsList;
184  for i := 0 to High(exts) do
185    combo_extension.Items.Add(exts[i]);
186  combo_extension.ItemIndex := 0;
187  combo_extensionClick(Self);
188end;
189
190
191
192
193procedure TForm_BinEdit.LoadFileNames;
194var
195  Extension: String[4];
196  no_zero_bytes: Boolean;
197  pattern: String;
198  files: TStringArray;
199  i: LongWord;
200begin
201  Extension := MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex], 1, 4);
202  no_zero_bytes := not check_zerobyte.Checked;
203  pattern := '';
204  if check_filtername.Checked then
205    pattern := edit_filtername.Text;
206  if Extension = '_All' then
207    Extension := '';
208
209  files := OniDataConnection.GetFilesList(extension, pattern, no_zero_bytes);
210  list.Items.Clear;
211  if Length(files) > 0 then
212    for i := 0 to High(files) do
213      list.Items.Add(files[i]);
214end;
215
216
217
218
219procedure TForm_BinEdit.panel_extensionResize(Sender: TObject);
220begin
221  combo_extension.Width := panel_extension.Width - 5;
222  edit_filtername.Width := panel_extension.Width - 5;
223end;
224
225
226
227
228procedure TForm_BinEdit.combo_extensionClick(Sender: TObject);
229begin
230  LoadFileNames;
231end;
232
233
234
235
236procedure TForm_BinEdit.check_zerobyteClick(Sender: TObject);
237begin
238  LoadFileNames;
239end;
240
241
242
243
244procedure TForm_BinEdit.check_filternameClick(Sender: TObject);
245begin
246  edit_filtername.Enabled := not check_filtername.Checked;
247  LoadFileNames;
248end;
249
250
251
252
253procedure TForm_BinEdit.listClick(Sender: TObject);
254begin
255  LoadDat(OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]));
256end;
257
258
259
260
261procedure TForm_BinEdit.listMouseDown(Sender: TObject; Button: TMouseButton;
262  Shift: TShiftState; X, Y: Integer);
263var
264  pt: TPoint;
265begin
266  pt.X := x;
267  pt.Y := y;
268  list.ItemIndex := list.ItemAtPos(pt, true);
269  if list.ItemIndex > -1 then
270    Self.listClick(Self);
271end;
272
273function IntToBin(Value: Byte): String;
274var
275  i: Byte;
276begin
277  Result := '';
278  for i := 7 downto 0 do
279  begin
280    Result := Result + IntToStr((Value shr i) and $01);
281  end;
282end;
283
284
285
286
287function TForm_BinEdit.GetValue(datatype: Word; offset: LongWord): String;
288var
289  Data: Tdata;
290  i:    Word;
291begin
292  case datatype of
293    1:
294      Result := IntToStr(hex.Data[offset]);
295    2:
296      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
297    3:
298      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
299    4:
300      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
301        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
302    5:
303      Result := '0x' + IntToHex(hex.Data[offset], 2);
304    6:
305      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4);
306    7:
307      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
308        hex.Data[offset + 2] * 256 * 256, 6);
309    8:
310      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
311        hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8);
312    9:
313    begin
314      SetLength(Data, 4);
315      Data[0] := hex.Data[offset];
316      Data[1] := hex.Data[offset + 1];
317      Data[2] := hex.Data[offset + 2];
318      Data[3] := hex.Data[offset + 3];
319      Result  := FloatToStr(Decode_Float(Data));
320    end;
321    10:
322      Result := IntToBin(hex.Data[offset]);
323    11:
324      Result := '0x' + IntToHex(OniDataConnection.GetRawInfo(fileid, offset).raw_addr, 8);
325    12:
326      Result := FormatNumber(hex.Data[offset + 1] + hex.Data[offset + 2] * 256 +
327        hex.Data[offset + 3] * 256 * 256, 5, '0');
328    13:
329      Result := IntToStr(hex.Data[offset]);
330    14:
331      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
332    15:
333      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
334    16:
335      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
336        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
337    17:
338      Result := IntToStr((hex.Data[offset + 3]) div 2);
339    100..300:
340    begin
341      Result := '';
342      for i := 1 to datatype - 100 do
343      begin
344        if hex.Data[offset + i - 1] >= 32 then
345          Result := Result + Chr(hex.Data[offset + i - 1])
346        else
347          Break;
348      end;
349    end;
350    1000..9999:
351    begin
352      Result := '';
353      for i := 1 to datatype - 1000 do
354      begin
355        if hex.Data[offset + i - 1] >= 32 then
356          Result := Result + Chr(hex.Data[offset + i - 1])
357        else
358          Result := Result + '.';
359      end;
360    end;
361    10000..65535:
362    begin
363      Result := '';
364      for i := 1 to datatype - 10000 do
365      begin
366        if hex.Data[offset + i - 1] >= 32 then
367          Result := Result + Chr(hex.Data[offset + i - 1])
368        else
369          Result := Result + '.';
370      end;
371    end;
372  end;
373end;
374
375
376
377
378procedure TForm_BinEdit.WriteStructureInfos;
379var
380  i, j:    LongWord;
381  pdata:   PNodeData;
382  Data:    TNodeData;
383  node:    PVirtualNode;
384  structs: TStructDef;
385begin
386  VST.BeginUpdate;
387  if VST.RootNodeCount = 0 then
388  begin
389    structs := LoadStructureDefinition(fileid);
390    if structs.Data then
391    begin
392      if Length(structs.Global) > 0 then
393      begin
394        for i := 0 to High(structs.Global) do
395        begin
396          Data.Caption  := structs.Global[i].Name;
397          Data.Offset   := structs.Global[i].offset;
398          Data.DataType := structs.Global[i].datatype;
399          Data.Value    := GetValue(structs.Global[i].datatype, structs.Global[i].offset);
400          Data.Description := structs.Global[i].description;
401          AddVSTEntry(VST, nil, Data);
402        end;
403      end;
404      if Length(structs.Subs) > 0 then
405      begin
406        for i := 0 to High(structs.Subs) do
407        begin
408          with structs.Subs[i] do
409          begin
410            if Length(Entries) > 0 then
411            begin
412              if Pos('#', SubName) > 0 then
413              begin
414                Data.Offset  := HexToLong(MidStr(SubName, Pos('#', SubName) + 1, 8));
415                Data.Value   :=
416                  MidStr(SubName, PosEx('#', SubName, Pos('#', SubName) + 1) + 1, 8);
417                Data.Caption := MidStr(SubName, 1, Pos('#', SubName) - 1);
418                Data.Description := SubDesc;
419              end
420              else
421              begin
422                Data.Caption := SubName;
423                Data.Description := SubDesc;
424                Data.Offset := 0;
425                Data.Value := '';
426              end;
427              Data.DataType := 0;
428              node := AddVSTEntry(VST, nil, Data);
429              Data.Description := '';
430              for j := 0 to High(Entries) do
431              begin
432                Data.Caption  := Entries[j].Name;
433                Data.Offset   := Entries[j].offset;
434                Data.DataType := Entries[j].datatype;
435                Data.Value    := GetValue(Entries[j].datatype, Entries[j].offset);
436                Data.Description := Entries[j].description;
437                AddVSTEntry(VST, node, Data);
438              end;
439            end;
440          end;
441        end;
442      end;
443    end;
444    if VST.RootNodeCount > 0 then
445      VST.FocusedNode := VST.GetFirst;
446  end
447  else
448  begin
449    Node := VST.GetFirst;
450    while Assigned(Node) do
451    begin
452      pdata := VST.GetNodeData(Node);
453      if pdata.DataType > 0 then
454        pdata.Value := GetValue(pdata.Datatype, pdata.Offset);
455      Node := VST.GetNext(Node);
456    end;
457  end;
458  VST.EndUpdate;
459end;
460
461
462
463
464procedure TForm_BinEdit.ClearValues;
465var
466  i: Byte;
467begin
468  for i := 1 to value_viewer.RowCount - 1 do
469  begin
470    value_viewer.Cells[1, i] := '';
471  end;
472end;
473
474
475
476
477procedure TForm_BinEdit.WriteValues;
478var
479  i, j:  Byte;
480  Data:  Tdata;
481  str:   String;
482  Value: LongWord;
483begin
484  for i := 1 to value_viewer.RowCount - 1 do
485  begin
486    if value_viewer.Cells[0, i] = '1 byte, unsigned' then
487    begin
488      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
489        ((hex.SelStart + 1) > hex.DataSize) then
490      begin
491        Value := hex.Data[hex.SelStart];
492        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2);
493      end
494      else
495        value_viewer.Cells[1, i] := '';
496    end;
497    if value_viewer.Cells[0, i] = '2 bytes, unsigned' then
498    begin
499      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
500        ((hex.SelStart + 2) > hex.DataSize) then
501      begin
502        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
503        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4);
504      end
505      else
506        value_viewer.Cells[1, i] := '';
507    end;
508    if value_viewer.Cells[0, i] = '4 bytes, unsigned' then
509    begin
510      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
511        ((hex.SelStart + 4) > hex.DataSize) then
512      begin
513        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
514          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
515        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8);
516      end
517      else
518        value_viewer.Cells[1, i] := '';
519    end;
520    if value_viewer.Cells[0, i] = 'Bitset' then
521    begin
522      if (hex.SelCount <= 8) then
523      begin
524        if hex.SelCount = 0 then
525        begin
526          SetLength(Data, 1);
527          Data[0] := hex.Data[hex.SelStart];
528        end
529        else
530        begin
531          SetLength(Data, hex.SelCount);
532          for j := 0 to hex.SelCount - 1 do
533            Data[j] := hex.Data[hex.SelStart + j];
534        end;
535        value_viewer.Cells[1, i] := DataToBin(Data);
536      end
537      else
538        value_viewer.Cells[1, i] := '';
539    end;
540    if value_viewer.Cells[0, i] = 'Float' then
541    begin
542      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
543        ((hex.SelStart + 4) > hex.DataSize) then
544      begin
545        SetLength(Data, 4);
546        for j := 0 to 3 do
547          Data[j] := hex.Data[hex.SelStart + j];
548        value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data));
549      end
550      else
551        value_viewer.Cells[1, i] := '';
552    end;
553    if value_viewer.Cells[0, i] = 'Selected length' then
554    begin
555      value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes';
556    end;
557    if value_viewer.Cells[0, i] = 'String' then
558    begin
559      j   := 0;
560      str := '';
561      if hex.SelCount = 0 then
562      begin
563        while (hex.Data[hex.SelStart + j] > 0) and ((hex.SelStart + j) < hex.DataSize) do
564        begin
565          if hex.Data[hex.selstart + j] >= 32 then
566            str := str + Char(hex.Data[hex.SelStart + j])
567          else
568            str := str + '.';
569          Inc(j);
570        end;
571      end
572      else
573      begin
574        for j := 0 to hex.SelCount - 1 do
575          if hex.Data[hex.selstart + j] >= 32 then
576            str := str + Char(hex.Data[hex.SelStart + j])
577          else if hex.Data[hex.selstart + j] > 0 then
578            str := str + '.'
579          else
580            Break;
581      end;
582      value_viewer.Cells[1, i] := str;
583    end;
584  end;
585end;
586
587
588
589
590procedure TForm_BinEdit.FormCreate(Sender: TObject);
591begin
592  Self.Caption := '';
593  fileid     := 0;
594  VST.NodeDataSize := SizeOf(TNodeData);
595  value_viewer.ColCount := 2;
596  value_viewer.RowCount := 8;
597  value_viewer.FixedRows := 1;
598  value_viewer.Cells[0, 0] := 'Type';
599  value_viewer.Cells[1, 0] := 'Value';
600  value_viewer.Cells[0, 1] := '1 byte, unsigned';
601  value_viewer.Cells[0, 2] := '2 bytes, unsigned';
602  value_viewer.Cells[0, 3] := '4 bytes, unsigned';
603  value_viewer.Cells[0, 4] := 'Bitset';
604  value_viewer.Cells[0, 5] := 'Float';
605  value_viewer.Cells[0, 6] := 'String';
606  value_viewer.Cells[0, 7] := 'Selected length';
607  value_viewer.ColWidths[0] := 100;
608  value_viewer.ColWidths[1] := value_viewer.Width - 150;
609  hex.Height := panel_data.Height - 215;
610  //
611  value_viewer.Font.Charset := AppSettings.CharSet;
612  VST.Font.Charset := AppSettings.CharSet;
613  hex.Translation := tkAsIs;
614  hex.Font.Charset := AppSettings.CharSet;
615  //
616end;
617
618
619
620
621function TForm_BinEdit.Save: Boolean;
622var
623  mem:  TMemoryStream;
624  Data: Tdata;
625  i:    LongWord;
626begin
627  case MessageBox(Self.Handle, PChar('Save changes to file ' +
628      OniDataConnection.GetFileInfo(fileid).FileName + '?'), PChar('Data changed...'),
629      MB_YESNOCANCEL) of
630    idYes:
631    begin
632      mem := TMemoryStream.Create;
633      hex.SaveToStream(mem);
634      mem.Seek(0, soFromBeginning);
635      SetLength(Data, mem.Size);
636      mem.Read(Data[0], mem.Size);
637      mem.Free;
638      OniDataConnection.UpdateDatFile(fileid, Data);
639      hex.Modified := False;
640      for i := 0 to hex.Datasize - 1 do
641        hex.ByteChanged[i] := False;
642      Result := True;
643    end;
644    idNo:
645      Result := True;
646    idCancel:
647    begin
648      Result := False;
649    end;
650  end;
651end;
652
653
654
655
656procedure TForm_BinEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
657begin
658  if hex.Modified then
659  begin
660    if not Save then
661      CanClose := False;
662  end;
663end;
664
665
666
667
668procedure TForm_BinEdit.ClearStructViewer;
669begin
670  VST.Clear;
671end;
672
673
674
675
676procedure TForm_BinEdit.FormResize(Sender: TObject);
677begin
678  if Self.Width >= 650 then
679  begin
680  end
681  else
682    Self.Width := 650;
683  if Self.Height >= 450 then
684  begin
685  end
686  else
687    Self.Height := 450;
688end;
689
690
691
692
693procedure TForm_BinEdit.hexChange(Sender: TObject);
694begin
695  ClearValues;
696  if hex.DataSize > 0 then
697  begin
698    WriteStructureInfos;
699    WriteValues;
700  end;
701end;
702
703
704
705
706procedure TForm_BinEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
707var
708  temps: String;
709begin
710  if (Shift = [ssCtrl]) and (Key = Ord('C')) then
711  begin
712    if hex.SelCount > 0 then
713    begin
714      if hex.InCharField then
715        Clipboard.AsText := hex.SelectionAsText
716      else
717        Clipboard.AsText := hex.SelectionAsHex;
718    end;
719  end;
720  if (Shift = [ssCtrl]) and (Key = Ord('V')) then
721  begin
722{      temps:=Clipboard.AsText;
723      IF hex.SelStart+Length(temps)>hex.DataSize THEN
724        SetLength(temps, hex.DataSize-hex.SelStart);
725      hex.Sel
726      hex.SelCount:=Length(temps);
727      hex.ReplaceSelection(temps,Length(temps));
728}    end;
729end;
730
731
732
733
734procedure TForm_BinEdit.hexSelectionChanged(Sender: TObject);
735var
736  selstart: Integer;
737  node:     PVirtualNode;
738  pdata:    PNodeData;
739begin
740  if hex.DataSize > 0 then
741  begin
742    WriteValues;
743    selstart := hex.SelStart;
744    if VST.RootNodeCount > 0 then
745    begin
746      Node := VST.GetFirst;
747      while Assigned(Node) do
748      begin
749        pdata := VST.GetNodeData(Node);
750        if pdata.DataType > 0 then
751        begin
752          if ((selstart - pdata.Offset) < GetTypeDataLength(pdata.DataType)) and
753            ((selstart - pdata.Offset) >= 0) then
754          begin
755            VST.FocusedNode    := Node;
756            VST.Selected[Node] := True;
757            Break;
758          end;
759        end;
760        Node := VST.GetNext(Node);
761      end;
762    end;
763  end;
764end;
765
766
767
768
769procedure TForm_BinEdit.FormClose(Sender: TObject; var Action: TCloseAction);
770begin
771  Action := caFree;
772end;
773
774
775
776
777procedure TForm_BinEdit.panel_imexportResize(Sender: TObject);
778begin
779  btn_import.Width := panel_imexport.Width - 8;
780  btn_export.Width := panel_imexport.Width - 8;
781end;
782
783
784
785
786procedure TForm_BinEdit.btn_exportClick(Sender: TObject);
787begin
788  saved.Filter     := 'Files of matching extension (*.' + OniDataConnection.GetFileInfo(
789    fileid).Extension + ')|*.' + OniDataConnection.GetFileInfo(fileid).Extension +
790    '|All files|*.*';
791  saved.DefaultExt := OniDataConnection.GetFileInfo(fileid).Extension;
792  if saved.Execute then
793  begin
794    ExportDatFile(fileid, saved.FileName);
795  end;
796end;
797
798
799
800
801procedure TForm_BinEdit.btn_importClick(Sender: TObject);
802var
803  fs: TFileStream;
804begin
805  opend.Filter := 'Files of matching extension (*.' + OniDataConnection.GetFileInfo(
806    fileid).Extension + ')|*.' + OniDataConnection.GetFileInfo(fileid).Extension +
807    '|All files|*.*';
808  if opend.Execute then
809  begin
810    fs := TFileStream.Create(opend.FileName, fmOpenRead);
811    if fs.Size <> hex.DataSize then
812    begin
813      ShowMessage('Can''t import ' + ExtractFilename(opend.FileName) +
814        ', file has to have same size as file in .dat.' + CrLf +
815        'Size of file in .dat: ' + FormatFileSize(hex.datasize) + CrLf +
816        'Size of chosen file: ' + FormatFileSize(fs.Size));
817    end
818    else
819    begin
820      hex.LoadFromStream(fs);
821      hex.Modified := True;
822    end;
823    fs.Free;
824  end;
825end;
826
827
828
829
830procedure TForm_BinEdit.value_viewer_contextPopup(Sender: TObject);
831var
832  i: Byte;
833begin
834  for i := 0 to value_viewer_context.Items.Count - 1 do
835    value_viewer_context.Items.Items[i].Visible := False;
836  with value_viewer do
837  begin
838    if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then
839    begin
840      if Pos(' byte', Cells[0, Row]) = 2 then
841      begin
842        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
843        value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True;
844        value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True;
845      end;
846      if Pos('Float', Cells[0, Row]) = 1 then
847        value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True;
848      if Pos('Bitset', Cells[0, Row]) = 1 then
849        value_viewer_context.Items.Find(
850          'Copy to clipboard (as &bitset)').Visible := True;
851      if Pos('String', Cells[0, Row]) = 1 then
852        value_viewer_context.Items.Find(
853          'Copy to clipboard (as &string)').Visible := True;
854      if Pos('Selected length', Cells[0, Row]) = 1 then
855        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
856    end;
857  end;
858end;
859
860
861
862
863procedure TForm_BinEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
864  Shift: TShiftState; X, Y: Integer);
865var
866  ACol, ARow: Integer;
867begin
868  if Button = mbRight then
869  begin
870    value_viewer.MouseToCell(x, y, ACol, ARow);
871    if ARow > 0 then
872    begin
873      value_viewer.Col := ACol;
874      value_viewer.Row := ARow;
875    end;
876  end;
877end;
878
879
880
881
882procedure TForm_BinEdit.value_viewer_context_copyClick(Sender: TObject);
883var
884  Name:  String;
885  Value: LongWord;
886begin
887  Name := TMenuItem(Sender).Name;
888  if Pos('asstring', Name) > 0 then
889  begin
890    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
891  end
892  else if Pos('asfloat', Name) > 0 then
893  begin
894    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
895  end
896  else if Pos('asbitset', Name) > 0 then
897  begin
898    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
899  end
900  else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then
901  begin
902    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
903    begin
904      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
905        ((hex.SelStart + 1) > hex.DataSize) then
906        Value := hex.Data[hex.SelStart];
907    end;
908    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
909    begin
910      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
911        ((hex.SelStart + 2) > hex.DataSize) then
912        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
913    end;
914    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
915    begin
916      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
917        ((hex.SelStart + 4) > hex.DataSize) then
918        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
919          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
920    end;
921    if Pos('asdec', Name) > 0 then
922    begin
923      Clipboard.AsText := IntToStr(Value);
924    end
925    else
926    begin
927      if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
928        Clipboard.AsText := '0x' + IntToHex(Value, 2);
929      if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
930        Clipboard.AsText := '0x' + IntToHex(Value, 4);
931      if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
932        Clipboard.AsText := '0x' + IntToHex(Value, 8);
933    end;
934  end
935  else
936  begin
937    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
938  end;
939end;
940
941
942
943
944procedure TForm_BinEdit.VSTDblClick(Sender: TObject);
945var
946  node: PVirtualNode;
947  nodedata: PNodeData;
948  id: Integer;
949begin
950  if VST.FocusedColumn = 3 then
951  begin
952    node     := VST.FocusedNode;
953    nodedata := VST.GetNodeData(node);
954
955    if not (nodedata.datatype in [11, 12]) and
956      ((nodedata.DataType < 100) or (nodedata.DataType > 300)) then
957    begin
958      Form_ValueEdit.MakeVarInput(nodedata.Caption, nodedata.offset,
959        nodedata.datatype, nodedata.Value, Self);
960    end
961    else
962    begin
963      if nodedata.DataType = 11 then
964      begin
965        if OniDataConnection.GetRawInfo(fileid, nodedata.offset).raw_size > 0 then
966        begin
967          if Form_Main.open_child('rawedit') then
968          begin
969            TForm_RawEdit(Form_Main.ActiveMDIChild).LoadRaw(
970              OniDataConnection.GetRawInfo(fileid, nodedata.offset));
971          end;
972        end;
973      end;
974      if nodedata.DataType = 12 then
975      begin
976        if (StrToInt(nodedata.Value) < OniDataConnection.GetFilesCount) and
977          (StrToInt(nodedata.Value) > 0) and
978          (StrToInt(nodedata.Value) <> fileid) then
979        begin
980          if OniDataConnection.GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then
981          begin
982            if Form_Main.open_child('binedit') then
983            begin
984              TForm_BinEdit(Form_Main.ActiveMDIChild).LoadDat(StrToInt(nodedata.Value));
985            end;
986          end
987          else
988          begin
989            ShowMessage('Linked filed is a zero-byte-file');
990          end;
991        end;
992      end;
993      if (nodedata.DataType >= 100) and (nodedata.DataType <= 300) then
994      begin
995        if Form_Main.open_child('binedit') then
996        begin
997          TForm_BinEdit(Form_Main.ActiveMDIChild).edit_filtername.Text := nodedata.Value;
998          TForm_BinEdit(Form_Main.ActiveMDIChild).check_filtername.Checked := True;
999          TForm_BinEdit(Form_Main.ActiveMDIChild).check_filternameClick(Self);
1000        end;
1001      end;
1002    end;
1003
1004  end;
1005end;
1006
1007
1008
1009
1010procedure TForm_BinEdit.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
1011  Column: TColumnIndex);
1012var
1013  Data: PNodeData;
1014begin
1015  Data := VST.GetNodeData(node);
1016  if Data.DataType > 0 then
1017  begin
1018    hex.SelStart := Data.Offset;
1019    hex.SelEnd   := Data.Offset + GetTypeDataLength(Data.DataType) - 1;
1020  end
1021  else
1022  begin
1023    hex.SelStart := Data.Offset;
1024    hex.SelEnd   := Data.Offset + HexToLong(Data.Value) - 1;
1025  end;
1026end;
1027
1028
1029
1030
1031procedure TForm_BinEdit.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
1032  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
1033var
1034  Data: PNodeData;
1035begin
1036  Data     := Sender.GetNodeData(Node);
1037  CellText := '';
1038  if TextType = ttNormal then
1039  begin
1040    case Column of
1041      0:
1042        CellText := Data.Caption;
1043      1:
1044        if Data.DataType > 0 then
1045          CellText := '0x' + IntToHex(Data.Offset, 8)
1046        else if Data.Offset > 0 then
1047          CellText := '0x' + IntToHex(Data.Offset, 8);
1048      2:
1049        if Data.DataType > 0 then
1050          CellText := GetDataType(Data.DataType);
1051      3:
1052        if Data.DataType > 0 then
1053          CellText := Data.Value //GetValue(data.DataType, data.Offset)
1054        else if Length(Data.Value) > 0 then
1055          CellText := IntToStr(HexToLong(Data.Value)) + ' Bytes';
1056      4:
1057        CellText := Data.Description;
1058    end;
1059  end;
1060end;
1061
1062
1063
1064
1065procedure TForm_BinEdit.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
1066  OldPosition: Integer);
1067begin
1068  if Sender.Columns.Items[column].Position < 1 then
1069    Sender.Columns.Items[column].Position := OldPosition;
1070end;
1071
1072
1073
1074
1075procedure TForm_BinEdit.VTHPopupColumnChange(const Sender: TBaseVirtualTree;
1076  const Column: TColumnIndex; Visible: Boolean);
1077begin
1078  if column = 0 then
1079    TVirtualStringTree(Sender).Header.Columns.Items[column].Options :=
1080      TVirtualStringTree(Sender).Header.Columns.Items[column].Options + [coVisible];
1081end;
1082
1083
1084
1085
1086procedure TForm_BinEdit.SetNewValue(datatype: Word; offset: LongWord; Value: String);
1087var
1088  Data: Tdata;
1089  value_int: LongWord;
1090  value_float: Single;
1091  i: Word;
1092begin
1093  case datatype of
1094    1..4:
1095    begin
1096      value_int := StrToInt(Value);
1097      SetLength(Data, datatype);
1098      for i := 0 to datatype - 1 do
1099      begin
1100        Data[i]   := value_int mod 256;
1101        value_int := value_int div 256;
1102      end;
1103    end;
1104    5..8:
1105    begin
1106      value_int := StrToInt('$' + Value);
1107      SetLength(Data, datatype - 4);
1108      for i := 0 to datatype - 5 do
1109      begin
1110        Data[i]   := value_int mod 256;
1111        value_int := value_int div 256;
1112      end;
1113    end;
1114    9:
1115    begin
1116      value_float := StrToFloat(Value);
1117      Data := Encode_Float(value_float);
1118    end;
1119    10:
1120    begin
1121      value_int := BinToInt(Value);
1122      SetLength(Data, 1);
1123      Data[0] := value_int;
1124    end;
1125    10000..65535:
1126    begin
1127      SetLength(Data, datatype - 10000);
1128      for i := 1 to datatype - 10000 do
1129      begin
1130        if i <= Length(Value) then
1131          Data[i - 1] := Ord(Value[i])
1132        else
1133          Data[i - 1] := 0;
1134      end;
1135    end;
1136  end;
1137  for i := 0 to High(Data) do
1138  begin
1139    if hex.Data[offset + i] <> Data[i] then
1140      hex.ByteChanged[offset + i] := True;
1141    hex.Data[offset + i] := Data[i];
1142  end;
1143  hex.Modified := True;
1144  hexChange(Self);
1145  hex.Repaint;
1146end;
1147
1148
1149
1150
1151procedure TForm_BinEdit.value_viewerDblClick(Sender: TObject);
1152var
1153  offset:     LongWord;
1154  datatype:   Word;
1155  objectname: String;
1156  Value:      String;
1157begin
1158  if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then
1159  begin
1160    offset := hex.SelStart;
1161    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
1162      datatype := 1;
1163    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
1164      datatype := 2;
1165    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
1166      datatype := 4;
1167    if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then
1168      datatype := 10;
1169    if value_viewer.Cells[0, value_viewer.Row] = 'Float' then
1170      datatype := 9;
1171    if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then
1172      Exit;
1173    if value_viewer.Cells[0, value_viewer.Row] = 'String' then
1174    begin
1175      if hex.SelCount > 0 then
1176        datatype := 10000 + hex.SelCount
1177      else
1178        datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]);
1179    end;
1180    objectname := '';
1181    Value      := GetValue(datatype, offset);
1182    Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self);
1183  end;
1184end;
1185
1186
1187
1188
1189procedure TForm_BinEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
1190begin
1191  if (Shift = [ssCtrl]) and (Key = 83) then
1192    if hex.Modified then
1193      if not Save then
1194        Exit;
1195end;
1196
1197
1198end.
Note: See TracBrowser for help on using the repository browser.