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

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