source: oup/rewrite/Tools/BinEdit.pas @ 105

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